import assert from 'node:assert/strict' import { test } from 'node:test' import { createEveningDetectiveServerClient } from './api/generated/crabs/evening_detective_server/index.js' import { apiPlan, apiScreenMode, apiScreenCommand } from './api-values.js' import { parsePlan } from './screen-plan.js' import { parseRemote } from './remote-state.js' test('клиент proto задаёт маршруты, методы и JSON enum существующего gateway', async () => { const calls: { path: string; method: string; body: string | null }[] = [] const client = createEveningDetectiveServerClient(async (request) => { calls.push(request) return {} }) await client.Login({ email: 'dev@example.test', password: 'SECRET' }) await client.Refresh({ refreshToken: 'SECRET' }) await client.GetMe({}) await client.GetGames({}) await client.GetGame({ ID: 7 }) await client.GetScreenPlan({ gameID: 7 }) await client.GetGameMusic({ gameID: 7 }) const plan = parsePlan({ steps: [ { mode: 8, text: 'Улика' }, { mode: 7, timerDurationSeconds: 60 }, ], }) await client.SaveScreenPlan({ gameID: 7, ...apiPlan(plan) }) await client.SetScreenMode({ gameID: 7, mode: apiScreenMode(2) }) await client.SendScreenCommand({ gameID: 7, command: apiScreenCommand(6), positionMs: 1500, volume: 50, }) assert.deepEqual( calls.map((c) => [c.method, c.path]), [ ['POST', 'api/auth/login'], ['POST', 'api/auth/refresh'], ['GET', 'api/users/me'], ['GET', 'api/games'], ['GET', 'api/games/7'], ['GET', 'api/games/7/screen-plan'], ['GET', 'api/games/7/music'], ['PUT', 'api/games/7/screen-plan'], ['POST', 'api/games/7/screens/mode'], ['POST', 'api/games/7/screens/command'], ], ) assert.deepEqual(parsePlan(JSON.parse(calls[7]!.body!)), plan) assert.equal(JSON.parse(calls[7]!.body!).steps[0].mode, 'SCREEN_MODE_TEXT') assert.equal(JSON.parse(calls[8]!.body!).mode, 'SCREEN_MODE_INTRO') assert.equal(JSON.parse(calls[9]!.body!).command, 'SCREEN_COMMAND_SEEK') assert.throws(() => apiScreenMode(99), /режим/) assert.throws(() => apiScreenCommand(99), /команда/) }) test('ответ proto сохраняет строковый int64, enum и отсутствующие поля для проверки границы', async () => { const client = createEveningDetectiveServerClient(async () => JSON.parse( '{"state":{"stateVersion":"9007199254740993","mode":"SCREEN_MODE_TEXT","text":"Текст","positionMs":"1500"}}', ), ) const next = parseRemote( (await client.GetScreenState({ screenID: '12', accessToken: 'SECRET' })).state, ) assert.equal(next.version, 9007199254740993n) assert.equal(next.mode, 8) assert.equal(next.position, 1.5) assert.equal(next.music, null) const invalid = createEveningDetectiveServerClient(async () => ({ state: { stateVersion: 9007199254740992 }, })) assert.throws(() => parseRemote({ stateVersion: 9007199254740992 }), /версия/) await assert.rejects( async () => parseRemote((await invalid.GetScreenState({ screenID: '12', accessToken: 'SECRET' })).state), /версия/, ) })