import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import { compileFunction } from 'node:vm'; import { createRequire } from 'node:module'; import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import ts from 'typescript'; const require = createRequire(import.meta.url), root = new URL('../../resources/js/', import.meta.url); let page = { component: 'portal/about', url: '/sobre', props: { auth: { user: null } }, }; const MenuPlacement = React.createContext(false); const PortalMenu = ({ primary = false }) => React.useContext(MenuPlacement) && !primary ? null : React.createElement( 'header', { 'data-portal-horizontal-menu': true }, 'Dropdown common header', ); const passthrough = ({ children }) => children; const mocks = { '@inertiajs/react': { usePage: () => page, Link: ({ href, children, ...props }) => React.createElement('a', { href, ...props }, children), }, '@/components/portal-menu': { MenuPlacement, PortalMenu }, '@/components/search-feedback': { default: () => null }, '@/lib/search-territory': { searchTerritoryHref: (href) => href }, '@/components/tempo-brand': { TempoUiProvider: passthrough, useTempoUi: () => ({ t: (x) => x }), }, '@/translation/page-translator': { PageTranslator: () => null }, '@/components/tempo-footer': { TempoFooter: () => null }, '@/components/navigation-context': { NavigationContextProvider: passthrough, NavigationContextSummary: () => React.createElement('div', { 'data-context-summary': true }), }, '@/components/breadcrumbs': { Breadcrumbs: ({ breadcrumbs }) => React.createElement( 'nav', { 'aria-label': 'Local breadcrumbs' }, breadcrumbs.map((b) => b.title).join('/'), ), }, }; function load(name) { const output = ts.transpileModule( fs.readFileSync(new URL(name, root), 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX, }, }, ).outputText; const module = { exports: {} }; compileFunction(output, ['require', 'module', 'exports'])( (name) => mocks[name] ?? require(name), module, module.exports, ); return module.exports.default; } const PortalNavigation = load('layouts/portal-navigation.tsx'), AppHeaderLayout = load('layouts/app/app-header-layout.tsx'); mocks['@/layouts/app/app-header-layout'] = { default: AppHeaderLayout }; const AppLayout = load('layouts/app-layout.tsx'); const app = fs.readFileSync(new URL('app.tsx', root), 'utf8'), match = app.match( /layout: (\(name\) => \{[\s\S]*?\n \}),\n strictMode/, ); assert.ok(match); const resolveLayout = compileFunction('return ' + match[1], [ 'PortalNavigation', 'AuthLayout', 'AppLayout', 'SettingsLayout', ])(PortalNavigation, passthrough, AppLayout, passthrough); const files = fs .readdirSync(new URL('pages/', root), { recursive: true }) .filter((f) => f.endsWith('.tsx')); void test('every registered page layout renders exactly one common horizontal header, including auth/settings/private screens', () => { for (const file of files) { const name = file.replaceAll(path.sep, '/').replace(/\.tsx$/, ''); page = { component: name, url: '/qa-layout-check', props: { auth: { user: null } }, }; const layouts = [resolveLayout(name)].flat(), child = React.createElement( 'section', { 'data-page-content': true }, React.createElement(PortalMenu), name, ); const tree = layouts.reduceRight( (children, Layout) => React.createElement( Layout, { breadcrumbs: [{ title: 'QA breadcrumb', href: '/qa' }] }, children, ), child, ); const html = renderToStaticMarkup(tree); assert.equal( (html.match(/data-portal-horizontal-menu/g) ?? []).length, 1, name, ); assert.match(html, /data-page-content/, name); assert.match(html, /data-context-summary/, name); assert.doesNotMatch(html, /sidebar-trigger|data-sidebar=/, name); } }); void test('private layout keeps page breadcrumbs without reintroducing a separate navigation or sidebar provider', () => { const html = renderToStaticMarkup( React.createElement( AppLayout, { breadcrumbs: [{ title: 'Histórico', href: '/historico' }] }, 'Existing private content', ), ); assert.match(html, /Histórico/); assert.match(html, /Existing private content/); assert.doesNotMatch(html, /Dropdown common header/); }); void test('main five shortcuts remain in the hero while discovery no longer repeats them', () => { const hero = fs.readFileSync( new URL('components/portal-hero.tsx', root), 'utf8', ); for (const href of [ '/porque-investir', '/investimentos/iniciar', '/oportunidades', '/simulador-fiscal', '/sectores', ]) assert.ok(hero.includes('href="' + href + '"'), href); }); console.log( 'Page layout coverage:', files.length, 'existing TSX pages; structural SSR only, not browser/viewport proof.', );