- FIX 1: Replace <button @click="router.push"> with <RouterLink custom> + <a> for real link semantics (middle-click, ⌘-click, screen-reader); custom isNavItemActive prefix-match stays the active source of truth; adds :aria-current="page" on active items; drops useRouter/router.push. RouterLink to prop cast via itemTo() helper (RouteLocationRaw from unplugin-vue-router) to satisfy typed RouterLinkTyped<RouteNamedMap>. - FIX 2: Align .nav-item comment to actual template values (py-[9px] rounded-md, not CSS vars); replace inaccurate Tailwind v3/v4 before: composability justification in <style scoped> with the real reason (accent bar at left:-10px is clipped by the overflow-y-auto nav). - FIX 3: text-left → text-start (logical property, RTL-safe). - FIX 4: Document id=route-name assumption in useV2Nav.ts with a one-line comment at the id: assignment. - FIX 5: Reword misleading "dotted names" spec description to state the real invariant (id = v1 route name, already kebab-case). - FIX 6: Add 2 tests — useV2Nav wrapper .value equality, and consecutive-headings edge case (empty-items group produced). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
102 lines
3.2 KiB
TypeScript
102 lines
3.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { toV2NavGroups, useV2Nav } from '@/composables/useV2Nav'
|
|
import type { V2NavItem } from '@/types/v2/nav'
|
|
|
|
// Hand-built fixture — does NOT depend on the real orgNavItems contents.
|
|
const fixture = [
|
|
{ title: 'Alpha', to: { name: 'alpha' }, icon: { icon: 'tabler-home' } },
|
|
{ title: 'Beta', to: { name: 'beta' }, icon: { icon: 'tabler-bell' } },
|
|
{ heading: 'Group One' },
|
|
{ title: 'Gamma', to: { name: 'gamma' }, icon: { icon: 'tabler-star' }, count: 5 },
|
|
{ heading: 'Group Two' },
|
|
{ title: 'Delta', to: { name: 'delta' }, icon: { icon: 'tabler-settings' } },
|
|
] as const
|
|
|
|
describe('toV2NavGroups', () => {
|
|
it('places items before the first heading into a leading group with label ""', () => {
|
|
const groups = toV2NavGroups(fixture)
|
|
|
|
expect(groups[0].label).toBe('')
|
|
expect(groups[0].items).toHaveLength(2)
|
|
})
|
|
|
|
it('starts a new group when a heading entry is encountered', () => {
|
|
const groups = toV2NavGroups(fixture)
|
|
|
|
expect(groups).toHaveLength(3)
|
|
expect(groups[1].label).toBe('Group One')
|
|
expect(groups[2].label).toBe('Group Two')
|
|
})
|
|
|
|
it('maps item fields correctly: id, label, icon, to', () => {
|
|
const groups = toV2NavGroups(fixture)
|
|
const alpha = groups[0].items[0] as V2NavItem
|
|
|
|
expect(alpha.id).toBe('alpha')
|
|
expect(alpha.label).toBe('Alpha')
|
|
expect(alpha.icon).toBe('tabler-home')
|
|
expect(alpha.to).toEqual({ name: 'alpha' })
|
|
})
|
|
|
|
it('passes count through when present', () => {
|
|
const groups = toV2NavGroups(fixture)
|
|
const gamma = groups[1].items[0] as V2NavItem
|
|
|
|
expect(gamma.count).toBe(5)
|
|
})
|
|
|
|
it('leaves count undefined when absent', () => {
|
|
const groups = toV2NavGroups(fixture)
|
|
const alpha = groups[0].items[0] as V2NavItem
|
|
|
|
expect(alpha.count).toBeUndefined()
|
|
})
|
|
|
|
it('id equals the v1 route name (already kebab-case; no normalisation applied)', () => {
|
|
const groups = toV2NavGroups(fixture)
|
|
const delta = groups[2].items[0] as V2NavItem
|
|
|
|
expect(delta.id).toBe('delta')
|
|
})
|
|
|
|
it('returns empty groups array for an empty input', () => {
|
|
expect(toV2NavGroups([])).toEqual([])
|
|
})
|
|
|
|
it('items-only input (no headings) returns a single leading group', () => {
|
|
const onlyItems = [
|
|
{ title: 'A', to: { name: 'a' }, icon: { icon: 'tabler-a' } },
|
|
] as const
|
|
|
|
const groups = toV2NavGroups(onlyItems)
|
|
|
|
expect(groups).toHaveLength(1)
|
|
expect(groups[0].label).toBe('')
|
|
expect(groups[0].items).toHaveLength(1)
|
|
})
|
|
})
|
|
|
|
describe('useV2Nav', () => {
|
|
it('returns a computed whose .value equals toV2NavGroups(items)', () => {
|
|
const { groups } = useV2Nav(fixture)
|
|
|
|
expect(groups.value).toEqual(toV2NavGroups(fixture))
|
|
})
|
|
|
|
it('consecutive headings produce an empty-items group then the next group', () => {
|
|
const consecutiveHeadings = [
|
|
{ heading: 'First' },
|
|
{ heading: 'Second' },
|
|
{ title: 'Alpha', to: { name: 'alpha' }, icon: { icon: 'tabler-home' } },
|
|
] as const
|
|
|
|
const groups = toV2NavGroups(consecutiveHeadings)
|
|
|
|
expect(groups).toHaveLength(2)
|
|
expect(groups[0].label).toBe('First')
|
|
expect(groups[0].items).toHaveLength(0)
|
|
expect(groups[1].label).toBe('Second')
|
|
expect(groups[1].items).toHaveLength(1)
|
|
})
|
|
})
|