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."