chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:18 +08:00
commit 6d5d58c1a9
18293 changed files with 3502153 additions and 0 deletions
@@ -0,0 +1,206 @@
import { describe, expect, it } from "vitest";
import {
buildResultArtifactName,
mergeBuildResultFiles,
parseBuildOutputs,
shouldRedeployStaging,
successSet,
} from "../build-outputs";
import type { BuildOutcome, ServiceBuildResult } from "../build-outputs";
const sample: ServiceBuildResult[] = [
{ service: "showcase-mastra", status: "success" },
{ service: "showcase-ag2", status: "failure" },
{ service: "shell-docs", status: "skipped" },
{ service: "showcase-aimock", status: "success" },
];
describe("build-outputs", () => {
it("parses a JSON array of {service,status} entries", () => {
const json = JSON.stringify(sample);
expect(parseBuildOutputs(json)).toEqual(sample);
});
it("throws on malformed JSON", () => {
expect(() => parseBuildOutputs("not json")).toThrow(/parse/i);
});
it("throws on entries missing fields", () => {
expect(() => parseBuildOutputs(JSON.stringify([{ service: "x" }]))).toThrow(
/status/i,
);
});
it("throws on an unknown status value", () => {
const bad = JSON.stringify([{ service: "x", status: "weird" }]);
expect(() => parseBuildOutputs(bad)).toThrow(/status/i);
});
it("rejects an empty service string", () => {
const bad = JSON.stringify([{ service: "", status: "success" }]);
expect(() => parseBuildOutputs(bad)).toThrow(/service/i);
});
it("rejects a whitespace-only service string", () => {
const bad = JSON.stringify([{ service: " ", status: "success" }]);
expect(() => parseBuildOutputs(bad)).toThrow(/service/i);
});
it("error message for parseBuildOutputs includes the entry index", () => {
const bad = JSON.stringify([
{ service: "ok", status: "success" },
{ service: "x", status: "weird" },
]);
expect(() => parseBuildOutputs(bad)).toThrow(/\[1\]/);
});
it("successSet returns only services with status === 'success'", () => {
expect(successSet(sample).sort()).toEqual(
["showcase-aimock", "showcase-mastra"].sort(),
);
});
it("successSet returns empty when no services succeeded", () => {
const allFailed: ServiceBuildResult[] = [
{ service: "a", status: "failure" },
{ service: "b", status: "failure" },
];
expect(successSet(allFailed)).toEqual([]);
});
it("type BuildOutcome enumerates success|failure|skipped", () => {
const outcomes: BuildOutcome[] = ["success", "failure", "skipped"];
expect(outcomes).toHaveLength(3);
});
});
describe("buildResultArtifactName", () => {
it("returns the canonical per-slot artifact name", () => {
expect(buildResultArtifactName("showcase-aimock")).toBe(
"build-result-showcase-aimock",
);
});
it("rejects empty service names (would collide with aggregate artifact)", () => {
expect(() => buildResultArtifactName("")).toThrow(/service/i);
});
it("rejects whitespace-only service names", () => {
expect(() => buildResultArtifactName(" ")).toThrow(/service/i);
});
});
describe("mergeBuildResultFiles", () => {
it("merges per-slot {service,status} JSON payloads into a single array", () => {
const slotPayloads = [
'{"service":"showcase-mastra","status":"success"}',
'{"service":"showcase-ag2","status":"failure"}',
'{"service":"showcase-aimock","status":"success"}',
];
expect(mergeBuildResultFiles(slotPayloads)).toEqual([
{ service: "showcase-mastra", status: "success" },
{ service: "showcase-ag2", status: "failure" },
{ service: "showcase-aimock", status: "success" },
]);
});
it("throws when a slot payload is missing service or status", () => {
expect(() => mergeBuildResultFiles(['{"service":"x"}'])).toThrow(/status/i);
});
it("throws on an invalid status value", () => {
expect(() =>
mergeBuildResultFiles(['{"service":"x","status":"weird"}']),
).toThrow(/status/i);
});
it("returns an empty array when no slot payloads are provided", () => {
expect(mergeBuildResultFiles([])).toEqual([]);
});
it("rejects an empty service in a slot payload", () => {
expect(() =>
mergeBuildResultFiles(['{"service":"","status":"success"}']),
).toThrow(/service/i);
});
it("rejects a whitespace-only service in a slot payload", () => {
expect(() =>
mergeBuildResultFiles(['{"service":" ","status":"success"}']),
).toThrow(/service/i);
});
it("throws when duplicate service names appear across slot payloads", () => {
const slotPayloads = [
'{"service":"dup","status":"failure"}',
'{"service":"other","status":"success"}',
'{"service":"dup","status":"success"}',
];
expect(() => mergeBuildResultFiles(slotPayloads)).toThrow(/duplicate/i);
expect(() => mergeBuildResultFiles(slotPayloads)).toThrow(/dup/);
});
it("normalizes trailing whitespace in service to its trimmed canonical form", () => {
const result = mergeBuildResultFiles([
'{"service":"foo ","status":"success"}',
]);
expect(result).toEqual([{ service: "foo", status: "success" }]);
});
it("normalizes leading whitespace in service to its trimmed canonical form", () => {
const result = mergeBuildResultFiles([
'{"service":" foo","status":"success"}',
]);
expect(result).toEqual([{ service: "foo", status: "success" }]);
});
it("parseBuildOutputs also returns the trimmed canonical service", () => {
const json = JSON.stringify([{ service: " bar ", status: "success" }]);
expect(parseBuildOutputs(json)).toEqual([
{ service: "bar", status: "success" },
]);
});
it("detects duplicates that differ only by surrounding whitespace", () => {
const slotPayloads = [
'{"service":"foo","status":"failure"}',
'{"service":"foo ","status":"success"}',
];
expect(() => mergeBuildResultFiles(slotPayloads)).toThrow(/duplicate/i);
expect(() => mergeBuildResultFiles(slotPayloads)).toThrow(/foo/);
});
it("rejects an array payload with a clear 'expected object' error (not 'missing service')", () => {
expect(() => mergeBuildResultFiles(["[]"])).toThrow(/expected object/i);
expect(() => mergeBuildResultFiles(["[]"])).not.toThrow(/missing/i);
});
it("parseBuildOutputs rejects an array nested as an entry with 'expected object'", () => {
const bad = JSON.stringify([[]]);
expect(() => parseBuildOutputs(bad)).toThrow(/expected object/i);
});
});
describe("shouldRedeployStaging", () => {
it("returns true when at least one service succeeded", () => {
expect(
shouldRedeployStaging([
{ service: "a", status: "success" },
{ service: "b", status: "failure" },
]),
).toBe(true);
});
it("returns false when every service failed or was skipped", () => {
expect(
shouldRedeployStaging([
{ service: "a", status: "failure" },
{ service: "b", status: "skipped" },
]),
).toBe(false);
});
it("returns false on empty input", () => {
expect(shouldRedeployStaging([])).toBe(false);
});
});
@@ -0,0 +1,719 @@
/**
* Tests for showcase/scripts/lib/manifest.ts.
*
* parseManifest is the single source of truth for reading and shape-validating
* manifest.yaml. Tests pin the tagged-union return shape that the consumers
* (audit.ts / validate-parity.ts / capture-previews.ts) rely on.
*/
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import fs from "fs";
import os from "os";
import path from "path";
import { parseManifest, createDemoId, type DemoId } from "../manifest.js";
// chmod-enforcement probe so tests that rely on EACCES can be cleanly
// skipped on CI runners that ignore chmod (running as root, certain
// network mounts). Mirrors the probe in validate-pins.test.ts.
const isRoot = process.getuid?.() === 0;
function probeChmodEnforced(): boolean {
if (isRoot) return false;
let probe: string | undefined;
try {
probe = fs.mkdtempSync(path.join(os.tmpdir(), "lib-manifest-chmod-probe-"));
fs.chmodSync(probe, 0o000);
try {
fs.readdirSync(probe);
return false;
} catch (e) {
const err = e as NodeJS.ErrnoException;
return err.code === "EACCES";
}
} catch {
return false;
} finally {
if (probe) {
try {
fs.chmodSync(probe, 0o755);
} catch {
// best-effort restore
}
try {
fs.rmSync(probe, { recursive: true, force: true });
} catch {
// best-effort
}
}
}
}
const chmodEnforced = probeChmodEnforced();
const cannotEnforceEacces = isRoot || !chmodEnforced;
function tmpdir(prefix = "lib-manifest-"): string {
return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
}
function write(file: string, body: string): void {
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, body, "utf-8");
}
describe("parseManifest", () => {
let root: string;
beforeEach(() => {
root = tmpdir();
});
afterEach(() => {
fs.rmSync(root, { recursive: true, force: true });
});
it("returns {kind:'missing'} when the file does not exist", () => {
const r = parseManifest(path.join(root, "does-not-exist.yaml"));
expect(r.kind).toBe("missing");
});
it("returns {kind:'malformed', subkind:'shape'} for an empty file (yaml.parse → null)", () => {
// Empty YAML parses to null, which is not a valid manifest mapping. The
// guard must reject it before callers try to read .demos / .deployed.
// This is a SHAPE error (YAML parsed, result was null), not a syntax
// error.
const f = path.join(root, "manifest.yaml");
write(f, "");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error.length).toBeGreaterThan(0);
}
});
it("returns {kind:'malformed', subkind:'shape'} for a non-object YAML (bare scalar)", () => {
const f = path.join(root, "manifest.yaml");
write(f, "42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
}
});
it("returns {kind:'malformed', subkind:'shape'} for an array at top level", () => {
const f = path.join(root, "manifest.yaml");
write(f, "- a\n- b\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
}
});
it("returns {kind:'malformed', subkind:'syntax'} for a syntactically broken YAML", () => {
// Subkind discriminator separates YAML parser failures (syntax) from
// post-parse shape-mismatch failures (shape). CI can route these
// differently — a syntax error is almost always a typo; a shape error
// points at a schema-drift issue.
const f = path.join(root, "manifest.yaml");
write(f, "demos: [[[\nunterminated\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("syntax");
}
});
it("returns {kind:'malformed', subkind:'shape'} when slug is missing", () => {
// slug is required — every consumer (audit.ts / validate-parity.ts /
// capture-previews.ts) relies on it. Missing slug = unconditional bug.
const f = path.join(root, "manifest.yaml");
write(f, "name: My Pkg\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/slug/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when slug is not a string", () => {
// YAML `slug: 42` parses to a number; the `as Manifest` cast would
// previously have let the number propagate. parseManifest must reject.
const f = path.join(root, "manifest.yaml");
write(f, "slug: 42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/slug/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when slug is the empty string", () => {
const f = path.join(root, "manifest.yaml");
write(f, 'slug: ""\n');
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
}
});
it("returns {kind:'malformed', subkind:'shape'} when name is present but not a string", () => {
// name is optional but, if present, must be a string. Previously the
// `as Manifest` cast would have let a number through silently.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\nname: 42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/name/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos is not an array", () => {
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos: not-array\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/demos/i);
}
});
it("accepts {kind:'ok'} when demos is explicitly null (treated as omitted)", () => {
// `demos: ~` (YAML explicit null) is semantically equivalent to
// "demos omitted" — the current implementation short-circuits on
// `obj.demos != null` so both null and undefined are allowed. This
// test locks in that behavior. Prior to the simplification, the code
// path guarded on `obj.demos !== undefined` which meant YAML's null
// hit the non-array branch and reported "expected array, got object"
// (because `typeof null === "object"`) — a confusing message.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos: ~\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
});
it("reports non-nullish non-array demos with precise type (number, not 'object')", () => {
// describeType special-cases null/array so the error message is
// correct for the JS footgun where `typeof null === "object"` and
// `typeof [] === "object"`. Here a number should say "got number".
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos: 42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.error).toMatch(/got number/);
}
});
it("returns {kind:'malformed', subkind:'shape'} when a demo entry lacks a string id", () => {
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - noid: true\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/id/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when deployed is present but not a boolean", () => {
const f = path.join(root, "manifest.yaml");
write(f, 'slug: x\ndeployed: "yes"\n');
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/deployed/i);
}
});
it("returns {kind:'ok', manifest} for a valid manifest", () => {
const f = path.join(root, "manifest.yaml");
write(
f,
"slug: mypkg\nname: My Pkg\ndeployed: true\ndemos:\n - id: foo\n name: Foo\n - id: bar\n",
);
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
expect(r.manifest.slug).toBe("mypkg");
expect(r.manifest.name).toBe("My Pkg");
expect(r.manifest.deployed).toBe(true);
expect(r.manifest.demos?.length).toBe(2);
expect(r.manifest.demos?.[0].id).toBe("foo");
}
});
it("returns {kind:'ok', manifest} with deployed:false preserved", () => {
// Symmetric to the deployed:true positive test above. `deployed: false`
// is a legal boolean and must parse as {kind:"ok"} with the flag
// preserved, not collapsed into undefined. The strict boolean guard
// rejects stringly-typed "no", "false", etc., but a real boolean false
// must round-trip cleanly.
const f = path.join(root, "manifest.yaml");
write(f, "slug: mypkg\ndeployed: false\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
expect(r.manifest.slug).toBe("mypkg");
expect(r.manifest.deployed).toBe(false);
}
});
it("returns {kind:'ok'} with an empty demos array when demos is omitted", () => {
// `demos` is always set by parseManifest: empty readonly
// array when the manifest omits the field, so callers can iterate
// without `?.` chaining. The old optional-undefined shape is gone.
const f = path.join(root, "manifest.yaml");
write(f, "slug: mypkg\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
expect(r.manifest.demos).toEqual([]);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i] is null", () => {
// YAML `demos: [~]` parses to `[null]`. The per-entry object guard must
// reject this as shape-malformed rather than crashing on `d.id` later.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - ~\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/demos\[0\].*null/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i] is a scalar", () => {
// YAML `demos: [42]` parses to `[42]`. The per-entry object guard must
// describe the concrete scalar type in the error (not "object").
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - 42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/demos\[0\].*number/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i].id is an empty string", () => {
// Empty ids would round-trip as valid strings but make downstream
// demo-path construction (`integrations/<slug>/src/app/demos/<id>`) collapse
// onto the demos dir itself. Reject at validation time.
const f = path.join(root, "manifest.yaml");
write(f, 'slug: x\ndemos:\n - id: ""\n');
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/demos\[0\]\.id.*non-empty/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} on duplicate demo ids", () => {
// Two demos with the same id used to silently propagate — audit.ts
// would build two missing-demo-dir anomalies for the same path and
// validate-parity.ts would double-count coverage. Reject up-front.
const f = path.join(root, "manifest.yaml");
write(
f,
"slug: x\ndemos:\n - id: agentic-chat\n - id: human-in-the-loop\n - id: agentic-chat\n",
);
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/duplicate demo id.*agentic-chat/i);
}
});
it("verifies manifest.slug matches the expected dir slug", () => {
// parseManifest accepts an optional `dirSlug` parameter so callers
// that derive filePath from a slug can detect drift between the
// manifest's declared slug and the directory that holds it (copy/
// paste error, rename-without-updating). Catch at the parser so
// downstream tools don't silently apply the wrong slug.
const f = path.join(root, "manifest.yaml");
write(f, "slug: bar-pkg\n");
const r = parseManifest(f, "foo-pkg");
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/slug.*mismatch|mismatch.*slug/i);
expect(r.error).toContain("foo-pkg");
expect(r.error).toContain("bar-pkg");
}
});
it("accepts a manifest where the declared slug matches dirSlug", () => {
// Positive case for the slug-mismatch check: matching slug and
// dirSlug should still return {kind:'ok'}.
const f = path.join(root, "manifest.yaml");
write(f, "slug: mypkg\n");
const r = parseManifest(f, "mypkg");
expect(r.kind).toBe("ok");
});
it("skips the slug-mismatch check when dirSlug is omitted (backwards-compatible)", () => {
// Callers that don't operate against the packages tree (test
// fixtures, programmatic invocations with synthetic paths) should
// continue to work unchanged when they don't pass dirSlug.
const f = path.join(root, "manifest.yaml");
write(f, "slug: whatever\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
});
it("returns {kind:'malformed', subkind:'shape'} when a demo's name field is not a string", () => {
// Prior permissive behavior silently coerced non-string `name` to
// undefined. Match the strictness applied to top-level `name`:
// present-but-wrong-type is a shape malformed.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n name: 42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/demos\[0\]\.name/i);
}
});
it("freezes the returned manifest and its demos array", () => {
// parseManifest must return a frozen Manifest: downstream tools
// share the value across buckets and a mutation by one would poison
// the rest. Both the outer object and the nested demos array must
// be frozen.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n - id: bar\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
expect(Object.isFrozen(r.manifest)).toBe(true);
expect(Object.isFrozen(r.manifest.demos)).toBe(true);
expect(() => {
(r.manifest as unknown as Record<string, unknown>)["new"] = "bogus";
}).toThrow();
expect(() => {
(r.manifest.demos as unknown as unknown[])[0] = { id: "x" };
}).toThrow();
}
});
// --- demo.route validation (added by R2 fix cycle) ---------------------
//
// `route` is optional on each demo. When present, it must be a non-empty
// string that begins with "/demos/". Downstream validators (validate-parity
// routeToDirName, bundle-demo-content) rely on the "/demos/" prefix to
// strip it uniformly; accepting a bare "/hitl" or a number silently
// produces the wrong on-disk directory lookup.
it("returns {kind:'malformed', subkind:'shape'} when demos[i].route is a number", () => {
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n route: 42\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/route/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i].route is null", () => {
// YAML `route: ~` parses to null. hasOwnProp is true but the value is
// not a string, so the non-empty-string guard rejects it.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n route: ~\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/route/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i].route is an object", () => {
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n route:\n nested: true\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/route/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i].route is the empty string", () => {
const f = path.join(root, "manifest.yaml");
write(f, 'slug: x\ndemos:\n - id: foo\n route: ""\n');
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/route/i);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i].route does not start with /demos/", () => {
// Catches the exact anti-pattern the prefix guard exists for: a bare
// "/hitl" looks route-shaped but routeToDirName's prefix strip would
// return the whole string unchanged, then miss a real directory match.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n route: /hitl\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/\/demos\//);
}
});
it("returns {kind:'malformed', subkind:'shape'} when demos[i].route is exactly '/demos/'", () => {
// The `/demos/` prefix guard accepts any string that starts with the
// prefix, including the bare prefix with an empty tail. Downstream
// consumers (routeToDirName, bundle-demo-content) strip the prefix and
// expect a non-empty segment to follow; an empty tail would silently
// point at the parent demos/ directory rather than a specific demo.
// Reject at the parser boundary so validate-parity / bundle-demo-content
// can treat a successful parse as a non-empty-segment invariant.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n route: /demos/\n");
const r = parseManifest(f);
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/non-empty segment/i);
}
});
it("returns {kind:'ok'} and persists demo.route on the frozen entry when well-formed", () => {
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n route: /demos/hitl-in-chat\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
const first = r.manifest.demos?.[0];
expect(first?.id).toBe("foo");
expect(first?.route).toBe("/demos/hitl-in-chat");
expect(Object.isFrozen(first)).toBe(true);
}
});
it("returns {kind:'ok'} with demo.route undefined when route is omitted (backward compat)", () => {
// Absence of `route` must not be treated as shape-malformed. Existing
// manifests predate this field; they must still parse cleanly and the
// frozen demo entry's .route must be undefined (not null, not a
// placeholder).
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\ndemos:\n - id: foo\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
const first = r.manifest.demos?.[0];
expect(first?.id).toBe("foo");
expect(first?.route).toBeUndefined();
expect(Object.isFrozen(first)).toBe(true);
}
});
it("sets demos to a frozen empty readonly array when demos is omitted", () => {
// `demos` is non-optional in the public type: when absent, return an
// empty readonly array so consumers can iterate without `?.` chains.
const f = path.join(root, "manifest.yaml");
write(f, "slug: x\n");
const r = parseManifest(f);
expect(r.kind).toBe("ok");
if (r.kind === "ok") {
expect(r.manifest.demos).toEqual([]);
expect(Object.isFrozen(r.manifest.demos)).toBe(true);
}
});
it.skipIf(cannotEnforceEacces)(
"returns {kind:'unreadable'} when the parent dir is unreadable (EACCES on stat)",
() => {
// Regression for FX30-C Fix 2 (R29-2 H3): parseManifest used
// fs.existsSync which CONFLATES ENOENT with EACCES — a manifest
// whose parent dir is 0700 owned by another user collapses to
// "missing" instead of surfacing as "unreadable". That's the
// exact anti-pattern probeDir in validate-parity.ts was written
// to avoid. parseManifest must use statSync + errno inspection
// so EACCES/ENOTDIR/etc route to `{kind:"unreadable"}`.
const root = fs.mkdtempSync(
path.join(os.tmpdir(), "lib-manifest-parent-eacces-"),
);
const parentDir = path.join(root, "locked");
fs.mkdirSync(parentDir);
const manifestFile = path.join(parentDir, "manifest.yaml");
fs.writeFileSync(manifestFile, "slug: ok\n");
fs.chmodSync(parentDir, 0o000);
try {
const r = parseManifest(manifestFile);
expect(r.kind).toBe("unreadable");
} finally {
try {
fs.chmodSync(parentDir, 0o755);
} catch {
// best-effort
}
fs.rmSync(root, { recursive: true, force: true });
}
},
);
it("returns {kind:'unreadable'} when statSync throws a non-ENOENT errno", () => {
// Deterministic variant of the chmod-based test above: stub statSync
// to throw EACCES so the behavior is verified even on FS layers that
// ignore chmod. Pre-ENOENT semantics (via fs.existsSync) would have
// collapsed this to {kind:"missing"}.
const tmp = fs.mkdtempSync(
path.join(os.tmpdir(), "lib-manifest-stat-spy-"),
);
const f = path.join(tmp, "manifest.yaml");
fs.writeFileSync(f, "slug: ok\n");
const orig = fs.statSync;
const spy = vi.spyOn(fs, "statSync").mockImplementation(((
p: fs.PathLike,
options?: unknown,
) => {
if (typeof p === "string" && p === f) {
const e: NodeJS.ErrnoException = new Error("EACCES: injected");
e.code = "EACCES";
throw e;
}
return (orig as unknown as (p: fs.PathLike, o?: unknown) => unknown)(
p,
options,
);
}) as typeof fs.statSync);
try {
const r = parseManifest(f);
expect(r.kind).toBe("unreadable");
if (r.kind === "unreadable") {
expect(r.error).toContain("EACCES");
}
} finally {
spy.mockRestore();
fs.rmSync(tmp, { recursive: true, force: true });
}
});
it("returns {kind:'missing'} (not 'unreadable') when statSync throws ENOENT", () => {
// ENOENT is the legitimate "file absent" signal and must continue to
// route to {kind:"missing"}. Only non-ENOENT errno values escalate
// to "unreadable".
const r = parseManifest(
path.join(os.tmpdir(), "definitely-absent-xyz", "manifest.yaml"),
);
expect(r.kind).toBe("missing");
});
it("returns {kind:'malformed'} when dirSlug is the empty string (caller bug)", () => {
// Regression for FX30-C Fix 3 (R29-2 H2): `""` is NOT a valid opt-out
// sentinel — `undefined` means "caller opted out of slug-check".
// An empty string usually comes from path.basename on a weird path
// (trailing slash, etc.) in the caller; silently collapsing it to
// undefined hides a caller bug. The parser must surface it.
const tmp = fs.mkdtempSync(
path.join(os.tmpdir(), "lib-manifest-empty-slug-"),
);
const f = path.join(tmp, "manifest.yaml");
fs.writeFileSync(f, "slug: mypkg\n");
try {
const r = parseManifest(f, "");
expect(r.kind).toBe("malformed");
if (r.kind === "malformed") {
expect(r.subkind).toBe("shape");
expect(r.error).toMatch(/empty.*dirSlug|dirSlug.*empty/i);
}
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}
});
it("returns {kind:'unreadable'} when readFileSync throws (e.g. EACCES)", () => {
// Simulate a permission error via spy. existsSync returns true but
// readFileSync throws — the parser must surface this as 'unreadable',
// distinct from 'missing' (file absent) and 'malformed' (file present,
// contents bad).
//
// The spy falls through to the original implementation for any path
// other than the target manifest. Throwing "unexpected readFileSync
// call" from within a spy masked the real failure (e.g. vitest's own
// readFileSync for transform cache) with a confusing error — fall-
// through is the correct behavior for a mock of this shape.
const f = path.join(root, "manifest.yaml");
write(f, "slug: ok\n");
const orig = fs.readFileSync;
const spy = vi.spyOn(fs, "readFileSync").mockImplementation(((
p: fs.PathOrFileDescriptor,
options?: unknown,
) => {
if (typeof p === "string" && p === f) {
const e: NodeJS.ErrnoException = new Error("EACCES: permission denied");
e.code = "EACCES";
throw e;
}
return (
orig as unknown as (p: fs.PathOrFileDescriptor, o?: unknown) => unknown
)(p, options);
}) as typeof fs.readFileSync);
try {
const r = parseManifest(f);
expect(r.kind).toBe("unreadable");
if (r.kind === "unreadable") {
expect(r.error).toContain("EACCES");
}
} finally {
spy.mockRestore();
}
});
});
describe("createDemoId", () => {
it("accepts a non-empty string and returns a branded DemoId", () => {
const id = createDemoId("foo");
expect(id).toBe("foo");
});
it("returns null for the empty string", () => {
expect(createDemoId("")).toBeNull();
});
it("accepts unknown input and returns null for non-string values", () => {
// Signature widened from (s: string) to (s: unknown) so the dead
// typeof check becomes a live guard. Non-string inputs at API
// boundaries (yaml.parse results, untyped JSON) return null rather
// than silently producing a fake branded id.
expect(createDemoId(null)).toBeNull();
expect(createDemoId(undefined)).toBeNull();
expect(createDemoId(42)).toBeNull();
expect(createDemoId({})).toBeNull();
expect(createDemoId([])).toBeNull();
expect(createDemoId(true)).toBeNull();
});
it("narrows its input via a type predicate (compile-time shape)", () => {
// The returned value, when non-null, is both a DemoId AND carries a
// TypeScript narrowing that lets callers read it as a string without
// further casts. This test is mostly structural — the assertion is
// that the code compiles; we still run a basic runtime check.
const candidate: unknown = "abc";
const id = createDemoId(candidate);
if (id !== null) {
// Compiler should accept DemoId as assignable to a string-slot.
const asString: string = id;
expect(asString).toBe("abc");
// Also exercise the DemoId type import to ensure the export exists.
const branded: DemoId = id;
expect(branded).toBe("abc");
}
});
});
@@ -0,0 +1,53 @@
import { describe, expect, it } from "vitest";
import { execFileSync } from "node:child_process";
import path from "node:path";
const REPO_ROOT = path.resolve(__dirname, "../../../..");
describe("Railway GraphQL host unification", () => {
it("no source file references backboard.railway.com (must be .app)", () => {
// grep across showcase/ and .github/workflows/. Use -F (literal) so
// the dot in the pattern is not regex-interpreted. The test file
// itself contains the forbidden literal; exclude it via git pathspec
// `:(exclude)` magic. Also exclude two files that legitimately
// reference the deprecated host in documentation/negative-assertion
// form (no functional use):
// - railway-graphql.ts JSDoc explains the deprecated .com endpoint
// - railway-graphql.test.ts asserts the endpoint is NOT .com
// Use --untracked so a newly-added (not-yet-committed) file that
// reintroduces the forbidden host still trips the guard. Use
// execFileSync with an args array so REPO_ROOT is not shell-parsed.
let out = "";
try {
out = execFileSync(
"git",
[
"-C",
REPO_ROOT,
"grep",
"--untracked",
"-nF",
"backboard.railway.com",
"--",
"showcase",
":(exclude)showcase/scripts/lib/__tests__/railway-graphql.scan.test.ts",
":(exclude)showcase/scripts/lib/railway-graphql.ts",
":(exclude)showcase/scripts/lib/__tests__/railway-graphql.test.ts",
".github/workflows",
],
{ encoding: "utf-8" },
);
} catch (err) {
// git grep exits 1 when no matches — that's the clean-miss success
// case. Any other exit status (git missing, bad cwd, pathspec
// syntax error, etc.) must fail loud rather than silently pass.
const status = (err as { status?: number }).status;
if (status === 1) {
out = "";
} else {
throw err;
}
}
expect(out).toBe("");
});
});
@@ -0,0 +1,14 @@
import { describe, expect, it } from "vitest";
import { RAILWAY_GRAPHQL_ENDPOINT } from "../railway-graphql";
describe("railway-graphql", () => {
it("uses the canonical backboard.railway.app host", () => {
expect(RAILWAY_GRAPHQL_ENDPOINT).toBe(
"https://backboard.railway.app/graphql/v2",
);
});
it("never resolves to the .com host (historical drift target)", () => {
expect(RAILWAY_GRAPHQL_ENDPOINT).not.toContain("backboard.railway.com");
});
});
@@ -0,0 +1,152 @@
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { resolveRailwayToken, RailwayTokenError } from "../railway-token";
/**
* Envelope-level tests for resolveRailwayToken — the unified resolver
* used by redeploy-env.ts and verify-railway-image-refs.ts.
*
* Each failure mode must throw a DISTINCT, actionable error so the
* silent-token-fallthrough diagnostic gap can never re-open.
*/
describe("resolveRailwayToken (envelope)", () => {
let dir: string;
const originalEnv = process.env.RAILWAY_TOKEN;
const originalHome = process.env.HOME;
beforeEach(() => {
dir = mkdtempSync(join(tmpdir(), "rwy-token-env-"));
delete process.env.RAILWAY_TOKEN;
process.env.HOME = dir;
});
afterEach(() => {
rmSync(dir, { recursive: true, force: true });
if (originalEnv === undefined) delete process.env.RAILWAY_TOKEN;
else process.env.RAILWAY_TOKEN = originalEnv;
if (originalHome === undefined) delete process.env.HOME;
else process.env.HOME = originalHome;
});
it("returns RAILWAY_TOKEN env var when set, source='env'", () => {
process.env.RAILWAY_TOKEN = "env-token-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const result = resolveRailwayToken();
expect(result.token).toBe("env-token-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
expect(result.source).toBe("env");
});
it("returns token from ~/.railway/config.json when env unset, source='config'", () => {
mkdirSync(join(dir, ".railway"));
writeFileSync(
join(dir, ".railway", "config.json"),
JSON.stringify({
user: { accessToken: "from-config-aaaaaaaaaaaaaaaaaaaaaaaa" },
}),
);
const result = resolveRailwayToken();
expect(result.token).toBe("from-config-aaaaaaaaaaaaaaaaaaaaaaaa");
expect(result.source).toBe("config");
});
it("throws DISTINCT error when $HOME is unset and env-var also unset", () => {
delete process.env.HOME;
expect(() => resolveRailwayToken()).toThrow(RailwayTokenError);
try {
resolveRailwayToken();
throw new Error("should have thrown");
} catch (e) {
expect(e).toBeInstanceOf(RailwayTokenError);
const err = e as RailwayTokenError;
expect(err.code).toBe("NO_HOME");
expect(err.message).toMatch(/\$HOME/);
}
});
it("trims RAILWAY_TOKEN env var (padded with whitespace/newline)", () => {
process.env.RAILWAY_TOKEN = " padded-token-xxxxxxxxxxxxxxxxxxxxxxxx\n";
const result = resolveRailwayToken();
expect(result.token).toBe("padded-token-xxxxxxxxxxxxxxxxxxxxxxxx");
expect(result.source).toBe("env");
});
it("treats whitespace-only RAILWAY_TOKEN as UNSET and falls through to config", () => {
process.env.RAILWAY_TOKEN = " ";
mkdirSync(join(dir, ".railway"));
writeFileSync(
join(dir, ".railway", "config.json"),
JSON.stringify({
user: { accessToken: "from-config-bbbbbbbbbbbbbbbbbbbbbbbb" },
}),
);
const result = resolveRailwayToken();
expect(result.token).toBe("from-config-bbbbbbbbbbbbbbbbbbbbbbbb");
expect(result.source).toBe("config");
});
it("treats whitespace-only RAILWAY_TOKEN as UNSET and surfaces NO_FILE when no config exists", () => {
process.env.RAILWAY_TOKEN = " \n";
try {
resolveRailwayToken();
throw new Error("should have thrown");
} catch (e) {
expect(e).toBeInstanceOf(RailwayTokenError);
const err = e as RailwayTokenError;
// Must NOT be returned as source="env" with a whitespace token —
// that produces invalid Bearer headers and silent 401s.
expect(err.code).toBe("NO_FILE");
}
});
it("throws DISTINCT error when ~/.railway/config.json does not exist", () => {
try {
resolveRailwayToken();
throw new Error("should have thrown");
} catch (e) {
expect(e).toBeInstanceOf(RailwayTokenError);
const err = e as RailwayTokenError;
expect(err.code).toBe("NO_FILE");
expect(err.message).toMatch(/RAILWAY_TOKEN/);
expect(err.message).toMatch(/railway login/);
}
});
it("throws DISTINCT error when ~/.railway/config.json is malformed JSON", () => {
mkdirSync(join(dir, ".railway"));
writeFileSync(join(dir, ".railway", "config.json"), "{ not json");
try {
resolveRailwayToken();
throw new Error("should have thrown");
} catch (e) {
expect(e).toBeInstanceOf(RailwayTokenError);
const err = e as RailwayTokenError;
expect(err.code).toBe("MALFORMED");
expect(err.message).toMatch(/Malformed ~\/\.railway\/config\.json/);
}
});
it("throws DISTINCT error when config parses but yields no usable token (the silent-fallthrough gap)", () => {
mkdirSync(join(dir, ".railway"));
// Parses fine — just no token field at any layer.
writeFileSync(
join(dir, ".railway", "config.json"),
JSON.stringify({ projects: { something: "else" } }),
);
try {
resolveRailwayToken();
throw new Error("should have thrown");
} catch (e) {
expect(e).toBeInstanceOf(RailwayTokenError);
const err = e as RailwayTokenError;
// CRITICAL: must NOT be the generic NO_FILE message — the
// user needs to know the file WAS found but had no token.
expect(err.code).toBe("NO_TOKEN_IN_CONFIG");
expect(err.message).toMatch(
/~\/\.railway\/config\.json.*no.*token|found.*no.*token/i,
);
// Must also hint at the remedy.
expect(err.message).toMatch(/railway login|RAILWAY_TOKEN/);
}
});
});
@@ -0,0 +1,193 @@
import { describe, expect, it, vi } from "vitest";
import { resolveRailwayTokenFromConfig } from "../railway-token";
import type { RailwayConfigShape } from "../railway-token";
describe("resolveRailwayTokenFromConfig", () => {
it("prefers user.accessToken when present", () => {
const cfg: RailwayConfigShape = {
user: {
accessToken: "new-access-token-43-chars-or-more-aaaaaaaa",
token: "legacy-short-token",
},
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("new-access-token-43-chars-or-more-aaaaaaaa");
expect(warn).not.toHaveBeenCalled();
});
it("falls back to top-level accessToken", () => {
const cfg: RailwayConfigShape = {
accessToken: "top-level-access-token-aaaaaaaaaaaaaaaaaaaa",
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("top-level-access-token-aaaaaaaaaaaaaaaaaaaa");
expect(warn).not.toHaveBeenCalled();
});
it("falls back to legacy user.token AND emits a deprecation warning", () => {
const cfg: RailwayConfigShape = {
user: { token: "legacy-short-token-aaaaaaaaaa" },
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("legacy-short-token-aaaaaaaaaa");
expect(warn).toHaveBeenCalledTimes(1);
expect(warn.mock.calls[0][0]).toMatch(
/deprecated.*user\.token.*accessToken/i,
);
});
it("falls back to top-level token with deprecation warning", () => {
const cfg: RailwayConfigShape = { token: "legacy-top-aaaaaaaaa" };
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("legacy-top-aaaaaaaaa");
expect(warn).toHaveBeenCalledTimes(1);
});
it("returns undefined and does not warn on an empty config", () => {
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig({}, { warn });
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("ignores empty-string tokens at every layer", () => {
const cfg: RailwayConfigShape = {
user: { accessToken: "", token: "" },
accessToken: "",
token: "",
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBeUndefined();
});
it("treats whitespace-only user.accessToken as empty and falls through", () => {
const cfg: RailwayConfigShape = {
user: { accessToken: " " },
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("falls through whitespace-only user.accessToken to legacy user.token with warn", () => {
const cfg: RailwayConfigShape = {
user: {
accessToken: "\n\t ",
token: "legacy-short-token-aaaaaaaaaa",
},
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("legacy-short-token-aaaaaaaaaa");
expect(warn).toHaveBeenCalledTimes(1);
});
it("treats whitespace-only tokens at every layer as empty", () => {
const cfg: RailwayConfigShape = {
user: { accessToken: " ", token: "\t" },
accessToken: "\n",
token: " ",
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("returns undefined when config is null", () => {
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(null, { warn });
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("returns undefined when config is undefined", () => {
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(undefined, { warn });
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("returns undefined when config is a string (non-object JSON)", () => {
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(
"not-an-object" as unknown as RailwayConfigShape,
{ warn },
);
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("returns undefined when config is a number", () => {
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(
42 as unknown as RailwayConfigShape,
{ warn },
);
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
it("returns the trimmed token when user.accessToken has surrounding whitespace", () => {
const cfg: RailwayConfigShape = {
user: { accessToken: " padded-token-aaaaaaaaaaaaaaaaaaaa " },
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("padded-token-aaaaaaaaaaaaaaaaaaaa");
expect(warn).not.toHaveBeenCalled();
});
it("returns the trimmed token when user.accessToken has a trailing newline", () => {
const cfg: RailwayConfigShape = {
user: { accessToken: "abc-access-token-aaaaaaaaaaaaaaaaaaaa\n" },
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("abc-access-token-aaaaaaaaaaaaaaaaaaaa");
});
it("returns the trimmed token when top-level accessToken has surrounding whitespace", () => {
const cfg: RailwayConfigShape = {
accessToken: "\ttop-padded-aaaaaaaaaaaaaaaaaaaaaaaa\n",
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("top-padded-aaaaaaaaaaaaaaaaaaaaaaaa");
expect(warn).not.toHaveBeenCalled();
});
it("returns the trimmed token for legacy user.token (with warn)", () => {
const cfg: RailwayConfigShape = {
user: { token: " legacy-user-token-aaaaaaaaaa\n" },
};
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("legacy-user-token-aaaaaaaaaa");
expect(warn).toHaveBeenCalledTimes(1);
});
it("returns the trimmed token for legacy top-level token (with warn)", () => {
const cfg: RailwayConfigShape = { token: "\nlegacy-top-aaaaaaaaa " };
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(cfg, { warn });
expect(result).toBe("legacy-top-aaaaaaaaa");
expect(warn).toHaveBeenCalledTimes(1);
});
it("returns undefined when config is an array", () => {
const warn = vi.fn();
const result = resolveRailwayTokenFromConfig(
[] as unknown as RailwayConfigShape,
{ warn },
);
expect(result).toBeUndefined();
expect(warn).not.toHaveBeenCalled();
});
});
@@ -0,0 +1,431 @@
/**
* Tests for showcase/scripts/lib/slug-map.ts.
*
* Pins the shared slug/examples mapping tables and the
* born-in-showcase set so all three validators agree.
*/
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import fs from "fs";
import os from "os";
import path from "path";
import { fileURLToPath } from "url";
import {
BORN_IN_SHOWCASE,
SLUG_MAP,
SLUG_TO_EXAMPLES,
FALLBACK_MAP,
isShowcaseSlug,
} from "../slug-map.js";
import type { ShowcaseSlug } from "../slug-map.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const PACKAGES_DIR = path.resolve(__dirname, "..", "..", "..", "integrations");
describe("BORN_IN_SHOWCASE", () => {
it("contains the 7 known born-in-showcase slugs", () => {
expect(BORN_IN_SHOWCASE.has("ag2")).toBe(true);
expect(BORN_IN_SHOWCASE.has("claude-sdk-python")).toBe(true);
expect(BORN_IN_SHOWCASE.has("claude-sdk-typescript")).toBe(true);
expect(BORN_IN_SHOWCASE.has("langroid")).toBe(true);
expect(BORN_IN_SHOWCASE.has("ms-agent-harness-dotnet")).toBe(true);
expect(BORN_IN_SHOWCASE.has("spring-ai")).toBe(true);
expect(BORN_IN_SHOWCASE.has("strands-typescript")).toBe(true);
});
it("has exactly 7 entries — guards against accidental additions", () => {
// Size assertion: if someone adds a new born-in-showcase slug without
// updating the test above, this pins the cardinality so the addition
// is caught rather than silently accepted.
expect(BORN_IN_SHOWCASE.size).toBe(7);
});
it("is a frozen / immutable ReadonlySet (add throws)", () => {
// Callers must not mutate the shared set at runtime. A ReadonlySet type
// is compile-time only; we back it with a frozen Set so a runtime
// `.add()` attempt throws in strict mode rather than silently diverging
// from the other validator copies.
const s = BORN_IN_SHOWCASE as unknown as Set<string>;
expect(() => s.add("sneaky-mutation")).toThrow();
});
it("rejects .delete and .clear on the frozen set", () => {
const s = BORN_IN_SHOWCASE as unknown as Set<string>;
expect(() => s.delete("ag2")).toThrow();
expect(() => s.clear()).toThrow();
});
});
describe("SLUG_TO_EXAMPLES (showcase slug → examples dir names)", () => {
// This test reads the live showcase/integrations/ tree. In sparse
// checkouts (CI shards, partial clones) the directory may be absent;
// skip rather than false-fail when that happens.
it.skipIf(!fs.existsSync(PACKAGES_DIR))(
"has no dead entries — every target dir exists under showcase/integrations/",
() => {
// Regression guard: the old audit.ts map contained crewai-flows,
// agent-spec-langgraph, and mcp-apps which produced phantom "no
// examples source" anomalies. Removing them here is the whole point of
// the extraction.
for (const slug of Object.keys(SLUG_TO_EXAMPLES)) {
const pkgPath = path.join(PACKAGES_DIR, slug);
expect(
fs.existsSync(pkgPath),
`SLUG_TO_EXAMPLES slug '${slug}' has no matching showcase/integrations/${slug}/`,
).toBe(true);
}
},
);
// Companion to the skipIf test above — runs UNCONDITIONALLY against a
// fixture tmpdir so the invariant ("every SLUG_TO_EXAMPLES key has a
// matching integrations/<slug>/ dir") is still exercised on sparse
// checkouts / CI shards / Docker build contexts where the real
// showcase/integrations/ tree is absent. A skipIf without a contra-positive
// assertion is indistinguishable from "test was deleted."
describe("fixture-based invariant (runs regardless of checkout layout)", () => {
let fixtureDir: string;
let fixturePackagesDir: string;
beforeAll(() => {
fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), "slug-map-fixture-"));
fixturePackagesDir = path.join(fixtureDir, "integrations");
fs.mkdirSync(fixturePackagesDir, { recursive: true });
// Seed a directory for every SLUG_TO_EXAMPLES key. This mirrors the
// expected layout of showcase/integrations/ — the invariant check below
// is identical in spirit to the skipIf test, just pointed at a
// fixture whose contents we fully control.
for (const slug of Object.keys(SLUG_TO_EXAMPLES)) {
fs.mkdirSync(path.join(fixturePackagesDir, slug), { recursive: true });
}
});
afterAll(() => {
fs.rmSync(fixtureDir, { recursive: true, force: true });
});
it("every SLUG_TO_EXAMPLES key resolves to a real dir in the fixture", () => {
const seen: string[] = [];
for (const slug of Object.keys(SLUG_TO_EXAMPLES)) {
const pkgPath = path.join(fixturePackagesDir, slug);
expect(
fs.existsSync(pkgPath),
`fixture missing integrations/${slug}/ — invariant seeding is broken`,
).toBe(true);
seen.push(slug);
}
// Sentinel: assert we actually iterated at least one slug. A silent
// empty SLUG_TO_EXAMPLES would otherwise pass vacuously.
expect(seen.length).toBeGreaterThan(0);
});
});
it("does not include the three known dead entries", () => {
expect(
(SLUG_TO_EXAMPLES as Record<string, unknown>)["crewai-flows"],
).toBeUndefined();
expect(
(SLUG_TO_EXAMPLES as Record<string, unknown>)["agent-spec-langgraph"],
).toBeUndefined();
expect(
(SLUG_TO_EXAMPLES as Record<string, unknown>)["mcp-apps"],
).toBeUndefined();
});
it("rejects adding a new top-level key at runtime", () => {
// Object.isFrozen is the weak form of this assertion: it only checks
// a flag. An actual mutation attempt is the real invariant — strict
// mode is active in ESM, so assignment on a frozen object throws.
expect(() => {
(SLUG_TO_EXAMPLES as unknown as Record<string, readonly string[]>)[
"bogus-new-slug"
] = ["nothing"];
}).toThrow();
});
it("rejects reassigning an existing top-level entry at runtime", () => {
expect(() => {
(SLUG_TO_EXAMPLES as unknown as Record<string, readonly string[]>)[
"mastra"
] = ["replaced"];
}).toThrow();
});
it("rejects mutating an inner array (element assignment throws)", () => {
// freezeMap2D must freeze BOTH the outer record AND each inner array.
// Without the inner freeze, `SLUG_TO_EXAMPLES.mastra[0] = "x"` would
// silently succeed even though the outer Object.isFrozen reports true.
expect(() => {
(SLUG_TO_EXAMPLES.mastra as unknown as string[])[0] = "mutated";
}).toThrow();
});
it("rejects .push on an inner array (all mutation methods fail)", () => {
expect(() => {
(SLUG_TO_EXAMPLES.mastra as unknown as string[]).push("extra");
}).toThrow();
});
});
describe("SLUG_MAP (examples dir → showcase slug)", () => {
it("contains the known mapping for langgraph-js → langgraph-typescript", () => {
// Sample entry inversely matched with SLUG_TO_EXAMPLES.
expect(SLUG_MAP.get("langgraph-js")).toBe("langgraph-typescript");
});
it("inverse of SLUG_MAP covers a sample SLUG_TO_EXAMPLES entry", () => {
// For a slug with a unique examples dir (not a fan-out like crewai-*),
// the entries should be bidirectionally consistent.
const exampleDirs = SLUG_TO_EXAMPLES["langgraph-typescript"];
expect(exampleDirs).toBeDefined();
for (const dir of exampleDirs!) {
expect(SLUG_MAP.get(dir)).toBe("langgraph-typescript");
}
});
// Reads the live showcase/integrations/ tree — skip in sparse checkouts
// where that directory is not materialized.
it.skipIf(!fs.existsSync(PACKAGES_DIR))(
"every VALUE in SLUG_MAP names a real showcase/integrations/<slug>/ dir",
() => {
// Dead-entry guard: the old SLUG_MAP carried values like `crewai`,
// `maf-dotnet`, `maf-python`, `aws-strands`, `agent-spec-langgraph`,
// `a2a`, `mcp-apps`, `pydanticai` that did NOT exist under
// showcase/integrations/. Those broke validate-pins.ts's reverse lookup
// and forced FALLBACK_MAP to re-express the corrections.
for (const [, slug] of SLUG_MAP) {
const pkgPath = path.join(PACKAGES_DIR, slug);
expect(
fs.existsSync(pkgPath),
`SLUG_MAP value '${slug}' has no matching showcase/integrations/${slug}/`,
).toBe(true);
}
},
);
// Companion to the skipIf test above — runs UNCONDITIONALLY against a
// fixture tmpdir so the SLUG_MAP value invariant is exercised even
// when showcase/integrations/ is absent. Without this, a sparse CI
// checkout would silently skip the invariant and a regression
// (reintroducing a dead value like `crewai` / `mcp-apps`) would pass.
describe("fixture-based SLUG_MAP invariant (runs regardless of checkout layout)", () => {
let fixtureDir: string;
let fixturePackagesDir: string;
beforeAll(() => {
fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), "slug-map-fixture-"));
fixturePackagesDir = path.join(fixtureDir, "integrations");
fs.mkdirSync(fixturePackagesDir, { recursive: true });
// Seed the fixture with every unique VALUE in SLUG_MAP plus every
// FALLBACK_MAP target — those are the invariants we enforce.
const targets = new Set<string>();
for (const [, slug] of SLUG_MAP) targets.add(slug);
for (const target of Object.values(FALLBACK_MAP)) targets.add(target);
for (const slug of targets) {
fs.mkdirSync(path.join(fixturePackagesDir, slug), { recursive: true });
}
});
afterAll(() => {
fs.rmSync(fixtureDir, { recursive: true, force: true });
});
it("every SLUG_MAP value resolves to a real dir in the fixture", () => {
let iter = 0;
for (const [, slug] of SLUG_MAP) {
const pkgPath = path.join(fixturePackagesDir, slug);
expect(
fs.existsSync(pkgPath),
`fixture missing integrations/${slug}/ — seeding is broken`,
).toBe(true);
iter++;
}
expect(iter).toBeGreaterThan(0);
});
it("every FALLBACK_MAP target resolves to a real dir in the fixture", () => {
let iter = 0;
for (const [slug, target] of Object.entries(FALLBACK_MAP)) {
const pkgPath = path.join(fixturePackagesDir, target);
expect(
fs.existsSync(pkgPath),
`FALLBACK_MAP['${slug}'] = '${target}' has no matching dir`,
).toBe(true);
iter++;
}
expect(iter).toBeGreaterThan(0);
});
});
it("is frozen — .set throws", () => {
const m = SLUG_MAP as unknown as Map<string, string>;
expect(() => m.set("bad", "mutation")).toThrow();
});
it("is frozen — .delete and .clear throw", () => {
const m = SLUG_MAP as unknown as Map<string, string>;
expect(() => m.delete("langgraph-js")).toThrow();
expect(() => m.clear()).toThrow();
});
});
describe("isShowcaseSlug runtime validator", () => {
it("accepts a non-empty, kebab-cased-or-plain slug string", () => {
expect(isShowcaseSlug("ag2")).toBe(true);
expect(isShowcaseSlug("langgraph-typescript")).toBe(true);
expect(isShowcaseSlug("ms-agent-framework-python")).toBe(true);
});
it("rejects the empty string", () => {
expect(isShowcaseSlug("")).toBe(false);
});
it("rejects non-string inputs via defensive typeof check", () => {
// Signature widened from (s: string) to (s: unknown) so the guard
// is a live validator at any API boundary. Pass the values directly
// — no `as unknown as string` casts needed now that the parameter
// type accepts unknown.
expect(isShowcaseSlug(null)).toBe(false);
expect(isShowcaseSlug(undefined)).toBe(false);
expect(isShowcaseSlug(42)).toBe(false);
expect(isShowcaseSlug({})).toBe(false);
expect(isShowcaseSlug([])).toBe(false);
expect(isShowcaseSlug(true)).toBe(false);
});
it("narrows its argument via a user-defined type predicate", () => {
// isShowcaseSlug is declared `(s: unknown): s is ShowcaseSlug`, so
// when it returns true the compiler narrows the caller's variable to
// ShowcaseSlug. This test is primarily a compile-time assertion; a
// runtime check backs it up.
const candidate: unknown = "ag2";
if (isShowcaseSlug(candidate)) {
// Must be assignable to ShowcaseSlug without further casts.
const s: ShowcaseSlug = candidate;
expect(s).toBe("ag2");
} else {
throw new Error("expected 'ag2' to satisfy isShowcaseSlug");
}
});
it("rejects slugs containing whitespace or path separators", () => {
// These are the most likely garbage-input patterns at the boundary.
expect(isShowcaseSlug("foo bar")).toBe(false);
expect(isShowcaseSlug("foo/bar")).toBe(false);
expect(isShowcaseSlug("foo\\bar")).toBe(false);
});
it("is applied at construction — every BORN_IN_SHOWCASE and SLUG_MAP slug satisfies it", () => {
for (const s of BORN_IN_SHOWCASE) expect(isShowcaseSlug(s)).toBe(true);
for (const [, slug] of SLUG_MAP) expect(isShowcaseSlug(slug)).toBe(true);
for (const slug of Object.keys(SLUG_TO_EXAMPLES))
expect(isShowcaseSlug(slug)).toBe(true);
for (const slug of Object.keys(FALLBACK_MAP))
expect(isShowcaseSlug(slug)).toBe(true);
});
});
describe("freezeSet / freezeMap behavioral invariants", () => {
it("BORN_IN_SHOWCASE rejects re-defining its mutation methods", () => {
// Behavioral form of the old descriptor-bit check: the concrete
// invariant is that a later caller cannot restore a working `.add`
// by re-replacing the property. Assert that any re-defineProperty
// attempt throws, rather than inspecting descriptor bits directly —
// tests should pin observable behavior, not implementation shape.
const s = BORN_IN_SHOWCASE as unknown as Set<string>;
expect(() => {
Object.defineProperty(s, "add", { value: (_v: string) => s });
}).toThrow();
expect(() => {
Object.defineProperty(s, "delete", { value: (_v: string) => true });
}).toThrow();
expect(() => {
Object.defineProperty(s, "clear", { value: () => undefined });
}).toThrow();
});
it("SLUG_MAP rejects re-defining its mutation methods", () => {
const m = SLUG_MAP as unknown as Map<string, string>;
expect(() => {
Object.defineProperty(m, "set", {
value: (_k: string, _v: string) => m,
});
}).toThrow();
expect(() => {
Object.defineProperty(m, "delete", { value: (_k: string) => true });
}).toThrow();
expect(() => {
Object.defineProperty(m, "clear", { value: () => undefined });
}).toThrow();
});
});
describe("SLUG_TO_EXAMPLES / FALLBACK_MAP / BORN_IN_SHOWCASE derive from one entries source", () => {
it("every FALLBACK_MAP entry names a slug also present in SLUG_TO_EXAMPLES", () => {
// Derivation invariant: both maps come from the same per-slug entry
// (slug, examples dirs, optional fallback). A FALLBACK_MAP key with
// no SLUG_TO_EXAMPLES counterpart would mean the two maps were edited
// independently and fell out of sync.
for (const slug of Object.keys(FALLBACK_MAP)) {
expect(
(SLUG_TO_EXAMPLES as Record<string, unknown>)[slug],
`FALLBACK_MAP slug '${slug}' missing from SLUG_TO_EXAMPLES`,
).toBeDefined();
}
});
it("FALLBACK_MAP target equals the first SLUG_TO_EXAMPLES candidate for the same slug", () => {
// Both maps share the same underlying entry; the fallback is simply
// the chosen preferred dir out of SLUG_TO_EXAMPLES[slug]. If someone
// edits one side but not the other, the two maps will disagree.
for (const [slug, target] of Object.entries(FALLBACK_MAP)) {
const dirs = SLUG_TO_EXAMPLES[slug];
expect(dirs).toBeDefined();
expect(dirs![0]).toBe(target);
}
});
it("BORN_IN_SHOWCASE and SLUG_TO_EXAMPLES are disjoint (no slug is both)", () => {
// A born-in-showcase slug has no examples counterpart by definition;
// putting it in SLUG_TO_EXAMPLES would contradict that. The derivation
// pipeline enforces that an entry with `bornInShowcase: true` has NO
// examples dirs, so the two outputs can never overlap.
for (const slug of BORN_IN_SHOWCASE) {
expect(
(SLUG_TO_EXAMPLES as Record<string, unknown>)[slug],
`'${slug}' is in both BORN_IN_SHOWCASE and SLUG_TO_EXAMPLES`,
).toBeUndefined();
}
});
it("BORN_IN_SHOWCASE and FALLBACK_MAP are disjoint", () => {
// Same pairing: born-in-showcase slugs have no examples dir, so a
// FALLBACK_MAP target for one would be nonsensical.
for (const slug of BORN_IN_SHOWCASE) {
expect(
(FALLBACK_MAP as Record<string, unknown>)[slug],
`'${slug}' is in both BORN_IN_SHOWCASE and FALLBACK_MAP`,
).toBeUndefined();
}
});
});
describe("FALLBACK_MAP (documents SLUG_MAP staleness)", () => {
it("contains the stale-mapping entries validate-pins.ts relied on", () => {
expect(FALLBACK_MAP["crewai-crews"]).toBe("crewai-crews");
expect(FALLBACK_MAP["ms-agent-dotnet"]).toBe("ms-agent-framework-dotnet");
expect(FALLBACK_MAP["ms-agent-python"]).toBe("ms-agent-framework-python");
expect(FALLBACK_MAP["pydantic-ai"]).toBe("pydantic-ai");
expect(FALLBACK_MAP["strands"]).toBe("strands-python");
});
it("rejects runtime mutation", () => {
expect(() => {
(FALLBACK_MAP as unknown as Record<string, string>)["new-key"] = "bogus";
}).toThrow();
expect(() => {
(FALLBACK_MAP as unknown as Record<string, string>)["strands"] = "other";
}).toThrow();
});
});