A Solution for Stubbing GraphQL Requests
See original GitHub issueHere is a potential solution to stubbing graphql requests in Cypress
Caveats
- the requests cannot be
waited
on, but they do return promises that resolve immediately so it shouldn’t be an issue in practice - a new
visit
is required to set or change a stub, so this can have a negative performance impact on the tests - assumes your app is using
fetch
but can probably be modified to work forxhr
- assumes you are using Cypress v0.20.x (I think)
- does not provide any error handling
Details
1. Create a Cypress Command
to make life easier
/*
* Create a command named `visitStubbed` that wraps the normal `cy.visit`. It
* takes the url as the first parameter and * an object with your graphql
* request stubs. Each key of the object must match the `operationName` of the
* graphql request to be stubbed and each value is an object containing the
* stubbed graphql response.
*
* Ex.
* ```
* cy.visitStubbed('/home', {
* fetchWidgets: {
* data: {
* widgets: [{
* id: 1,
* name: 'Cool Widget',
* __typename: 'Widget',
* //...
* }]
* }
* }
* })
* ```
*/
// import the function from the following step (optional)
import { runQuery } from '../support/graphql'
Cypress.Commands.add('visitStubbed', function(url, operations = {}) {
cy.visit(url, {
onBeforeLoad: win => {
cy
// stub `fetch`
.stub(win, 'fetch')
// your graphql endpoint
.withArgs('/graphql')
// call our stub
.callsFake(serverStub)
},
})
function serverStub(_, req) {
// parse the request
const { operationName, query, variables } = JSON.parse(req.body)
// return the stub if it was provided
const resultStub = operations[operationName]
if (resultStub) {
return Promise.resolve(responseStub(resultStub))
}
// else {
// return {}
// }
// If you want, fallback to default mock data if stub for operation is not specified (optional)
return runQuery(query, variables).then(responseStub)
}
})
function responseStub(result) {
return {
json() {
return Promise.resolve(result)
},
ok: true,
}
}
2. Create a mock GraphQL server (Optional)
You only need this if you want a fallback to a mock server. This requires your schema in SDL format to be exported as a string from a .js file. We handle this by generating the file before running Cypress using get-graphql-schema
:
ORIGIN=https://some-url.com
SCHEMA_FILE=cypress/schema.js
echo "module.exports = \`" > $SCHEMA_FILE
node_modules/.bin/get-graphql-schema $URL >> $SCHEMA_FILE
echo "\`" >> $SCHEMA_FILE
import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools'
import { graphql } from 'graphql'
// Your schema in SDL format exported as a string
import typeDefs from '../schema'
const schema = makeExecutableSchema({ typeDefs })
addMockFunctionsToSchema({ schema })
export function runQuery(query, variables) {
return graphql(schema, query, {}, {}, variables)
}
Issue Analytics
- State:
- Created 6 years ago
- Reactions:33
- Comments:84 (6 by maintainers)
Top Results From Across the Web
Stubbing GraphQL using Cypress - Jay Freestone
A more ergonomic solution to stubbing out multiple GraphQL responses using Cypress.
Read more >Smart GraphQL Stubbing in Cypress - Gleb Bahmutov
How to spy on and stub GraphQL calls from the application using Cypress and its new cy.route2 API. Testing GraphQL calls; Testing without ......
Read more >Mock Graphql server with multiple stubs in Cypress
For anyone else hitting this issue, there is a working solution with ... With that is posible to stub exact request queries and...
Read more >Cypress: Mocking GraphQL Requests | by Viskantas Juodenas
A helper function is going to mock all window.fetch calls that are executed with /graphql endpoint. The fetch stub will look for mock...
Read more >Cypress and GraphQL - Udacity Eng & Data
This article will detail solutions to these problems. Network Stubbing and Aliasing. Unlike a REST API, GraphQL requests are all sent to a...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@egucciar @joshuataylor very nice solution! It works for me.
I just prefer to stick with custom command, so I don’t have to explicitly export and import the function.
If I have this in
support/index.js
:Then I’ll add this in
support/commands.js
:I write my stub in
fixtures/allCars.json
:And I can use the command in
integration/my-page.spec.js
:It looks very neat.
Thanks so much for these solutions so far! I used a lot of the code in this discussion to create an entirely separate
mockGraphQL
command rather than creating an extendedvisit
command:With that, I can then simply call
mockGraphQL
before thevisit
call in my test:Note that I used the event approach described here rather than overriding visit.
I think this approach is a little tighter and more explicit than the other solutions so far, but that may just be my personal preference. Sharing here in case someone else feels the same way.