@furystack/websocket-api
Version:
HTTP Api FuryStack package
119 lines (104 loc) • 3.52 kB
text/typescript
import { addStore, InMemoryStore, StoreManager, User } from '@furystack/core'
import { getPort } from '@furystack/core/port-generator'
import { Injector } from '@furystack/inject'
import {
DefaultSession,
HttpUserContext,
ServerManager,
useHttpAuthentication,
useRestService,
} from '@furystack/rest-service'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { WebSocket } from 'ws'
import { WhoAmI } from './actions/whoami.js'
import { useWebsockets } from './helpers.js'
describe('WebSocket Integration tests', () => {
const host = 'localhost'
const path = '/ws'
let i!: Injector
let client: WebSocket
let port: number
beforeEach(async () => {
i = new Injector()
port = getPort()
await useRestService({
injector: i,
api: {},
root: '',
port,
hostName: host,
})
addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' })).addStore(
new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }),
)
useHttpAuthentication(i, {})
useWebsockets(i, { actions: [WhoAmI], path, port, host })
await new Promise<void>((resolve, reject) => {
i.getInstance(ServerManager)
.getOrCreate({ port })
.then(() => {
client = new WebSocket(`ws://${host}:${port}/ws`)
client
.on('open', () => {
resolve()
})
.on('error', reject)
})
.catch(reject)
})
})
afterEach(async () => {
await i[Symbol.asyncDispose]()
})
const getWhoAmIResult = async (subjectClient: WebSocket) => {
return new Promise<{ currentUser: User }>((resolve, reject) => {
subjectClient.once('message', (data: Buffer) => {
resolve(JSON.parse(data.toString()) as { currentUser: User })
})
subjectClient.once('error', reject)
subjectClient.send('whoami')
})
}
describe('Authentication', () => {
it('Should be unauthenticated by default', async () => {
expect((await getWhoAmIResult(client)).currentUser).toBe(null)
})
})
it('Should be authenticated, roles should be updated and should be logged out', async () => {
const testUser = { username: 'test', password: 'test', roles: [] } as User
const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username')
await userStore.add(testUser)
const userCtx = i.getInstance(HttpUserContext)
let cookie = ''
await userCtx.cookieLogin(testUser, {
setHeader: (_setCookie, cookieValue) => {
cookie = cookieValue
},
})
const authenticatedClient = await new Promise<WebSocket>((done, reject) => {
const cl = new WebSocket(`ws://${host}:${port}/ws`, {
headers: { cookie },
})
cl.once('open', () => {
done(cl)
}).once('error', reject)
})
const whoAmIResult = await getWhoAmIResult(authenticatedClient)
expect(whoAmIResult.currentUser).toEqual(testUser)
await userStore.update(testUser.username, { ...testUser, roles: ['newFancyRole'] })
const updatedWhoAmIResult = await getWhoAmIResult(authenticatedClient)
expect(updatedWhoAmIResult.currentUser.roles).toEqual(['newFancyRole'])
await userCtx.cookieLogout(
{
headers: {
cookie,
},
},
{
setHeader: vi.fn(),
},
)
const loggedOutWhoAmIResult = await getWhoAmIResult(authenticatedClient)
expect(loggedOutWhoAmIResult.currentUser).toBe(null)
})
})