From d3214731388070df5dfafde4762d47d6e81af88c Mon Sep 17 00:00:00 2001 From: Denis Badurina Date: Fri, 11 Jun 2021 11:21:50 +0200 Subject: [PATCH] chore(jest): use `jest-jasmine2` test runner instead At least until https://github.com/facebook/jest/issues/10529 lands. --- jest.config.js | 1 + src/tests/client.ts | 187 ++++++------ src/tests/server.ts | 601 +++++++++++++++++++-------------------- src/tests/use.ts | 148 +++++----- src/tests/utils/index.ts | 8 - 5 files changed, 440 insertions(+), 505 deletions(-) diff --git a/jest.config.js b/jest.config.js index 864bf74f..d48152e5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,6 @@ module.exports = { testEnvironment: 'node', + testRunner: 'jest-jasmine2', moduleFileExtensions: ['ts', 'js'], testRegex: '/tests/.+.ts$', testPathIgnorePatterns: ['/node_modules/', '/fixtures/', '/utils/'], diff --git a/src/tests/client.ts b/src/tests/client.ts index 72469262..6e7ead0e 100644 --- a/src/tests/client.ts +++ b/src/tests/client.ts @@ -11,7 +11,7 @@ import { stringifyMessage, SubscribePayload, } from '../common'; -import { startWSTServer as startTServer, waitForDone } from './utils'; +import { startWSTServer as startTServer } from './utils'; // simulate browser environment for easier client testing beforeEach(() => { @@ -167,31 +167,28 @@ it('should not accept invalid WebSocket implementations', async () => { ).toThrow(); }); -it( - 'should recieve optional connection ack payload in event handler', - waitForDone(async (done) => { - const { url } = await startTServer({ - onConnect: () => ({ itsa: 'me' }), - }); +it('should recieve optional connection ack payload in event handler', async (done) => { + const { url } = await startTServer({ + onConnect: () => ({ itsa: 'me' }), + }); - createClient({ - url, - retryAttempts: 0, - onNonLazyError: noop, - lazy: false, - on: { - connected: (_socket, payload) => { - try { - expect(payload).toEqual({ itsa: 'me' }); - } catch (err) { - fail(err); - } - done(); - }, + createClient({ + url, + retryAttempts: 0, + onNonLazyError: noop, + lazy: false, + on: { + connected: (_socket, payload) => { + try { + expect(payload).toEqual({ itsa: 'me' }); + } catch (err) { + fail(err); + } + done(); }, - }); - }), -); + }, + }); +}); it('should close with error message during connecting issues', async () => { const { url } = await startTServer(); @@ -379,32 +376,29 @@ it('should use a custom JSON message reviver function', async () => { }); }); -it( - 'should use a custom JSON message replacer function', - waitForDone(async (done) => { - const { url, waitForClient } = await startTServer(); +it('should use a custom JSON message replacer function', async (done) => { + const { url, waitForClient } = await startTServer(); - createClient({ - url, - lazy: false, - retryAttempts: 0, - onNonLazyError: noop, - jsonMessageReplacer: (key, value) => { - if (key === 'type') { - return 'CONNECTION_INIT'; - } - return value; - }, - }); + createClient({ + url, + lazy: false, + retryAttempts: 0, + onNonLazyError: noop, + jsonMessageReplacer: (key, value) => { + if (key === 'type') { + return 'CONNECTION_INIT'; + } + return value; + }, + }); - await waitForClient((client) => { - client.onMessage((data) => { - expect(data).toBe('{"type":"CONNECTION_INIT"}'); - done(); - }); + await waitForClient((client) => { + client.onMessage((data) => { + expect(data).toBe('{"type":"CONNECTION_INIT"}'); + done(); }); - }), -); + }); +}); describe('ping/pong', () => { it('should respond with a pong to a ping', async () => { @@ -520,29 +514,26 @@ describe('ping/pong', () => { }, 20); }); - it( - 'should ping the server after the keepAlive timeout', - waitForDone(async (done) => { - const { url, waitForConnect, waitForClient } = await startTServer(); + it('should ping the server after the keepAlive timeout', async (done) => { + const { url, waitForConnect, waitForClient } = await startTServer(); - createClient({ - url, - lazy: false, - retryAttempts: 0, - onNonLazyError: noop, - keepAlive: 20, - }); + createClient({ + url, + lazy: false, + retryAttempts: 0, + onNonLazyError: noop, + keepAlive: 20, + }); - await waitForConnect(); + await waitForConnect(); - await waitForClient((client) => { - client.onMessage((data) => { - expect(data).toBe('{"type":"ping"}'); - done(); - }); + await waitForClient((client) => { + client.onMessage((data) => { + expect(data).toBe('{"type":"ping"}'); + done(); }); - }), - ); + }); + }); }); describe('query operation', () => { @@ -951,26 +942,23 @@ describe('lazy', () => { await server.waitForClientClose(); }); - it( - 'should report errors to the `onNonLazyError` callback', - waitForDone(async (done) => { - const { url, ...server } = await startTServer(); + it('should report errors to the `onNonLazyError` callback', async (done) => { + const { url, ...server } = await startTServer(); - createClient({ - url, - lazy: false, - retryAttempts: 0, - onNonLazyError: (err) => { - expect((err as CloseEvent).code).toBe(1005); - done(); - }, - }); + createClient({ + url, + lazy: false, + retryAttempts: 0, + onNonLazyError: (err) => { + expect((err as CloseEvent).code).toBe(1005); + done(); + }, + }); - await server.waitForClient((client) => { - client.close(); - }); - }), - ); + await server.waitForClient((client) => { + client.close(); + }); + }); it('should not close connection if a subscription is disposed multiple times', async () => { const { url, ...server } = await startTServer(); @@ -1543,26 +1531,23 @@ describe('events', () => { }); }); - it( - 'should emit closed event when disposing', - waitForDone(async (done) => { - const { url, waitForClient } = await startTServer(); + it('should emit closed event when disposing', async (done) => { + const { url, waitForClient } = await startTServer(); - const client = createClient({ - url, - lazy: false, - retryAttempts: 0, - onNonLazyError: noop, - on: { - closed: () => done(), - }, - }); + const client = createClient({ + url, + lazy: false, + retryAttempts: 0, + onNonLazyError: noop, + on: { + closed: () => done(), + }, + }); - await waitForClient(); + await waitForClient(); - client.dispose(); - }), - ); + client.dispose(); + }); it('should emit the websocket connection error', (done) => { expect.assertions(3); diff --git a/src/tests/server.ts b/src/tests/server.ts index dd57dd64..da2f5287 100644 --- a/src/tests/server.ts +++ b/src/tests/server.ts @@ -15,53 +15,46 @@ import { stringifyMessage, } from '../common'; import { schema, schemaConfig } from './fixtures/simple'; -import { - waitForDone, - createTClient, - startWSTServer as startTServer, -} from './utils'; +import { createTClient, startWSTServer as startTServer } from './utils'; /** * Tests */ -it( - 'should use the schema resolved from a promise on subscribe', - waitForDone(async (done) => { - expect.assertions(2); +it('should use the schema resolved from a promise on subscribe', async (done) => { + expect.assertions(2); - const schema = new GraphQLSchema(schemaConfig); + const schema = new GraphQLSchema(schemaConfig); - const { url } = await startTServer({ - schema: (_, msg) => { - expect(msg.id).toBe('1'); - return Promise.resolve(schema); - }, - execute: (args) => { - expect(args.schema).toBe(schema); - return execute(args); - }, - onComplete: () => done(), - }); - const client = await createTClient(url, GRAPHQL_TRANSPORT_WS_PROTOCOL); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); - await client.waitForMessage(); // ack + const { url } = await startTServer({ + schema: (_, msg) => { + expect(msg.id).toBe('1'); + return Promise.resolve(schema); + }, + execute: (args) => { + expect(args.schema).toBe(schema); + return execute(args); + }, + onComplete: () => done(), + }); + const client = await createTClient(url, GRAPHQL_TRANSPORT_WS_PROTOCOL); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); + await client.waitForMessage(); // ack - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Subscribe, - payload: { - query: '{ getValue }', - }, - }), - ); - }), -); + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Subscribe, + payload: { + query: '{ getValue }', + }, + }), + ); +}); it('should use the provided validate function', async () => { const { url } = await startTServer({ @@ -248,148 +241,139 @@ it('should pass in the context value from the config', async () => { expect(subscribeFn.mock.calls[0][0].contextValue).toBe(context); }); -it( - 'should pass the `onSubscribe` exec args to the `context` option and use it', - waitForDone(async (done) => { - const context = {}; - const execArgs = { - // no context here - schema, - document: parse(`query { getValue }`), - }; - - const { url } = await startTServer({ - onSubscribe: () => { - return execArgs; - }, - context: (_ctx, _msg, args) => { - expect(args).toBe(args); // from `onSubscribe` - return context; // will be injected - }, - execute: (args) => { - expect(args).toBe(execArgs); // from `onSubscribe` - expect(args.contextValue).toBe(context); // injected by `context` - done(); - return execute(args); - }, - subscribe, - }); +it('should pass the `onSubscribe` exec args to the `context` option and use it', async (done) => { + const context = {}; + const execArgs = { + // no context here + schema, + document: parse(`query { getValue }`), + }; - const client = await createTClient(url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); - }); + const { url } = await startTServer({ + onSubscribe: () => { + return execArgs; + }, + context: (_ctx, _msg, args) => { + expect(args).toBe(args); // from `onSubscribe` + return context; // will be injected + }, + execute: (args) => { + expect(args).toBe(execArgs); // from `onSubscribe` + expect(args.contextValue).toBe(context); // injected by `context` + done(); + return execute(args); + }, + subscribe, + }); - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Subscribe, - payload: { - query: `{ getValue }`, - }, - }), - ); - }), -); - -it( - 'should use the root from the `roots` option if the `onSubscribe` doesnt provide one', - waitForDone(async (done) => { - const rootValue = {}; - const execArgs = { - // no rootValue here - schema, - document: parse(`query { getValue }`), - }; + const client = await createTClient(url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); + }); - const { url } = await startTServer({ - roots: { - query: rootValue, - }, - onSubscribe: () => { - return execArgs; - }, - execute: (args) => { - expect(args).toBe(execArgs); // from `onSubscribe` - expect(args.rootValue).toBe(rootValue); // injected by `roots` - done(); - return execute(args); + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Subscribe, + payload: { + query: `{ getValue }`, }, - subscribe, - }); + }), + ); +}); - const client = await createTClient(url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); - }); +it('should use the root from the `roots` option if the `onSubscribe` doesnt provide one', async (done) => { + const rootValue = {}; + const execArgs = { + // no rootValue here + schema, + document: parse(`query { getValue }`), + }; - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Subscribe, - payload: { - query: `{ getValue }`, - }, - }), - ); - }), -); - -it( - 'should prefer the `onSubscribe` context value even if `context` option is set', - waitForDone(async (done) => { - const context = 'not-me'; - const execArgs = { - contextValue: 'me-me', // my custom context - schema, - document: parse(`query { getValue }`), - }; + const { url } = await startTServer({ + roots: { + query: rootValue, + }, + onSubscribe: () => { + return execArgs; + }, + execute: (args) => { + expect(args).toBe(execArgs); // from `onSubscribe` + expect(args.rootValue).toBe(rootValue); // injected by `roots` + done(); + return execute(args); + }, + subscribe, + }); - const { url } = await startTServer({ - onSubscribe: () => { - return execArgs; - }, - context, // should be ignored because there is one in `execArgs` - execute: (args) => { - expect(args).toBe(execArgs); // from `onSubscribe` - expect(args.contextValue).not.toBe(context); // from `onSubscribe` - done(); - return execute(args); + const client = await createTClient(url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); + }); + + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Subscribe, + payload: { + query: `{ getValue }`, }, - subscribe, - }); + }), + ); +}); - const client = await createTClient(url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); - }); +it('should prefer the `onSubscribe` context value even if `context` option is set', async (done) => { + const context = 'not-me'; + const execArgs = { + contextValue: 'me-me', // my custom context + schema, + document: parse(`query { getValue }`), + }; - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Subscribe, - payload: { - query: `{ getValue }`, - }, - }), - ); - }), -); + const { url } = await startTServer({ + onSubscribe: () => { + return execArgs; + }, + context, // should be ignored because there is one in `execArgs` + execute: (args) => { + expect(args).toBe(execArgs); // from `onSubscribe` + expect(args.contextValue).not.toBe(context); // from `onSubscribe` + done(); + return execute(args); + }, + subscribe, + }); + + const client = await createTClient(url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); + }); + + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Subscribe, + payload: { + query: `{ getValue }`, + }, + }), + ); +}); it('should use a custom JSON message replacer function', async () => { const { url } = await startTServer({ @@ -520,33 +504,30 @@ describe('Connect', () => { }); }); - it( - 'should pass in the `connectionParams` through the context and have other flags correctly set', - waitForDone(async (done) => { - const connectionParams = { - some: 'string', - with: 'a', - number: 10, - }; + it('should pass in the `connectionParams` through the context and have other flags correctly set', async (done) => { + const connectionParams = { + some: 'string', + with: 'a', + number: 10, + }; - const { url } = await startTServer({ - onConnect: (ctx) => { - expect(ctx.connectionParams).toEqual(connectionParams); - expect(ctx.connectionInitReceived).toBeTruthy(); // obviously received - expect(ctx.acknowledged).toBeFalsy(); // not yet acknowledged - done(); - return true; - }, - }); + const { url } = await startTServer({ + onConnect: (ctx) => { + expect(ctx.connectionParams).toEqual(connectionParams); + expect(ctx.connectionInitReceived).toBeTruthy(); // obviously received + expect(ctx.acknowledged).toBeFalsy(); // not yet acknowledged + done(); + return true; + }, + }); - (await createTClient(url)).ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - payload: connectionParams, - }), - ); - }), - ); + (await createTClient(url)).ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + payload: connectionParams, + }), + ); + }); it('should close the socket after the `connectionInitWaitTimeout` has passed without having received a `ConnectionInit` message', async () => { const { url } = await startTServer({ connectionInitWaitTimeout: 10 }); @@ -1467,94 +1448,88 @@ describe('Subscribe', () => { }); }); - it( - 'should call `onComplete` callback when client completes', - waitForDone(async (done) => { - const server = await startTServer({ - onComplete: () => { - done(); - }, - }); + it('should call `onComplete` callback when client completes', async (done) => { + const server = await startTServer({ + onComplete: () => { + done(); + }, + }); - const client = await createTClient(server.url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); + const client = await createTClient(server.url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); - }); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); + }); - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Subscribe, - payload: { - query: 'subscription { ping }', - }, - }), - ); - await server.waitForOperation(); + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Subscribe, + payload: { + query: 'subscription { ping }', + }, + }), + ); + await server.waitForOperation(); - // just to make sure we're streaming - server.pong(); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.Next); - }); + // just to make sure we're streaming + server.pong(); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.Next); + }); - // complete and done - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Complete, - }), - ); - }), - ); + // complete and done + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Complete, + }), + ); + }); - it( - 'should call `onComplete` callback even if socket terminates abruptly', - waitForDone(async (done) => { - const server = await startTServer({ - onComplete: () => { - done(); - }, - }); + it('should call `onComplete` callback even if socket terminates abruptly', async (done) => { + const server = await startTServer({ + onComplete: () => { + done(); + }, + }); - const client = await createTClient(server.url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); + const client = await createTClient(server.url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); - }); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.ConnectionAck); + }); - client.ws.send( - stringifyMessage({ - id: '1', - type: MessageType.Subscribe, - payload: { - query: 'subscription { ping }', - }, - }), - ); - await server.waitForOperation(); + client.ws.send( + stringifyMessage({ + id: '1', + type: MessageType.Subscribe, + payload: { + query: 'subscription { ping }', + }, + }), + ); + await server.waitForOperation(); - // just to make sure we're streaming - server.pong(); - await client.waitForMessage(({ data }) => { - expect(parseMessage(data).type).toBe(MessageType.Next); - }); + // just to make sure we're streaming + server.pong(); + await client.waitForMessage(({ data }) => { + expect(parseMessage(data).type).toBe(MessageType.Next); + }); - // terminate socket abruptly - client.ws.terminate(); - }), - ); + // terminate socket abruptly + client.ws.terminate(); + }); it('should respect completed subscriptions even if subscribe operation stalls', async () => { let continueSubscribe: (() => void) | undefined = undefined; @@ -1621,53 +1596,47 @@ describe('Subscribe', () => { }); describe('Disconnect/close', () => { - it( - 'should report close code and reason to disconnect and close callback after connection acknowledgement', - waitForDone(async (done) => { - const { url, waitForConnect } = await startTServer({ - // 1st - onDisconnect: (_ctx, code, reason) => { - expect(code).toBe(4321); - expect(reason).toBe('Byebye'); - }, - // 2nd - onClose: (_ctx, code, reason) => { - expect(code).toBe(4321); - expect(reason).toBe('Byebye'); - done(); - }, - }); + it('should report close code and reason to disconnect and close callback after connection acknowledgement', async (done) => { + const { url, waitForConnect } = await startTServer({ + // 1st + onDisconnect: (_ctx, code, reason) => { + expect(code).toBe(4321); + expect(reason).toBe('Byebye'); + }, + // 2nd + onClose: (_ctx, code, reason) => { + expect(code).toBe(4321); + expect(reason).toBe('Byebye'); + done(); + }, + }); - const client = await createTClient(url); + const client = await createTClient(url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); - await waitForConnect(); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); + await waitForConnect(); - client.ws.close(4321, 'Byebye'); - }), - ); + client.ws.close(4321, 'Byebye'); + }); - it( - 'should trigger the close callback instead of disconnect if connection is not acknowledged', - waitForDone(async (done) => { - const { url } = await startTServer({ - onDisconnect: () => { - fail("Disconnect callback shouldn't be triggered"); - }, - onClose: (_ctx, code, reason) => { - expect(code).toBe(4321); - expect(reason).toBe('Byebye'); - done(); - }, - }); + it('should trigger the close callback instead of disconnect if connection is not acknowledged', async (done) => { + const { url } = await startTServer({ + onDisconnect: () => { + fail("Disconnect callback shouldn't be triggered"); + }, + onClose: (_ctx, code, reason) => { + expect(code).toBe(4321); + expect(reason).toBe('Byebye'); + done(); + }, + }); - const client = await createTClient(url); + const client = await createTClient(url); - client.ws.close(4321, 'Byebye'); - }), - ); + client.ws.close(4321, 'Byebye'); + }); }); diff --git a/src/tests/use.ts b/src/tests/use.ts index 41b1742b..bb201646 100644 --- a/src/tests/use.ts +++ b/src/tests/use.ts @@ -14,7 +14,6 @@ import { WSExtra, UWSExtra, FastifyExtra, - waitForDone, } from './utils'; for (const { tServer, startTServer } of tServers) { @@ -80,59 +79,54 @@ for (const { tServer, startTServer } of tServers) { }); }); - it( - 'should add the initial request and websocket in the context extra', - waitForDone(async (done) => { - const server = await startTServer({ - onConnect: (ctx) => { - if (tServer === 'uWebSockets.js') { - // uWebSocket.js does not export classes, we can rely on the name only - expect((ctx.extra as UWSExtra).socket.constructor.name).toEqual( - 'uWS.WebSocket', - ); - expect((ctx.extra as UWSExtra).persistedRequest.method).toBe( - 'get', - ); - expect((ctx.extra as UWSExtra).persistedRequest.url).toBe( - '/simple', - ); - expect((ctx.extra as UWSExtra).persistedRequest.query).toBe( - 'te=st', - ); - expect( - (ctx.extra as UWSExtra).persistedRequest.headers, - ).toBeInstanceOf(Object); - } else if (tServer === 'ws') { - expect((ctx.extra as WSExtra).socket).toBeInstanceOf(ws); - expect((ctx.extra as WSExtra).request).toBeInstanceOf( - http.IncomingMessage, - ); - } else if (tServer === 'fastify-websocket') { - expect((ctx.extra as FastifyExtra).connection).toBeInstanceOf( - stream.Duplex, - ); - expect( - (ctx.extra as FastifyExtra).connection.socket, - ).toBeInstanceOf(ws); - expect((ctx.extra as FastifyExtra).request.constructor.name).toBe( - 'Request', - ); - } else { - throw new Error('Missing test case for ' + tServer); - } - done(); - return false; // reject client for sake of test - }, - }); + it('should add the initial request and websocket in the context extra', async (done) => { + const server = await startTServer({ + onConnect: (ctx) => { + if (tServer === 'uWebSockets.js') { + // uWebSocket.js does not export classes, we can rely on the name only + expect((ctx.extra as UWSExtra).socket.constructor.name).toEqual( + 'uWS.WebSocket', + ); + expect((ctx.extra as UWSExtra).persistedRequest.method).toBe('get'); + expect((ctx.extra as UWSExtra).persistedRequest.url).toBe( + '/simple', + ); + expect((ctx.extra as UWSExtra).persistedRequest.query).toBe( + 'te=st', + ); + expect( + (ctx.extra as UWSExtra).persistedRequest.headers, + ).toBeInstanceOf(Object); + } else if (tServer === 'ws') { + expect((ctx.extra as WSExtra).socket).toBeInstanceOf(ws); + expect((ctx.extra as WSExtra).request).toBeInstanceOf( + http.IncomingMessage, + ); + } else if (tServer === 'fastify-websocket') { + expect((ctx.extra as FastifyExtra).connection).toBeInstanceOf( + stream.Duplex, + ); + expect( + (ctx.extra as FastifyExtra).connection.socket, + ).toBeInstanceOf(ws); + expect((ctx.extra as FastifyExtra).request.constructor.name).toBe( + 'Request', + ); + } else { + throw new Error('Missing test case for ' + tServer); + } + done(); + return false; // reject client for sake of test + }, + }); - const client = await createTClient(server.url + '?te=st'); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); - }), - ); + const client = await createTClient(server.url + '?te=st'); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); + }); it('should close the socket with errors thrown from any callback', async () => { const error = new Error('Stop'); @@ -367,39 +361,33 @@ for (const { tServer, startTServer } of tServers) { ); describe('Keep-Alive', () => { - it( - 'should dispatch pings after the timeout has passed', - waitForDone(async (done) => { - const { url } = await startTServer(undefined, 50); + it('should dispatch pings after the timeout has passed', async (done) => { + const { url } = await startTServer(undefined, 50); - const client = await createTClient(url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); + const client = await createTClient(url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); - client.ws.once('ping', () => done()); - }), - ); + client.ws.once('ping', () => done()); + }); - it( - 'should not dispatch pings if disabled with nullish timeout', - waitForDone(async (done) => { - const { url } = await startTServer(undefined, 0); + it('should not dispatch pings if disabled with nullish timeout', async (done) => { + const { url } = await startTServer(undefined, 0); - const client = await createTClient(url); - client.ws.send( - stringifyMessage({ - type: MessageType.ConnectionInit, - }), - ); + const client = await createTClient(url); + client.ws.send( + stringifyMessage({ + type: MessageType.ConnectionInit, + }), + ); - client.ws.once('ping', () => fail('Shouldnt have pinged')); + client.ws.once('ping', () => fail('Shouldnt have pinged')); - setTimeout(done, 50); - }), - ); + setTimeout(done, 50); + }); it('should terminate the socket if no pong is sent in response to a ping', async () => { const { url } = await startTServer(undefined, 50); diff --git a/src/tests/utils/index.ts b/src/tests/utils/index.ts index ffad4f37..75ec99fd 100644 --- a/src/tests/utils/index.ts +++ b/src/tests/utils/index.ts @@ -1,10 +1,2 @@ export * from './tclient'; export * from './tservers'; - -/** A simple since Jest v27 does not allow combining async and using the done argument. */ -export function waitForDone( - cb: (done: () => void) => Promise, -): () => Promise { - return () => - new Promise((resolve, reject) => cb(resolve).catch(reject)); -}