Add Playwright E2E suite against the built dist/

Pin @playwright/test 1.62.0 (matches the cached chromium
revision) and serve dist/ via python3 http.server, so the
deployed artifact is what gets tested. Covers page load,
terminal commands, vim mode, achievements, and the nav menu.
Ignore node_modules, test-results, playwright-report, and the
phased-execution runtime scratch (.agents/phase-sessions,
pipeline.log).
This commit is contained in:
2026-09-18 17:23:30 -04:00
parent 7f4f0b4ef1
commit 3898dc3c5e
10 changed files with 682 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
// @ts-check
const { test, expect } = require('@playwright/test');
test.describe('Navigation menu', () => {
test('desktop: inline nav visible, hamburger hidden', async ({ page }) => {
await page.goto('/');
await expect(page.locator('#hamburger')).toBeHidden();
await expect(page.locator('#navLinks')).toBeVisible();
await expect(page.locator('#navLinks a')).toHaveCount(7);
});
test('mobile: hamburger opens and closes the menu', async ({ page }) => {
await page.goto('/');
await page.setViewportSize({ width: 375, height: 812 });
await expect(page.locator('#hamburger')).toBeVisible();
const links = page.locator('#navLinks');
await expect(links).toBeHidden();
await page.locator('#hamburger').click();
await expect(page.locator('#hamburger')).toHaveClass(/active/);
await expect(links).toHaveClass(/active/);
await expect(links).toBeVisible();
// clicking a link closes the menu
await links.locator('a[href="#about"]').click();
await expect(links).not.toHaveClass(/active/);
});
test('clicking outside closes an open mobile menu', async ({ page }) => {
await page.goto('/');
await page.setViewportSize({ width: 375, height: 812 });
await page.locator('#hamburger').click();
await expect(page.locator('#navLinks')).toHaveClass(/active/);
// click a point below the open dropdown (y≈700): outside both the
// nav and the hamburger, so the document-level click handler closes it
await page.mouse.click(187, 700);
await expect(page.locator('#navLinks')).not.toHaveClass(/active/);
});
});