@@ -36,39 +36,69 @@ action:
3636
3737 ## Step 3 — Run smoke tests
3838
39- Write a Playwright script to /tmp/smoke-test.mjs:
39+ Write a Playwright script to /tmp/smoke-test.mjs.
40+
41+ The script must only test routes that exist. Before testing a route, do a HEAD
42+ request first — if it returns 404, skip that check (do not count it as a failure).
43+
44+ Test user credentials are available as env vars:
45+ TEST_USER_EMAIL, TEST_USER_PASSWORD
46+ Use these for any authenticated flows (e.g., login, dashboard access).
4047
4148 ```js
4249 import { chromium } from 'playwright';
4350
4451 const BASE = 'https://memo.software-factory.dev';
4552 const failures = [];
53+ const skipped = [];
4654 const browser = await chromium.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
4755 const page = await browser.newPage();
4856 const consoleErrors = [];
4957 page.on('console', m => { if (m.type() === 'error') consoleErrors.push(m.text()); });
5058
51- // 1. Landing page
59+ // Helper: check if a route exists before testing it
60+ async function routeExists(path) {
61+ try {
62+ const res = await fetch(BASE + path, { method: 'HEAD', redirect: 'manual' });
63+ return res.status !== 404;
64+ } catch { return false; }
65+ }
66+
67+ // 1. Landing page (always exists)
5268 const res = await page.goto(BASE, { waitUntil: 'networkidle', timeout: 15000 });
5369 if (!res || res.status() >= 400) failures.push('Landing page returned ' + (res?.status() ?? 'no response'));
5470 const title = await page.title();
5571 if (!title) failures.push('Landing page has no title');
5672
57- // 2. Login page renders
58- await page.goto(BASE + '/login', { waitUntil: 'networkidle', timeout: 15000 });
59- const hasEmailInput = await page.locator('input[type=email]').count();
60- if (!hasEmailInput) failures.push('Login page missing email input');
73+ // 2. Login page (skip if not yet built)
74+ if (await routeExists('/login')) {
75+ await page.goto(BASE + '/login', { waitUntil: 'networkidle', timeout: 15000 });
76+ const hasEmailInput = await page.locator('input[type=email]').count();
77+ if (!hasEmailInput) failures.push('Login page missing email input');
78+ } else {
79+ skipped.push('/login (not yet built)');
80+ }
6181
6282 // 3. Health endpoint
6383 const healthRes = await page.goto(BASE + '/api/health', { waitUntil: 'networkidle', timeout: 10000 });
6484 const healthBody = await page.textContent('body');
6585 if (!healthRes || healthRes.status() >= 400) failures.push('Health endpoint returned ' + (healthRes?.status() ?? 'no response'));
6686 if (healthBody && healthBody.includes('"status":"down"')) failures.push('Health endpoint reports down');
6787
68- // 4. Console errors
88+ // 4. Dashboard (skip if not yet built — requires auth)
89+ if (await routeExists('/dashboard')) {
90+ const dashRes = await page.goto(BASE + '/dashboard', { waitUntil: 'networkidle', timeout: 15000 });
91+ // Unauthenticated should redirect to /login, not 500
92+ if (dashRes && dashRes.status() >= 500) failures.push('Dashboard returned ' + dashRes.status());
93+ } else {
94+ skipped.push('/dashboard (not yet built)');
95+ }
96+
97+ // 5. Console errors
6998 if (consoleErrors.length) failures.push('Console errors: ' + consoleErrors.slice(0, 5).join('; '));
7099
71100 await browser.close();
101+ if (skipped.length) console.log('Skipped: ' + skipped.join(', '));
72102 if (failures.length) { console.error(JSON.stringify(failures)); process.exit(1); }
73103 console.log('OK');
74104 ```
@@ -82,7 +112,7 @@ action:
82112
83113 If all checks pass:
84114 Comment on the merged PR:
85- > ✅ Post-merge verification passed — landing page, login, and health endpoint all working.
115+ > ✅ Post-merge verification passed. [list which routes were tested and which were skipped]
86116
87117 If any check fails:
88118 1. Create a GitHub Issue:
@@ -94,12 +124,11 @@ action:
94124
95125 ## Expanding checks
96126
97- As features ship, add checks to the Playwright script. Only check features that exist:
98- - After workspace/page CRUD ships: verify /dashboard loads (unauthenticated → redirects to /login)
99- - After editor ships: verify a page URL returns 200
100- - After search ships: verify the search endpoint responds
127+ As features ship, add new route checks to the Playwright script. Always use the
128+ `routeExists()` guard so the script doesn't fail on routes that haven't been built yet.
101129
102- Do NOT test flows that require authentication credentials.
130+ Test user credentials for authenticated flows:
131+ TEST_USER_EMAIL, TEST_USER_PASSWORD (available as env vars)
103132
104133 ## Do NOT
105134 - Retry failed checks — report the failure and stop.
0 commit comments