UNPKG

@furystack/websocket-api

Version:
99 lines (89 loc) 3.83 kB
import { InMemoryStore, User, addStore } from '@furystack/core' import { getPort } from '@furystack/core/port-generator' import { Injectable, Injector } from '@furystack/inject' import { DefaultSession } from '@furystack/rest-service' import { usingAsync } from '@furystack/utils' import { describe, expect, it } from 'vitest' import { WebSocket, type Data } from 'ws' import { useWebsockets } from './helpers.js' import type { WebSocketAction } from './models/websocket-action.js' import { WebSocketApi } from './websocket-api.js' describe('WebSocketApi', () => { it('Should be built', async () => { await usingAsync(new Injector(), async (i) => { addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore( new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }), ) useWebsockets(i, { port: getPort() }) expect(i.getInstance(WebSocketApi)).toBeInstanceOf(WebSocketApi) }) }) it('Should be built with settings', async () => { await usingAsync(new Injector(), async (i) => { addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore( new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }), ) useWebsockets(i, { path: '/web-socket', port: getPort() }) expect(i.getInstance(WebSocketApi)).toBeInstanceOf(WebSocketApi) }) }) it('Should broadcast messages', async () => { const port = getPort() await usingAsync(new Injector(), async (i) => { addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore( new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }), ) expect.assertions(5) // All 5 clients should receive the message useWebsockets(i, { path: '/web-socket', port }) const api = i.getInstance(WebSocketApi) await Promise.all( [1, 2, 3, 4, 5].map(async () => { const client = new WebSocket(`ws://localhost:${port}/web-socket`) await new Promise<void>((resolve) => client.once('open', () => { resolve() }), ) client.once('message', (data) => { expect((data as Buffer).toString()).toBe('alma') }) await api.broadcast(({ ws }) => { ws.send('alma') }) client.close() await new Promise<void>((resolve) => client.once('close', () => resolve())) }), ) }) }) it('Should receive client messages', async () => { const port = getPort() await usingAsync(new Injector(), async (i) => { addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore( new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }), ) expect.assertions(1) const data = { value: 'alma' } @Injectable() class ExampleWsAction implements WebSocketAction { public [Symbol.dispose]() { /** */ } public static canExecute() { return true } public async execute(incomingData: { data: Data }) { expect(JSON.parse((incomingData.data as Buffer).toString())).toEqual(data) } } useWebsockets(i, { path: '/web-socket', port, actions: [ExampleWsAction] }) const client = new WebSocket(`ws://localhost:${port}/web-socket`) await new Promise<void>((resolve) => client.once('open', () => resolve())) await new Promise<void>((resolve, reject) => client.send(JSON.stringify(data), (err) => (err ? reject(err) : resolve())), ) client.close() await new Promise<void>((resolve) => client.once('close', () => resolve())) }) }) })