Files
story/web/test/subject-save.test.mjs
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

37 lines
2.4 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { mutationOutcomeUnknown, needsSaveVerification, subjectSaveLabel, subjectMatchesUpdate, verifiedSaveStatus } from '../src/pages/subject-save.ts';
const original = { id: 'synthetic-elder', household_id: 'synthetic-home', version: 4, preferred_name: '合成长者', profile_data: { interests: ['养花'], background: '合成背景' } };
const input = { preferred_name: '合成长者(已编辑)', profile_data: { background: '合成背景', interests: ['养花'] } };
const attempt = { householdID: original.household_id, baseVersion: 4, input, status: 'uncertain' };
test('lost and gateway responses are unknown, while explicit rejection is distinct', () => {
for (const status of [0, 408, 500, 502, 503, 504]) assert.equal(mutationOutcomeUnknown({ status }), true);
for (const status of [400, 401, 403, 409, 412, 422, 429]) assert.equal(mutationOutcomeUnknown({ status }), false);
assert.equal(mutationOutcomeUnknown(new TypeError('network failure')), true);
assert.equal(mutationOutcomeUnknown(new SyntaxError('invalid JSON')), true);
});
test('a background refresh does not convert an uncertain save into a success label', () => {
assert.match(subjectSaveLabel(attempt, false), /尚未确认/);
assert.equal(needsSaveVerification(attempt), true);
assert.doesNotMatch(subjectSaveLabel(undefined, false), /已保存|最新版本/);
});
test('read-only verification requires matching all submitted fields and a non-stale version', () => {
const committed = { ...original, ...input, version: 5 };
assert.equal(subjectMatchesUpdate(committed, input), true);
assert.equal(verifiedSaveStatus(committed, attempt), 'verified');
assert.equal(verifiedSaveStatus(original, attempt), 'uncertain');
assert.equal(verifiedSaveStatus({ ...committed, version: 3 }, attempt), 'uncertain');
assert.equal(verifiedSaveStatus({ ...committed, preferred_name: '另一项并发修改' }, attempt), 'conflict');
assert.equal(verifiedSaveStatus({ ...committed, profile_data: { ...input.profile_data, interests: [] } }, attempt), 'conflict');
});
test('editing after an acknowledged save has a draft label again', () => {
assert.equal(subjectSaveLabel({ ...attempt, status: 'saved' }, true), '修改尚未保存');
assert.equal(subjectSaveLabel({ ...attempt, status: 'saved' }, false), '服务器已确认保存');
assert.equal(needsSaveVerification({ ...attempt, status: 'saved' }), false);
});