mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Closes the "e2e never runs in CI" hole. Adds per-PR e2e smoke gate, nightly full-suite workflows, parallel vitest forks (per-fork DBs), Playwright parallel/serial/visual projects against production builds, metadata-generated test suites (drift guards, hostile inputs, format matrix, pairwise settings, property-based fuzz), Stryker mutation testing, Schemathesis API fuzz, coverage ratchet, and fixes for three session-poisoning bugs that caused 200+ serial-bucket failures. Bug fix included: favicon/split/bulk-rename could hang clients forever when ZIP streaming failed after reply.hijack().
51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
import { TOOLS } from "@snapotter/shared";
|
|
import { describe, expect, it } from "vitest";
|
|
import { TOOL_DISPLAY_MODES } from "@/lib/tool-display-modes";
|
|
import { toolRegistry } from "@/lib/tool-registry";
|
|
|
|
/**
|
|
* Drift guards: the shared TOOLS catalog, the frontend registry, and the
|
|
* display-mode map must always describe the same set of tools. A new tool
|
|
* that misses one of the three fails here at PR time instead of shipping
|
|
* a dead tool page.
|
|
*/
|
|
describe("tool registry drift", () => {
|
|
it("every TOOLS entry has a frontend registry entry", () => {
|
|
for (const tool of TOOLS) {
|
|
expect(toolRegistry.has(tool.id), `tool "${tool.id}" missing from tool-registry.tsx`).toBe(
|
|
true,
|
|
);
|
|
}
|
|
});
|
|
|
|
it("every TOOLS entry has a display mode", () => {
|
|
for (const tool of TOOLS) {
|
|
expect(
|
|
TOOL_DISPLAY_MODES[tool.id],
|
|
`tool "${tool.id}" missing from tool-display-modes.ts`,
|
|
).toBeTruthy();
|
|
}
|
|
});
|
|
|
|
it("registry has no orphan entries (tools removed from TOOLS but not the registry)", () => {
|
|
const ids = new Set(TOOLS.map((t) => t.id));
|
|
for (const id of toolRegistry.keys()) {
|
|
expect(ids.has(id), `registry entry "${id}" has no TOOLS definition`).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("display-mode map has no orphan entries", () => {
|
|
const ids = new Set(TOOLS.map((t) => t.id));
|
|
for (const id of Object.keys(TOOL_DISPLAY_MODES)) {
|
|
expect(ids.has(id), `display-mode entry "${id}" has no TOOLS definition`).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("every registry entry has a Settings component and a valid display mode", () => {
|
|
for (const [id, entry] of toolRegistry) {
|
|
expect(entry.Settings, `tool "${id}" has no Settings component`).toBeTruthy();
|
|
expect(entry.displayMode, `tool "${id}" has no displayMode`).toBe(TOOL_DISPLAY_MODES[id]);
|
|
}
|
|
});
|
|
});
|