trying to get rooms up

This commit is contained in:
Devin Zuczek
2026-06-15 00:29:11 -04:00
parent 796442e0cf
commit 0dbd388249
14 changed files with 5282 additions and 219 deletions
+81 -42
View File
@@ -1,10 +1,50 @@
import { SELF } from 'cloudflare:test'
import { describe, expect, it } from 'vitest'
import { env, SELF } from 'cloudflare:test'
import { beforeAll, describe, expect, it } from 'vitest'
import '../../rooms.app'
import importRooms from '../../../static/ImportRooms.json'
import { SCHEMA_DDL } from '../../rooms-db'
import type { Env } from '../../context'
declare module 'cloudflare:test' {
interface ProvidedEnv extends Env {}
}
const ORIGIN = 'https://rooms.rec.djdevin.net'
// Mint a token the way the `auth` worker does, using the same dev secret.
const DEV_SECRET = 'dev-insecure-signing-key-change-me'
function b64url(input: ArrayBuffer | string): string {
const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : new Uint8Array(input)
let binary = ''
for (const byte of bytes) binary += String.fromCharCode(byte)
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
}
async function bearer(sub: string): Promise<Record<string, string>> {
const now = Math.floor(Date.now() / 1000)
const signingInput = `${b64url(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))}.${b64url(
JSON.stringify({ sub, exp: now + 3600 })
)}`
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode(DEV_SECRET),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
)
const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(signingInput))
return { Authorization: `Bearer ${signingInput}.${b64url(sig)}` }
}
// Apply the schema + seed the imported rooms into the test D1 (mirrors the migrations).
beforeAll(async () => {
for (const stmt of SCHEMA_DDL) await env.DB.prepare(stmt).run()
const insert = env.DB.prepare('INSERT OR IGNORE INTO rooms (data) VALUES (?1)')
await env.DB.batch(importRooms.map((r) => insert.bind(JSON.stringify(r))))
})
describe('rooms endpoints', () => {
it('GET / reports service status', async () => {
const res = await SELF.fetch(`${ORIGIN}/`)
@@ -12,34 +52,33 @@ describe('rooms endpoints', () => {
expect(await res.json()).toEqual({ service: 'rooms', status: 'ok' })
})
it('GET /rooms/1 returns the dorm room (ignoring include/unityAsset params)', async () => {
const res = await SELF.fetch(
`${ORIGIN}/rooms/1?include=1325&unityAssetTarget=0&unityAssetVersion=1`
)
it('GET /rooms/1 returns the seeded dorm with its SubRoom scene', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms/1?include=1325`)
expect(res.status).toBe(200)
const body = (await res.json()) as {
RoomId: number
Name: string
IsDorm: boolean
Stats: object
SubRooms: Array<{ UnitySceneId: string }>
}
expect(body).toMatchObject({ RoomId: 1, Name: 'DormRoom', IsDorm: true })
expect(body).toHaveProperty('Stats')
const subRooms = (body as unknown as { SubRooms: Array<{ UnitySceneId: string }> }).SubRooms
expect(subRooms[0].UnitySceneId).toBe('76d98498-60a1-430c-ab76-b54a29b7a163')
expect(body.SubRooms[0].UnitySceneId).toBe('76d98498-60a1-430c-ab76-b54a29b7a163')
})
it('GET /rooms/:id synthesizes a generic room for other ids', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms/42`)
expect(res.status).toBe(200)
const body = (await res.json()) as { RoomId: number; Name: string; IsDorm: boolean }
expect(body).toMatchObject({ RoomId: 42, Name: 'Room42', IsDorm: false })
it('GET /rooms/:id 404s for a room not in D1', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms/99999`)
expect(res.status).toBe(404)
})
it('GET /rooms?id=1 returns the matching room', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms?id=1`)
it('GET /rooms?name= resolves a real room case-insensitively', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms?name=reccenter`)
expect(res.status).toBe(200)
expect(await res.json()).toMatchObject({ RoomId: 1, Name: 'DormRoom' })
expect(await res.json()).toMatchObject({ Name: 'RecCenter' })
})
it('GET /rooms?name= returns {} when nothing matches', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms?name=NoSuchRoomHere`)
expect(await res.json()).toEqual({})
})
it('GET /rooms with no id or name returns 400', async () => {
@@ -47,36 +86,36 @@ describe('rooms endpoints', () => {
expect(res.status).toBe(400)
})
it('GET /roomserver/photon_access_token returns permissions + instance id', async () => {
const res = await SELF.fetch(`${ORIGIN}/roomserver/photon_access_token`)
it('GET /rooms/bulk?id= returns the matching rooms', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms/bulk?id=1,2`)
expect(res.status).toBe(200)
const body = (await res.json()) as { Permissions: unknown[]; RoomInstanceId: number }
expect(body.Permissions.length).toBeGreaterThan(0)
expect(body.RoomInstanceId).toBe(1)
const body = (await res.json()) as Array<{ RoomId: number; Name: string }>
expect(body.map((r) => r.Name).sort()).toEqual(['DormRoom', 'RecCenter'])
})
it('GET /rooms/bulk?id= returns an array; ?name= returns []', async () => {
const byId = await SELF.fetch(`${ORIGIN}/rooms/bulk?id=1,2`)
expect(byId.status).toBe(200)
expect(((await byId.json()) as unknown[]).length).toBe(2)
const byName = await SELF.fetch(`${ORIGIN}/rooms/bulk?name=RecCenter`)
expect(byName.status).toBe(200)
expect(await byName.json()).toEqual([])
it('GET /rooms/bulk?name=RecCenter returns [RecCenter]', async () => {
const res = await SELF.fetch(`${ORIGIN}/rooms/bulk?name=RecCenter`)
const body = (await res.json()) as Array<{ Name: string }>
expect(body.map((r) => r.Name)).toEqual(['RecCenter'])
})
it('GET /photon_access_token (bare) also returns permissions', async () => {
const res = await SELF.fetch(`${ORIGIN}/photon_access_token`)
expect(res.status).toBe(200)
const body = (await res.json()) as { Permissions: unknown[]; RoomInstanceId: number }
expect(body.Permissions.length).toBeGreaterThan(0)
expect(body.RoomInstanceId).toBe(1)
it('GET /rooms/ownedby/me returns the caller created rooms (auth-scoped)', async () => {
// No token → stub account 1, which owns all the seeded rooms.
const mine = (await (await SELF.fetch(`${ORIGIN}/rooms/ownedby/me`)).json()) as unknown[]
expect(mine.length).toBe(importRooms.length)
// A different account owns none of them.
const other = (await (
await SELF.fetch(`${ORIGIN}/rooms/ownedby/me`, { headers: await bearer('999') })
).json()) as unknown[]
expect(other).toEqual([])
})
it('GET /roomserver/rooms/createdby/me returns the owned rooms array', async () => {
const res = await SELF.fetch(`${ORIGIN}/roomserver/rooms/createdby/me`)
expect(res.status).toBe(200)
const body = (await res.json()) as Array<{ RoomId: number }>
expect(Array.isArray(body)).toBe(true)
expect(body[0]).toMatchObject({ RoomId: 1, Name: 'DormRoom' })
it('GET /photon_access_token (bare + /roomserver) returns permissions', async () => {
for (const path of ['/photon_access_token', '/roomserver/photon_access_token']) {
const res = await SELF.fetch(`${ORIGIN}${path}`)
expect(res.status).toBe(200)
const body = (await res.json()) as { Permissions: unknown[]; RoomInstanceId: number }
expect(body.Permissions.length).toBeGreaterThan(0)
}
})
})