import { test } from 'node:test' import assert from 'node:assert/strict' import { createPinia, setActivePinia } from 'pinia' import type { EventSettings } from '@/shared' /** * 榜单口径(standings.individual_to_team_weight)的保存契约。 * * adminApi 的 http 实例在模块初始化时就绑定了 `globalThis.fetch`,所以这里先替换 fetch, * 再用动态 import 拿到 store 与控制器,才能观察到真实请求的 URL / 方法与载荷。 */ const SETTINGS: EventSettings = { event: { name: '测试赛事', subtitle: null, host: null, logoPath: null, primaryColor: null }, display: { background: null, logo: null, title: '测试赛事', subtitle: null, primaryColor: null, rotateSeconds: 15 }, standings: { individualToTeamWeight: 1, rankingMode: 'points', showIndividualBoard: true, showIndividualMedals: true, }, defaultProfileId: null, requireApproval: false, } interface Captured { url: string method: string body: Record | null } function stubFetch(weight: number): Captured { const captured: Captured = { url: '', method: '', body: null } globalThis.fetch = (async (input: unknown, init?: RequestInit) => { captured.url = String(input) captured.method = init?.method ?? 'GET' captured.body = init?.body === undefined ? null : (JSON.parse(String(init.body)) as Record) const data: EventSettings = { ...SETTINGS, standings: { ...SETTINGS.standings, individualToTeamWeight: weight } } return new Response(JSON.stringify({ ok: true, data }), { status: 200, headers: { 'Content-Type': 'application/json' }, }) }) as typeof fetch return captured } test('保存榜单口径 PUT /api/settings,提交完整 standings 并回写 event store', async () => { const captured = stubFetch(0.5) const { useEventStore } = await import('../stores/event') const { useBaseData } = await import('../components/baseData/useBaseData') setActivePinia(createPinia()) const event = useEventStore() event.settings = { ...SETTINGS } const data = useBaseData() const saved = await data.saveIndividualToTeamWeight(0.5) assert.equal(captured.url, '/api/settings') assert.equal(captured.method, 'PUT') const standings = captured.body?.standings as Record assert.equal(standings.individualToTeamWeight, 0.5) // 只提交一个字段会把其余口径留在服务端旧值上,所以整个 standings 子对象原样回传。 assert.equal(standings.rankingMode, 'points') assert.equal(standings.showIndividualBoard, true) assert.equal(standings.showIndividualMedals, true) assert.equal(saved.standings.individualToTeamWeight, 0.5) // 成绩录入页与积分预览直接读 event store 的设置,不回写就等于「保存成功但预览没变」。 assert.equal(event.settings?.standings.individualToTeamWeight, 0.5) assert.equal(data.settings.value?.standings.individualToTeamWeight, 0.5) })