Files
app/smoke-s4-9c.js

61 lines
3.2 KiB
JavaScript

const { chromium } = require('playwright');
const fs = require('fs');
const BASE = process.env.PLAYWRIGHT_BASE_URL || 'http://192.168.0.251:13000';
const EMAIL = process.env.VITE_TEST_TEACHER_EMAIL || '[email protected]';
const PASSWORD = process.env.VITE_TEST_TEACHER_PASSWORD || process.env.SEED_TEACHER_PASSWORD;
const TEMPLATE_ID = process.env.TEMPLATE_ID || '31d92cf3-9bbd-4a7e-b2dc-b37f8b69bc34';
const OUT = process.env.OUT || '/out';
async function run(mode) {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ colorScheme: mode, viewport: { width: 1440, height: 980 } });
const page = await context.newPage();
const messages = [];
page.on('console', msg => messages.push(`${msg.type()}: ${msg.text()}`));
page.on('pageerror', err => messages.push(`pageerror: ${err.message}`));
await page.goto(`${BASE}/login`, { waitUntil: 'domcontentloaded' });
if (await page.getByLabel('Email').count()) {
if (!PASSWORD) throw new Error('missing password env');
await page.getByLabel('Email').fill(EMAIL);
await page.getByLabel('Password').fill(PASSWORD);
await page.getByRole('button', { name: 'Login' }).click();
await page.waitForURL(url => /\/dashboard|\/exam-marker|\/node\//.test(url.pathname), { timeout: 20000 });
}
await page.goto(`${BASE}/exam-marker/${TEMPLATE_ID}/setup`, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-testid="exam-template-setup-canvas"]', { timeout: 20000 });
await page.waitForTimeout(3500);
const text = await page.locator('body').innerText();
const checks = {
hasBoundaryTool: text.includes('Boundary'),
hasPartTool: text.includes('Part'),
hasResponseTool: text.includes('Response'),
hasContextTool: text.includes('Context'),
hasQuestionNumberTool: text.includes('Q Number'),
hasMarkAreaTool: text.includes('Mark Area'),
hasReferenceTool: text.includes('Reference'),
hasFurnitureTool: text.includes('Furniture'),
hasHintPanel: text.includes('Setup guide') && text.includes('Boundary pairing preview'),
hasMultiPageCopy: text.includes('later page') || text.includes('multi-page'),
hasPdfStatus: text.includes('PDF backdrop:'),
crashOverlay: text.includes('Template setup canvas crashed'),
};
await page.screenshot({ path: `${OUT}/s4-9c-${mode}.png`, fullPage: true });
await browser.close();
return { mode, url: `${BASE}/exam-marker/${TEMPLATE_ID}/setup`, checks, consoleMessages: messages };
}
(async () => {
fs.mkdirSync(OUT, { recursive: true });
const results = [];
for (const mode of ['light', 'dark']) results.push(await run(mode));
fs.writeFileSync(`${OUT}/s4-9c-smoke.json`, JSON.stringify(results, null, 2));
const failures = results.flatMap(r => Object.entries(r.checks).filter(([k,v]) => k === 'crashOverlay' ? v : !v).map(([k]) => `${r.mode}:${k}`));
const consoleErrors = results.flatMap(r => r.consoleMessages.filter(m => /^(error|pageerror):/i.test(m) && !/Failed to load resource/i.test(m)));
console.log(JSON.stringify({ results, failures, consoleErrors }, null, 2));
if (failures.length || consoleErrors.length) process.exit(1);
})().catch(err => { console.error(err); process.exit(1); });