// Fixture-only browser review. All API calls are intercepted; no real messages are sent. const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const { chromium } = require(process.env.REVIEW_PLAYWRIGHT || 'playwright') const base = process.env.REVIEW_BASE || 'http://localhost:3114' const output = process.env.REVIEW_DIR const preview = JSON.parse(fs.readFileSync(process.env.REVIEW_EMAIL_FIXTURE, 'utf8')) ;(async () => { const browser = await chromium.launch({ headless: true }) try { const context = await browser.newContext() await context.addCookies([{ name: 'magent_logged_in', value: '1', url: base }]) const calls = [] let role = 'admin' let failPreview = false let email = 'viewer@example.test' let settings = { enabled: false, day: 2, hour: 9, public_url: 'https://beta.example.test', next_send_at: null } let preference = { state: 'off', email, can_subscribe: true, detail: 'Ready', schedule_enabled: false, day: 2, hour: 9, next_send_at: null, resend_after: null } let deliveries = [] let tokenState = 'ready' const months = Array.from({ length: 23 }, (_, index) => new Date(Date.UTC(2026, 7 - index, 1)).toISOString().slice(0, 7)) await context.route('**/api/**', async (route) => { const request = route.request() const url = new URL(request.url()) const payload = request.postDataJSON() calls.push({ method: request.method(), path: url.pathname, payload }) if (url.pathname === '/api/auth/me') return route.fulfill({ json: { username: 'Fixture viewer', role, email } }) if (url.pathname === '/api/auth/profile') return route.fulfill({ json: { user: { username: 'Fixture viewer', role, email, auth_provider: 'jellyfin', password_change_supported: true, password_provider: 'jellyfin' }, activity: { recent: [] } } }) if (url.pathname === '/api/auth/profile/email') { email = payload.email; preference = { ...preference, email, state: 'off' }; return route.fulfill({ json: { email } }) } if (url.pathname === '/api/profile/email-recaps') { if (request.method() === 'PUT') preference = { ...preference, state: payload.enabled ? 'pending' : 'off', resend_after: payload.enabled ? Date.now() / 1000 + 300 : null } return route.fulfill({ json: preference }) } if (url.pathname.startsWith('/api/admin/email-recaps')) { if (role !== 'admin') return route.fulfill({ status: role === 'unauthorized' ? 401 : 403, json: { detail: 'Administrator access is required.' } }) if (url.pathname.endsWith('/preview')) { if (failPreview) return route.fulfill({ status: 502, json: { detail: 'Your report is temporarily unavailable. Please try again shortly.' } }) return route.fulfill({ json: { ...preview, month: url.searchParams.get('month') } }) } if (url.pathname.endsWith('/test')) { assert.deepEqual(Object.keys(payload).sort(), ['month', 'request_id']) deliveries = [{ id: payload.request_id, month: payload.month, kind: 'test', email, username: 'Fixture viewer', state: 'queued', attempts: 0, created_at: Date.now() / 1000, updated_at: Date.now() / 1000, next_attempt_at: Date.now() / 1000, detail: '' }] return route.fulfill({ status: 202, json: { id: payload.request_id, message: 'Test queued for your confirmed email. Check delivery history for the result.' } }) } if (request.method() === 'PUT') { settings = { ...payload, next_send_at: payload.enabled ? Date.UTC(2026, 9, payload.day, payload.hour) / 1000 : null }; return route.fulfill({ json: settings }) } return route.fulfill({ json: { settings, months, ready: true, detail: 'Ready', deliveries, total: deliveries.length, subscribers: 12, worker_enabled: true } }) } if (url.pathname.startsWith('/api/email-recaps/')) { if (url.pathname.endsWith('/confirm')) tokenState = payload.action === 'confirm' ? 'enabled' : 'off' return route.fulfill({ json: { action: payload.action, state: tokenState } }) } if (url.pathname.includes('/events/stream')) return route.fulfill({ contentType: 'text/event-stream', body: ': fixture\n\n' }) return route.fulfill({ json: {} }) }) const page = await context.newPage() const errors = [] page.on('pageerror', (error) => errors.push(error.message)) if (output) fs.mkdirSync(output, { recursive: true }) for (const width of [1440, 980, 390, 320]) { await page.setViewportSize({ width, height: 1000 }) await page.goto(`${base}/admin/recaps`) await page.getByRole('heading', { name: 'Monthly schedule', exact: true }).waitFor() assert.equal(await page.getByLabel('Enable scheduled monthly recaps').isChecked(), false) assert.equal(await page.getByRole('button', { name: 'Send test to me', exact: true }).isDisabled(), true) assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), `Admin overflow at ${width}`) if (output) await page.screenshot({ path: path.join(output, `recaps-admin-${width}.png`), fullPage: true }) await page.getByRole('button', { name: 'Preview my recap', exact: true }).click() const frame = page.frameLocator('iframe[title="Monthly recap email preview"]') await frame.getByRole('heading', { name: 'August 2026', exact: true }).waitFor() assert.equal(await page.locator('iframe').getAttribute('sandbox'), '') assert.equal(await frame.getByRole('link', { name: /Explore your full report/ }).getAttribute('href'), 'https://beta.example.test/insights/reports?month=2026-08') assert(await frame.locator('body').evaluate(() => document.documentElement.scrollWidth <= innerWidth), `Email overflow at ${width}`) if (output) await page.locator('.recap-preview').screenshot({ path: path.join(output, `recap-preview-${width}.png`) }) await page.getByRole('button', { name: 'Plain text', exact: true }).click() assert.match(await page.locator('.recap-plain-preview').innerText(), /Minutes watched: 1,500/) await page.goto(`${base}/profile`) await page.getByRole('heading', { name: 'Your month, delivered.', exact: true }).waitFor() await page.getByRole('button', { name: 'Email me my monthly recap', exact: true }).waitFor() assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), `Profile overflow at ${width}`) if (output) await page.screenshot({ path: path.join(output, `recap-profile-${width}.png`), fullPage: true }) } await page.getByRole('button', { name: 'Email me my monthly recap', exact: true }).click() await page.getByText('Check your inbox', { exact: true }).waitFor() assert.equal(await page.getByRole('button', { name: 'Send a new confirmation', exact: true }).isDisabled(), true) await page.getByRole('button', { name: 'Cancel subscription', exact: true }).click() await page.getByText('Off', { exact: true }).waitFor() preference = { ...preference, state: 'enabled' } await page.getByRole('button', { name: 'Refresh preference', exact: true }).click() await page.getByText('Subscribed', { exact: true }).waitFor() await page.getByRole('textbox', { name: 'Email address', exact: true }).fill('changed@example.test') await page.getByRole('button', { name: 'Save email', exact: true }).click() await page.getByText('Off', { exact: true }).waitFor() await page.goto(`${base}/admin/recaps`) await page.getByLabel('Day of the month').selectOption('3') await page.getByLabel('Enable scheduled monthly recaps').check() assert.equal(await page.getByRole('button', { name: 'Preview my recap', exact: true }).isDisabled(), true) await page.getByRole('button', { name: 'Save schedule', exact: true }).click() await page.getByText('Schedule running', { exact: true }).waitFor() assert.equal(settings.day, 3) assert.equal(settings.enabled, true) await page.getByRole('button', { name: 'Preview my recap', exact: true }).click() await page.locator('iframe').waitFor() await page.getByRole('button', { name: 'Send test to me', exact: true }).click() await page.getByText('Queued', { exact: true }).waitFor() deliveries = ['sent', 'retry', 'unknown', 'failed', 'cancelled'].map((state, index) => ({ ...deliveries[0], id: `fixture-${index}`, state, attempts: index + 1, detail: state === 'unknown' ? 'Check the mail server.' : 'Fixture delivery result.' })) await page.getByRole('button', { name: 'Refresh history', exact: true }).click() await page.getByText('Needs review', { exact: true }).waitFor() assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'History overflows mobile viewport') assert.match(await page.locator('.recap-history').innerText(), /Automatic retries are stopped/) await page.setViewportSize({ width: 1440, height: 1000 }) if (output) await page.screenshot({ path: path.join(output, 'recap-delivery-history.png'), fullPage: true }) failPreview = true await page.getByRole('button', { name: 'Preview my recap', exact: true }).click() await page.getByRole('alert').filter({ hasText: 'temporarily unavailable' }).waitFor() await context.clearCookies() const token = 'fixture'.repeat(7) tokenState = 'ready' await page.goto(`${base}/email-recaps#action=confirm&token=${token}`) await page.getByRole('button', { name: 'Confirm email recaps', exact: true }).waitFor() assert.equal(calls.filter((call) => call.path === '/api/email-recaps/confirm').length, 0) assert.equal(await page.locator('.header').count(), 0) await page.getByRole('button', { name: 'Confirm email recaps', exact: true }).click() await page.getByRole('heading', { name: 'You’re on the list.', exact: true }).waitFor() assert.equal(new URL(page.url()).hash, '') tokenState = 'ready' await page.setViewportSize({ width: 320, height: 800 }) await page.goto(`${base}/email-recaps#action=unsubscribe&token=${token}`) await page.getByRole('button', { name: 'Unsubscribe from recaps', exact: true }).waitFor() if (output) await page.screenshot({ path: path.join(output, 'recap-unsubscribe-mobile.png'), fullPage: true }) assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'Unsubscribe overflow') await page.getByRole('button', { name: 'Unsubscribe from recaps', exact: true }).click() await page.getByRole('heading', { name: 'Recaps are turned off.', exact: true }).waitFor() await page.goto(`${base}/email-recaps`) await page.getByRole('alert').filter({ hasText: 'incomplete' }).waitFor() role = 'user' await page.goto(`${base}/admin/recaps`) await page.waitForURL(`${base}/`) role = 'unauthorized' await page.goto(`${base}/admin/recaps`) await page.waitForURL(/\/login\?next=/) assert.deepEqual(errors, []) console.log(`Email recap UI passed: desktop/mobile layout, preview isolation, consent, schedule, test queue, history, public links and access control; ${calls.length} intercepted API calls.`) } finally { await browser.close() } })().catch((error) => { console.error(error); process.exitCode = 1 })