Files
Epicnabbo-Catalogus-Updated…/src/features/housekeeping/migration/validate-matrix.test.ts
T

137 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { LegacyPage, MigrationEntry } from "./types";
import { validateMigrationEntries } from "./validate-matrix";
const page = (legacyPath: string): LegacyPage => ({
surface: legacyPath.startsWith("/mod") ? "mod" : "admin",
legacyPath,
sourceFile: `src/app${legacyPath}/page.tsx`,
});
const entry = (legacyPath: string): MigrationEntry => ({
...page(legacyPath),
targetDomain: "system",
targetPath: "/admin/system/example",
decision: "REHOST",
capabilities: { read: ["admin.dashboard"], mutate: [] },
dependencies: { queries: [], mutations: [] },
auditRequirement: "NONE",
localization: "COMPLETE",
accessibility: "COMPLETE",
requiredTests: ["unit"],
parityEvidence: [],
status: "PLANNED",
notes: [],
});
describe("validateMigrationEntries", () => {
it("reports missing, duplicate, and unknown legacy rows", () => {
const discovered = [page("/admin"), page("/admin/users")];
expect(
validateMigrationEntries(discovered, [
entry("/admin"),
entry("/admin"),
entry("/admin/ghost"),
]),
).toEqual([
"duplicate legacyPath: /admin",
"missing legacyPath: /admin/users",
"unknown legacyPath: /admin/ghost",
]);
});
it("rejects incomplete decisions", () => {
const issues = validateMigrationEntries(
[page("/admin")],
[{ ...entry("/admin"), targetPath: null, decision: "REBUILD" }],
);
expect(issues).toContain("REBUILD requires targetPath: /admin");
});
it("rejects a discovery surface mismatch for the same legacy path", () => {
expect(
validateMigrationEntries(
[page("/admin")],
[{ ...entry("/admin"), surface: "mod" }],
),
).toEqual([
"surface mismatch for legacyPath /admin: expected admin, received mod",
]);
});
it("rejects a discovery source file mismatch for the same legacy path", () => {
expect(
validateMigrationEntries(
[page("/admin")],
[
{
...entry("/admin"),
sourceFile: "src/app/admin/renamed/page.tsx",
},
],
),
).toEqual([
"sourceFile mismatch for legacyPath /admin: expected src/app/admin/page.tsx, received src/app/admin/renamed/page.tsx",
]);
});
it("rejects removal with a non-null target", () => {
expect(
validateMigrationEntries(
[page("/admin")],
[
{
...entry("/admin"),
decision: "REMOVE",
targetPath: "/admin/system/legacy",
},
],
),
).toEqual(["REMOVE requires null targetPath: /admin"]);
});
it("enforces migration safety evidence", () => {
const issues = validateMigrationEntries(
[page("/admin")],
[
{
...entry("/admin"),
targetPath: "/mod/unsupported",
decision: "MERGE",
requiredTests: [],
dependencies: { queries: [], mutations: ["users.disable"] },
status: "VERIFIED",
notes: ["TODO confirm ownership"],
},
],
);
expect(issues).toEqual([
"MERGE requires requiredTests: /admin",
"mutation dependencies require auditRequirement: /admin",
"mutation dependencies require mutate capabilities: /admin",
"non-REMOVE targetPath must start with /admin/: /admin",
"prohibited placeholder: /admin",
"VERIFIED requires parityEvidence: /admin",
]);
});
it("allows removal without a target and rejects non-removal null targets", () => {
expect(
validateMigrationEntries(
[page("/admin")],
[{ ...entry("/admin"), decision: "REMOVE", targetPath: null }],
),
).toEqual([]);
expect(
validateMigrationEntries(
[page("/admin")],
[{ ...entry("/admin"), targetPath: null }],
),
).toEqual(["REHOST requires targetPath: /admin"]);
});
});