test(scripts): re-anchor 12 assertions that could not fail - #449
Merged
Conversation
Twelve assertion sites across twelve test files were verified to survive the
defect they name. Each was reproduced by applying the mutation to a clean
worktree and running the whole suite green before it was touched.
Three shapes:
* value pins written in terms of the constant the implementation reads, so
changing the constant satisfies them ('neutral' -> 'dark' for every PDF
export re-themes diagrams dark, undetected);
* discriminators neutralised by the arguments the test supplies, or by an
unbounded gap in a source regex that lets the match land on a different
site than the one under test;
* assertions with no reachable subject at all - a fixture restated back to
itself, a sum of array lengths asserted non-negative, `new X() instanceof
X`, and an underscore count between two strings the line above already
asserted equal.
Six of these were deleted rather than repaired, each dominated by a stronger
executable assertion that is named in a comment where it was removed.
`MERMAID_PRINT_THEME` was exported only so a test could compare the print
theme against itself; the assertion now spells 'neutral' and the export is
gone. No other behaviour in `src/` or `src-tauri/` changes.
`exportSanitize.test.ts:68` was reported as unreachable and is not: replacing
`MARKDOWN_SANITIZE_CONFIG.ALLOWED_URI_REGEXP` with a permissive pattern fails
it. Left as it stands.
Ten of the twelve files did not exist at v2.6.14. This is debt from the recent
PR series, not inherited.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PathGao
force-pushed
the
fix/tests-that-cannot-fail-values
branch
from
August 3, 2026 13:36
a62a6eb to
77211ab
Compare
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.
Twelve assertions in twelve test files survive the defect they name. Each was reproduced first: the mutation applied to a clean worktree,
npm testrun, 584/584 green, source restored. None of them is the failure #440 fixed — those were anchors that were missing, so the slice degenerated to"". These are anchors that are too far apart, values compared against the constant they were read from, and assertions with no reachable subject.These tests are recent, and they were added by the same series of changes that is now fixing them. Ten of the twelve files did not exist at
v2.6.14; onlyeditorToolbar.test.tsandwindowClosePerTab.test.tspredate it. This is not inherited debt.Based on
df80968(#447).npm test586/586,npm run check638 files / 0 errors,npm run buildclean. No Rust touched.The one that was live
mermaidPrintTheme.test.tsexists so that PDF export renders diagrams light — Mermaid bakes theme colours into the SVG as attributes, so a dark preview exports dark boxes with dark text onto white paper. The file assertedassert.deepEqual(mermaid.themes, [MERMAID_PRINT_THEME]), andMERMAID_PRINT_THEMEis the constantrenderDiagramsForPrintreads.584 tests, 584 passing. Every PDF export re-themes every diagram dark, and the file whose whole purpose is the print theme has nothing to say about it.
Making the implementation stop using the constant is caught, so the call sequencing was real — only the value was unpinned. The assertion now spells
'neutral', andMERMAID_PRINT_THEMEwas exported for nothing else, so theexportgoes with it.Shape 1 — value pins that pin nothing
mermaidPrintTheme.test.ts:103,108,114deepEqual(mermaid.themes, [MERMAID_PRINT_THEME])['neutral']— the literal is the claimeditorToolbar.test.ts:14-26,41DEFAULT_EDITOR_TOOLBAR_ORDER, which isEDITOR_TOOLBAR_TOOLS.map(t => t.id)Deleting the Underline tool from the editor toolbar catalogue outright left the whole file green: expectations written in terms of a derived constant shrink with it.
titlebarToolbar.test.tshas the same derived shape but also asserts literal id lists, so the same deletion there reddens three tests;editorToolbar.test.tsnow does too. The added test also coversname,label,groupandshortcut, which nothing tested — a tool that silently loses its accelerator still renders.Shape 2 — discriminators neutralised
exportRichContent.test.ts:299— "a document with no math carries no KaTeX fonts at all" calledinlineKatexFontFaces(css, new Set(), new Map()). The empty byte map deletes every face through the "bytes could not be read" branch, so the empty family set decides nothing. Deleting the family filter fromexportFonts.ts:171was green across the whole suite, integration assertions included. The test now supplies every face's bytes, so the family filter is the only thing left that can drop them.previewAnchorRestore.test.ts:327—/import \{[\s\S]*findAnchorElement[\s\S]*\} from '\.\/utils\/previewAnchor\.js'/. Both gaps are unbounded, so the match starts at the first import in the file and runs past every brace between there and line 46. ForkingfindAnchorElement/getAnchorScrollTopinto another module, leaving the rest of the import in place, was green. Now read out of the one import statement ([^}]*) and checked as a specifier list.editorPdfExport.test.ts:379-380— the test is named "a failed refresh does not pass off a stale export as a fresh one" and asserted/catch \(error\)/and/addToast\(/.Green, both regexes still matching, with the claim in the test's name inverted. The export deliberately still goes ahead on a failed refresh — printing the stale DOM beats not printing — so the entire contract lives in the severity. That is what is asserted now: exactly one toast in the catch, severity
warning.Shape 3 — over-fitted spellings
Two
doesNotMatchguards pinned the exact one-line spelling a fixed defect happened to be written in. Both defects were reintroduced in ordinary brace /for…ofspelling; both green.liveModeWatchedPath.test.ts:26—/isLiveMode\(\)\) invoke\('watch_file'/againstdocumentSession.svelte.ts, where neither token occurs any more. #296 removed theisLiveModeoption from that module entirely, so the guard has been reading a file that cannot contain its pattern. Re-anchored to who may own the watcher:filesMatching(readSourceFiles('src'), /invoke\(\s*'watch_file'/)must be['src/lib/MarkdownViewer.svelte'], andcallbackBodies(viewer, '$effect')must contain exactly one effect that watches — which is also where the matchingunwatch_filehas to live.windowClosePerTab.test.ts:25—/tabManager\.tabs\.forEach\(\(t\) => \(t\.isDirty = false\)\)/. Now/\.isDirty\s*=\s*false/over the close handler: the assignment, not the loop it is written in. (This is one of the two files that predatev2.6.14.)Deleted rather than repaired
Five sites have no reachable subject. Each is dominated by an assertion that already covers the ground, named in a comment where the dead one was.
exportSanitize.test.ts:56assert.match(POC, /onerror=/)—POCis a template literal three lines aboveuriIsAllowed('x')runs the real regexp and staysi18nCoverage.test.ts:453assert.ok(total >= 0)on a sum of array lengths:249every key the source asks for exists in English,:267no language defines a key English does not havesettingsPersistence.test.ts:195new SettingsStore() instanceof SettingsStore— a constructor that throws fails the line above, one that returns fails nothingrenderProtocol.test.ts:252-256:242already asserted strictly equal:242-246scrollSync.test.ts:52(200/1000)*600 === 120over the file's own two fixture constants:54-55, on numbers the mapping returnedThe
renderProtocolcase was checked rather than argued: makingprocessDisplayMathBlocksstrip underscores fromdata-math-sourcefails at line 242, so line 252 never runs.scrollSync.test.ts:52's 120 is genuinely useful documentation — it is the number the whole two-section design exists to avoid — so it stays, in the comment that already stated it.Reported as unreachable, and is not
exportSanitize.test.ts:68—assert.equal(MARKDOWN_SANITIZE_CONFIG.ALLOWED_URI_REGEXP, ALLOWED_MARKDOWN_URI_REGEXP)compares the field against the constant it is assigned from one line earlier insanitize.ts, and the two are the same object reference. But the assignment is reachable:fails it, and
previewSanitize.test.tswith it. Left as it stands.Mutation check
Each mutation applied to
df80968, the suite run, the source restored; then re-applied against this branch. "before" is the full suite (584 tests atdf80968), "after" is the file under test.mermaidPrintTheme:103,108,114MERMAID_PRINT_THEME'neutral'→'dark'actual: [ 'dark' ],expected: [ 'neutral' ]mermaidPrintTheme:187-189MarkdownViewer.svelte:1072(preview) tomermaidTheme: 'dark', leaving the HTML export at 1886actual: [ "'dark'" ],expected: [], every diagram render must resolve the theme the way the print restore does (currentMermaidTheme())mermaidPrintTheme:152if (diagrams.length === 0) return () => {};actual: [ 'neutral' ],expected: [], nothing to re-render must not re-theme mermaidmermaidPrintTheme:152if (!root || !mermaid) return () => {};TypeError: Cannot read properties of null (reading 'initialize')editorToolbar:14-26,41EDITOR_TOOLBAR_TOOLSexportRichContent:299if (!usedFamilies.has(face.family)) continue;fromexportFonts.ts:171/@font-face/previewAnchorRestore:327findAnchorElement/getAnchorScrollTopinto a second module, leave the other two specifiersactual: [ 'findAnchorElement', 'getAnchorScrollTop' ],expected: []editorPdfExport:379-380addToast('Export refreshed', 'success')actual: [ 'success' ],expected: [ 'warning' ]liveModeWatchedPath:26documentSession.loadMarkdownre-issuesinvoke('watch_file', …)in an ordinaryif (…) { … }actual: [ 'src/lib/MarkdownViewer.svelte', 'src/lib/sessions/documentSession.svelte.ts' ],expected: [ 'src/lib/MarkdownViewer.svelte' ]windowClosePerTab:25for (const t of tabManager.tabs) t.isDirty = false;at the top of the dirty branchrenderProtocol:252-256data-math-sourcewritten with underscores stripped:242, never reaching:252— which is why:252-256is deletedexportSanitize:68ALLOWED_URI_REGEXP: /^[\s\S]*$/One honest gap. The survey's mutation for site 3 was make the early-return closure write a global; that is still green here, and the rewritten test does not claim otherwise. Writing an unrelated global is not a defect shape this helper has. What the test now claims — and what 3a and 3b prove — is that the handle the export's
finallycalls re-themes nothing and touches no DOM.Not covered
truncatedBufferGuard,viewModeWithoutSaving,previewSanitize,windowOrganization,recentFilesMultiWindowandeditorContextMenuI18nare untouched here — six sites where an unprotected guard, rather than a dead assertion, is the finding.🤖 Generated with Claude Code