You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TL;DR: The recurring test-coverage gap tracked in #133 (new interactive behavior landing untested) keeps taking the same shape: specs assert on wrapper.props(...) passed into a stubbed child, not on the actual rendered DOM/accessible state. @vue/test-utils's API makes that the easy thing to reach for. Testing Library's query-by-role/label/accessible-name style makes the wrong thing hard to write instead of relying on someone remembering to write the right one.
#133 states the rule ("assert on the rendered effect, not the prop passed into a mock"), but a written rule still depends on someone applying it — and the API itself works against that: item.props('active') is one call away, while asserting on real aria-current/aria-pressed state on the actual rendered element takes more effort with @vue/test-utils alone. Testing Library's design principle is the opposite: getByRole('link', { name: 'Documents', current: 'page' }) structurally cannot pass unless the real DOM has the real attribute — there's no props-only shortcut available.
Concretely, this would have caught the #130 sidebar-dedupe bug (two nav entries both getting aria-current="page"): a query like getByRole('link', { current: 'page' }) returning more than one element is a direct, obvious assertion failure, whereas checking items.map(i => i.props('active')) never touches the actual collision.
Proposed scope
Add @testing-library/vue (verified: 8.1.0, vue: >= 3 peer dep, published 2026-08-07) and @testing-library/jest-dom (verified: 7.0.1, published 2026-08-09) alongside the existing @vue/test-utils suite — not a replacement. @vue/test-utils's shallowMount/prop-based assertions remain fine for pure logic/wiring checks where DOM fidelity isn't the point.
TL;DR: The recurring test-coverage gap tracked in #133 (new interactive behavior landing untested) keeps taking the same shape: specs assert on
wrapper.props(...)passed into a stubbed child, not on the actual rendered DOM/accessible state.@vue/test-utils's API makes that the easy thing to reach for. Testing Library's query-by-role/label/accessible-name style makes the wrong thing hard to write instead of relying on someone remembering to write the right one.Detail
Why this is a different fix than #133
#133 states the rule ("assert on the rendered effect, not the prop passed into a mock"), but a written rule still depends on someone applying it — and the API itself works against that:
item.props('active')is one call away, while asserting on realaria-current/aria-pressedstate on the actual rendered element takes more effort with@vue/test-utilsalone. Testing Library's design principle is the opposite:getByRole('link', { name: 'Documents', current: 'page' })structurally cannot pass unless the real DOM has the real attribute — there's no props-only shortcut available.Concretely, this would have caught the #130 sidebar-dedupe bug (two nav entries both getting
aria-current="page"): a query likegetByRole('link', { current: 'page' })returning more than one element is a direct, obvious assertion failure, whereas checkingitems.map(i => i.props('active'))never touches the actual collision.Proposed scope
@testing-library/vue(verified:8.1.0,vue: >= 3peer dep, published 2026-08-07) and@testing-library/jest-dom(verified:7.0.1, published 2026-08-09) alongside the existing@vue/test-utilssuite — not a replacement.@vue/test-utils'sshallowMount/prop-based assertions remain fine for pure logic/wiring checks where DOM fidelity isn't the point.aria-current,aria-pressed, accessible names) — the exact category of thing docs: close a testing-trigger gap for existing-file behavior changes #133's rule targets.Related
Found during review of #125/#127/#130, all three of which hit this same gap independently.