feat(PBI-ll): voeg lib/product-switch-path.ts toe met resolveProductSwitchTarget

Pure helper die doel-URL bij product-wissel bepaalt; unit-tests dekken alle pad-gevallen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scrum4Me Agent 2026-05-14 21:36:57 +02:00
parent 3ad352c10f
commit ab8a73d7c3
2 changed files with 69 additions and 0 deletions

View file

@ -0,0 +1,55 @@
import { describe, it, expect } from 'vitest'
import { resolveProductSwitchTarget } from '@/lib/product-switch-path'
describe('resolveProductSwitchTarget', () => {
it('returns null for non-product pages', () => {
expect(resolveProductSwitchTarget('/dashboard', 'new-id')).toBeNull()
expect(resolveProductSwitchTarget('/insights', 'new-id')).toBeNull()
expect(resolveProductSwitchTarget('/ideas', 'new-id')).toBeNull()
expect(resolveProductSwitchTarget('/jobs', 'new-id')).toBeNull()
})
it('maps /products/<old> to /products/<new>', () => {
expect(resolveProductSwitchTarget('/products/old-id', 'new-id')).toBe('/products/new-id')
})
it('maps /products/<old>/ to /products/<new>', () => {
expect(resolveProductSwitchTarget('/products/old-id/', 'new-id')).toBe('/products/new-id')
})
it('maps /products/<old>/sprint to /products/<new>/sprint', () => {
expect(resolveProductSwitchTarget('/products/old-id/sprint', 'new-id')).toBe(
'/products/new-id/sprint',
)
})
it('maps /products/<old>/sprint/<sprintId> to /products/<new>/sprint', () => {
expect(resolveProductSwitchTarget('/products/old-id/sprint/abc123', 'new-id')).toBe(
'/products/new-id/sprint',
)
})
it('maps /products/<old>/sprint/.../planning to /products/<new>/sprint', () => {
expect(resolveProductSwitchTarget('/products/old-id/sprint/abc123/planning', 'new-id')).toBe(
'/products/new-id/sprint',
)
})
it('maps /products/<old>/solo to /products/<new>/solo', () => {
expect(resolveProductSwitchTarget('/products/old-id/solo', 'new-id')).toBe(
'/products/new-id/solo',
)
})
it('falls back to /products/<new> for /products/<old>/settings', () => {
expect(resolveProductSwitchTarget('/products/old-id/settings', 'new-id')).toBe(
'/products/new-id',
)
})
it('falls back to /products/<new> for unknown sub-segments', () => {
expect(resolveProductSwitchTarget('/products/old-id/unknown/deep', 'new-id')).toBe(
'/products/new-id',
)
})
})

View file

@ -0,0 +1,14 @@
export function resolveProductSwitchTarget(
pathname: string,
newProductId: string,
): string | null {
const match = pathname.match(/^\/products\/([^/]+)(\/.*)?$/)
if (!match) return null
const rest = match[2] ?? ''
if (!rest || rest === '/') return `/products/${newProductId}`
if (rest.startsWith('/sprint')) return `/products/${newProductId}/sprint`
if (rest.startsWith('/solo')) return `/products/${newProductId}/solo`
return `/products/${newProductId}`
}