Files

55 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

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);
});