Testing GraphQL Yoga Subscriptions with Jest is stuck and causing timeout errors

194 views Asked by At

I have been trying to write some jest tests on a graphql yoga subscription but can't seem to get it to work as I keep getting timeout errors, can't seem to find what is making it timeout.

My GraphQL Yoga code below:

server.js

import {createYoga, createPubSub} from 'graphql-yoga'
import { makeExecutableSchema} from '@graphql-tools/schema';
import { SubscriptionServer} from 'subscriptions-transport-ws';
import { execute, subscribe } from 'graphql';
import {applyMiddleware} from 'graphql-middleware'
import resolvers from './resolvers/index'

import {createServer} from 'node:http'
import gprf from 'graphql-parse-relation-fields'
import dbRelationalFields from "./helpers/db-relational-fields";
import userFragmentMiddleware from './middleware/userFragmentMiddleware'
import typeDefs from './typeDefs';
import prismaContext from './prismaContext';
const pubsub = createPubSub()


const schema = makeExecutableSchema({typeDefs, resolvers})
const schemaWithMiddleware = applyMiddleware(schema, userFragmentMiddleware)
const yoga = createYoga({
  schema: schemaWithMiddleware,
  
  context({request}){
    
    return {
      
      pubsub,
      gprf,
      prisma:prismaContext,
      dbRelationalFields,
      request 
      
  }
  },


})
const server = createServer(yoga)


export {server}

index.js

import {server} from './server'

import * as dotenv from 'dotenv'



dotenv.config()


const main = async() => {
    
 
  
 
    let port = process.env.PORT || 4000
    
  server.listen(port, ()=>{
    console.log(`the server is up on port: ${port}`)
})



}

main();

Now The Jest side of things

getClient.js

import { ApolloClient, InMemoryCache, createHttpLink, split } from '@apollo/client';
import { getMainDefinition } from '@apollo/client/utilities';
import { setContext } from '@apollo/client/link/context';
import { WebSocketLink } from '@apollo/client/link/ws';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import WebSocket from 'ws';

const getClient = (jwt = '') => {
   const wsLink = new SubscriptionClient(
     'ws://localhost:4000/graphql',
    {
      reconnect: true,
      connectionParams: {
        authToken: !!jwt ? jwt : null
      }
    },
    WebSocket
  );
  let uri = 'http://localhost:4000/graphql';
  let httpLink = createHttpLink({ uri });
  const authLink = setContext((_, { headers }) => {
    return {
      headers: {
        ...headers,
        authorization: !!jwt ? `Bearer ${jwt}` : ''
      }
    };
  });
  const splitLink = split(
    ({ query }) => {
      const definition = getMainDefinition(query);
      return (
        definition.kind === 'OperationDefinition' &&
        definition.operation === 'subscription'
      );
    },
    wsLink,
    authLink.concat(httpLink)
  );

  

  return new ApolloClient({
    link: splitLink,
    cache: new InMemoryCache(),
    request(operation) {
      if (!!jwt === true) {
        operation.setContext({ headers: { authorization: `Bearer ${jwt}` } });
      }
    }
  });
};

export { getClient as default };

The test operation file comment-operation.js

import {gql } from '@apollo/client';




const deleteComment = gql`
mutation deleteComment($id: ID!, $postId: ID!){
    deleteComment(id: $id, postId: $postId){
        id
        text
        author {
            id
        }
        post {
            id
        }

    }

}
`


const subscribeToComments = gql`
subscription subscribeToComments($postId: ID!){
    comment(postId: $postId){
        mutation
        data {
            id
            text
            updateCheckField
        }
    }
}

`

export {deleteComment, subscribeToComments}

The Comment test file comment.spec.js

import 'cross-fetch/polyfill'
import React from 'react';
import ReactDOM from 'react-dom';
import bcrypt from 'bcryptjs'
import { execute, subscribe }  from '@apollo/client/link/core'
import { gql } from '@apollo/client';
import PrismaContext from '../src/prismaContext'
import { v4 as uuidv4 } from 'uuid';
import seedDatabase, {userOne, userTwo} from './utils/seedDatabase'
import getClient, {wsLink} from './utils/getClient'
import {deleteComment, subscribeToComments} from './utils/comment-operations'
import {deletePost} from './utils/post-operations'
const client = getClient();

beforeEach(seedDatabase)


test('should subscribe to comments for a post', async(done)=>{
    const client = getClient(userTwo.jwt)
    
    const variables = {
        postId: userTwo.posts[0]["id"]
    }

  

    //const observable = client.subscribe({ query: subscribeToComments, variables})
    const subscription = client.subscribe({ query: subscribeToComments, variables}).subscribe({
        next: (result) => {
          // Perform assertions on the received subscription data
          expect(result.data.comment.mutation).toBe('DELETED')
      expect(result.data.comment.data.updateCheckField).toBe(`${userTwo.comments[1].id}${userOne.user.id}${userTwo.posts[0].id}`)
          subscription.unsubscribe();
          done();
        },
      });
    
  
      

    
    
    //delete a post
    const client1 = getClient(userOne.jwt)
    const variables1 = {
        id: userTwo.comments[1]["id"],
        postId: userTwo.posts[0]["id"]  
    }



    client1.mutate({mutation: deleteComment, variables: variables1})
    .then((response)=>{
        
    })
    .catch((err)=> console.log('nawaooo', err))
  
})

The Error Message: thrown: "Exceeded timeout of 5000 ms for a test while waiting for done() to be called. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

0

There are 0 answers