import { describe, expect, it, vi } from 'vitest'; import { z } from 'zod'; 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'; import { AuthSecp256k1 } from '../../../source/auth/auth.ts'; import { toRoutes } from '../../helpers/misc.ts'; /** * A mock of the AuthSecp256k1 service */ const auth = { verifySignature: vi.fn().mockResolvedValue(true), verifyUniqueRequest: vi.fn().mockResolvedValue(true), assertTimestampFreshness: vi.fn().mockResolvedValue(true), } as unknown as AuthSecp256k1; describe('WebSocket request decoding', (): void => { it('decodes the minimal route-agnostic envelope and Extended JSON body', async (): Promise => { await expect(WsTransportRouter.decodeWebSocketRequest(toExtendedJson({ id: 'request-1', path: '/data/write', body: { value: new Uint8Array([ 1, 2, 3 ]) }, }))).resolves.toEqual({ requestId: 'request-1', path: '/data/write', body: { value: new Uint8Array([ 1, 2, 3 ]) }, }); }); it.each([ '{}', '{"path":42}', '{"path":"/data/get","id":1}', '{"path":"/data/get","method":"POST"}' ])( 'rejects an invalid envelope: %s', async (payload) => { await expect(WsTransportRouter.decodeWebSocketRequest(payload)).rejects.toBeInstanceOf(z.ZodError); }, ); it('rejects malformed JSON', async (): Promise => { 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({ auth, }, [ toRoutes([ { url: '/data/write', handler: async (stream): Promise => { await stream.send({}); }, }, ]), ]); const transport = new WsTransportRouter(router, debug, 1024); expect(transport['wsServer'].options.maxPayload).toBe(1024); await transport.stop(); }); });