55 lines
3.1 KiB
JavaScript
55 lines
3.1 KiB
JavaScript
import test from 'node:test';
|
||||
|
|
import assert from 'node:assert/strict';
|
|||
|
|
import { householdSelectionKey, readHouseholdSelection, writeHouseholdSelection, resolveHouseholdSelection, timezoneError, parseContextList, contextListError, privacyStatusLabel, privacyRequestStatus, isPrivacyRequestProcessing } from '../src/pages/portal-validation.ts';
|
|||
|
|
|
|||
|
|
test('family choice survives reload and only resolves accessible families', () => {
|
|||
|
|
const values = new Map();
|
|||
|
|
globalThis.window = { localStorage: { getItem: key => values.get(key), setItem: (key, value) => values.set(key, value), removeItem: key => values.delete(key) } };
|
|||
|
|
const accounts = [{ tenant_id: 'tenant-a', user_id: 'user-a' }, { tenant_id: 'tenant-b', user_id: 'user-b' }];
|
|||
|
|
const key = householdSelectionKey(accounts);
|
|||
|
|
assert.equal(key, householdSelectionKey([...accounts].reverse()));
|
|||
|
|
writeHouseholdSelection(key, 'A');
|
|||
|
|
assert.equal(resolveHouseholdSelection([{ id: 'B' }, { id: 'A' }], readHouseholdSelection(key)), 'A');
|
|||
|
|
assert.equal(resolveHouseholdSelection([{ id: 'B' }], readHouseholdSelection(key)), 'B');
|
|||
|
|
assert.equal(readHouseholdSelection(householdSelectionKey([{ tenant_id: 'tenant-a', user_id: 'other-user' }])), undefined);
|
|||
|
|
assert.equal(resolveHouseholdSelection([], 'A'), undefined);
|
|||
|
|
writeHouseholdSelection(key);
|
|||
|
|
assert.equal(readHouseholdSelection(key), undefined);
|
|||
|
|
globalThis.window = { get localStorage() { throw new Error('Storage unavailable'); } };
|
|||
|
|
assert.doesNotThrow(() => writeHouseholdSelection(key, 'A'));
|
|||
|
|
assert.equal(readHouseholdSelection(key), undefined);
|
|||
|
|
delete globalThis.window;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('invalid timezones fail before confirmation', () => {
|
|||
|
|
assert.equal(timezoneError('Asia/Shanghai'), '');
|
|||
|
|
assert.equal(timezoneError('America/New_York'), '');
|
|||
|
|
assert.equal(timezoneError('UTC'), '');
|
|||
|
|
assert.ok(timezoneError('Invalid/Zone'));
|
|||
|
|
assert.ok(timezoneError(''));
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('topic parsing preserves excess entries for explicit validation', () => {
|
|||
|
|
const items = parseContextList('1、2,3,4、5、6、7、8、9');
|
|||
|
|
assert.equal(items.length, 9);
|
|||
|
|
assert.ok(contextListError(items));
|
|||
|
|
assert.equal(contextListError(items.slice(0, 8)), '');
|
|||
|
|
assert.ok(contextListError(['很'.repeat(51)]));
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('every privacy request state has a Chinese label', () => {
|
|||
|
|
for (const state of ['SUBMITTED', 'VERIFYING', 'EXECUTING', 'COMPLETED', 'PARTIAL_FAILED']) {
|
|||
|
|
assert.notEqual(privacyStatusLabel(state), state);
|
|||
|
|
assert.equal(privacyStatusLabel(state.toLowerCase()), privacyStatusLabel(state));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('failed deletion subtasks override a stale executing status until reconciliation completes', () => {
|
|||
|
|
const request = { status: 'EXECUTING', subtasks: [{ status: 'COMPLETED' }, { status: 'FAILED' }] };
|
|||
|
|
assert.equal(privacyRequestStatus(request), 'PARTIAL_FAILED');
|
|||
|
|
assert.equal(isPrivacyRequestProcessing(request), false);
|
|||
|
|
assert.equal(isPrivacyRequestProcessing({ ...request, subtasks: [{ status: 'RUNNING' }] }), true);
|
|||
|
|
assert.equal(privacyRequestStatus({ status: 'COMPLETED', subtasks: [{ status: 'COMPLETED' }] }), 'COMPLETED');
|
|||
|
|
assert.equal(isPrivacyRequestProcessing({ status: 'COMPLETED' }), false);
|
|||
|
|
});
|