diff --git a/tests/rendered-html.test.mjs b/tests/rendered-html.test.mjs
index 11ec629..6337b89 100644
--- a/tests/rendered-html.test.mjs
+++ b/tests/rendered-html.test.mjs
@@ -1,91 +1,89 @@
import assert from "node:assert/strict";
-import { access, readFile, readdir } from "node:fs/promises";
+import { access } from "node:fs/promises";
import test from "node:test";
-const developmentPreviewMeta =
- /]*\bname=["']codex-preview["'])(?=[^>]*\bcontent=["']development["'])[^>]*>/i;
const templateRoot = new URL("../", import.meta.url);
-const previewRoot = new URL("../app/_sites-preview/", import.meta.url);
-async function render() {
+/**
+ * Renders the built worker the way the platform does. The query string keeps
+ * each `import()` distinct so tests do not share a module instance.
+ */
+async function render(path = "/") {
const workerUrl = new URL("../dist/server/index.js", import.meta.url);
workerUrl.searchParams.set("test", `${process.pid}-${Date.now()}`);
const { default: worker } = await import(workerUrl.href);
return worker.fetch(
- new Request("http://localhost/", {
- headers: { accept: "text/html" },
- }),
- {
- ASSETS: {
- fetch: async () => new Response("Not found", { status: 404 }),
- },
- },
- {
- waitUntil() {},
- passThroughOnException() {},
- },
+ new Request(`http://localhost${path}`, { headers: { accept: "text/html" } }),
+ { ASSETS: { fetch: async () => new Response("Not found", { status: 404 }) } },
+ { waitUntil() {}, passThroughOnException() {} },
);
}
-test("server-renders the starter loading skeleton", async () => {
+let cached;
+async function html() {
+ cached ??= await render().then((response) => response.text());
+ return cached;
+}
+
+test("serves the document", async () => {
const response = await render();
assert.equal(response.status, 200);
assert.match(response.headers.get("content-type") ?? "", /^text\/html\b/i);
-
- const html = await response.text();
- assert.match(html, developmentPreviewMeta);
- assert.match(html, /
Your site is taking shape<\/title>/i);
- assert.match(html, /Building your site/);
- assert.match(html, /Your site is taking shape/);
- assert.match(
- html,
- /Your first version will appear here automatically when it’s ready\./,
- );
- assert.doesNotMatch(html, /Codex/);
- assert.match(html, /react-loading-skeleton/);
- assert.match(html, /role="status"/);
});
-test("keeps the loading skeleton scoped and disposable", async () => {
- const [preview, css, page, layout, packageJson, files] = await Promise.all([
- readFile(new URL("SkeletonPreview.tsx", previewRoot), "utf8"),
- readFile(new URL("preview.css", previewRoot), "utf8"),
- readFile(new URL("../app/page.tsx", import.meta.url), "utf8"),
- readFile(new URL("../app/layout.tsx", import.meta.url), "utf8"),
- readFile(new URL("../package.json", import.meta.url), "utf8"),
- readdir(previewRoot),
- ]);
+test("renders the page identity and its social metadata", async () => {
+ const page = await html();
+ assert.match(page, /Anatomy Atelier — Learn anatomy like an artist<\/title>/);
+ assert.match(page, / {
+ const page = await html();
+ assert.match(page, /Organ library/);
+ for (const organ of ["Heart", "Brain", "Lungs", "Liver", "Kidneys", "Eye", "Intestine", "Pancreas", "Skin"]) {
+ assert.ok(page.includes(`>${organ}<`), `organ library is missing ${organ}`);
+ }
+});
- const shellIndex = preview.indexOf('className="sites-skeleton-shell"');
- const statusIndex = preview.indexOf('className="sites-skeleton-status"');
- assert.ok(shellIndex >= 0 && statusIndex > shellIndex);
- assert.match(css, /position:\s*fixed/);
- assert.match(css, /inset:\s*0/);
- assert.match(css, /opacity:\s*0\.52/);
- assert.match(css, /prefers-reduced-motion:\s*reduce/);
- assert.doesNotMatch(css, /#020617|canvas|pets|progress/i);
- assert.doesNotMatch(
- preview,
- /loading-spinner|status-mark|status-progress|canvas|cookie|random/i,
- );
+test("server-renders the selected organ rather than an empty shell", async () => {
+ const page = await html();
+ // Heart is the default selection: name, scientific name, poetic line, the
+ // tissue and a clinical note all come from anatomy-data.
+ assert.match(page, /The tireless pump/);
+ assert.match(page, /Cardiovascular/);
+ assert.match(page, /Cor/);
+ assert.match(page, /Cardiac muscle tissue/);
+ assert.match(page, /Coronary artery disease/);
+ assert.match(page, /anatomy\/heart\/thumb\.webp/);
+});
- assert.match(page, /export const metadata:\s*Metadata/);
- assert.match(page, /"codex-preview": "development"/);
- assert.match(page, //);
- assert.match(layout, /title:\s*"Starter Project"/);
- assert.doesNotMatch(layout, /codex-preview|_sites-preview|themeColor|\bViewport\b/);
- assert.doesNotMatch(css, /(^|\s)(html|body)\s*\{/m);
+test("ships the viewer mount and a text equivalent for its hotspots", async () => {
+ const page = await html();
+ // The canvas is created on the client, so the server must at least emit the
+ // mount and the labelled controls around it.
+ assert.match(page, /three-mount/);
+ assert.match(page, /viewer-tools/);
+ assert.match(page, /aria-label/);
+ // Hotspot dots live inside the canvas; this list is their accessible
+ // equivalent and has to be in the server output to be of any use.
+ assert.match(page, /hotspot-index/);
+ assert.match(page, /Aorta/);
+ assert.match(page, /Left Atrium/);
+});
- await assert.rejects(
- access(new URL("public/_sites-preview", templateRoot)),
- );
+test("carries no trace of the vinext starter it was scaffolded from", async () => {
+ const page = await html();
+ for (const leftover of [
+ "react-loading-skeleton",
+ "Your site is taking shape",
+ "Starter Project",
+ "codex-preview",
+ ]) {
+ assert.ok(!page.includes(leftover), `starter leftover in rendered output: ${leftover}`);
+ }
+ await assert.rejects(access(new URL("app/_sites-preview", templateRoot)));
+ await assert.rejects(access(new URL("public/_sites-preview", templateRoot)));
});