127 lines
7.2 KiB
JavaScript
127 lines
7.2 KiB
JavaScript
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { failureCount, gates, settingsApiOnboardingInventoryScanRoots, renderReport, reportPath, runSettingsApiOnboardingInventory } from "./verify-settings-api-onboarding-baseline.mjs";
|
|
|
|
const focusedSmokeTargets = [
|
|
"apps/web/app/routes/app.$tenant/settings/members.test.ts",
|
|
"apps/web/app/routes/app.$tenant/settings/profile.mfa.test.tsx",
|
|
"packages/db/src/api-keys.server.test.ts",
|
|
"packages/entitlements/src/index.test.ts",
|
|
"apps/web/app/routes/app.$tenant.test.tsx",
|
|
];
|
|
|
|
describe("Settings API Onboarding baseline runner configuration", () => {
|
|
it("defines the required non-E2E gates and report path", () => {
|
|
expect(reportPath).toMatch(/\.tc\/baselines\/settings-api-onboarding\/baseline-health\.md$/);
|
|
expect(gates.map((gate) => gate.id)).toEqual(["typecheck", "lint", "ci-baseline", "vitest-settingsApiOnboarding-smoke", "settingsApiOnboarding-settings-api-onboarding-inventory"]);
|
|
expect(gates.some((gate) => gate.args?.some((arg) => /playwright|cypress|browser|e2e/i.test(arg)))).toBe(false);
|
|
expect(settingsApiOnboardingInventoryScanRoots).toEqual(["apps/web/app/routes", "apps/web/app/components", "apps/web/app/utils", "packages/db/src", "packages/entitlements/src", "prisma"]);
|
|
});
|
|
|
|
it("keeps focused smoke tests in the Vitest gate", () => {
|
|
const vitestGate = gates.find((gate) => gate.id === "vitest-settingsApiOnboarding-smoke");
|
|
|
|
expect(vitestGate?.args).toEqual(["exec", "vitest", "run", ...focusedSmokeTargets]);
|
|
});
|
|
});
|
|
|
|
describe("Settings API Onboarding baseline runner failure counting", () => {
|
|
it("counts failed shell diagnostics conservatively", () => {
|
|
expect(failureCount("typecheck", "app/a.ts(1,1): error TS2322: nope\napp/b.ts(2,2): error TS7006: nope", "", 1)).toBe(2);
|
|
expect(failureCount("lint", "✖ 5 problems (3 errors, 2 warnings)", "", 1)).toBe(3);
|
|
expect(failureCount("vitest-settingsApiOnboarding-smoke", "Tests 4 failed | 8 passed", "", 1)).toBe(4);
|
|
expect(failureCount("ci-baseline", "Summary: 8 passed, 0 observed, 2 failed", "", 1)).toBe(2);
|
|
expect(failureCount("ci-baseline", "baseline crashed", "", 1)).toBe(1);
|
|
});
|
|
|
|
it("returns zero for clean exits and read-only inventory gates", () => {
|
|
expect(failureCount("typecheck", "warning only", "", 0)).toBe(0);
|
|
expect(failureCount("settingsApiOnboarding-settings-api-onboarding-inventory", "total matches: 12", "", 1)).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("Settings API Onboarding settings/API-key/onboarding inventory", () => {
|
|
it("scans existing roots, records missing roots, and ignores generated dependency and TC paths", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "settingsApiOnboarding-baseline-inventory-"));
|
|
await mkdir(join(root, "apps", "web", "app", "routes"), { recursive: true });
|
|
await mkdir(join(root, "apps", "web", "app", "components"), { recursive: true });
|
|
await mkdir(join(root, "packages", "db", "src"), { recursive: true });
|
|
await mkdir(join(root, ".tc"), { recursive: true });
|
|
await mkdir(join(root, "apps", "web", "app", "routes", "generated"), { recursive: true });
|
|
await mkdir(join(root, "node_modules", "ignored"), { recursive: true });
|
|
|
|
await writeFile(
|
|
join(root, "apps", "web", "app", "routes", "settings.tsx"),
|
|
[
|
|
"const workspaceSettings = 'tenant settings preferences';",
|
|
"const account = 'profile password mfa totp session impersonation';",
|
|
"const api = 'apiKey API key scopes secret hash';",
|
|
"const rotation = 'rotate rotation revoke revocation active expires';",
|
|
"const onboarding = 'onboarding step wizard setup welcome';",
|
|
].join("\n"),
|
|
"utf8",
|
|
);
|
|
await writeFile(join(root, "apps", "web", "app", "components", "Roles.tsx"), "export const label = 'roles permissions policy groups members admin owner';", "utf8");
|
|
await writeFile(join(root, "packages", "db", "src", "billing.ts"), "export const billing = 'subscription plan quota notification policy entitlement';", "utf8");
|
|
const ignoredSignal = "workspaceSettings profile apiKey rotate onboarding roles billing";
|
|
await writeFile(join(root, ".tc", "ignored.tsx"), ignoredSignal, "utf8");
|
|
await writeFile(join(root, "apps", "web", "app", "routes", "generated", "ignored.tsx"), ignoredSignal, "utf8");
|
|
await writeFile(join(root, "node_modules", "ignored", "ignored.tsx"), ignoredSignal, "utf8");
|
|
|
|
const inventory = await runSettingsApiOnboardingInventory(root);
|
|
const allMatches = inventory.matches.join("\n");
|
|
|
|
expect(inventory.roots).toEqual(["apps/web/app/routes", "apps/web/app/components", "packages/db/src"]);
|
|
expect(inventory.missingRoots).toEqual(["apps/web/app/utils", "packages/entitlements/src", "prisma"]);
|
|
expect(inventory.counts).toMatchObject({
|
|
"workspace-settings": 3,
|
|
"user-account-settings": 6,
|
|
"api-keys-scopes": 6,
|
|
"api-keys-rotation-revocation": 7,
|
|
"onboarding-steps": 6,
|
|
"roles-permissions": 8,
|
|
"billing-notifications-policies": 8,
|
|
});
|
|
expect(allMatches).toContain("apps/web/app/routes/settings.tsx");
|
|
expect(allMatches).toContain("apps/web/app/components/Roles.tsx");
|
|
expect(allMatches).toContain("packages/db/src/billing.ts");
|
|
expect(allMatches).not.toContain(".tc/ignored.tsx");
|
|
expect(allMatches).not.toContain("generated/ignored.tsx");
|
|
expect(allMatches).not.toContain("node_modules/ignored/ignored.tsx");
|
|
});
|
|
});
|
|
|
|
describe("Settings API Onboarding report rendering", () => {
|
|
it("renders gate metadata, aggregate status, fingerprints, and inventory counts", () => {
|
|
const report = renderReport([
|
|
{ id: "typecheck", command: "pnpm run typecheck", exitCode: 2, durationMs: 1500, failureCount: 7, fingerprint: { hash: "abc123def456", excerpt: "error TS2322" } },
|
|
{
|
|
id: "settingsApiOnboarding-settings-api-onboarding-inventory",
|
|
command: "read-only Settings API Onboarding settings/API-key/onboarding inventory",
|
|
exitCode: 0,
|
|
durationMs: 42,
|
|
failureCount: 0,
|
|
inventory: { roots: ["apps/web/app/routes"], missingRoots: ["prisma"], filesScanned: 3, counts: { "workspace-settings": 1, "api-keys-scopes": 2 }, totalMatches: 3, matches: [] },
|
|
fingerprint: { hash: "fed456abc123", excerpt: "workspace-settings: 1" },
|
|
},
|
|
]);
|
|
|
|
expect(report).toContain("# Settings API Onboarding Baseline Health");
|
|
expect(report).toContain("non-E2E baseline gates for Settings API Onboarding baseline");
|
|
expect(report).toContain("Aggregated Exitcode: 1");
|
|
expect(report).toContain("Failed Shell Gates: 1");
|
|
expect(report).toContain("## typecheck");
|
|
expect(report).toContain("## settingsApiOnboarding-settings-api-onboarding-inventory");
|
|
expect(report).toContain("- Exitcode: 2");
|
|
expect(report).toContain("- Failure Count: 7");
|
|
expect(report).toContain("- Output Fingerprint: abc123def456");
|
|
expect(report).toContain("- Inventory Roots: apps/web/app/routes");
|
|
expect(report).toContain("- Missing Roots Skipped: prisma");
|
|
expect(report).toContain(" - workspace-settings: 1");
|
|
expect(report).toContain("- Total Inventory Matches: 3");
|
|
});
|
|
});
|