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