Files
multica/packages/views/common/task-transcript/redact.test.ts
2a643cc740 MUL-6291: stop paying for jsdom in pure-logic frontend suites (#7081)
MUL-6291. Vitest's own breakdown for `@multica/views` showed the shape of the
problem: environment 633s and import 644s against only 508s of actual test
execution. Two thirds of a cold frontend-test run went on building a jsdom per
file and importing its module graph, not on running assertions.

- 94 pure-logic `.test.ts` files across views/web/desktop now declare
  `// @vitest-environment node`. Measured on the 45 converted views files:
  environment 53.15s -> 4ms, wall 8.72s -> 2.03s. Candidates were picked by
  module-graph analysis (skipping type-only imports) and rejected when the code
  under test branches on `typeof window`/`document`, where node would silently
  take the SSR path and still pass; the remainder were verified empirically and
  reverted where they failed.
- The three jsdom setup files bail out when there is no DOM, so a node-env suite
  can share them.
- schedule-editor: the pure state transitions (isFullDay, displayWindow,
  timeAnchorOf, defaultAtTime, defaultEveryTime, clampWindow, toggleDay) move
  out of the component into transitions.ts, with the full combination matrix as
  a table-driven node-env suite. 34 cases in 3ms, replacing four DOM mounts.
- Cross-layer duplicates removed where a canonical layer already owns the
  matrix: originSourceUrl (skills/lib/origin.test.ts) was re-run through the
  refresh dialog and the detail page; needsSourceBackfill
  (core/onboarding/needs-backfill.test.ts) through the backfill modal. Each
  component keeps one wiring case naming the canonical file.

No behaviour change: the transitions extraction is a pure move, and every
removal names where the same contract is still covered.

Co-authored-by: Bohan-J <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-08-17 18:40:19 +08:00

111 lines
4.3 KiB
TypeScript

// @vitest-environment node
import { describe, it, expect } from "vitest";
import { redactSecrets } from "./redact";
describe("redactSecrets", () => {
it("redacts AWS access key", () => {
const result = redactSecrets("key: AKIAIOSFODNN7EXAMPLE");
expect(result).not.toContain("AKIAIOSFODNN7EXAMPLE");
expect(result).toContain("[REDACTED AWS KEY]");
});
it("redacts AWS secret key", () => {
const result = redactSecrets("aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY");
expect(result).not.toContain("wJalrXUtnFEMI");
});
it("redacts PEM private keys", () => {
const input = "-----BEGIN RSA PRIVATE KEY-----\nMIIEow...\n-----END RSA PRIVATE KEY-----";
const result = redactSecrets(input);
expect(result).not.toContain("MIIEow");
expect(result).toContain("[REDACTED PRIVATE KEY]");
});
it("redacts GitHub tokens", () => {
const result = redactSecrets("GITHUB_TOKEN=ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn");
expect(result).not.toContain("ghp_");
});
it("redacts GitHub fine-grained PATs (github_pat_)", () => {
const key = ["github_", "pat_", "11ABCDEFG0aBcDeFgHiJkL_mNoPqRsTuVwXyZ0123456789AbCdEfGhIjKlMnOpQrSt"].join("");
const result = redactSecrets(`the build left ${key} in the log`);
expect(result).not.toContain("github_pat_");
expect(result).toContain("[REDACTED GITHUB TOKEN]");
});
it("redacts Google API keys (AIza...)", () => {
const key = ["AIza", "SyD1234567890abcdefghijklmnopqrstuv"].join("");
const result = redactSecrets(`the config still had ${key} in it`);
expect(result).not.toContain("AIzaSy");
expect(result).toContain("[REDACTED GOOGLE API KEY]");
});
it("redacts Google API keys ending with dash", () => {
const key = ["AIza", "SyB1cD3fGhIjKlMnOpQrStUvWxYz012345-"].join("");
const result = redactSecrets(`the config still had "${key}" in it`);
expect(result).not.toContain("AIzaSy");
expect(result).toContain('"[REDACTED GOOGLE API KEY]" in it');
});
it("redacts GitLab tokens", () => {
const result = redactSecrets("glpat-AbCdEfGhIjKlMnOpQrStUvWx");
expect(result).not.toContain("glpat-");
expect(result).toContain("[REDACTED GITLAB TOKEN]");
});
it("redacts OpenAI/Anthropic API keys", () => {
const result = redactSecrets("sk-proj-abc123def456ghi789jkl012mno345");
expect(result).not.toContain("sk-proj");
expect(result).toContain("[REDACTED API KEY]");
});
it("redacts Slack tokens", () => {
const result = redactSecrets("xoxb-123456789012-1234567890123-AbCdEfGhIjKl");
expect(result).not.toContain("xoxb-");
});
it("redacts JWT tokens", () => {
const result = redactSecrets("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
expect(result).not.toContain("eyJhbGci");
expect(result).toContain("[REDACTED JWT]");
});
it("redacts Bearer tokens", () => {
const result = redactSecrets("Authorization: Bearer abc123xyz.def456");
expect(result).toContain("Bearer [REDACTED]");
expect(result).not.toContain("abc123xyz");
});
it("redacts connection strings", () => {
const result = redactSecrets("postgres://admin:[email protected]:5432/mydb");
expect(result).not.toContain("s3cret");
});
it("redacts generic credential env vars", () => {
for (const key of ["PASSWORD", "SECRET", "TOKEN", "DATABASE_URL", "API_KEY"]) {
const result = redactSecrets(`${key}=supersecretvalue123`);
expect(result).toContain("[REDACTED CREDENTIAL]");
expect(result).not.toContain("supersecretvalue123");
}
});
it("redacts multiple secrets in one string", () => {
const result = redactSecrets("AKIAIOSFODNN7EXAMPLE and ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn");
expect(result).not.toContain("AKIAIOSFODNN7EXAMPLE");
expect(result).not.toContain("ghp_");
});
it("does not alter normal text", () => {
const inputs = [
"This is a normal commit message about fixing a bug",
"The function returns skip-navigation as the class name",
"Created PR #42 for the authentication feature",
"Running tests in /tmp/test-workspace/project",
"The API endpoint /api/issues/123 was updated",
];
for (const input of inputs) {
expect(redactSecrets(input)).toBe(input);
}
});
});