Files
jobtrackingapp/job-tracker-ui/scripts/verify-a3-account-admin.mjs
T

260 lines
28 KiB
JavaScript

// Actual exported React views; all API responses controlled. No credentials or real account operations.
import { chromium, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
import ts from 'typescript';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
const compiled = ts.transpileModule(fs.readFileSync(new URL('../src/i18n/translations.ts', import.meta.url), 'utf8'), { compilerOptions: { module: ts.ModuleKind.ESNext } }).outputText;
const { translations } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`);
const accountOnly = Boolean(process.env.A3_ACCOUNT_FLAT);
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 auditSearch = Boolean(process.env.A3_AUDIT_SEARCH);
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(!auditSearch || auditDateOnly, 'Audit search uses the populated Audit fixture.');
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, auditSearch ? '../../docs/ui-modernisation/visual-correction/evidence/audit-search' : 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();
const processingOnly = Boolean(process.env.A3_PROCESSING_ONLY);
assert.ok(!(processingOnly && accountOnly), 'Account and processing qualification are distinct scopes.');
assert.ok(!adminOnly || !(processingOnly || accountOnly), 'Admin qualification is a distinct scope.');
try {
const configurations = process.env.A3_PILOT ? (userAlignmentOnly ? [[1440, 'en', 'light']] : auditSearch ? [[320, 'nb', 'dark']] : auditDateOnly ? [[768, 'nb', 'dark']] : adminOnly ? [[320, 'en', 'light'], [1440, 'en', 'light']] : [[320, 'en', 'light']]) : (accountOnly || adminOnly ? [320, 360, 390, 430, 768, 1024, 1280, 1440, 1920] : [320, 390, 768, 1440]).flatMap(width => ['en', 'nb'].flatMap(language => ['light', 'dark'].map(mode => [width, language, mode])));
for (const [width, language, mode] of configurations) {
console.log(`Checking ${width}/${language}/${mode}`);
const t = key => { assert.ok(translations[language][key], key); return translations[language][key]; };
const context = await browser.newContext({ viewport: { width, height: 1000 }, reducedMotion: 'reduce' });
const page = await context.newPage(); page.on('pageerror', error => report.errors.push(error.message));
await page.addInitScript(({ language, mode }) => { localStorage.setItem('uiLanguage', language); localStorage.setItem('jobtracker.themeMode', mode); }, { language, mode });
const session = { id: 'current', deviceLabel: 'Synthetic current device', isCurrentSession: true, createdAtUtc: '2026-11-03T10:00:00Z', lastSeenAtUtc: '2026-11-03T10:00:00Z', expiresAtUtc: '2026-12-03T10:00:00Z' };
const operation = { id: '11111111-1111-4111-8111-111111111111', owner: { id: 'a3-admin-owner', name: 'Alex Sample', email: 'alex@example.test' }, taskType: 'cv.process', status: 'failed', stage: 'cv_extracting', attemptCount: 1, maxAttempts: 3, createdAtUtc: '2026-11-03T10:00:00Z', startedAtUtc: null, completedAtUtc: null, lastHeartbeatAtUtc: null, durationSeconds: 8, worker: 'document', workerEnabled: false, failureCode: 'parser_failed', lastFailureAtUtc: '2026-11-03T10:00:08Z', lastFailureStage: 'cv_extracting', job: { id: 42, title: 'Recorded teacher application', company: 'Synthetic school', canOpen: false }, document: { importId: 7, name: 'Recorded teacher CV.pdf', type: 'application/pdf', bytes: 500, pages: 2, state: 'failed' } };
const listing = { items: [operation], total: 1, counts: { failed: 1 }, workers: [{ name: 'CvDocumentImports', flagEnabled: false, individualOperationsRecorded: true }] };
let populatedAudit = false, systemAvailable = false;
const system = {
environment: 'Synthetic qualification', contentRoot: '/synthetic/app', version: 'fixture', commitSha: 'fixture', buildStamp: '2026-11-04',
storage: { dataRoot: '/synthetic', dbPath: '/synthetic/db', dbExists: true, dbSizeBytes: 2048, companyCount: 3, jobCount: 7, deletedCount: 1 },
email: { enabled: false, host: 'smtp.example.test', port: 587, enableSsl: true, from: 'noreply@example.test', fromName: 'Synthetic' },
database: { provider: 'mariadb', looksConfigured: true, canConnect: true, target: 'synthetic', usesFileStorage: false, warning: null },
runtime: { framework: 'Synthetic .NET', osDescription: 'Fixture', processArchitecture: 'X64', machineName: 'fixture' },
auth: { required: true, hasJwtKey: true, googleConfigured: false, gmailConfigured: false },
ai: { healthy: false, model: null, device: null, gpuAvailable: false, gpuName: null, ocrAvailable: false, ocrLanguages: '', ollamaConfigured: false, ollamaReachable: false, ollamaModel: null, ollamaModelAvailable: false, ollamaVersion: null, ollamaInstalledModels: [], ollamaLoadedModels: [], ollamaLoadedCount: 0, healthLatencyMs: 0, probeLatencyMs: 0, probeFailures: 0, requests: 0, cacheHits: 0, cacheMisses: 0, failures: 0, averageLatencyMs: 0, ocrRequests: 0, ocrFailures: 0, averageOcrLatencyMs: 0, lastError: null },
};
const benchmark = { rootPath: '/synthetic/benchmarks', lastUpdatedAtUtc: '2026-11-04T10:00:00Z', reportMarkdown: '# Synthetic report\n\nFixture only.', indexJson: JSON.stringify({ CorpusRoot: '/synthetic/corpus', OutputRoot: '/synthetic/benchmarks', GeneratedAtUtc: '2026-11-04T10:00:00Z', TotalFiles: 1, AverageCoverage: 0.5, AverageConfidence: 0.65, AverageConsistency: 0.8, FilesWithSuspiciousLocations: 1, MissingApprovedFixtures: 1, Entries: [{ FileName: 'Synthetic-teacher.txt', Slug: 'synthetic-teacher', Extension: '.txt', Characters: 2000, OutputPath: '/synthetic/output.json', ApprovedFixturePath: null, CandidateFixturePath: '/synthetic/candidate.json', ContactLocation: 'Oslo, Hobbies', FirstJob: 'Teacher', FirstEducation: 'Education degree', QualificationLevels: ['Other'], SuspiciousLocations: [], CoverageScore: 0.5, ConfidenceScore: 0.65, ConsistencyScore: 0.8, DiffSummary: 'Synthetic unapproved fixture.' }] }) };
await page.route('**/*', route => {
const req = route.request(), url = new URL(req.url()), p = url.pathname;
if (url.origin !== 'http://localhost:4338' && !(url.origin === 'http://localhost:5202' && p.startsWith('/api/'))) { report.blockedExternal.push(url.origin); return route.abort(); }
if (!p.startsWith('/api/')) return route.continue();
const answer = data => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(data) });
if (req.method() === 'POST' && p === '/api/export/account') {
report.exportDenials.push({ width, language, mode }); return route.fulfill({ status: 403, contentType: 'application/problem+json', body: JSON.stringify({ detail: 'Controlled recent-sign-in denial.' }) });
}
if (req.method() !== 'GET') { report.unexpectedWrites.push(p); return route.abort(); }
const fixtures = {
'/api/auth/config': { requireAuth: true, allowRegistration: false },
'/api/auth/me': { id: 'a3-admin-owner', sessionContext: 'a3-admin-session', provider: 'local', firstName: 'Alex', lastName: 'Sample', userName: 'alex', displayName: 'Alex Sample', email: 'alex@example.test', roles: ['Admin'], plan: 'pro', entitlements: { ai: false, proThemes: true }, uiLanguage: language === 'nb' ? 'nb-NO' : 'en', googleLink: { linked: false }, microsoftLink: { linked: false } },
'/api/auth/email-change': { pendingEmail: null }, '/api/auth/2fa/status': { enabled: true, enabledAtUtc: '2026-11-03T10:00:00Z' }, '/api/auth/2fa/trusted-devices': [],
'/api/auth/sessions': [session, { ...session, id: 'other', deviceLabel: 'Synthetic other device', isCurrentSession: false }],
'/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, 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 },
};
if (systemAvailable) Object.assign(fixtures, {
'/api/admin/system': system,
'/api/admin/system/email-settings': { ...system.email, user: 'mailer@example.test', timeoutMs: 15000, usesOverrides: false, hasPassword: false },
'/api/admin/system/cv-benchmark': benchmark,
'/api/admin/system/maintenance-jobs': [{ id: 'cv-benchmark', title: 'Synthetic benchmark', description: 'Fixture only', available: false, runsUrl: null }],
});
if (Object.hasOwn(fixtures, p)) return answer(fixtures[p]);
report.unavailableReads.push(p); return route.fulfill({ status: 503, contentType: 'application/json', body: JSON.stringify({ detail: 'Controlled offline read unavailable.' }) });
});
const scan = async (state, keepScroll = false) => {
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth + 1), false, `overflow:${state}`);
const result = await new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa']).analyze();
report.screens.push({ width, language, mode, state, capture: keepScroll ? 'focused viewport' : width >= 768 ? 'full page at top' : 'viewport at top', violations: result.violations }); assert.deepEqual(result.violations, [], `${state} accessibility`);
if (!keepScroll) { await page.evaluate(() => window.scrollTo({ top: 0, behavior: 'instant' })); await expect.poll(() => page.evaluate(() => window.scrollY)).toBe(0); }
await page.screenshot({ path: path.join(out, `${state}-${language}-${mode}-${width}.png`), fullPage: width >= 768 && !keepScroll });
};
const checkHeading = async (title, subtitle) => {
if (!adminHeadings) return;
const heading = page.getByRole('heading', { name: t(title), exact: true });
await expect(heading).toHaveCount(1);
await expect(page.getByRole('heading', { name: t(title), exact: true, level: 1 })).toBeVisible();
await expect(page.getByText(t(subtitle), { exact: true })).toBeVisible();
};
if (systemRefreshOnly) {
await page.goto('http://localhost:4338/admin/system');
const loadError = page.getByText(t('adminSystemLoadFailed'), { exact: true });
const staleError = page.getByText(t('adminSystemRefreshFailed'), { exact: true });
const time = page.getByText(t('adminSystemStatusReceivedAt') + ':', { exact: true }).locator('..').locator('time');
await expect(loadError).toBeVisible();
await expect(time).toHaveCount(0);
await scan('system-unavailable');
systemAvailable = true;
const refresh = page.getByRole('button', { name: t('adminSystemRefresh'), exact: true });
await refresh.press('Enter');
await expect(time).toBeVisible();
const firstRead = await time.getAttribute('datetime');
assert.ok(firstRead && Number.isFinite(Date.parse(firstRead)));
await scan('system-normal');
systemAvailable = false;
await refresh.press('Enter');
await expect(staleError).toBeVisible();
await expect(time).toHaveAttribute('datetime', firstRead);
await expect(page.getByText(system.environment, { exact: true })).toBeVisible();
const benchmarkError = await page.getByText(t('adminSystemBenchmarkLoadFailed'), { exact: true }).boundingBox();
assert.ok((await time.boundingBox()).y < benchmarkError.y, 'The stale timestamp stays above ancillary errors.');
await scan('system-stale');
systemAvailable = true;
await staleError.locator('xpath=ancestor::*[@role="alert"]').getByRole('button', { name: t('retry'), exact: true }).press('Enter');
await expect(staleError).toHaveCount(0);
await expect(time).not.toHaveAttribute('datetime', firstRead);
assert.ok(Date.parse(await time.getAttribute('datetime')) > Date.parse(firstRead));
report.journeys.push({ width, language, mode, lastSuccessfulReadPreservedAndRenewed: 'PASS' });
await context.close();
continue;
}
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 => {
const cellBounds = cell.getBoundingClientRect();
const range = document.createRange();
range.selectNodeContents(cell);
const content = cell.firstElementChild?.getBoundingClientRect() ?? range.getBoundingClientRect();
return { field: cell.dataset.field, offset: content.y + content.height / 2 - (cellBounds.y + cellBounds.height / 2) };
})) : [];
report.journeys.push({ width, language, mode, cellOffsets: cells, lastAdminActionsDisabled: 'PASS' });
if (width >= 768) {
assert.equal(cells.length, 5);
assert.ok(cells.every(cell => Math.abs(cell.offset) < 3), `Admin user cell content is misaligned: ${JSON.stringify(cells)}`);
} else await expect(grid).toHaveCount(0);
await context.close(); continue;
}
if (auditDateOnly) {
populatedAudit = true;
await page.goto('http://localhost:4338/admin/audit');
const table = page.getByRole('table', { name: t('adminAuditTitle'), exact: true });
await expect(table.getByRole('cell', { name: 'Applied -> Interview Synthetic audit event', exact: true })).toBeVisible();
if (auditSearch) {
const input = page.getByRole('searchbox', { name: t('adminAuditSearch'), exact: true });
await expect(input).toHaveAccessibleDescription(t('adminAuditSearchScope'));
await input.pressSequentially('42');
await expect(table.getByText('StatusChanged', { exact: true })).toBeVisible();
await input.fill('Synthetic audit event');
const empty = page.getByText(t('adminAuditNoMatches'), { exact: true });
await expect(empty).toBeVisible();
assert.ok(await empty.evaluate(node => node.scrollWidth <= node.clientWidth && node.getBoundingClientRect().right <= innerWidth), 'Empty search feedback fits the viewport.');
await scan('audit-no-matches');
await input.press('ControlOrMeta+a');
await input.press('Backspace');
await expect(table.getByText('StatusChanged', { exact: true })).toBeVisible();
}
const heading = table.getByRole('columnheader', { name: t('adminAuditAt'), exact: true });
const dateCell = table.getByRole('row').nth(1).getByRole('cell').first();
const wordsStayOnOneLine = element => {
const text = element.firstChild;
if (!text || text.nodeType !== Node.TEXT_NODE) return false;
return [...text.textContent.matchAll(/\S+/g)].every(word => {
const range = document.createRange();
range.setStart(text, word.index);
range.setEnd(text, word.index + word[0].length);
return range.getClientRects().length === 1;
});
};
assert.ok(await heading.evaluate(wordsStayOnOneLine), 'Audit column heading breaks within a word');
assert.ok(await dateCell.evaluate(wordsStayOnOneLine), 'Audit date or time breaks within its formatted value');
const headerBounds = await table.getByRole('row').first().boundingBox();
const eventBounds = await table.getByRole('row').nth(1).boundingBox();
assert.ok(headerBounds.height <= 72 && eventBounds.height <= 128, `A short audit event should stay compact (header ${headerBounds.height}px, row ${eventBounds.height}px)`);
await scan('audit-populated');
const region = page.getByRole('region', { name: t('adminAuditTitle'), exact: true });
const requiresScroll = await region.evaluate(node => node.scrollWidth > node.clientWidth);
if (requiresScroll) {
await region.press('ArrowRight');
await expect(region).toBeFocused();
await expect.poll(() => region.evaluate(node => node.scrollLeft)).toBeGreaterThan(0);
}
report.journeys.push({ width, language, mode, auditSearch: auditSearch ? 'PASS' : 'NOT RUN', auditTimestampReadable: 'PASS', headerHeight: headerBounds.height, eventHeight: eventBounds.height, keyboardScroll: requiresScroll ? 'PASS' : 'NOT REQUIRED', auditMutations: 'NOT RUN' });
await context.close(); continue;
}
if (!processingOnly) {
if (!adminOnly) {
await page.goto('http://localhost:4338/profile');
const name = page.getByRole('textbox', { name: t('profileDisplayName'), exact: true }); await expect(name).toHaveValue('Alex Sample'); await name.fill('Unsaved account name');
const nav = page.getByRole('navigation', { name: t('accountWorkspaceNavigation'), exact: true });
for (const [id, key] of [['account-details', 'profileAccountSection'], ['account-connections', 'accountWorkspaceConnections'], ['account-security', 'accountWorkspaceSecurity']]) {
await nav.getByRole('button', { name: t(key), exact: true }).press('Enter'); await expect(page.locator(`#${id}`)).toBeFocused(); await expect(name).toHaveValue('Unsaved account name');
if (accountOnly) await scan(id, true);
}
await scan('account');
await page.getByRole('button', { name: t('sessionsRevokeOthers'), exact: true }).click(); const confirmation = page.getByRole('dialog');
await expect(confirmation).toContainText(t('sessionsRevokeOthersConfirmTitle')); await scan('session-confirmation'); await confirmation.getByRole('button', { name: t('cancel'), exact: true }).click();
await nav.getByRole('link', { name: t('accountWorkspaceData'), exact: true }).click(); await expect(page.getByRole('tabpanel', { name: t('settingsTabBackup'), exact: true })).toBeVisible();
await page.getByRole('button', { name: t('accountExportDownload'), exact: true }).click(); await expect(page.getByText(t('accountExportFailed'), { exact: true })).toBeVisible();
await page.getByRole('button', { name: t('accountDeleteButton'), exact: true }).click(); const deletion = page.getByRole('dialog'); await expect(deletion).toContainText('DELETE alex@example.test'); await scan('data-confirmation'); await deletion.getByRole('button', { name: t('cancel'), exact: true }).click();
await page.goto('http://localhost:4338/settings/connected-accounts'); await expect(page.getByRole('heading', { name: t('connectedAccounts'), exact: true })).toBeVisible(); await scan('connections');
}
if (!accountOnly) {
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(); await checkHeading('users', 'adminUsersSubtitle'); await scan('last-admin');
await page.goto('http://localhost:4338/admin/audit'); await expect(page.getByText(t('adminAuditNoEvents'), { exact: true })).toBeVisible(); await scan('audit-empty');
if (adminOnly) { populatedAudit = true; await page.reload(); await expect(page.getByRole('cell', { name: 'Applied -> Interview Synthetic audit event', exact: true })).toBeVisible(); await checkHeading('auditLog', 'adminAuditSubtitle'); await scan('audit-populated'); }
await page.goto('http://localhost:4338/admin/system'); await expect(page.getByText(t('adminSystemLoadFailed'), { exact: true })).toBeVisible(); await scan('system-unavailable');
if (adminOnly) {
systemAvailable = true; await page.reload(); await expect(page.getByText(system.environment, { exact: true })).toBeVisible(); await checkHeading('systemStatus', 'adminSystemSubtitle'); await scan('system-normal');
if (adminHeadings) {
const refresh = page.getByRole('button', { name: t('adminSystemRefresh'), exact: true });
await refresh.press('Enter');
await expect(refresh).toBeFocused();
}
const benchmarkHeading = page.getByRole('heading', { name: t('adminBenchmarkTitle'), exact: true });
await benchmarkHeading.evaluate(el => window.scrollBy({ top: el.getBoundingClientRect().top - 90, behavior: 'instant' })); await scan('system-benchmark', true);
await page.getByRole('heading', { name: t('adminBenchmarkTopFindings'), exact: true }).evaluate(el => window.scrollBy({ top: el.getBoundingClientRect().top - 90, behavior: 'instant' })); await scan('system-findings', true);
await page.getByRole('tab', { name: t('adminSystemSettingsTab'), exact: true }).click(); await scan('system-settings');
}
}
}
if (!accountOnly) {
await page.goto('http://localhost:4338/admin/processing'); await expect(page.getByRole('button', { name: t('processingViewDetails').replace('{id}', operation.id), exact: true })).toBeVisible();
await checkHeading('processingTitle', 'processingSubtitle');
for (const key of ['processingStatus', 'processingTask', 'processingWorkerFilter', 'processingFailureCode']) {
const control = page.getByRole('combobox', { name: t(key), exact: true });
const label = page.locator(`label[for=${JSON.stringify(await control.getAttribute('id'))}]`);
await expect.poll(async () => { const a = await label.boundingBox(), b = await control.boundingBox(); return a && b && a.y + a.height < b.y + b.height / 2; }, { message: `${key}: label must stay above the selected text` }).toBe(true);
}
assert.ok((await page.getByRole('columnheader', { name: t('processingElapsed'), exact: true }).boundingBox()).width >= 96, 'Duration column remains readable');
await page.getByRole('button', { name: t('processingPause'), exact: true }).click(); await page.getByRole('button', { name: t('processingJumpResults'), exact: true }).press('Enter'); await expect(page.getByRole('group', { name: t('processingResults'), exact: true })).toBeFocused();
await page.getByRole('button', { name: t('processingReturnFilters'), exact: true }).click(); await expect(page.getByRole('form', { name: t('processingFilters'), exact: true })).toBeFocused();
await page.getByRole('button', { name: t('processingViewDetails').replace('{id}', operation.id), exact: true }).click(); await expect(page.getByRole('heading', { name: t('processingDetails'), exact: true })).toBeFocused();
await expect(page.getByRole('link', { name: operation.job.title, exact: true })).toHaveCount(0); await scan('processing-detail');
}
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 * (auditSearch ? 2 : 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.' : 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();
}