test: cover the eleven components we wrote that nothing tested - #519
Merged
Conversation
#86 is an inventory of everything untested; this is one slice of it, chosen by provenance. Re-measured against `nuxt/ui@v4`: of the 68 components no spec imports, all but thirteen are upstream's, and upstream does not test them either. Writing those would be testing somebody else's code twice. The thirteen are ours, and nothing anywhere covers them. Eleven of them are covered here — `PageCardGroup`, `SidebarLayout` with its six wrappers, and `Navbar` with its three. `ModalDialogClose` is left: it is a nineteen-line `DialogClose` passthrough that needs a dialog around it to say anything. `PageCardGroup` carries the logic worth the most: single versus multiple selection, the four key-mapping props, grouping by category, and the colour fallbacks. Every behavioural claim it makes in JSDoc now has a test, and each was mutation-checked. Two defects came out of writing them. `SidebarLayout` rendered `data-state="isLoading ? 'loading' : 'show'"` as a literal string — the binding was written without its colon, so the attribute carried the source of the expression rather than its value, on every layout, always. It is the only unbound `data-state` in `src/runtime/components`. `offContentScrollbar` is a public prop on `SidebarLayout` that does nothing. Both branches of its variant in `src/theme/sidebar-layout.ts` are empty strings, and the single compound reading it has its whole `class` block commented out. No test is added for it — a case would be byte-identical to `with isInner` and would read as coverage of a prop that does not work. Left as a finding rather than fixed: restoring those classes or dropping the prop is a decision about public API, not a test change. Three things the specs do that are worth copying: - Only `useRoute` is replaced in `SidebarLayout.spec.ts`, not the router. Installing one fails the other project every time: the `nuxt` project has no router, so `useRoute()` warns about a missing injection, and the `vue` project's shim already installs one, so a second plugin re-registers `RouterLink`. Each project's fix is the other's console-gate failure. - Element assertions read through `[data-slot="root"]`. A template that opens with an HTML comment renders as a fragment, and `wrapper.element` is then Vue Test Utils' own wrapper — `Navbar` looked like it rendered a `div` until that was accounted for. - The generated `size` and `columns` matrices skip the default value, because a case for it is byte-identical to `with items` (#454). The collision guard caught three such cases in the first draft, and a fixture too thin to let two content props differ. Coverage 71.89% to 74.31% of statements. Refs #86
9 tasks
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.
Linked issue
Refs #86 — one slice of it, not the whole inventory.
Type of change
revert(Scope): ...)How the slice was chosen
#86 lists everything untested. Re-measured, its June figures have moved — 66 components without a spec of their own rather than 76, 13 untested composables rather than 19, and
tv.ts, which the issue calls out as "the theme merge engine!", has had a spec for a while.The measure that mattered was different: 68 components are imported by no spec at all, and of those, all but thirteen exist in
nuxt/ui@v4— where they have no specs either. Writing those would be testing somebody else's code twice, in a file we re-sync from them. The thirteen that are ours have no coverage anywhere.Eleven are covered here.
ModalDialogCloseis left out: a nineteen-lineDialogClosepassthrough that needs a dialog around it before it can say anything.PageCardGroupSidebarLayoutSidebarBody/Footer/Header/Heading/Section/Spaceras/class/ slot contractNavbarNavbarDivider/Section/Spaceras/classcontractTwo defects found while writing them
SidebarLayoutrendered itsdata-stateas a literal string. The binding was written without its colon:so every layout put the source of the expression into the DOM instead of its value, always. It is the only unbound
data-stateinsrc/runtime/components. Fixed, with a test that reddens when the colon is removed again.offContentScrollbaris a public prop that does nothing. Both branches of its variant insrc/theme/sidebar-layout.tsare empty strings, and the one compound that reads it has its entireclassblock commented out:Not fixed here. Restoring those classes or removing the prop is a decision about public API shape, not a test change. No case is added for it either — one would be byte-identical to
with isInnerand would read as coverage of a prop that does not work.Three things in the specs worth copying
useRouteis mocked inSidebarLayout.spec.ts, not the router. Installing one fails the other project every time: thenuxtproject has none, souseRoute()warns about a missing injection on every mount; thevueproject's shim already installs one, so a second plugin re-registersRouterLink. Each project's fix is the other's console-gate failure.[data-slot="root"]. A template that opens with an HTML comment renders as a fragment, andwrapper.elementis then Vue Test Utils' own wrapper.Navbarlooked like it rendered adivuntil that was accounted for — the component was fine, the assertion was not.sizeandcolumnsmatrices skip the default value, because a case for it is byte-identical towith items(test: fourteen specs assert a default because the fixture never reaches the branch #454).What the #454 guard caught in the first draft
Three cases that asserted nothing, and it was right about all three: two default-valued variants of
PageCardGroup, and aSidebarLayoutfixture too thin foruseLightContentto have any content to shape. Fixed by narrowing the matrices and giving the fixture a slot, not by regenerating the baseline — the baseline is unchanged.Mutation-checked throughout. Where a claim could not be made to fail —
categoryKey: ''short-circuits to the same output as looking the empty key up, andicon-over-avataris enforced twice, ingetItemAvatarand again inPageCard— the spec says so instead of carrying a test that cannot go red.Gate
lint,typecheck, 328 test files / 7618 tests,test:module, and coverage 71.89 → 74.31% statements, 69.93 → 71.53 branches, 71.19 → 73.35 functions, 71.44 → 73.80 lines, against thresholds of 70 / 68 / 70 / 70.Checklist
Generated by Claude Code