websocketgraphqlcypresse2e-testing

Cypress E2E Mock GraphQL Subscription as Query


Is there a way to mock a subscription from GraphQL? I only need to return some data once. So pretty much instead of a subscription have a GET query.

I did have a look into the Cypress-Documentation but I only saw something about queries and mutations.

Subscriptions use the wss instead of the https protocol and are not POST methods. Thus, I do not think it is possible to use the

cy.intercept('POST', 'http://localhost:3000/graphql', (req) => {...})

style of request mocking.

For the GraphQL requests, I am using the React Apollo library.

It is peculiar that I didn't find anything in this direction. I am new in E2E testing so maybe my thought process is wrong.

I am using Cypress v13.


Solution

  • There is an issue thread with a custom command here Mock websockets #2492 which apparently works for the author, and has 7 thumbs.

    import { Server, WebSocket } from "mock-socket"
    
    const mockGraphQlSocket = new Server(Cypress.env("GRAPHQL_WEB_SOCKET"))
    
    Cypress.Commands.add("mockGraphQLSocket", mocks => {
      cy.on("window:before:load", win => {
        win.WebSocket = WebSocket
        mockGraphQlSocket.on("connection", socket => {
          socket.on("message", data => {
            const { id, payload } = JSON.parse(data)
    
            if (payload && mocks.hasOwnProperty(payload.operationName)) {
              mocks[payload.operationName](
                // Delegate the socket send call to the party owning the mock data since multiple calls might need to be made (for example to update multiple individual entries)
                data =>
                  socket.send(
                    JSON.stringify({
                      type: "data",
                      id,
                      payload: { errors: [], data }
                    })
                  ),
                payload.variables
              )
            }
          })
        })
      })
    })
    

    In the test

    cy.mockGraphQLSocket({
        yourGraphQlQuery: (send, { uuids }) => {
          uuids.forEach(id => {
            send({
              yourGraphQlQuery: {
                ...yourMockData,
                id
              }
            })
          })
        }
      })