From 8cb8c10d011753c6ad1f526023b87ba9ded0af77 Mon Sep 17 00:00:00 2001 From: yu859 <15715093608@163.com> Date: Sun, 28 Jun 2026 12:53:33 +0800 Subject: [PATCH] fix(ui): avoid double slash in item selection URL --- tests/e2e/ui.spec.ts | 18 ++++++++++++++++++ ui/composables/useSelectedItemSync.ts | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/e2e/ui.spec.ts b/tests/e2e/ui.spec.ts index a7a6d5e..c3d5462 100644 --- a/tests/e2e/ui.spec.ts +++ b/tests/e2e/ui.spec.ts @@ -28,6 +28,24 @@ test.describe('ui mode smoke', () => { expect(errors).toEqual([]) }) + test('clicking an item updates the URL to /N (no double slash)', async ({ page }) => { + const errors = captureErrors(page) + await page.goto(`${BASE}/`) + await expect(page.locator('[data-testid="navbar"]')).toBeVisible({ timeout: 10_000 }) + + const row = page.locator('[data-testid="item-row"]').first() + await expect(row).toBeVisible({ timeout: 10_000 }) + const number = await row.getAttribute('data-item-number') + + await row.click() + // Regression: UI-mode selection must produce `/N`, never `//N` (which + // vue-router can't match — see useSelectedItemSync.buildBase). + await expect(page).toHaveURL(`${BASE}/${number}`) + // The selected row is still mounted (view not torn down by a bad redirect). + await expect(page.locator(`[data-testid="item-row"][data-item-number="${number}"]`)).toBeVisible() + expect(errors).toEqual([]) + }) + test('Cmd+K opens the command palette and filters by query', async ({ page }) => { const errors = captureErrors(page) await page.goto(`${BASE}/`) diff --git a/ui/composables/useSelectedItemSync.ts b/ui/composables/useSelectedItemSync.ts index 82d296c..68c1764 100644 --- a/ui/composables/useSelectedItemSync.ts +++ b/ui/composables/useSelectedItemSync.ts @@ -24,9 +24,9 @@ export function useSelectedItemSync(projectId: MaybeRefOrGetter, initial function buildBase(id: string): string { const mode = hub.capabilities.value?.mode if (mode !== 'hub') - return '/' + return '' const project = hub.projects.value.find(p => p.id === id) - return project ? `/${project.repo}` : '/' + return project ? `/${project.repo}` : '' } // Apply the URL number on mount/route change. @@ -50,7 +50,7 @@ export function useSelectedItemSync(projectId: MaybeRefOrGetter, initial if (!id) return const base = buildBase(id) - const target = number == null ? base : `${base}/${number}` + const target = number == null ? (base || '/') : `${base}/${number}` if (route.path === target) return router.replace(target).catch(() => {})