diff --git a/web/scripts/standard-site.test.mjs b/web/scripts/standard-site.test.mjs
--- a/web/scripts/standard-site.test.mjs
+++ b/web/scripts/standard-site.test.mjs
@@ -13,24 +13,30 @@
import { test, after } from "node:test";
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
-import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
+import {
+ existsSync,
+ readFileSync,
+ readdirSync,
+ rmSync,
+ writeFileSync,
+} from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
const web = fileURLToPath(new URL("../", import.meta.url));
const WELL_KNOWN = join(web, "public/.well-known/site.standard.publication");
+const POSTS = join(web, "src/content/blog");
// Nothing resolvable. A DID that looked real would be followed by the first
// person who copied it out of here.
const DOCUMENT = "at://did:plc:example/site.standard.document/fakerkey";
-// No post in src/content/blog has a record, so the published case needs one
-// written for the build and taken away again. Under web/.astro, which is
-// gitignored and already the build's scratch - not os.tmpdir(), because the
-// last thing a build does is rename its output into place and a rename across
-// filesystems is EXDEV.
-const SLUG = "fixture-borborygmus";
-const fixture = join(web, "src/content/blog", `${SLUG}.md`);
+// A post that has been published, which the tree may or may not have one of on
+// any given day. Written for the build and taken away again. Under web/.astro,
+// which is gitignored and already the build's scratch - not os.tmpdir(),
+// because the last thing a build does is rename its output into place and a
+// rename across filesystems is EXDEV.
+const fixture = join(POSTS, "fixture-borborygmus.md");
const outDir = join(web, ".astro/standard-site");
writeFileSync(
@@ -45,6 +51,21 @@
Borborygmus quincunx widdershins.
`,
);
+
+// Which posts claim a record, read while the fixture is still on disk. Slugs
+// are filenames, which is what Astro's glob loader makes its ids from. Sequoia
+// writes the value quoted, so the quotes come off.
+const published = new Map(
+ readdirSync(POSTS)
+ .filter((file) => file.endsWith(".md"))
+ .map((file) => [
+ file.replace(/\.md$/, ""),
+ /^atUri:\s*["']?(at:\/\/\S+?)["']?\s*$/m.exec(
+ readFileSync(join(POSTS, file), "utf8"),
+ )?.[1],
+ ]),
+);
+
try {
execFileSync(
join(web, "node_modules/.bin/astro"),
@@ -60,20 +81,28 @@
after(() => rmSync(outDir, { recursive: true, force: true }));
-const page = (path) => readFileSync(join(outDir, path, "index.html"), "utf8");
+test("a post links to its record, and only if it has one", () => {
+ const built = readdirSync(join(outDir, "blog"), { withFileTypes: true })
+ .filter((entry) => entry.isDirectory())
+ .map((entry) => entry.name);
+ assert.ok(built.length > 1, "the fixture and at least one post should build");
-test("a post with atUri links to its record", () => {
- assert.match(
- page(`blog/${SLUG}`),
- new RegExp(` {
- assert.ok(
- !page("blog/placeholder-borborygmus").includes("site.standard.document"),
- "an unpublished post rendered a document link",
- );
+ for (const slug of built) {
+ const html = readFileSync(join(outDir, "blog", slug, "index.html"), "utf8");
+ const atUri = published.get(slug);
+ if (atUri) {
+ assert.match(
+ html,
+ new RegExp(` {
@@ -82,11 +111,13 @@
// edited by hand, and the symptom is a publication nobody can verify.
if (!existsSync(WELL_KNOWN)) return;
- const body = readFileSync(WELL_KNOWN, "utf8");
+ // Trimmed: the end-of-file-fixer hook adds a newline to every file in the
+ // repo, this one included, so the bytes on disk are never exactly the URI.
+ const body = readFileSync(WELL_KNOWN, "utf8").trim();
assert.match(
body,
- /^at:\/\/did:[^\s]+\/site\.standard\.publication\/[^\s]+$/,
- "the key must be one AT-URI, with no trailing newline",
+ /^at:\/\/did:\S+\/site\.standard\.publication\/\S+$/,
+ "the key must be one AT-URI and nothing else",
);
assert.equal(
body,