import { test } from 'node:test' import assert from 'node:assert/strict' import { createPinia, setActivePinia } from 'pinia' import { adminApi, mockMode } from '../api/client' import { useEventStore } from '../stores/event' // P0-1:WS 身份在握手时确定,登录 / 退出 / 改密后必须重建连接。 // 旧连接被服务端 1008 拒绝后客户端会停止重连,没有 restartRealtime 就永远停在 offline。 class FakeSocket { static readonly CONNECTING = 0 static readonly OPEN = 1 static readonly CLOSED = 3 static instances: FakeSocket[] = [] readyState = FakeSocket.CONNECTING onopen: (() => void) | null = null onmessage: ((event: { data: unknown }) => void) | null = null onerror: (() => void) | null = null onclose: ((event: { code: number }) => void) | null = null readonly url: string readonly sent: string[] = [] constructor(url: string) { this.url = url FakeSocket.instances.push(this) } send(data: string): void { this.sent.push(data) } close(): void { this.readyState = FakeSocket.CLOSED this.onclose?.({ code: 1006 }) } open(): void { this.readyState = FakeSocket.OPEN this.onopen?.() } } test('restartRealtime 关闭旧连接并按当前会话重建', async () => { FakeSocket.instances = [] ;(globalThis as { WebSocket?: unknown }).WebSocket = FakeSocket setActivePinia(createPinia()) adminApi.bootstrap = async () => ({ settings: null, teams: [], sports: [], events: [], profiles: [], standings: [], athleteStandings: [], }) adminApi.health = async () => { throw new Error('health 不可达') } const store = useEventStore() await store.load() assert.equal(store.realtimeStatus, 'connecting') assert.equal(FakeSocket.instances.length, 1) const first = FakeSocket.instances[0] assert.ok(first) first.open() assert.equal(store.realtimeStatus, 'online') // 改密后服务端作废全部会话,旧连接以 1008 关闭并停在 offline first.readyState = FakeSocket.CLOSED first.onclose?.({ code: 1008 }) assert.equal(store.realtimeStatus, 'offline') store.restartRealtime() assert.equal(first.readyState, FakeSocket.CLOSED) assert.equal(FakeSocket.instances.length, 2) assert.equal(store.realtimeStatus, 'connecting') const second = FakeSocket.instances[1] assert.ok(second) second.open() assert.equal(store.realtimeStatus, 'online') // 示例数据模式不建真实连接 mockMode.value = true store.restartRealtime() assert.equal(store.realtimeStatus, 'idle') assert.equal(FakeSocket.instances.length, 2) })