Files
TREK/client/src/components/Layout/navItems.test.ts
T
Maurice c04e740ff1 fix(mobile-nav): dock Journey by default, move Atlas one tap further
Feedback from Discord: on a phone in the field the two things you reach
for are the itinerary and the journal, but the default dock spends its
two free slots on Vacay and Atlas. Journey sits under More, and most
people never open the navbar customiser to fix that.

DEFAULT_DOCK_IDS becomes a priority list instead of a membership test:
the first MOBILE_NAV_MAX_BAR entries that are actually enabled take the
slots. Journey ships disabled, so an instance that never turned it on
keeps the exact Vacay/Atlas dock it has today. Listing all four known
global addons also fills the dock when one of them is switched off,
where the old membership test left the slot empty.

Accounts that saved their own bar/more split are untouched: a non-empty
config still wins over the default, so nobody's arrangement moves.
2026-09-07 23:18:23 +02:00

79 lines
3.5 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { LayoutGrid } from 'lucide-react'
import { buildNavItems, splitMobileNav, type NavItemDef } from './navItems'
const item = (id: string): NavItemDef => ({ id, to: `/${id}`, label: id, icon: LayoutGrid })
const ids = (xs: NavItemDef[]) => xs.map((x) => x.id)
// Dashboard + four global addons in store order.
const items = [item('dashboard'), item('vacay'), item('atlas'), item('journey'), item('collections')]
describe('buildNavItems', () => {
const t = (k: string) => k // untranslated → falls back to the addon/plugin name
it('puts Dashboard first, then addons, then page plugins as plugin:<id>', () => {
const out = buildNavItems(
[{ id: 'vacay', name: 'Vacay', icon: 'CalendarDays' }],
[{ id: 'foo', name: 'My Plugin', icon: null }],
t,
)
expect(ids(out)).toEqual(['dashboard', 'vacay', 'plugin:foo'])
expect(out[0].pinned).toBe(true)
expect(out[2].to).toBe('/plugins/foo')
expect(out[2].label).toBe('My Plugin')
})
})
describe('splitMobileNav', () => {
it('docks the top two enabled defaults when there is no config', () => {
for (const cfg of [undefined, { bar: [], more: [] }]) {
const s = splitMobileNav(items, cfg)
expect(ids(s.bar)).toEqual(['dashboard', 'vacay', 'journey'])
// Atlas is still reachable, one tap further under More.
expect(ids(s.more)).toEqual(['atlas', 'collections'])
}
})
it('keeps the Vacay/Atlas dock on an instance where Journey is switched off', () => {
const s = splitMobileNav([item('dashboard'), item('vacay'), item('atlas')], undefined)
expect(ids(s.bar)).toEqual(['dashboard', 'vacay', 'atlas'])
expect(ids(s.more)).toEqual([])
})
it('fills the free slot from the next default rather than leaving it empty', () => {
const s = splitMobileNav([item('dashboard'), item('atlas'), item('journey')], undefined)
expect(ids(s.bar)).toEqual(['dashboard', 'journey', 'atlas'])
expect(ids(s.more)).toEqual([])
})
it('leaves an account that picked its own dock alone', () => {
const s = splitMobileNav(items, { bar: ['vacay', 'atlas'], more: ['journey', 'collections'] })
expect(ids(s.bar)).toEqual(['dashboard', 'vacay', 'atlas'])
expect(ids(s.more)).toEqual(['journey', 'collections'])
})
it('honours a custom split and order, Dashboard still first', () => {
const s = splitMobileNav(items, { bar: ['journey'], more: ['collections', 'vacay', 'atlas'] })
expect(ids(s.bar)).toEqual(['dashboard', 'journey'])
expect(ids(s.more)).toEqual(['collections', 'vacay', 'atlas'])
})
it('drops stored ids that no longer exist and appends newly available ones under More', () => {
const s = splitMobileNav(items, { bar: ['ghost', 'vacay'], more: ['journey'] })
expect(ids(s.bar)).toEqual(['dashboard', 'vacay'])
// atlas + collections are new since the config was saved → appended to More
expect(ids(s.more)).toEqual(['journey', 'atlas', 'collections'])
})
it('caps the bar and overflows the excess into More', () => {
const s = splitMobileNav(items, { bar: ['vacay', 'atlas', 'journey', 'collections'], more: [] })
expect(ids(s.bar)).toEqual(['dashboard', 'vacay', 'atlas']) // Dashboard + 2
expect(ids(s.more)).toEqual(['journey', 'collections'])
})
it('never lets a stored dashboard id take a bar slot from the pinned one', () => {
const s = splitMobileNav(items, { bar: ['dashboard', 'vacay'], more: [] })
expect(ids(s.bar)).toEqual(['dashboard', 'vacay'])
})
})