fix: a path that names nothing yet has no breadcrumb leaf

`splitItemPath` documents that it gives up on a path still being typed, but
`f/demo/` is three parts and returned a leaf with an empty name — a blank
segment in the trail. The editor binds the path live, so the breadcrumb sees
every keystroke.

Tested here rather than `navPageFor`'s sort: no two `NAV_PAGES` paths nest, so
the longest-prefix case that test claimed to pin has only one candidate. Renamed
it to what it actually checks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem Lemouel
2026-09-30 10:27:33 -07:00
co-authored by Claude Opus 5
parent 3906774eba
commit 7208ffc10f
3 changed files with 24 additions and 1 deletions
@@ -0,0 +1,20 @@
import { describe, it, expect } from 'vitest'
import { splitItemPath } from './breadcrumbPath'
describe('splitItemPath', () => {
it('walks the scope, each subfolder, then the item, each with its cumulative path', () => {
expect(splitItemPath('f/demo/sub/weather_report')).toEqual({
dirs: [
{ name: 'f/demo', fullPath: 'f/demo' },
{ name: 'sub', fullPath: 'f/demo/sub' }
],
leaf: { name: 'weather_report', fullPath: 'f/demo/sub/weather_report' }
})
})
it('gives up on a path that names nothing yet, trailing separator included', () => {
// The editor binds the path live, so every keystroke reaches the breadcrumb.
expect(splitItemPath('f/demo')).toBeUndefined()
expect(splitItemPath('f/demo/')).toBeUndefined()
})
})
@@ -13,6 +13,9 @@ export function splitItemPath(path: string): { dirs: PathDir[]; leaf: PathDir }
if (parts.length < 3) return undefined
const scope = parts.slice(0, 2).join('/')
const slug = parts.slice(2)
// `f/demo/` is three parts but names nothing yet, and a leaf with an empty name draws a blank
// segment. The editor's path is bound live, so the breadcrumb sees every keystroke.
if (slug[slug.length - 1] === '') return undefined
const dirs: PathDir[] = [{ name: scope, fullPath: scope }]
let acc = scope
for (let i = 0; i < slug.length - 1; i++) {
@@ -6,7 +6,7 @@ describe('navPageFor', () => {
expect(navPageFor('/base/runs', '/base')?.label).toBe('Runs')
})
it('keeps an item route on its page (longest prefix wins)', () => {
it('keeps an item route on its page', () => {
expect(navPageFor('/runs/f/demo/x', '')?.label).toBe('Runs')
})