diff --git a/e2e/tools-smoke.spec.ts b/e2e/tools-smoke.spec.ts new file mode 100644 index 0000000..0feec5f --- /dev/null +++ b/e2e/tools-smoke.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from '@playwright/test'; +import { tools } from '../src/registry/tools'; + +/** + * Render smoke over EVERY registered tool: each page must return 200, mount its + * island (a visible

), and not throw an uncaught exception. This one spec + * auto-covers all existing tools and every future tool the moment it's added to + * the registry — the cheap safety net beneath the per-tool happy-path specs. + * + * `pageerror` (uncaught JS) is collected but reported as an annotation rather + * than a hard failure, because a few tools legitimately throw on load in a + * headless browser (no WebGPU / camera / mic). The hard signal is: page loads + * and the island hydrates. + */ +const pages = tools.filter(t => !t.desktopOnly).map(t => ({ id: t.id, route: t.route })); + +for (const { id, route } of pages) { + test(`tool page renders: ${id}`, async ({ page }, testInfo) => { + const errors: string[] = []; + page.on('pageerror', e => errors.push(e.message)); + const resp = await page.goto(route); + expect(resp?.ok(), `${route} returned HTTP ${resp?.status()}`).toBeTruthy(); + await expect(page.locator('h1').first()).toBeVisible(); + if (errors.length) testInfo.annotations.push({ type: 'pageerror', description: `${route}: ${errors.join(' | ')}` }); + }); +}