| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import assert from 'node:assert/strict'
- import { test } from 'node:test'
- import {
- addRecord,
- advanceMockResults,
- createInitialState,
- formatTime,
- markRead,
- recognizePhotos,
- students,
- validateUpload
- } from '../src/data/workbench.ts'
- const photo = (id) => ({ id, path: '', name: id, demo: true })
- const metadata = { name: '测试卷', year: '2026', paperType: '模拟', province: '浙江省' }
- test('appending and deleting photos retains question edits and renumbers pages', () => {
- const first = recognizePhotos([photo('a'), photo('b')])
- first[0].content = '修改后的题干'
- first[0].options[0] = '修改后的选项'
- first[0].isWrong = true
- first[0].tags.push('几何')
- const appended = recognizePhotos([photo('a'), photo('b'), photo('c')], first)
- assert.equal(appended.length, 9)
- assert.equal(appended[0].content, '修改后的题干')
- assert.equal(appended[0].options[0], '修改后的选项')
- assert.equal(appended[0].isWrong, true)
- assert.ok(appended[0].tags.includes('几何'))
- const removed = recognizePhotos([photo('b'), photo('c')], appended)
- assert.equal(removed.length, 6)
- assert.equal(removed[0].page, 1)
- assert.equal(removed[3].page, 2)
- assert.deepEqual(
- removed.map((q) => q.num),
- [1, 2, 3, 4, 5, 6]
- )
- })
- test('required fields and student identity work across different classes with identical names', () => {
- assert.notEqual(students[0].id, students[3].id)
- assert.equal(students[0].name, students[3].name)
- assert.equal(validateUpload('mistakes', [photo('a')], [], metadata), '请先关联学生')
- assert.equal(validateUpload('mistakes', [photo('a')], [students[0], students[3]], metadata), '')
- for (const field of ['name', 'year', 'paperType', 'province'])
- assert.ok(validateUpload('papers', [photo('a')], [], { ...metadata, [field]: '' }))
- assert.equal(validateUpload('answers', [], [], metadata), '请先添加照片')
- })
- test('submission, approval and explanation completion are idempotent and survive serialization', () => {
- const now = Date.now()
- let state = createInitialState()
- const record = {
- id: 'new-paper',
- kind: 'papers',
- ...metadata,
- photos: [photo('a')],
- questions: recognizePhotos([photo('a')]),
- students: [],
- submittedAt: new Date(now).toISOString(),
- reviewStatus: 'pending'
- }
- state = addRecord(state, record)
- assert.equal(addRecord(state, record), state)
- assert.equal(state.records[0].reviewStatus, 'pending')
- state = JSON.parse(JSON.stringify(state))
- const complete = advanceMockResults(state, now + 21000)
- assert.equal(complete.records[0].reviewStatus, 'approved')
- assert.equal(complete.notices.filter((n) => n.id === 'approved-new-paper').length, 1)
- assert.equal(
- complete.explanations.find((v) => v.status === 'waiting'),
- undefined
- )
- assert.equal(advanceMockResults(complete, now + 30000), complete)
- assert.equal(state.records[0].reviewStatus, 'pending', 'previous state must remain immutable')
- })
- test('opening an explanation synchronizes its message badge, while unrelated notices stay unread', () => {
- const initial = createInitialState()
- const read = markRead(initial, initial.explanations[0].id)
- assert.equal(read.explanations[0].unread, false)
- assert.equal(read.notices[0].unread, false)
- assert.equal(read.notices[1].unread, true)
- const all = markRead(read)
- assert.ok(all.notices.every((n) => !n.unread))
- assert.ok(all.explanations.every((v) => !v.unread))
- })
- test('China time display stays stable across device timezones', () => {
- assert.equal(formatTime('2026-10-26T01:05:00Z'), '2026/10/26 09:05')
- assert.equal(formatTime('invalid'), '待同步')
- })
|