145 lines
5.1 KiB
JavaScript
145 lines
5.1 KiB
JavaScript
import { compileFunction } from 'node:vm';
|
|
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import fs from 'node:fs';
|
|
import { createRequire } from 'node:module';
|
|
import React from 'react';
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import ts from 'typescript';
|
|
import {
|
|
portalNavigation,
|
|
currentNavigationItem,
|
|
} from '../../resources/js/lib/portal-navigation.ts';
|
|
import { searchTerritoryHref } from '../../resources/js/lib/search-territory.ts';
|
|
|
|
// Shallow SSR of the actual navigation component. Inertia and visual primitives
|
|
// are replaced by semantic wrappers; this is not a browser/viewport proof.
|
|
const require = createRequire(import.meta.url);
|
|
const source = fs.readFileSync(
|
|
new URL(
|
|
'../../resources/js/components/portal-sidebar-navigation.tsx',
|
|
import.meta.url,
|
|
),
|
|
'utf8',
|
|
);
|
|
const output = ts.transpileModule(source, {
|
|
compilerOptions: {
|
|
module: ts.ModuleKind.CommonJS,
|
|
target: ts.ScriptTarget.ES2022,
|
|
jsx: ts.JsxEmit.ReactJSX,
|
|
},
|
|
}).outputText;
|
|
const primitive =
|
|
(tag) =>
|
|
({ children, asChild, ...props }) =>
|
|
asChild
|
|
? React.cloneElement(children, {})
|
|
: React.createElement(tag, props, children);
|
|
const module = { exports: {} };
|
|
compileFunction(output, ['require', 'module', 'exports'])(
|
|
(name) => {
|
|
if (name === '@inertiajs/react')
|
|
return {
|
|
Link: ({ href, children, ...props }) =>
|
|
React.createElement('a', { href, ...props }, children),
|
|
};
|
|
if (name === '@/lib/portal-navigation')
|
|
return { currentNavigationItem };
|
|
if (name === '@/lib/search-territory') return { searchTerritoryHref };
|
|
if (name === 'lucide-react') return { LayoutGrid: () => null };
|
|
if (name === '@/components/ui/sidebar')
|
|
return {
|
|
SidebarGroup: primitive('section'),
|
|
SidebarGroupLabel: primitive('h2'),
|
|
SidebarMenu: primitive('ul'),
|
|
SidebarMenuButton: primitive('div'),
|
|
SidebarMenuItem: primitive('li'),
|
|
};
|
|
return require(name);
|
|
},
|
|
module,
|
|
module.exports,
|
|
);
|
|
const Component = module.exports.PortalSidebarNavigation;
|
|
const flatten = (rows) =>
|
|
rows.flatMap((r) => [
|
|
...(r.href ? [r.href] : []),
|
|
...flatten(r.children ?? []),
|
|
]);
|
|
const render = (access, url = '/') => {
|
|
const groups = portalNavigation(access);
|
|
return {
|
|
groups,
|
|
html: renderToStaticMarkup(
|
|
React.createElement(Component, { groups, url }),
|
|
),
|
|
};
|
|
};
|
|
void test('sidebar renders every nested authorised destination instead of a first-child shortcut', () => {
|
|
const { groups, html } = render({
|
|
authenticated: true,
|
|
manager: true,
|
|
businesses: true,
|
|
education: true,
|
|
ai: true,
|
|
contentManagementHref: '/gestao-conteudos',
|
|
contentManagementAccess: {
|
|
opportunities: {
|
|
index: '/management/opportunities',
|
|
create: '/management/opportunities/create',
|
|
},
|
|
},
|
|
scopedAdministration: [
|
|
{
|
|
label: 'Referências económicas',
|
|
href: '/management/economic-references/lot-01',
|
|
},
|
|
],
|
|
});
|
|
const hrefs = [...html.matchAll(/<a\b[^>]*href="([^"]+)"/g)].map((m) =>
|
|
m[1].replaceAll('&', '&'),
|
|
);
|
|
assert.deepEqual([...hrefs].sort(), flatten(groups).sort());
|
|
assert.equal(hrefs[0], '/gestao-conteudos');
|
|
for (const href of [
|
|
'/carteira',
|
|
'/zonas',
|
|
'/documentos',
|
|
'/legislacao',
|
|
'/management/opportunities',
|
|
'/management/economic-references/lot-01',
|
|
])
|
|
assert.ok(hrefs.includes(href), href);
|
|
assert.match(html, /Área de trabalho/);
|
|
});
|
|
void test('nested current destination is selected without changing its URL or replacing it with a group root', () => {
|
|
const { html } = render(
|
|
{ authenticated: true, manager: false },
|
|
'/zonas?category=zee',
|
|
);
|
|
const current = [...html.matchAll(/<a\b([^>]*aria-current="page"[^>]*)>/g)];
|
|
assert.equal(current.length, 1);
|
|
assert.match(current[0][1], /href="\/zonas"/);
|
|
});
|
|
void test('rendered visitor sidebar explains access without private operation links', () => {
|
|
const { html } = render({ authenticated: false, manager: false });
|
|
assert.match(html, /href="\/acesso-gestao"/);
|
|
assert.doesNotMatch(html, /href="\/management\//);
|
|
assert.doesNotMatch(html, /analysis=proactive/);
|
|
});
|
|
void test('sidebar carries the existing search territory when moving between catalogues', () => {
|
|
const { html } = render(
|
|
{ authenticated: false, manager: false },
|
|
'/oportunidades?province_id=QA-province&district_id=QA-district',
|
|
);
|
|
assert.match(
|
|
html,
|
|
/href="\/carteira\?province_id=QA-province&district_id=QA-district"/,
|
|
);
|
|
assert.match(
|
|
html,
|
|
/href="\/zonas\?province_id=QA-province&district_id=QA-district"/,
|
|
);
|
|
assert.match(html, /href="\/acesso-gestao"/);
|
|
});
|