- playwright.config.ts: desktop (1440) + mobile (Pixel 5) projects, static webServer over the exported out/; a PW_CHROME env override for the browser - tests/e2e: render + all core sections, tracked download hrefs with no R2 exposure, the live counter (mocked function), theme toggle, image loading, zero console errors, and responsive nav (desktop links / mobile menu reveal) - navbar: hide the closed mobile menu with `invisible` so its links stay out of the tab order and the accessibility tree, not merely clipped - add the test:e2e script and ignore test-results/ + playwright-report/
58 lines
1.9 KiB
JavaScript
58 lines
1.9 KiB
JavaScript
import { createServer } from "node:http";
|
|
import { readFile, stat } from "node:fs/promises";
|
|
import { extname, join, normalize } from "node:path";
|
|
|
|
// Minimal static server for the exported `out/` directory, used by the e2e
|
|
// suite. Cloudflare Pages Functions are not served here; tests that need
|
|
// `/api/*` mock those routes in the browser.
|
|
|
|
const root = process.argv[2] ?? "out";
|
|
const port = Number(process.argv[3] ?? 4319);
|
|
|
|
const contentTypes = {
|
|
".html": "text/html; charset=utf-8",
|
|
".css": "text/css; charset=utf-8",
|
|
".js": "text/javascript; charset=utf-8",
|
|
".json": "application/json; charset=utf-8",
|
|
".webp": "image/webp",
|
|
".png": "image/png",
|
|
".jpg": "image/jpeg",
|
|
".jpeg": "image/jpeg",
|
|
".svg": "image/svg+xml",
|
|
".ico": "image/x-icon",
|
|
".woff2": "font/woff2",
|
|
".txt": "text/plain; charset=utf-8",
|
|
".xml": "application/xml; charset=utf-8",
|
|
};
|
|
|
|
async function resolvePath(pathname) {
|
|
const clean = normalize(decodeURIComponent(pathname)).replace(/^(\.\.[/\\])+/, "");
|
|
let filePath = join(root, clean);
|
|
try {
|
|
const info = await stat(filePath);
|
|
if (info.isDirectory()) filePath = join(filePath, "index.html");
|
|
} catch {
|
|
if (!extname(filePath)) filePath += ".html";
|
|
}
|
|
return filePath;
|
|
}
|
|
|
|
createServer(async (request, response) => {
|
|
try {
|
|
const url = new URL(request.url, `http://127.0.0.1:${port}`);
|
|
const filePath = await resolvePath(url.pathname);
|
|
const body = await readFile(filePath);
|
|
response.writeHead(200, { "Content-Type": contentTypes[extname(filePath)] ?? "application/octet-stream" });
|
|
response.end(body);
|
|
} catch {
|
|
try {
|
|
const notFound = await readFile(join(root, "404.html"));
|
|
response.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
response.end(notFound);
|
|
} catch {
|
|
response.writeHead(404);
|
|
response.end("Not found");
|
|
}
|
|
}
|
|
}).listen(port, "127.0.0.1", () => console.log(`serving ${root} at http://127.0.0.1:${port}`));
|