import assert from 'node:assert/strict'; import fs from 'node:fs'; import { spawnSync } from 'node:child_process'; import { procurementNavigation, activeProcurementEntry, } from '../resources/js/lib/procurement-navigation.ts'; const result = spawnSync( 'php', ['artisan', 'route:list', '--json', '--except-vendor'], { encoding: 'utf8' }, ); assert.equal(result.status, 0, result.stderr); const routes = JSON.parse(result.stdout); const rows = new Map(); for (const role of [ 'admin', 'procurement', 'finance', 'department_head', 'warehouse', 'requester', ]) { for (const payables of [false, true]) { const groups = procurementNavigation(role, payables); assert.ok( groups.length <= 6, 'Navigation must stay within six related functional groups', ); const ids = groups.flatMap((group) => group.entries.map((entry) => entry.id), ); assert.equal( new Set(ids).size, ids.length, 'Navigation entries must not be duplicated', ); for (const group of groups) for (const entry of group.entries) { const uri = new URL(entry.path, 'http://local').pathname.slice( 1, ); const route = routes.find( (route) => route.uri === uri && route.method.split('|').includes('GET'), ); assert.ok( route, `${role}: ${entry.label} has no registered GET route (${uri})`, ); assert.equal( activeProcurementEntry(groups, entry.path), entry.id, `${role}: wrong active menu for ${entry.path}`, ); rows.set(`${role}:${entry.id}`, { role, group: group.label, id: entry.id, label: entry.label, path: entry.path, action: route.action, full_page: !!entry.fullPage, }); } assert.equal( groups.some((group) => group.entries.some( (entry) => entry.id === 'procurement_reports', ), ), ['admin', 'procurement', 'finance', 'department_head'].includes( role, ), ); } } const configuredFinance = procurementNavigation(['finance'], false).flatMap( (g) => g.entries, ); const separate = procurementNavigation('admin', true); assert.ok(separate.find((group) => group.id === 'purchasing').entries.every((entry) => !entry.path.startsWith('/pessoas'))); assert.ok(separate.find((group) => group.id === 'people').entries.every((entry) => entry.path.startsWith('/pessoas'))); for (const permission of ['people_service_prepare','people_service_review','people_staff_prepare','people_staff_review']) { const entries = procurementNavigation([permission], false).flatMap((group) => group.entries); assert.equal(entries.some((entry) => entry.id === 'people_hiring'), true); assert.equal(entries.some((entry) => entry.id === 'company' || entry.id === 'invoices' || entry.id === 'new_request'), false); } for (const permission of ['people_registry_read','people_registry_manage']) { const entries = procurementNavigation([permission],false).flatMap((group)=>group.entries); assert.equal(entries.some((entry)=>entry.id==='people_registry'),true); assert.equal(entries.some((entry)=>entry.id==='people_hiring'),false); } assert.equal( configuredFinance.some((e) => e.id === 'organization_parameters'), false, ); assert.equal( configuredFinance.some((e) => e.id === 'new_request'), false, ); const configuredMulti = procurementNavigation( ['finance', 'requester', 'admin'], false, ).flatMap((g) => g.entries); assert.equal( configuredMulti.some((e) => e.id === 'organization_parameters'), true, ); assert.equal( configuredMulti.some((e) => e.id === 'new_request'), true, ); const proof = { checked_at: new Date().toISOString(), result: 'passed', entries: rows.size, roles: 6, configurable_permissions_and_multiple_profiles: true, maximum_functional_groups: 6, source: 'procurementNavigation compared with actual Laravel GET routes', scope: 'Menu routing, active entry and visibility contract; not a substitute for functional or visual workflow acceptance', rows: [...rows.values()], }; fs.writeFileSync( 'docs/proofs/menu-code-contract.json', JSON.stringify(proof, null, 2) + '\n', ); console.log( JSON.stringify({ result: proof.result, entries: proof.entries, roles: proof.roles, }), );