website
git clone https://git.pyrossh.dev/website
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
tests/pages.test.js
import { after, before, describe, test } from "node:test";
import assert from "node:assert/strict";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { chromium } from "playwright";
import { startStaticServer } from "./helpers/static-server.js";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const distDir = path.join(__dirname, "..", "dist");
let server;
let browser;
let page;
const consoleErrors = [];
before(async () => {
server = await startStaticServer(distDir);
browser = await chromium.launch();
page = await browser.newPage();
page.on("console", (msg) => {
if (msg.type() === "error") consoleErrors.push(`[${page.url()}] ${msg.text()}`);
});
page.on("pageerror", (err) => {
consoleErrors.push(`[${page.url()}] ${err.message}`);
});
});
after(async () => {
await browser?.close();
await server?.close();
});
async function goto(urlPath) {
const response = await page.goto(`${server.url}${urlPath}`, { waitUntil: "domcontentloaded" });
return response;
}
describe("static pages", () => {
test("home page renders", async () => {
const response = await goto("/");
assert.equal(response.status(), 200);
await assert.doesNotReject(page.locator("h1.title").waitFor());
assert.match(await page.title(), /pyrossh/);
});
test("cv page renders", async () => {
const response = await goto("/cv/");
assert.equal(response.status(), 200);
await assert.doesNotReject(page.locator("h1").waitFor());
assert.equal(await page.locator("img[alt='Resume']").count(), 1);
});
test("posts index lists posts", async () => {
const response = await goto("/posts/");
assert.equal(response.status(), 200);
const links = page.locator("main a[href^='/posts/']");
assert.ok((await links.count()) > 0, "expected at least one post link");
});
test("a post page renders", async () => {
const response = await goto("/posts/react-powertools-swr/");
assert.equal(response.status(), 200);
assert.match(await page.title(), /React Powertools/);
});
test("only-bible-app pages render", async () => {
for (const url of ["/only-bible-app/", "/only-bible-app/privacy-policy/", "/only-bible-app/terms-and-conditions/"]) {
const response = await goto(url);
assert.equal(response.status(), 200, `expected 200 for ${url}`);
}
});
test("robots.txt and rss.xml are served", async () => {
const robots = await goto("/robots.txt");
assert.equal(robots.status(), 200);
assert.match(await page.content(), /User-agent/);
const rss = await goto("/rss.xml");
assert.equal(rss.status(), 200);
});
test("unknown route returns the 404 page", async () => {
const response = await goto("/this-page-does-not-exist/");
assert.equal(response.status(), 404);
assert.match(await page.locator("h1").textContent(), /404/);
});
});
describe("repo pages", () => {
const repoId = "website";
test("repo readme page renders", async () => {
const response = await goto(`/repos/${repoId}/`);
assert.equal(response.status(), 200);
await assert.doesNotReject(page.locator(".repo .header h1").waitFor());
assert.equal(await page.locator(".nav a.active-tab").textContent(), "Readme");
});
test("repo commits page lists commits", async () => {
const response = await goto(`/repos/${repoId}/commits/`);
assert.equal(response.status(), 200);
const commitLinks = page.locator(`a[href^='/repos/${repoId}/commits/']`);
assert.ok((await commitLinks.count()) > 0, "expected at least one commit link");
});
test("a single commit page renders", async () => {
await goto(`/repos/${repoId}/commits/`);
const firstCommitHref = await page.locator(`a[href^='/repos/${repoId}/commits/']`).first().getAttribute("href");
const response = await goto(firstCommitHref);
assert.equal(response.status(), 200);
assert.equal(await page.locator(".nav a.active-tab").textContent(), "Commits");
});
test("repo files index renders the tree and a default file", async () => {
const response = await goto(`/repos/${repoId}/files/`);
assert.equal(response.status(), 200);
assert.ok((await page.locator(".file-explorer-tree").count()) > 0);
});
test("a specific file, its history and blame views render", async () => {
const filePath = "eleventy.config.js";
const fileRes = await goto(`/repos/${repoId}/files/${filePath}/`);
assert.equal(fileRes.status(), 200);
const historyRes = await goto(`/repos/${repoId}/files/${filePath}/history/`);
assert.equal(historyRes.status(), 200);
const blameRes = await goto(`/repos/${repoId}/files/${filePath}/blame/`);
assert.equal(blameRes.status(), 200);
});
test("repo nav tabs swap content via htmx without a full reload", async () => {
await goto(`/repos/${repoId}/`);
await page.click(".nav a[href='/repos/website/files/']");
await page.waitForURL(`${server.url}/repos/${repoId}/files/`);
assert.equal(await page.locator(".nav a.active-tab").textContent(), "Code");
});
});
test("no unexpected console errors were logged across visited pages", () => {
// The deliberate 404 test above triggers a browser-level "failed to load
// resource" console entry for its own navigation request — that's the
// behavior under test there, not a bug, so it's excluded here.
const unexpected = consoleErrors.filter((msg) => !msg.includes("this-page-does-not-exist"));
assert.deepEqual(unexpected, []);
});