Introduction:
Testing GraphQL queries and mutations is a crucial part of ensuring the reliability and functionality of your React applications. There are multiple phases involved in creating test cases for GraphQL queries and changes with Jest. Jest is a well-liked JavaScript testing framework that works well for testing mutations and queries in GraphQL. Here’s a step-by-step guide on how to efficiently write test cases for GraphQL queries and mutations using Jest.
Prerequisites:
Before diving into testing, ensure you have the following technologies:
- React.js
- Jest
- GraphQL
Create a setup for Jest configuration below blog can help set up for jest.
Test React Typescript Component with Jest and RTL
Once the setup is complete, we’ll create a simple login form that includes GraphQL queries and mutations.
// login form
import React from "react";
import { useForm } from "react-hook-form";
import { useQuery, useMutation, ApolloError } from "@apollo/react-hooks";
import {
TextField,
Button,
Container,
Typography,
makeStyles,
ListItem,
List,
ListItemText,
Paper,
} from "@material-ui/core";
import { ADD_USER } from "../ApolloClient/GraphlQL/Mutation";
import { GET_USERS } from "../ApolloClient/GraphlQL/Query";
const useStyles = makeStyles((theme) => ({
formContainer: {
marginTop: theme.spacing(4),
display: "flex",
flexDirection: "column",
alignItems: "center",
},
formPaper: {
padding: theme.spacing(4),
boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.1)",
borderRadius: theme.spacing(1),
},
form: {
width: "100%",
maxWidth: "400px",
marginTop: theme.spacing(2),
},
submitButton: {
marginTop: theme.spacing(2),
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
"&:hover": {
backgroundColor: theme.palette.primary.dark,
},
},
userList: {
listStyle: "none",
padding: 0,
marginTop: theme.spacing(2),
width: "100%",
maxWidth: "400px",
},
userListItem: {
marginBottom: theme.spacing(1),
backgroundColor: "#d3d2d2",
borderRadius: theme.spacing(1),
"&:hover": {
boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.1)",
borderRadius: theme.spacing(1),
Color: "#ccc",
},
},
listItemText: {
color: theme.palette.text.primary,
},
}));
interface UserData {
id: string;
name: string;
email: string;
}
interface GetUsersData {
users: UserData[];
}
interface FormData {
name: string;
email: string;
}
function MaterialUIForm() {
const { register, handleSubmit, reset } = useForm();
const { loading, error, data } = useQuery(GET_USERS);
const [addUser] = useMutation(ADD_USER);
const classes = useStyles();
const onSubmit = async (formData: any) => {
try {
const { data: mutationData } = await addUser({
variables: {
input: {
name: formData.name,
email: formData.email,
},
},
});
reset();
if (mutationData && mutationData.addUser && mutationData.addUser.id) {
console.log(mutationData, "mutationData");
}
} catch (error) {
const mutationError = error as ApolloError;
console.error("Error adding user:", mutationError.message);
}
};
if (loading) return Loading...
;
if (error) return Error: {error.message}
;
return (
Add User
{/* Display existing users */}
Existing Users
{data?.users.map(
(user: {
id: React.Key | null | undefined;
name: any;
email: any;
}) => (
)
)}
);
}
export default MaterialUIForm;
In this form, I have used one query to retrieve existing user information and added a mutation for adding a new user.
Query:
export const GET_USERS = gql`
query getUsers {
users {
id
name
Email
}
}
`;
Mutation:
export const ADD_USER = gql`
mutation addUser($input: UserInput!) {
addUser(input: $input) {
id
name
email
}
}
`;
Write unit test cases for the query and mutation
Let’s start writing test cases for the above query and mutation.
- Install the necessary packages for testing GraphQL. These packages will help you mock and test GraphQL queries and mutations.
[ npm install --save-dev @apollo/client graphql ]
- Create a test file for your component, e.g., MaterialUIForm.test.tsx in the _tests_ directory.
- Import MockedProvider from @apollo/client/testing to handle GraphQL queries and mutations.
import { MockedProvider } from "@apollo/client/testing";
// Your desire component
-
- mocks is an array of mock responses to simulate GraphQL queries and mutations.
- addTypename={false} is used to exclude the typename field from the generated queries. It can be helpful when working with Apollo Client.
- Mock the GraphQL queries and mutations that your component will use.
const mocks = [
{
request: {
query: GET_USERS,
},
result: {
data: {
users: [
{
id: "1",
name: "John Doe",
email: "john@example.com",
},
],
},
},
},
{
request: {
query: ADD_USER,
variables: {
input: {
name: "Test User",
email: "test@example.com",
},
},
},
result: {
data: {
addUser: {
id: "3",
name: "Test User",
email: "test@example.com",
},
},
},
},
];
- Write a below test case for the GET_USERS query.
it("renders form and existing users", async () => {
render(
);
const inputName = await screen.findByTestId("Name");
await userEvent.type(inputName, "John Doe");
expect(inputName).toHaveValue("John Doe");
const inputEmail = await screen.findByTestId("Email");
await userEvent.type(inputEmail, "john@example.com");
expect(inputEmail).toHaveValue("john@example.com");
console.log(mocks[0]?.result?.data?.users, "GetUserData");
});
- Run your tests using the following command:
npm test
- As we finish writing test case for the query. Let’s now write a test cases for the ADD_USERS mutation.
it("submits the form and updates the UI", async () => {
render(
);
await waitFor(() => {
fireEvent.input(screen.getByTestId("Name"), {
target: { value: "john@example.com" },
});
});
await waitFor(() => {
fireEvent.input(screen.getByTestId("Email"), {
target: { value: "Test User" },
});
});
await waitFor(() => {
fireEvent.click(screen.getByTestId("save-form-data"));
});
await waitFor(() => {
expect(mocks[1]?.result?.data?.addUser?.id).toBe("3");
});
});
});
- Run your tests using the following command:
npm test
Services Our ReactJS Development Team offers:
- Unlock the potential of ReactJS with our Custom Application Development service. Tailored solutions for your unique needs. Expertise in building responsive, high-performance web apps. Let’s bring your vision to life with ReactJS.
- Integrate seamlessly with the ReactJS API Integration service. Connect your app to external data sources effortlessly. Enhance functionality and the user experience. Let’s bridge the gap between your app and the world!
- Elevate the user experience with ReactJS Single Page Development services. Craft dynamic, responsive apps for seamless navigation and engagement. Drive conversions and stand out in the digital realm. Let’s build your next-gen SPAs!