mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Coverage 83.6 to 87.36% lines, 81.63 to 84.14% branches. Mutation testing across five packages: image-engine 85, media-engine 92, doc-engine 87, shared+enterprise 86, apps/api security and jobs slice. Runs all five lanes weekly. Fixes the silently-broken mutation CI (babel pin), a redact-pdf envelope-shape test bug, an untested enterprise license valid-signature path, and an audit test that only exercised a hand-copied reproduction. Test and config only, no product code changes beyond the babel pin and one test-only oidc export. Full suite: 16,712 pass, 0 fail.
56 lines
2.0 KiB
TypeScript
56 lines
2.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { sanitizeEventProperties } from "../../../apps/api/src/lib/analytics-allowlist.js";
|
|
|
|
// Feed every allow-listed key through the sanitizer and assert it survives. Each
|
|
// assertion pins one string literal in the ALLOWED sets: a mutant that blanks
|
|
// "duration_ms" (etc.) removes it from the set, so the value is dropped and the
|
|
// matching case fails. Covers the L8-L12 and L28-L31 survivor clusters.
|
|
const ALLOWED: Record<string, string[]> = {
|
|
tool_used: [
|
|
"tool_id",
|
|
"status",
|
|
"duration_ms",
|
|
"category",
|
|
"is_ai_tool",
|
|
"is_batch",
|
|
"input_format",
|
|
"output_format",
|
|
"bytes_in",
|
|
"bytes_out",
|
|
"execution_hint",
|
|
"error_code",
|
|
"error_kind",
|
|
],
|
|
pipeline_executed: ["step_count", "tool_ids", "is_batch", "file_count", "duration_ms", "status"],
|
|
ai_bundle_action: ["bundle_id", "action", "duration_ms"],
|
|
instance_started: ["arch", "os_platform", "deploy_mode", "gpu_present"],
|
|
auth_login: ["method"],
|
|
auth_login_failed: ["method"],
|
|
};
|
|
|
|
describe("analytics-allowlist: each allow-listed key is kept", () => {
|
|
for (const [event, keys] of Object.entries(ALLOWED)) {
|
|
for (const key of keys) {
|
|
it(`${event}.${key} survives sanitization`, () => {
|
|
const value = key === "tool_ids" ? ["id-a", "id-b"] : "value";
|
|
const out = sanitizeEventProperties(event, { [key]: value });
|
|
expect(out[key]).toEqual(value);
|
|
});
|
|
}
|
|
}
|
|
|
|
it("keeps every key of an event at once (nothing silently dropped)", () => {
|
|
const props: Record<string, unknown> = {};
|
|
for (const key of ALLOWED.tool_used) props[key] = key === "tool_ids" ? ["x"] : "v";
|
|
const out = sanitizeEventProperties("tool_used", props);
|
|
expect(Object.keys(out).sort()).toEqual([...ALLOWED.tool_used].sort());
|
|
});
|
|
|
|
it("drops a key that belongs to a different event's set", () => {
|
|
// tool_id is allowed for tool_used but not for auth_login.
|
|
expect(sanitizeEventProperties("auth_login", { tool_id: "x", method: "oidc" })).toEqual({
|
|
method: "oidc",
|
|
});
|
|
});
|
|
});
|