import { test } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' /** * 示例数据模式下的写操作拦截(P2 A30)与「继续录入」的口径(P2 B09)。 * * A30:发布 / 批次 / 团体名次早就按「示例数据不能写」停用了,只有「存草稿」与「撤销发布」 * 还会真的发请求,拿回一句网络错误——操作员会以为是自己手滑,而不是「这台机没连上服务端」。 * B09:注释与 07 文档都写「默认聚焦上次编辑的项目」,实现是取第一个 pending, * 前端也从没持久化过录入位置,所以注释必须按实现写。 * * 项目没有组件测试工具(无 @vue/test-utils / jsdom),界面部分按仓库既有做法读源码断言。 */ const ENTRY_PAGE_SOURCE = readFileSync(new URL('../pages/EntryPage.vue', import.meta.url), 'utf8') function section(source: string, start: string, end: string): string { const from = source.indexOf(start) const to = source.indexOf(end, from) assert.ok(from >= 0 && to > from, `源码里找不到 ${start} … ${end} 这一段`) return source.slice(from, to) } test('示例数据模式下「存草稿」不发请求,提示与发布同一口径', () => { const saveDraft = section(ENTRY_PAGE_SOURCE, 'async function saveDraft(', 'function requestPublish(') assert.match(saveDraft, /if \(data\.isMock\) \{/) assert.match(saveDraft, /toast\.error\('示例数据模式不能保存草稿', '后端未就绪,草稿不会写入真实赛事'\)/) // 早退必须发生在真正调用写接口之前。 assert.ok( saveDraft.indexOf('data.isMock') < saveDraft.indexOf('await adminApi.saveDraft('), 'isMock 判断要在 saveDraft 调用之前', ) }) test('示例数据模式下「撤销发布」不发请求,提示与发布同一口径', () => { const confirmUnpublish = section(ENTRY_PAGE_SOURCE, 'async function confirmUnpublish(', '// ── 分批结算') assert.match(confirmUnpublish, /if \(data\.isMock\) \{/) assert.match(confirmUnpublish, /toast\.error\('示例数据模式不能撤销发布', '后端未就绪,撤销发布不会写入真实赛事'\)/) assert.ok( confirmUnpublish.indexOf('data.isMock') < confirmUnpublish.indexOf('await adminApi.unpublish('), 'isMock 判断要在 unpublish 调用之前', ) }) test('两个按钮在示例数据模式下直接禁用,避免点了才被告知不能写', () => { assert.match(ENTRY_PAGE_SOURCE, /:disabled="!canWrite \|\| saving \|\| allPublished \|\| data\.isMock"/) assert.match(ENTRY_PAGE_SOURCE, /:disabled="!canWrite \|\| data\.isMock"/) }) test('「继续录入」优先选上次录入的小项(按 id),兜底才是第一个 pending', () => { const pickInitial = section(ENTRY_PAGE_SOURCE, '进入录入页时默认选中小项', 'onMounted(') // 上次录入的小项按 id 记在本地:刚发布完的那个小项状态已是 published, // 只按「第一个 pending」兜底会把它排除掉,回录入页就换成了别的小项(撤销发布按钮跟着消失)。 assert.match(pickInitial, /lastId: readLastEntryEventId\(entryMemoryStorage\(\)\)/) assert.match(pickInitial, /events: data\.events/) // 兜底行为没变:没有记忆时仍是「第一个未开始(pending)的项目,都没有就取列表第一个」。 assert.match(pickInitial, /第一个未开始(pending)的项目/) assert.match(pickInitial, /pickInitialEventId/) }) test('整份 EntryPage 里不再残留「默认聚焦上次编辑」这类与实现不符的说法', () => { assert.doesNotMatch(ENTRY_PAGE_SOURCE, /默认聚焦上次编辑/) })