web: de-flake fetchTracking redaction test (#1757)#1759
Conversation
… leak checks (#1757) The secret-redaction tests assert the serialized tracked entry does not contain a secret value (e.g. `JSON.stringify(tracked[0]).not.toContain("shh")`). Redaction works, but the entry carries a random request id (`${timestamp}-${Math.random().toString(36)…}`) whose base36 tail can coincidentally contain a short secret substring (`…sw7kshhf0` contains "shh"), producing spurious failures that pass on re-run. Add a `serializedWithoutId(entry)` helper that serializes the entry with `id` overwritten to `undefined` (JSON.stringify drops undefined-valued keys), and route all nine whole-entry `.not.toContain(secret)` leak checks through it. The id is generated independently of any secret and can never legitimately carry one, so excluding it keeps every deterministic field under the leak check while removing the only source of nondeterminism. No production change. Closes #1757 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
@claude review |
|
Claude finished @cliffhall's task in 57s —— View job Review: de-flake fetchTracking redaction testVerified the fix against the source. This is a correct, well-scoped fix — nothing blocking.
The root cause claim checks out
const id = `${timestamp.getTime()}-${Math.random().toString(36).slice(2, 11)}`;That base36 tail is up to 9 chars of The fix is correct and complete
Minor, non-blocking observations
VerdictLGTM. The flake is eliminated structurally (the leak assertions no longer depend on the random id), redaction coverage is preserved, and the change is test-only. Ship it. |
… flake (#1760) (#1761) * web: disable Mantine transitions in tests to kill post-teardown timer flake (#1760) A Mantine `Transition`/`Modal` open/close `setTimeout` can fire after happy-dom tears down `window` at the end of a run, throwing an uncaught `ReferenceError: window is not defined` that fails the whole `coverage` job even when every assertion passed (seen on PR #1759's CI, originating in ServerRemoveConfirmModal.test.tsx). Set `env="test"` on the shared `renderWithMantine` MantineProvider so Mantine renders transitions synchronously (no timer). This removes the leak class for every test that renders through the shared wrapper (Modals, Menus, Popovers, …). Also apply it to ViewHeader's local forced-dark provider. The handful of tests that assert mid-flight transition state (ViewHeader's `data-anim="out"` crossfade checks, #1450) genuinely need real transitions, so add an opt-in `renderWithMantineTransitions` wrapper (env="default") and route those three tests through it — each already drives the transition to completion (waitFor/findBy) so it doesn't reintroduce the leak. Tests that assert only the entered state stay on the default (leak-free) wrapper. Full `npm run ci` green; unit run reports zero unhandled errors. Closes #1760 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * docs: note the renderWithMantine env=test invariant in AGENTS.md (#1760) Per review feedback: document that tests must render through `renderWithMantine` (env="test", transition-free) rather than a hand-rolled `MantineProvider`, and reserve `renderWithMantineTransitions` for asserting mid-flight animation state (driving the transition to completion). Keeps future tests from quietly reintroducing the post-teardown timer leak class. Refs #1760 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes #1757
Problem
The secret-redaction tests in
fetchTracking.test.tsprove a secret doesn't leak by asserting the serialized tracked entry doesn't contain it, e.g.expect(JSON.stringify(tracked[0])).not.toContain("shh"). Redaction works correctly, but each entry carries a random request id minted as${timestamp}-${Math.random().toString(36).slice(2,11)}. That base36 tail can coincidentally contain a short secret substring — the id…sw7kshhf0containsshh— so the whole-object substring check fails spuriously (and passes on re-run). Observed once on PR #1756's CI.Fix
Add a
serializedWithoutId(entry)helper that serializes the entry withidoverwritten toundefined(JSON.stringifydrops undefined-valued keys — no unused-var lint issue), and route all nine whole-entry.not.toContain(secret)leak checks through it.The
idis generated independently of any secret and can never legitimately carry one, so excluding it keeps every deterministic field (headers, url, request/response bodies) under the leak check while removing the only nondeterministic field. The stricter per-field redaction assertions (recorded.get("client_secret") === REDACTED, etc.) are unchanged. No production change.Verification
Full
npm run cigreen (validate, ≥90 coverage gate, smoke, 456 Storybook tests). The fix is structural — the leak assertions no longer depend on the random id, so the flake can't recur.🤖 Generated with Claude Code
https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5