test(i18n): qualify Gmail review counts across EN and NB

This commit is contained in:
cesnimda
2026-11-09 22:41:12 +01:00
parent e8e7d83958
commit 91e5a6bf3a
52 changed files with 2098 additions and 12 deletions
@@ -9,12 +9,13 @@ const compiled = ts.transpileModule(fs.readFileSync(new URL('../src/i18n/transla
const { translations } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`);
const visualMatrix = process.env.A3_VISUAL_MATRIX === '1';
const labelOnly = process.env.A3_LABEL_COUNT === '1';
const recoveryOnly = process.env.A3_MAIL_RECOVERY === '1';
const reviewCounts = process.env.A3_REVIEW_COUNTS === '1';
const recoveryOnly = process.env.A3_MAIL_RECOVERY === '1' || reviewCounts;
assert.ok(!(labelOnly && recoveryOnly), 'Count and recovery are separate scopes.');
const mailOnly = process.env.A3_MAIL_FLAT === '1' || labelOnly || recoveryOnly;
const widths = process.env.A3_PILOT ? [320] : visualMatrix ? [320, 360, 390, 430, 768, 1024, 1280, 1440, 1920] : [320, 390, 768, 1440];
const expectedJourneys = widths.length * (process.env.A3_PILOT ? 1 : 4);
const out = path.resolve(import.meta.dirname, recoveryOnly ? '../../docs/ui-modernisation/visual-correction/evidence/mail-recovery' : labelOnly ? '../../docs/ui-modernisation/visual-correction/evidence/mail-labels' : mailOnly ? '../../docs/ui-modernisation/visual-correction/evidence/mail-flat' : visualMatrix ? '../../docs/ui-modernisation/visual-correction/evidence/documents-inbox' : '../../docs/ui-modernisation/evidence/documents-inbox/browser'); fs.mkdirSync(out, { recursive: true });
const out = path.resolve(import.meta.dirname, reviewCounts ? '../../docs/ui-modernisation/visual-correction/evidence/mail-review-counts' : recoveryOnly ? '../../docs/ui-modernisation/visual-correction/evidence/mail-recovery' : labelOnly ? '../../docs/ui-modernisation/visual-correction/evidence/mail-labels' : mailOnly ? '../../docs/ui-modernisation/visual-correction/evidence/mail-flat' : visualMatrix ? '../../docs/ui-modernisation/visual-correction/evidence/documents-inbox' : '../../docs/ui-modernisation/evidence/documents-inbox/browser'); fs.mkdirSync(out, { recursive: true });
const report = { screens: [], journeys: [], errors: [], unexpectedWrites: [], mockedWrites: [], unavailableReads: [], blockedExternal: [] };
const browser = await chromium.launch();
try {
@@ -28,8 +29,8 @@ try {
const cv = { ...document, id: 'cv:3', resourceId: '3', type: 'cv', name: 'Teacher CV', dateKind: 'updated-utc', recordedAt: '2026-11-03T10:00:00Z', visibility: 'private', version: 4, sourceHref: '/career/builder/3', downloadHref: null };
const mail = { id: 1, jobApplicationId: 42, companyName: 'Synthetic school', jobTitle: 'Primary teacher', from: 'Recruiter', direction: 'inbound', subject: 'Interview invitation', channel: 'Email', date: '2026-11-03T10:00:00Z', contentPreview: 'Recorded invitation', externalThreadId: 'thread-1', externalMessageId: 'message-1', provider: 'gmail', externalFrom: 'recruiter@example.test', externalTo: 'alex@example.test', labelCount: 1, attachmentCount: 0 };
let draft = null, sends = 0, documentReads = 0, mailReads = 0;
let reviewState = 'unavailable';
const reviewThread = { threadId: 'review-thread-1', subject: 'Research technician application', latestDate: mail.date, messageCount: 2, routing: 'suggested', hasImportedMessages: false, decisionNote: '', matchedQueries: ['"Research technician"'], jobCandidates: [], messages: [] };
let reviewState = reviewCounts ? 'populated' : 'unavailable';
const reviewThread = { threadId: 'review-thread-1', subject: 'Research technician application', latestDate: mail.date, messageCount: reviewCounts ? 1 : 2, routing: 'suggested', hasImportedMessages: false, decisionNote: '', matchedQueries: ['"Research technician"'], jobCandidates: [], messages: [] };
const suggestion = { threadId: reviewThread.threadId, companyName: 'Synthetic laboratory', suggestedJobTitle: 'Research technician', subject: reviewThread.subject, preview: 'Recorded suggestion' };
const draftText = 'Thank you. Please confirm the available interview times.';
const revisedDraft = 'Unsaved revision after the interview was rescheduled.';
@@ -94,6 +95,16 @@ try {
const review = page.getByRole('button', { name: t('emailInboxReviewSuggestions'), exact: true });
await review.press('Enter');
const panel = page.getByRole('region', { name: t('gmailReviewEmbeddedTitle'), exact: true });
const article = panel.getByRole('article', { name: reviewThread.subject, exact: true });
if (reviewCounts) {
await expect(panel.getByText(t('gmailReviewCandidateThread').replace('{count}', '1'), { exact: true })).toBeVisible();
await expect(panel.getByText(t('gmailReviewSuggestedJobCount').replace('{count}', '1'), { exact: true })).toBeVisible();
const summary = t('gmailReviewSingleMessageSummary').replace('{count}', '1').replace('{route}', t('gmailReviewRouteSuggested'));
await expect(article.getByText(summary, { exact: true })).toBeVisible();
await scan('review-counts');
report.journeys.push({ width, language, mode, singularCandidateSuggestionAndMessage: 'PASS', send: 'NOT RUN' });
await context.close(); continue;
}
const retry = panel.getByRole('button', { name: t('retry'), exact: true });
const empty = panel.getByText(t('gmailReviewNoCandidates'), { exact: true });
await expect(panel.getByText(t('gmailReviewLoadFailed'), { exact: true })).toBeVisible();
@@ -102,7 +113,6 @@ try {
await expect(panel.getByRole('group', { name: t('gmailReviewEmbeddedTitle'), exact: true })).toBeFocused();
await expect(empty).toBeVisible(); await scan('review-empty', empty);
reviewState = 'populated'; await panel.getByRole('button', { name: t('correspondenceRefresh'), exact: true }).press('Enter');
const article = panel.getByRole('article', { name: reviewThread.subject, exact: true });
await expect(article).toContainText(suggestion.companyName);
await scan('review-suggestion', article);
await page.getByRole('button', { name: t('emailInboxLinkedMessages'), exact: true }).press('Enter');
@@ -146,6 +156,7 @@ try {
assert.equal(sends, 1); await expect(compose.getByRole('textbox', { name: t('emailInboxMessage'), exact: true })).toHaveValue(draft.bodyText); await scan('uncertain-send', compose.getByRole('textbox', { name: t('emailInboxMessage'), exact: true }));
report.journeys.push({ width, language, mode, documentFilterFocusDownloadSource: mailOnly ? 'NOT RUN' : 'PASS', inboxFocusPlainTextReplySaveExplicitConfirmUncertainNoRetry: 'PASS' }); await context.close();
}
assert.equal(report.journeys.length, expectedJourneys); assert.equal(report.screens.length, report.journeys.length * (labelOnly ? 1 : mailOnly ? 4 : 6)); assert.equal(report.mockedWrites.length, labelOnly ? 0 : report.journeys.length * 2); assert.deepEqual(report.errors, []); assert.deepEqual(report.unexpectedWrites, []); assert.ok(report.blockedExternal.every(origin => origin === 'https://fonts.googleapis.com'));
const displayOnly = labelOnly || reviewCounts;
assert.equal(report.journeys.length, expectedJourneys); assert.equal(report.screens.length, report.journeys.length * (displayOnly ? 1 : mailOnly ? 4 : 6)); assert.equal(report.mockedWrites.length, displayOnly ? 0 : report.journeys.length * 2); 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} document/mail journeys,${report.screens.length} axe scans/captures,${report.mockedWrites.length} intercepted write requests.`);
} finally { fs.writeFileSync(path.join(out, process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['Synthetic metadata/binary/mail/provider fixtures; not live storage, mailbox, OAuth or delivery.', recoveryOnly ? 'Review uses only fixture reads. Draft create and rejected update are intercepted; sending is blocked.' : 'Browser covers draft save, explicit confirmation and controlled uncertain outcome only; other recovery/conflict paths remain targeted tests.', 'No real sending, native device, final integrated security or release acceptance.'] }, null, 2)); await browser.close(); }
} finally { fs.writeFileSync(path.join(out, process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['Synthetic metadata/binary/mail/provider fixtures; not live storage, mailbox, OAuth or delivery.', reviewCounts ? 'Only the populated review counts are exercised. No draft or provider actions.' : recoveryOnly ? 'Review uses only fixture reads. Draft create and rejected update are intercepted; sending is blocked.' : 'Browser covers draft save, explicit confirmation and controlled uncertain outcome only; other recovery/conflict paths remain targeted tests.', 'No real sending, native device, final integrated security or release acceptance.'] }, null, 2)); await browser.close(); }