test(admin): qualify read-only account status

This commit is contained in:
cesnimda
2026-11-10 12:46:45 +01:00
parent e22f2d6450
commit 2717c6afaf
54 changed files with 2820 additions and 11 deletions
@@ -12,12 +12,14 @@ const adminOnly = Boolean(process.env.A3_ADMIN_FLAT);
const adminHeadings = Boolean(process.env.A3_ADMIN_HEADINGS);
const auditDateOnly = Boolean(process.env.A3_AUDIT_DATE);
const userAlignmentOnly = Boolean(process.env.A3_ADMIN_USER_ALIGNMENT);
const userTwoFactorOnly = Boolean(process.env.A3_ADMIN_USER_2FA);
const usersOnly = userAlignmentOnly || userTwoFactorOnly;
const systemRefreshOnly = Boolean(process.env.A3_SYSTEM_REFRESH);
assert.ok(!adminHeadings || adminOnly, 'Heading qualification uses the Admin fixtures.');
assert.ok(!auditDateOnly || (adminOnly && !adminHeadings), 'Audit timestamp qualification uses its own scope.');
assert.ok(!userAlignmentOnly || (adminOnly && !adminHeadings && !auditDateOnly), 'Admin Users alignment uses its own scope.');
assert.ok(!systemRefreshOnly || (adminOnly && !adminHeadings && !auditDateOnly && !userAlignmentOnly), 'System refresh qualification uses its own scope.');
const out = path.resolve(import.meta.dirname, systemRefreshOnly ? '../../docs/ui-modernisation/visual-correction/evidence/system-status-refresh' : userAlignmentOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-user-alignment' : auditDateOnly ? '../../docs/ui-modernisation/visual-correction/evidence/audit-date' : adminHeadings ? '../../docs/ui-modernisation/visual-correction/evidence/admin-headings' : adminOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-flat' : accountOnly ? '../../docs/ui-modernisation/visual-correction/evidence/account-flat' : '../../docs/ui-modernisation/evidence/account-admin/browser');
assert.ok(!usersOnly || (adminOnly && !adminHeadings && !auditDateOnly && !(userTwoFactorOnly && userAlignmentOnly)), 'Admin Users verification uses a single scope.');
assert.ok(!systemRefreshOnly || (adminOnly && !adminHeadings && !auditDateOnly && !usersOnly), 'System refresh qualification uses its own scope.');
const out = path.resolve(import.meta.dirname, userTwoFactorOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-user-2fa' : systemRefreshOnly ? '../../docs/ui-modernisation/visual-correction/evidence/system-status-refresh' : userAlignmentOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-user-alignment' : auditDateOnly ? '../../docs/ui-modernisation/visual-correction/evidence/audit-date' : adminHeadings ? '../../docs/ui-modernisation/visual-correction/evidence/admin-headings' : adminOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-flat' : accountOnly ? '../../docs/ui-modernisation/visual-correction/evidence/account-flat' : '../../docs/ui-modernisation/evidence/account-admin/browser');
fs.mkdirSync(out, { recursive: true });
const report = { screens: [], journeys: [], errors: [], unexpectedWrites: [], exportDenials: [], unavailableReads: [], blockedExternal: [] };
const browser = await chromium.launch();
@@ -63,7 +65,7 @@ try {
'/api/jobapplications/reminders': [], '/api/notifications/unread-count': { count: 0 }, '/api/notification-settings': { emailFollowUpRemindersEnabled: true },
'/api/account-lifecycle/status': { deletionEnabled: true, deletionStatus: 'active', requiredConfirmation: 'DELETE alex@example.test', request: null },
'/api/gmail/status': { connected: false, configured: false }, '/api/microsoft-graph/status': { connected: false, configured: false }, '/api/imap/status': { connected: false, configured: false },
'/api/users': [{ id: 'a3-admin-owner', email: 'alex@example.test', userName: 'alex', emailConfirmed: true, roles: ['Admin'], isCurrentUser: true, canRemoveAdmin: false }],
'/api/users': [{ id: 'a3-admin-owner', email: 'alex@example.test', userName: 'alex', emailConfirmed: true, twoFactorEnabled: userTwoFactorOnly ? true : undefined, roles: ['Admin'], isCurrentUser: true, canRemoveAdmin: false }],
'/api/admin/audit': populatedAudit ? [{ id: 1, type: 'StatusChanged', oldValue: 'Applied', newValue: 'Interview', note: 'Synthetic audit event', at: '2026-11-04T10:00:00Z', jobApplicationId: 42, jobTitle: operation.job.title, companyName: operation.job.company, ownerUserId: 'a3-admin-owner', ownerEmail: 'alex@example.test', ownerUserName: 'alex' }] : [], '/api/admin/processing': listing,
[`/api/admin/processing/${operation.id}`]: operation,
[`/api/admin/processing/${operation.id}/events`]: { items: [{ id: '9007199254740993', atUtc: '2026-11-03T10:00:08Z', kind: 'Failed', status: 'failed', stage: 'cv_extracting', attempt: 1, failureCode: 'parser_failed' }], hasMore: false, retentionDays: 30 },
@@ -123,10 +125,14 @@ try {
await context.close();
continue;
}
if (userAlignmentOnly) {
if (usersOnly) {
await page.goto('http://localhost:4338/admin/users');
await expect(page.getByRole('button', { name: t('adminUsersRemoveAdmin'), exact: true })).toBeDisabled();
await expect(page.getByRole('button', { name: t('adminUsersDelete'), exact: true })).toBeDisabled();
if (userTwoFactorOnly) {
await expect(page.getByText(t('adminUsers2faEnabled'), { exact: true })).toBeVisible();
await expect(page.getByText(`${t('adminUsersConfirmed')}: ${t('yes')}`, { exact: true })).toBeVisible();
}
await scan('last-admin');
const grid = page.getByRole('grid');
const cells = width >= 768 ? await grid.getByRole('gridcell').evaluateAll(nodes => nodes.map(cell => {
@@ -228,10 +234,10 @@ try {
}
report.journeys.push({ width, language, mode, draftPreservedAcrossKeyboardSections: processingOnly || adminOnly ? 'NOT RUN' : 'PASS', revocationAndDeletionCancelled: processingOnly || adminOnly ? 'NOT RUN' : 'PASS', recentExportDenial: processingOnly || adminOnly ? 'NOT RUN' : 'PASS', lastAdminActionsDisabled: processingOnly || accountOnly ? 'NOT RUN' : 'PASS', processingKeyboardAndOwnerLink: accountOnly ? 'NOT RUN' : 'PASS', processingFilterLabelsAndDurationGeometry: accountOnly ? 'NOT RUN' : 'PASS', populatedAdminReadStates: adminOnly ? 'PASS' : 'NOT RUN' }); await context.close();
}
assert.equal(report.screens.length, configurations.length * (systemRefreshOnly ? 3 : userAlignmentOnly || auditDateOnly || processingOnly ? 1 : accountOnly ? 7 : adminOnly ? 9 : 8)); assert.equal(report.journeys.length, configurations.length); assert.equal(report.exportDenials.length, processingOnly || adminOnly ? 0 : configurations.length);
assert.equal(report.screens.length, configurations.length * (systemRefreshOnly ? 3 : usersOnly || auditDateOnly || processingOnly ? 1 : accountOnly ? 7 : adminOnly ? 9 : 8)); assert.equal(report.journeys.length, configurations.length); assert.equal(report.exportDenials.length, processingOnly || adminOnly ? 0 : configurations.length);
assert.deepEqual(report.errors, []); assert.deepEqual(report.unexpectedWrites, []); assert.ok(report.blockedExternal.every(origin => origin === 'https://fonts.googleapis.com'));
console.log(`PASS:${report.journeys.length} controlled journeys,${report.screens.length} axe scans/captures; no mutation requests.`);
} finally {
fs.writeFileSync(path.join(out, processingOnly ? 'PROCESSING.json' : process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.', systemRefreshOnly ? 'Only initial unavailable, successful, stale and recovered System Status reads are exercised. No diagnostic action executed.' : userAlignmentOnly ? 'Only the Users table alignment, mobile layout and last-administrator disabled actions are exercised.' : auditDateOnly ? 'Only the populated audit table, timestamp geometry and keyboard scrolling are exercised.' : adminOnly ? 'System and audit populated states are synthetic read fixtures; no probe, maintenance, settings save, undo, restore or provider action executed.' : 'System monitor is unavailable and audit empty; detailed success/action scenarios are unit tests, not live qualification.', 'No real credentials, provider activation, model, native device, integrated security, production or release acceptance.'] }, null, 2));
fs.writeFileSync(path.join(out, processingOnly ? 'PROCESSING.json' : process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.', systemRefreshOnly ? 'Only initial unavailable, successful, stale and recovered System Status reads are exercised. No diagnostic action executed.' : userTwoFactorOnly ? 'Read-only 2FA and confirmation statuses are displayed alongside the existing last-administrator safeguards.' : userAlignmentOnly ? 'Only the Users table alignment, mobile layout and last-administrator disabled actions are exercised.' : auditDateOnly ? 'Only the populated audit table, timestamp geometry and keyboard scrolling are exercised.' : adminOnly ? 'System and audit populated states are synthetic read fixtures; no probe, maintenance, settings save, undo, restore or provider action executed.' : 'System monitor is unavailable and audit empty; detailed success/action scenarios are unit tests, not live qualification.', 'No real credentials, provider activation, model, native device, integrated security, production or release acceptance.'] }, null, 2));
await browser.close();
}