@furystack/websocket-api
Version:
HTTP Api FuryStack package
99 lines (89 loc) • 3.83 kB
text/typescript
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' }
()
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()))
})
})
})