test: mutate the rest of the logic, and close what it found - #59
Merged
Merged
Conversation
The scope was lib/utils and lib/composables. This adds the entry, the handler registry, the models, the services and the helpers: everything whose behaviour a unit test can actually observe. Components and views stay out, because most of their mutants are DOM glue and the score would measure the wrong thing. Two gaps worth the run, both in code that reads as finished. compareVersions had an assertion for a release outranking its own prerelease, and only in one direction. Nobody ever asked the other way round, and the election asks in whichever order the two copies happen to load, so a beta could have won a page against a release with nothing to show for it. There is now a test both ways, one that checks the comparison is antisymmetric across a spread of versions, and one that sorts a shuffled list. scope.ts went from 70.5% to 82.5%. Every handler answers for a whole selection, and `every` reads exactly like `some` until something asks. Nothing did, so a selection of a score and a PDF would have opened the sheet music viewer. Covered for all four handlers at once. logger.ts is excluded alongside plyrTranslations: its only mutant is the app name it labels lines with, which no test can see. Baseline across the widened scope is 74.6%. mediaPreloader reads as 0% because preloadMedia has no unit test and preloadPreview's arrive with #51. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #59 +/- ##
==========================================
+ Coverage 88.62% 88.80% +0.18%
==========================================
Files 39 39
Lines 2743 2743
Branches 562 564 +2
==========================================
+ Hits 2431 2436 +5
+ Misses 305 300 -5
Partials 7 7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Widens the mutation scope from
lib/utilsandlib/composablesto the entry, the handler registry, the models, the services and the helpers. Components and views stay out on purpose: most of their mutants are DOM glue that a unit test cannot observe, so the score would measure the wrong thing rather than a gap.Baseline across the new scope is 74.6%.
How I picked what to add
Three questions, in this order.
Would a wrong answer be silent? Code that throws when broken is already telling you. Code that returns a plausible wrong value is where this pays: comparisons, lookup tables, permission checks, a version election.
Is the coverage suspiciously high? 100% line coverage is a red flag, not a green one. It says every line ran and nothing about whether anything was checked.
Can a mutant be observed at all? String tables, log messages and anything behind a mock are excluded, because scoring them measures the test strategy rather than the tests.
That put the four models near the top, and they paid out exactly as the second question predicted:
models/sheetmusic.tsmodels/images.tsmodels/videos.tsmodels/audios.tsWhat it found
compareVersionswas only ever asked one way round. There was an assertion that a release outranks its own prerelease, and the mirror branch wasNoCoverage. The election asks in whichever order the two copies of the library happen to load, so on half the page loads a beta could have beaten a release and nothing would have said so. Everything we ship right now is a prerelease.Now tested both directions, plus a check that the comparison is antisymmetric across a spread of versions, plus sorting a shuffled list, which is the question the election actually asks.
scope.ts: 70.5% to 82.5%.Every handler answers for the whole selection, and
everyreads exactly likesomeuntil something asks. Nothing did. A selection of a score and a PDF would have opened the sheet music viewer. Covered for all four handlers at once, and the mutant is dead in each.Leftovers, named rather than hidden
logger.tsis excluded alongsideplyrTranslations.ts: its only mutant is the app name it labels log lines with.mediaPreloader.tsreads as 0%.preloadMediahas no unit test, andpreloadPreview's five arrive with #51, so I have left it rather than writing tests that will conflict.usePlyrPlayer.tsat 43% with 44 survivors is the largest remaining gap and the obvious next target.handlers.tsat 71.3% with 17 uncovered mutants is the other.390 unit tests.
👾 This pull request was assisted by Claude Code, commits carry an
Assisted-bytrailer.