test: close mutation coverage gaps for TypewriterCaption; exclude real-coding-agent-loaders.ts - #271
Merged
tbrandenburg merged 1 commit intoAug 31, 2026
Conversation
…l-coding-agent-loaders.ts
Resolves 2 open mutation-gap issues:
- TypewriterCaption.tsx: 0% -> 83.33% (30/36 mutants killed, above the
60% floor). Uses vi.useFakeTimers()/advanceTimersByTime() wrapped in
act() to deterministically drive the character-by-character typing
interval. Covers initial render, per-tick reveal, self-clearing on
completion (no overshoot), label-change restart, the set-working
store push overriding the label prop, visible:false hiding the
component, and unmount cleanup (both mid-animation and post-completion).
5 mutants remain unkilled: 3 are a defensive null-guard
(intervalRef.current !== null before the effect's own clearInterval)
that's dead code under normal React effect-cleanup semantics, 1 is an
equivalent-mutant null-guard inside the interval callback, and 1 is
the useState('') initial-value literal that gets overwritten
synchronously before any assertion can observe it. All five are
documented in the test file/PR as effectively-equivalent mutants, not
missing behavioral coverage.
- real-coding-agent-loaders.ts: excluded from Stryker's mutate glob,
following the exact same precedent as real-agent-core-loaders.ts
(issue #223): a test-support re-export helper with no independent
branching logic of its own.
Closes #226, #269
|
tbrandenburg
deleted the
fix/mutation-gaps-typewriter-caption-real-coding-agent-loaders
branch
August 31, 2026 06:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves 2 open
mutation-gapissues.src/renderer/components/TypewriterCaption.tsxsrc/main/agent/test-support/real-coding-agent-loaders.tsTypewriterCaption.tsx test approach
This is the first timer-based component test in this repo. Uses
vi.useFakeTimers()+vi.advanceTimersByTime()wrapped inact()(from@testing-library/react, matchingInputDialog.test.tsx's existing convention) to deterministically drive thesetInterval-based character-by-character typing animation. Covers: initial empty render + cursor presence, per-tick reveal and full completion, self-clearing behavior (verified viaclearIntervalspy +vi.getTimerCount(), not just visible text —.slice()naturally clamps and would mask whether the interval actually stopped), label-prop-change restart (asserting the stale interval is torn down before the new one starts), theset-workingstore push overriding thelabelprop,visible: falsehiding the component, and two unmount scenarios (mid-animation cleanup, and no redundantclearIntervalonce the interval already self-cleared).5 mutants remain unkilled (83.33%, still well above the 60% floor):
NoCoverage—useState("")'s initial-value literal, overwritten synchronously by the effect (setDisplayed("")) before any assertion can observe the pre-effect state, since Testing Library flushes effects duringrender().Survived— a defensiveif (intervalRef.current !== null) clearInterval(...)guard at the top of the effect (3 mutants:if(true),if(false),!==→===) that's dead code under normal React effect-cleanup semantics (React always runs the previous effect's cleanup, nulling the ref, before re-running on a dependency change), plus 1 equivalent-mutant null-guard inside the interval callback that's always non-null on every reachable execution path.These are documented as effectively-equivalent/dead-code mutants (defensive redundant guards), not missing behavioral coverage — driving them to
true/hitting the "already non-null" branch would require bypassing React's own effect lifecycle guarantees, which isn't a realistic test scenario.Why #269 got a config exclusion instead of a test
Identical pattern to the already-resolved #223:
real-coding-agent-loaders.tsis a test-support re-export helper that trivially forwards real@earendil-works/pi-coding-agentsymbols via a normal static import, with zero independent branching logic. Testing it would mean mocking the real library just to assert a wrapper calls through, defeating its purpose.Validation commands run
Risks / follow-ups
src/main/model/**test failures as prior rounds, confirmed unrelated (untouched by this branch's diff).Closes #226
Closes #269