Files
sync-server-v2/test/services/transports/ws-transport.test.ts
T

66 lines
2.9 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { z } from 'zod';
import type { WebSocketServer } from 'ws';
import { ApplicationRouter } from '../../../source/services/router.ts';
import { WsTransportRouter } from '../../../source/services/transport/ws-transport.ts';
import { Logger } from '../../../source/utils/logger.ts';
import { toExtendedJson } from '@xo-cash/utils';
describe('WebSocket request decoding', (): void => {
it('decodes the minimal route-agnostic envelope and Extended JSON body', async (): Promise<void> => {
await expect(WsTransportRouter.decodeWebSocketRequest(toExtendedJson({
id: 'request-1',
path: '/data/write',
body: { value: new Uint8Array([ 1, 2, 3 ]) },
headers: { 'X-Request-Token': 'ws-token' },
}))).resolves.toEqual({
requestId: 'request-1',
path: '/data/write',
body: { value: new Uint8Array([ 1, 2, 3 ]) },
headers: { 'x-request-token': 'ws-token' },
});
});
it('allows the optional headers object to be omitted', async (): Promise<void> => {
await expect(WsTransportRouter.decodeWebSocketRequest('{"path":"/data/get"}')).resolves.toEqual({ path: '/data/get' });
});
it.each([
'{}',
'{"path":42}',
'{"path":"/data/get","id":1}',
'{"path":"/data/get","method":"POST"}',
'{"path":"/data/get","headers":{"x-request-token":1}}',
])('rejects an invalid envelope: %s', async (payload) => {
await expect(WsTransportRouter.decodeWebSocketRequest(payload)).rejects.toBeInstanceOf(z.ZodError);
});
it.each([
'{"path":"/data/get","headers":{"bad header":"value"}}',
'{"path":"/data/get","headers":{"x-request-token":"first","X-Request-Token":"second"}}',
'{"path":"/data/get","headers":{"x-request-token":"first\\r\\nsecond"}}',
])('rejects malformed request headers: %s', async (payload): Promise<void> => {
await expect(WsTransportRouter.decodeWebSocketRequest(payload)).rejects.toMatchObject({ statusCode: 400 });
});
it('rejects malformed JSON', async (): Promise<void> => {
await expect(WsTransportRouter.decodeWebSocketRequest('{')).rejects.toMatchObject({
statusCode: 400,
message: 'Invalid JSON in WebSocket message',
});
});
});
describe('WsTransportRouter payload limits', (): void => {
it("configures Hono's ws server with the requested maxPayload", async () => {
const debug = new Logger('ws-transport-test');
const router = await ApplicationRouter.create([]);
const transport = new WsTransportRouter(router, debug, 1024);
const wsServer = transport.websocketServer as unknown as WebSocketServer;
expect(wsServer.options.maxPayload).toBe(1024);
await transport.stop();
});
});