E2E Testing with Cypress and GraphQL
You have a full-stack application and your server is running on GraphQL. It's common practice to mock out your back-end so you can test your front-end in isolation. They are separate systems after all and should be tested separately.
Until now this has been quite a difficult task. By default, cypress has poor support for mocking GraphQL servers.
This is a guide to achieving seamless GraphQL mocking in your cypress tests. With this you can easily test happy paths, edge cases and error states; all from the comfort of a single test file.
We'll be using a library specifically built for this problem.
https://github.com/warrenday/cypress-graphql-mock-network
With cypress-graphql-mock-network, you can provide your own GraphQL schema for auto-mocking, which means you only need to mock the parts you care about for each test.
Here's an example of how a test would look:
it('displays initial list of todos', () => {
cy.mockNetworkAdd({
Query: () => ({
todos: () => ([
{
id: '1',
title: 'Go shopping',
completed: true,
},
]),
}),
});
cy.get('li')
.eq(0)
.contains(/Go shopping/)
.should('exist');
});
Here's an example of how we might mock an error state
cy.mockNetworkAdd({
Query: () => ({
todos: () => {
throw new Error('Oh dear');
},
}),
});
Automocking
Under the hood we're using the mocking support of graphql-tools. So you only need to supply the parts of the mock you care about for a test. The rest will be automatically filled in based on the field's type.
Let's say we have the following schema
type Todo {
id: ID
title: String
completed: Boolean
}
type Query {
todo(id: ID!): Todo
}
In our mocks, if all we cared about was the title, we could do the following:
cy.mockNetworkAdd({
Query: () => ({
todo: () => ({
title: 'I expect to be this'
})
}),
});
Even if our application were to query for id, title and completed the mock would still work. We would end up receiving something like:
{
"id": 1,
"title": "I expect to be this",
"completed": false
}
Here id and completed are auto-mocked based on their type, so you can keep your tests streamlined and avoid providing a bunch of data you don't care about.
Service Workers
They'll be no monkey-patching here lad. cypress-graphql-mock-network uses the awesome https://github.com/mswjs/msw meaning real network requests are sent from your app and all mocking is inspectable in the network tab and console. This helps a ton when debugging.
The browser will continue to use the real Fetch and XHR APIs, which is much more realistic to a production environment.
Here you can see the network tab shows the request and the mocked response.

Setup
A full setup guide is available on GitHub, which also includes a demo cypress project, so head for more details on installation and setup: https://github.com/warrenday/cypress-graphql-mock-network
To see the demo tests in action, pull the repo then we need to do two things:
Run the demo app: Change directory to /demo, install node_modules with
yarn, then runyarn startRun the cypress tests: At the project root install node_modules again with
yarnand then runyarn cypress
With this we should then see our the tests passing.

Thanks for reading. If you have any further questions please let me know.