import { describe, expect, it } from "vitest";
import {
REGISTRY_ARTIFACT_SCHEMA_VERSION,
REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
REGISTRY_MANIFEST_SCHEMA_VERSION,
buildRegistryArtifact,
buildRegistryFile,
computeRegistryHash,
finalizeRegistryManifest,
registryArtifactDigest,
registryArtifactSchema,
registryInstallReceiptSchema,
registryManifestSchema,
type RegistryManifestDraft,
} from "./registry.js";
function manifestDraft(): RegistryManifestDraft {
const buttonSource = buildRegistryFile({
path: "components/Button/index.tsx",
role: "source",
content: "export function Button() { return ; }\n",
contentType: "text/tsx",
});
const buttonStyle = buildRegistryFile({
path: "components/Button/Button.module.scss",
role: "style",
content: ".button { color: var(--brand-accent); }\n",
contentType: "text/scss",
});
return {
schemaVersion: REGISTRY_MANIFEST_SCHEMA_VERSION,
registryId: "acme-ui",
name: "Acme UI",
channel: "stable",
version: "2026.06.14",
fcid: "a".repeat(64),
generatedAt: "2026-06-14T12:00:00.000Z",
source: {
kind: "github",
repoFullName: "acme/ui",
commitSha: "abc123",
path: "packages/ui",
},
components: {
button: {
componentId: "button",
publicRef: "acme-ui:button",
name: "Button",
status: "stable",
tier: "core",
category: "actions",
files: [buttonSource.metadata, buttonStyle.metadata],
styleFiles: [buttonStyle.metadata.path],
tokenDependencies: ["--brand-accent"],
runtimeDependencies: [
{
name: "@base-ui/react",
versionRange: "^1.0.0",
type: "runtime",
},
],
peerDependencies: [
{
name: "react",
versionRange: ">=18",
type: "peer",
},
],
internalDependencies: [],
exports: [{ name: "Button", path: buttonSource.metadata.path }],
contract: { a11y: ["requires-name"] },
examples: [{ name: "Default", code: "" }],
provenance: { scanner: "fixture" },
},
},
dependencies: [],
installProfiles: [
{
name: "react-app",
targetPath: "src/fragments/ui",
importPath: "@/fragments/ui",
stylePath: "src/fragments/ui/styles.scss",
includeTests: false,
},
],
};
}
describe("registry schemas", () => {
it("finalizes and validates a registry manifest", () => {
const manifest = finalizeRegistryManifest(manifestDraft());
expect(registryManifestSchema.parse(manifest).registryHash).toMatch(/^[0-9a-f]{64}$/);
expect(manifest.components.button.name).toBe("Button");
});
it("keeps the registry hash stable across generatedAt changes", () => {
const first = manifestDraft();
const second = {
...first,
generatedAt: "2026-06-14T13:00:00.000Z",
};
expect(computeRegistryHash(first)).toBe(computeRegistryHash(second));
});
it("changes the registry hash when file content changes", () => {
const first = manifestDraft();
const changedFile = buildRegistryFile({
path: "components/Button/index.tsx",
role: "source",
content: "export function Button() { return ; }\n",
contentType: "text/tsx",
});
const second = {
...first,
components: {
button: {
...first.components.button,
files: [changedFile.metadata, first.components.button.files[1]],
},
},
};
expect(computeRegistryHash(first)).not.toBe(computeRegistryHash(second));
});
it("rejects unsafe registry file paths", () => {
expect(() =>
buildRegistryFile({
path: "../Button.tsx",
role: "source",
content: "",
contentType: "text/tsx",
})
).toThrow(/must not contain \.\./i);
expect(() =>
buildRegistryFile({
path: "/tmp/Button.tsx",
role: "source",
content: "",
contentType: "text/tsx",
})
).toThrow(/not absolute/i);
});
it("builds local registry artifacts and detects missing content", () => {
const source = buildRegistryFile({
path: "components/Button/index.tsx",
role: "source",
content: "export const Button = () => null;\n",
contentType: "text/tsx",
});
const draft = manifestDraft();
const artifact = buildRegistryArtifact({
manifest: {
...draft,
components: {
button: {
...draft.components.button,
files: [source.metadata],
},
},
},
files: [source.content],
});
expect(registryArtifactDigest(artifact)).toMatch(/^[0-9a-f]{64}$/);
expect(() =>
buildRegistryArtifact({
manifest: artifact.manifest,
files: [source.content, source.content],
})
).toThrow(/Duplicate registry file content/);
const manifest = finalizeRegistryManifest({
...draft,
components: {
button: {
...draft.components.button,
files: [source.metadata],
},
},
});
expect(() =>
registryArtifactSchema.parse({
schemaVersion: REGISTRY_ARTIFACT_SCHEMA_VERSION,
manifest,
files: {},
})
).toThrow(/Missing content/);
expect(() =>
registryArtifactSchema.parse({
schemaVersion: REGISTRY_ARTIFACT_SCHEMA_VERSION,
manifest,
files: {
[source.metadata.path]: {
...source.content,
path: "components/Button/other.tsx",
},
},
})
).toThrow(/does not match content path/);
});
it("validates install receipts for committed local proof", () => {
const manifest = finalizeRegistryManifest(manifestDraft());
expect(() =>
registryInstallReceiptSchema.parse({
schemaVersion: REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
registryId: manifest.registryId,
registryVersion: manifest.version,
registryHash: manifest.registryHash,
fcid: manifest.fcid,
channel: manifest.channel,
targetPath: "src/fragments/ui",
importPath: "@/fragments/ui",
installedComponents: [
{
componentId: "button",
publicRef: "acme-ui:button",
name: "Button",
files: ["src/fragments/ui/components/Button/index.tsx"],
},
],
files: [
{
path: "src/fragments/ui/components/Button/index.tsx",
sourcePath: "components/Button/index.tsx",
sha256: manifest.components.button.files[0].sha256,
componentId: "button",
},
],
dependencies: manifest.components.button.peerDependencies,
installedAt: "2026-06-14T12:30:00.000Z",
})
).not.toThrow();
});
});