Skip to content

test: cover the search row and version-history dialog#118

Merged
aaronjmars merged 2 commits into
mainfrom
test/component-coverage-search-row
Jul 20, 2026
Merged

test: cover the search row and version-history dialog#118
aaronjmars merged 2 commits into
mainfrom
test/component-coverage-search-row

Conversation

@aaronjmars

Copy link
Copy Markdown
Collaborator

Follow-up to #117. The suite was entirely logic-level — nothing rendered a component — so the search-row behaviours had no coverage at all, despite one of them being a regression I caught by hand while writing #117. This adds the missing layer.

279 → 292 tests.

Infrastructure

Opt-in per file, so nothing existing changes:

  • environment: "node" stays the default; the 279 existing tests keep running DOM-free
  • component tests declare // @vitest-environment jsdom in a docblock
  • test/setup-dom.ts guards everything on document existing, so the node suites load it harmlessly
  • test/jest-dom.d.ts registers the matcher types, since the runtime import is dynamic and invisible to tsc

New devDeps: @testing-library/react, @testing-library/user-event, @testing-library/jest-dom, jsdom.

Every test was mutation-checked

A green test proves nothing until it's seen to fail, so I reverted the implementation to each broken form and confirmed the suite catches it:

Mutation Test that fails
searchActive && !searchOpen (condition- not edge-triggered) closes with an active query and stays closed
drop the / render adjustment opens and focuses the input when the / signal arrives
drop key={deckId} never shows the previous deck's rows after switching decks

The first is the #117 regression: it re-opens the row on the next render, making it impossible to dismiss.

The third only fails after tightening the test. My first version waited for the new deck's rows to appear, which happily tolerated the stale window that the key exists to close — the effect refetches on the deckId change regardless. It now holds deck B's read open and asserts that deck A's rows are already gone.

A comment this exercise corrected

Removing the open && guard from the dialog broke nothing — because DialogContent already unmounts its children on close, and that is what resets the state per open. The guard is belt-and-braces. My #117 comment implied it was the reset mechanism, so it's been rewritten to describe what actually happens and to explain what the key separately covers.

That's the only non-test source change in this PR.

Checks

eslint --max-warnings=0 clean · 292/292 tests · tsc --noEmit · next build. Node suites are unaffected — full run is ~4s.

Adds component-level testing. The suite was entirely logic-level — nothing
rendered a component — so the search-row behaviours had no coverage at all,
despite one of them being a regression caught by hand two PRs ago.

Infrastructure is opt-in per file: node stays the default environment so the
existing suites keep running DOM-free, and component tests declare
`@vitest-environment jsdom` in a docblock. The shared setup file guards
everything on `document` being present, so the node suites can load it
harmlessly.

Every test was mutation-checked — the implementation was reverted to the
broken form and the suite confirmed to fail:

  - condition-triggered search open (`searchActive && !searchOpen`) fails
    `closes with an active query and stays closed`, the regression that
    made the row impossible to dismiss
  - dropping the `/` render adjustment fails the shortcut test
  - dropping `key={deckId}` fails the deck-switch test

That last one only fails after tightening the test. The first version
waited for the new deck's rows, which tolerated the stale window the key
exists to close; it now asserts against the previous deck's rows while the
new read is still in flight.

The same exercise corrected a comment: removing the `open &&` guard broke
nothing, because DialogContent already unmounts its children on close.
That unmount is what resets the state per open — the guard is redundant and
the comment now says so rather than claiming credit for the reset.
The lockfile in the previous commit was written by npm 11, which hoists
vitest's nested @esbuild/* platform packages to the top level and drops the
nested entries. CI resolves the tree with the npm 10 that ships with Node
22 and expects them where they were, so `npm ci` failed on every platform
binary before a single test ran.

package.json pins packageManager to npm@10.9.8 for exactly this reason.
Regenerated with that version: the lockfile diff is now purely additive
(755 insertions, 0 deletions) and `npm ci` reproduces the tree cleanly.
@aaronjmars
aaronjmars merged commit bdc1e01 into main Jul 20, 2026
2 checks passed
@aaronjmars
aaronjmars deleted the test/component-coverage-search-row branch July 20, 2026 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant