// @vitest-environment jsdom // // Root layout — renders the top nav whose Home link + language switcher are // locale-prefixed off the CURRENT url (useUrlLocale → useLocation). We mock // useLocation (@voltro/web) to drive the active locale, and mock @voltro/i18n so // is a pass-through and resolves against the real catalogs. import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import { act, createElement, type ReactNode } from 'react' import { createRoot, type Root } from 'react-dom/client' import en from '../locales/en' import de from '../locales/de' const location = vi.fn<() => string>() vi.mock('@voltro/web', () => ({ useLocation: () => location() })) const catalogs: Record> = { en, de } const localeFor = (path: string): string => (/^\/de(?:\/|$)/.test(path) ? 'de' : 'en') vi.mock('@voltro/i18n', () => ({ // The locale catalogs call these at module top-level; identity mirrors the // real (compile-time-only) implementations so importing them doesn't throw. defineCatalog: (c: T): T => c, defineLocale: () => (c: T): T => c, I18nProvider: ({ children }: { children?: ReactNode }) => children, // The nav uses for link labels; resolve against the catalog of the // locale implied by the current path (matches what useUrlLocale computes). T: ({ id }: { id: string }) => catalogs[localeFor(location())]?.[id] ?? id, })) const { default: Layout } = await import('./layout') ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true let container: HTMLDivElement let root: Root const render = (node: ReactNode): void => { container = document.createElement('div') document.body.appendChild(container) act(() => { root = createRoot(container) root.render(node) }) } const hrefs = (): Array => Array.from(container.querySelectorAll('a')).map((a) => a.getAttribute('href')) beforeEach(() => location.mockReset()) afterEach(() => { if (root) act(() => root.unmount()) container?.remove() document.body.innerHTML = '' }) describe('landing layout — English (bare path)', () => { test('renders a bare Home link, an English nav label and the DE switcher target', () => { location.mockReturnValue('/') render(createElement(Layout, { children: createElement('p', null, 'page') })) const h = hrefs() expect(h).toContain('/') // the language switcher keeps you on the same bare page, re-prefixed per locale expect(h).toContain('/de') expect(container.textContent).toContain('Home') expect(container.textContent).toContain('page') }) }) describe('landing layout — German (/de prefix)', () => { test('prefixes the home link with /de and renders German labels', () => { location.mockReturnValue('/de') render(createElement(Layout, { children: null })) const h = hrefs() expect(h).toContain('/de') // switching back to en strips the prefix expect(h).toContain('/') expect(container.textContent).toContain('Start') }) })