UNPKG

@furystack/shades

Version:

A lightweight UI framework for FuryStack with JSX support

92 lines (83 loc) 3.4 kB
import { describe, expect, expectTypeOf, it } from 'vitest' import { defineNestedRoutes } from './define-nested-routes.js' const makeComponent = () => null as unknown as JSX.Element describe('defineNestedRoutes', () => { it('Should return the same object reference at runtime', () => { const input = { '/tabs': { component: () => makeComponent(), hash: ['a', 'b'] as const, }, } const result = defineNestedRoutes(input) expect(result).toBe(input) }) it('Should accept values that satisfy Record<string, NestedRoute<...>>', () => { const routes = defineNestedRoutes({ '/bare': { component: () => makeComponent() }, '/tabs': { component: () => makeComponent(), hash: ['a', 'b'] as const, query: (raw): { page: number } | null => (typeof raw.page === 'number' ? { page: raw.page } : null), }, }) expect(Object.keys(routes)).toEqual(['/bare', '/tabs']) }) describe('Type preservation', () => { it('Should preserve `hash` as a readonly tuple of literal values', () => { const routes = defineNestedRoutes({ '/tabs': { component: () => makeComponent(), hash: ['overview', 'details'] as const, }, }) expectTypeOf(routes['/tabs'].hash).toEqualTypeOf<readonly ['overview', 'details']>() }) it('Should preserve the declared return type of a `query` validator', () => { const routes = defineNestedRoutes({ '/list': { component: () => makeComponent(), query: (raw): { page: number } | null => (typeof raw.page === 'number' ? { page: raw.page } : null), }, }) type QueryFn = NonNullable<(typeof routes)['/list']['query']> expectTypeOf<ReturnType<QueryFn>>().toEqualTypeOf<{ page: number } | null>() }) it('Should preserve nested children literals', () => { const routes = defineNestedRoutes({ '/navigation': { component: () => makeComponent(), children: { '/tabs': { component: () => makeComponent(), hash: ['a'] as const, }, }, }, }) type TabsHash = NonNullable<(typeof routes)['/navigation']['children']>['/tabs']['hash'] expectTypeOf<TabsHash>().toEqualTypeOf<readonly ['a']>() }) it('Should reject values that do not satisfy the NestedRoute constraint', () => { // @ts-expect-error -- `component` is required on every route entry defineNestedRoutes({ '/invalid': { hash: ['a'] as const } }) }) }) describe('Satisfies-collapse regression coverage', () => { it('Should keep literal shape intact (unlike a bare `satisfies` assertion)', () => { // A plain `satisfies` on `Record<string, NestedRoute<any>>` would widen // the per-route `hash` to `readonly any[]` and drop the literal tuple. // `defineNestedRoutes` must preserve the narrow tuple so downstream // type extractors (`ExtractRouteHash`, `RouteAt`) can recover it. const routes = defineNestedRoutes({ '/tabs': { component: () => makeComponent(), hash: ['overview'] as const, }, }) type Hash = (typeof routes)['/tabs']['hash'] expectTypeOf<Hash>().not.toEqualTypeOf<readonly any[]>() expectTypeOf<Hash>().toEqualTypeOf<readonly ['overview']>() }) }) })