const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const ts = require('typescript'); // Transpile TypeScript modules on the fly function loadTsModule(relativePath) { const fullPath = path.resolve(__dirname, relativePath); const dir = path.dirname(fullPath); const tsCode = fs.readFileSync(fullPath, 'utf8'); const jsCode = ts.transpileModule(tsCode, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020, jsx: ts.JsxEmit.ReactJSX, }, }).outputText; const m = { exports: {} }; const customRequire = (specifier) => { if (specifier === './firebase-client' || specifier.includes('firebase-client')) { return { firestore: {}, firebaseAuth: { currentUser: null, authStateReady: async () => {} } }; } if (specifier === 'firebase/firestore') { return { collection: () => ({}), doc: (_db, ...parts) => ({ path: parts.join('/') }), getDoc: async () => ({ exists: () => false, data: () => ({}) }), getDocs: async () => ({ docs: [] }), query: () => ({}), where: () => ({}), limit: () => ({}), collectionGroup: () => ({}), updateDoc: async () => {}, serverTimestamp: () => new Date(), runTransaction: async (_db, cb) => cb({ get: async () => ({ exists: () => false }), update: () => {} }), }; } if (specifier.startsWith('.')) { const resolved = path.resolve(dir, specifier); if (fs.existsSync(resolved + '.ts')) return loadTsModule(path.relative(__dirname, resolved + '.ts')); if (fs.existsSync(resolved + '.tsx')) return loadTsModule(path.relative(__dirname, resolved + '.tsx')); if (fs.existsSync(resolved)) return require(resolved); } return require(specifier); }; const fn = new Function('require', 'exports', 'module', '__filename', '__dirname', jsCode); fn(customRequire, m.exports, m, fullPath, dir); return m.exports; } console.log('--- STARTING FOUNDER PORTAL TEST SUITE ---'); // 1. Load domain logic & fixtures const clubData = loadTsModule('../lib/club-data.ts'); const clubFixtures = loadTsModule('../lib/club-fixtures.ts'); const { getPortalPermissions, sanitizePortalError, fetchClubData, fetchManageableClubs, fetchFounderClubContext, updateClubProfile, updateClubAccessSettings, fetchEligibleTransferMembers, transferClubOwnership, archiveClub, } = clubData; const { FIXTURE_FOUNDER_CLUB, FIXTURE_METRICS } = clubFixtures; // ========================================================================= // TEST 1: Role-Based Portal Access (Owner vs Admin vs Member vs Unauthenticated) // ========================================================================= console.log('Testing: Role-based portal access...'); // Unauthenticated const unauthPerms = getPortalPermissions('member', false); assert.equal(unauthPerms.isAuthenticated, false); assert.equal(unauthPerms.canManageSettings, false); assert.equal(unauthPerms.canInviteMembers, false); assert.equal(unauthPerms.canApproveApplications, false); assert.equal(unauthPerms.canPlanRides, false); assert.equal(unauthPerms.canTransferOwnership, false); // Authenticated Member (Standard non-admin rider) const memberPerms = getPortalPermissions('member', true); assert.equal(memberPerms.isAuthenticated, true); assert.equal(memberPerms.role, 'member'); assert.equal(memberPerms.canManageSettings, false, 'Member must not manage settings'); assert.equal(memberPerms.canInviteMembers, false, 'Member must not invite members'); assert.equal(memberPerms.canApproveApplications, false, 'Member must not approve applications'); assert.equal(memberPerms.canPlanRides, false, 'Member must not plan club rides'); assert.equal(memberPerms.canTransferOwnership, false, 'Member must not transfer ownership'); // Authenticated Admin const adminPerms = getPortalPermissions('admin', true); assert.equal(adminPerms.isAuthenticated, true); assert.equal(adminPerms.role, 'admin'); assert.equal(adminPerms.canManageSettings, true, 'Admin can manage general settings'); assert.equal(adminPerms.canInviteMembers, true, 'Admin can invite members'); assert.equal(adminPerms.canApproveApplications, true, 'Admin can approve applications'); assert.equal(adminPerms.canPlanRides, true, 'Admin can plan club rides'); assert.equal(adminPerms.canTransferOwnership, false, 'Admin MUST NOT transfer ownership'); // Authenticated Owner const ownerPerms = getPortalPermissions('owner', true); assert.equal(ownerPerms.isAuthenticated, true); assert.equal(ownerPerms.role, 'owner'); assert.equal(ownerPerms.canManageSettings, true); assert.equal(ownerPerms.canInviteMembers, true); assert.equal(ownerPerms.canApproveApplications, true); assert.equal(ownerPerms.canPlanRides, true); assert.equal(ownerPerms.canTransferOwnership, true, 'Only Owner can transfer ownership'); console.log(' PASS: Role-based permissions strictly enforced (Owner, Admin, Member, Unauth).'); // ========================================================================= // TEST 2: Club Display Rank != Administrative Role (Rank never grants access) // ========================================================================= console.log('Testing: Club Rank does not escalate software permissions...'); // If a member has Display Rank 'President' but software role 'member': const spoofedRankPerms = getPortalPermissions('member', true); assert.equal(spoofedRankPerms.canApproveApplications, false); assert.equal(spoofedRankPerms.canTransferOwnership, false); console.log(' PASS: Club Rank is purely display/organizational; software permissions derive only from role.'); // ========================================================================= // TEST 3: Safe Error Sanitization (No raw backend exception leakage) // ========================================================================= console.log('Testing: Safe error sanitization & leak prevention...'); const leaks = [ 'FirebaseException: [cloud_firestore/permission-denied] Missing or insufficient permissions at /databases/(default)/documents/clubs/ms-atl-01', 'FAILED_PRECONDITION: The query requires an index.', 'Error: connect ECONNREFUSED 127.0.0.1:8080 at TCPConnectWrap.afterConnect [as oncomplete]', 'DocumentNotFoundException: document /databases/(default)/documents/clubs/unknown was not found', 'TypeError: Cannot read property uid of undefined at club_service.dart:142', ]; for (const rawLeak of leaks) { const sanitized = sanitizePortalError(rawLeak); assert(!sanitized.includes('FirebaseException'), `Leaked FirebaseException in: ${sanitized}`); assert(!sanitized.includes('FAILED_PRECONDITION'), `Leaked FAILED_PRECONDITION in: ${sanitized}`); assert(!sanitized.includes('/databases/'), `Leaked Firestore path in: ${sanitized}`); assert(!sanitized.includes('127.0.0.1'), `Leaked network internals in: ${sanitized}`); assert(!sanitized.includes('.dart:'), `Leaked stack trace in: ${sanitized}`); assert( sanitized === 'Club information is restricted or requires authentication.' || sanitized === "Club information couldn't be loaded. Check your network connection." || sanitized === 'Club information could not be found.' || sanitized === 'Something went wrong. Please try again.', `Unexpected sanitized message: ${sanitized}` ); } console.log(' PASS: Zero raw backend exception or Firestore path leakage.'); // ========================================================================= // TEST 4: No Silent Production Demo Fallbacks // ========================================================================= async function runAllTests() { console.log('Testing: No silent production demo fallbacks...'); let threw = false; try { await fetchClubData('nonexistent-club-id'); } catch (err) { threw = true; assert.equal(err.message, 'Club information could not be found.'); } assert.equal(threw, true, 'fetchClubData must throw not-found instead of returning demo club'); console.log(' PASS: Production runtime strictly refuses silent demo fallbacks.'); // ========================================================================= // TEST 5: ClubMember != GroupRideParticipant Invariant & Location Privacy // ========================================================================= console.log('Testing: ClubMember != GroupRideParticipant & Location Privacy Invariant...'); // Read ClubRideCard source to verify exact verbatim notice text const rideCardSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/club-ride-card.tsx'), 'utf8'); const verbatimNotice = 'Live location is shared only with eligible ride participants while sharing is enabled. Club membership alone never grants access to rider location.'; assert(rideCardSrc.includes(verbatimNotice), 'Missing verbatim live location privacy notice in ClubRideCard'); // Verify that forbidden claims are NOT made in ClubRideCard assert(!rideCardSrc.includes('end-to-end encryption'), 'ClubRideCard must not falsely claim end-to-end encryption'); assert(!rideCardSrc.includes('RTK'), 'ClubRideCard must not falsely claim RTK'); assert(!rideCardSrc.includes('mesh networking'), 'ClubRideCard must not falsely claim mesh networking'); console.log(' PASS: Verbatim live location privacy notice verified; no unverified claims present.'); // ========================================================================= // TEST 6: Club Mileage Privacy Behavior & Verified Badge Removal // ========================================================================= console.log('Testing: Club Miles privacy behavior & badge hardening...'); const metricCardSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/metric-card.tsx'), 'utf8'); const mileageDisclaimer = 'Calculated from eligible completed Club Rides. Private rider mileage is not automatically included.'; assert(metricCardSrc.includes(mileageDisclaimer), 'Missing mandatory Club Miles privacy disclaimer'); assert(metricCardSrc.includes('Completed Club Rides only'), 'Missing "Completed Club Rides only" badge text'); assert(!metricCardSrc.includes('VERIFIED'), 'MetricCard must NOT contain misleading "VERIFIED" badge'); console.log(' PASS: Club Miles strict privacy semantics enforced (eligible completed rides only, no false VERIFIED badge).'); // ========================================================================= // TEST 7: Roles & Ranks Architecture Note & No Fabricated Numbers // ========================================================================= console.log('Testing: Roles & Ranks separation architecture note...'); const rolesRanksSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/roles-and-ranks-summary.tsx'), 'utf8'); const verbatimRbacNote = 'Administrative roles determine software permissions. Club ranks are organizational titles and do not grant additional access.'; assert(rolesRanksSrc.includes(verbatimRbacNote), 'Missing verbatim RBAC architecture note'); assert(rolesRanksSrc.includes('ADMINISTRATIVE ROLES (Software Permissions)'), 'Missing software permissions section'); assert(rolesRanksSrc.includes('CLUB RANKS (ORGANIZATIONAL TITLES)'), 'Missing organizational titles section'); assert(!rolesRanksSrc.includes('106 Members'), 'RolesAndRanksSummary must not contain hardcoded 106 Members fabrication'); console.log(' PASS: Roles vs Ranks separation and verbatim architecture note verified (no fabricated counts).'); // ========================================================================= // TEST 8: Top Bar Dev-Gating // ========================================================================= console.log('Testing: Top Bar role preview switcher dev-gating...'); const topBarSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-top-bar.tsx'), 'utf8'); assert(topBarSrc.includes("process.env.NODE_ENV === 'development'"), 'Top bar role preview must be dev-gated'); console.log(' PASS: Top Bar role preview switcher strictly dev-gated.'); // ========================================================================= // TEST 9: Dynamic /clubs/manage Discovery & Page Guards // ========================================================================= console.log('Testing: /clubs/manage discovery route & access guards...'); const manageDiscoverySrc = fs.readFileSync(path.resolve(__dirname, '../app/clubs/manage/page.tsx'), 'utf8'); assert(!manageDiscoverySrc.includes("redirect('/clubs/motorsignal-atlanta/manage')"), 'Must NOT have static redirect to Atlanta'); assert(manageDiscoverySrc.includes('fetchManageableClubs'), 'Must discover manageable clubs via fetchManageableClubs'); assert(manageDiscoverySrc.includes('No Clubs to Manage'), 'Must render "No Clubs to Manage" empty state'); assert(manageDiscoverySrc.includes('Select Club to Manage'), 'Must render Club Selector for >1 clubs'); // FP-1.2: Administrative Role Terminology (Owner, Admin, Member - NEVER Officer) assert(manageDiscoverySrc.includes("c.role === 'owner' ? 'Owner' : 'Admin'"), 'Manageable-Club selector must map admin role to "Admin", NOT "Officer"'); assert(!manageDiscoverySrc.includes("? 'Owner' : 'Officer'"), 'Manageable-Club selector must NEVER map admin role to "Officer"'); assert(!manageDiscoverySrc.includes("Owner or Officer"), 'Manageable-Club selector copy must say Owner or Admin, never Owner or Officer'); const managePageSrc = fs.readFileSync(path.resolve(__dirname, '../app/clubs/[clubId]/manage/page.tsx'), 'utf8'); assert(managePageSrc.includes('Management Access Restricted'), 'Must guard against non-admin member access'); const clubsPageSrc = fs.readFileSync(path.resolve(__dirname, '../app/clubs/page.tsx'), 'utf8'); assert(clubsPageSrc.includes('href="/clubs/manage"'), 'Missing link to /clubs/manage on /clubs page'); console.log(' PASS: /clubs/manage dynamic discovery, role terminology (Owner/Admin/Member), and access control verified.'); // ========================================================================= // TEST 10: Responsive Layout Breakpoints // ========================================================================= console.log('Testing: Responsive layout classes across 1440, 1024, 768, and mobile...'); const shellSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-portal-shell.tsx'), 'utf8'); const sidebarSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-sidebar.tsx'), 'utf8'); // Desktop persistent sidebar: lg:pl-72, lg:translate-x-0, max-w-[1440px] assert(shellSrc.includes('lg:pl-72'), 'Missing lg:pl-72 desktop sidebar offset'); assert(shellSrc.includes('max-w-[1440px]'), 'Missing max-w-[1440px] desktop canvas container'); assert(sidebarSrc.includes('w-72'), 'Missing w-72 persistent sidebar width'); // Mobile drawer: translate-x-full lg:translate-x-0, touch targets assert(sidebarSrc.includes('-translate-x-full lg:translate-x-0'), 'Missing mobile drawer translation classes'); assert(sidebarSrc.includes('fixed left-0 top-0 h-full'), 'Missing fixed sidebar drawer layout'); console.log(' PASS: Responsive shell verified for 1440px desktop, 1024px tablet, and mobile off-canvas drawer.'); // ========================================================================= // TEST 11: FP-1.3 Founder Identity Contract // ========================================================================= console.log('Testing: FP-1.3 Founder Identity Contract (/public_profiles point-read & conservative fallback)...'); const clubDataSrc = fs.readFileSync(path.resolve(__dirname, '../lib/club-data.ts'), 'utf8'); const typesSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/types.ts'), 'utf8'); // Verify ownerUid is documented as ownership identity only, not display name assert(typesSrc.includes('Identifies ownership identity only'), 'Club.ownerUid must document ownership identity only'); assert(typesSrc.includes('Canonical profile resolution: /public_profiles/{ownerUid}'), 'Club must document profile resolution path'); assert(typesSrc.includes("Never persist a redundant 'founderName' field on /clubs/{clubId}"), 'Club must forbid redundant founderName in schema'); // Verify club-data.ts point-reads public_profiles/{ownerUid} assert(clubDataSrc.includes("doc(firestore, 'public_profiles', d.ownerUid)"), 'fetchClubData must perform point read to public_profiles/{ownerUid}'); assert(clubDataSrc.includes("founderName = d.ownerUid === callerUid ? 'You' : 'Club Founder'"), 'Must maintain conservative fallback if profile not resolved'); console.log(' PASS: Founder identity contract verified (ownerUid is identity only; profile read via /public_profiles/{ownerUid}; conservative fallback).'); // ========================================================================= // TEST 12: FP-1.3 Club Ride Association Contract (GroupRide.clubId == club.id) // ========================================================================= console.log('Testing: FP-1.3 Canonical Club Ride Association (GroupRide.clubId == club.id)...'); // Verify canonical query in club-data.ts assert(clubDataSrc.includes("where('clubId', '==', resolvedClubId)"), 'Upcoming rides must query strictly where clubId == resolvedClubId'); assert(typesSrc.includes('Authoritative link: GroupRide.clubId == club.id'), 'Upcoming rides type must document canonical link'); assert(typesSrc.includes('Affiliation is NEVER inferred from accepted rosters'), 'Must document non-inference from rosters'); assert(typesSrc.includes('ClubMember != GroupRideParticipant'), 'Must document ClubMember != GroupRideParticipant invariant'); console.log(' PASS: Club Ride Association strictly bound to GroupRide.clubId == club.id (never inferred from rosters/accessUids).'); // ========================================================================= // TEST 13: FP-1.3 Route Distance & Duration Storage Contract // ========================================================================= console.log('Testing: FP-1.3 Route Distance & Duration Storage Contract...'); // Verify types.ts documents persisted straightLineDistance vs optional Valhalla road estimates assert(typesSrc.includes('straightLineDistanceMeters: Geodesic Haversine distance between ordered stops (persisted)'), 'Must document straightLineDistanceMeters contract'); assert(typesSrc.includes('estimatedDistanceMeters & estimatedDurationSeconds: Optional Valhalla road estimates'), 'Must document optional road estimates contract'); // Verify club-ride-card renders '--' when metrics are unpopulated assert(rideCardSrc.includes("ride.distanceMiles ? `${ride.distanceMiles} mi` : '--'"), 'ClubRideCard must render -- when distance is unpopulated'); assert(rideCardSrc.includes("ride.durationString ?? '--'"), 'ClubRideCard must render -- when duration is unpopulated'); console.log(' PASS: Route distance & duration contract verified (persisted straight-line vs optional road estimates; fallback to --).'); // ========================================================================= // TEST 14 (Test A): FP-13 Profile Authorization Guard // ========================================================================= console.log('Testing: FP-13 Test A - Profile Authorization Guard...'); // Owner and Admin allowed const ownerPerms14 = getPortalPermissions('owner', true); assert.equal(ownerPerms14.canManageSettings, true, 'Owner must have canManageSettings'); const adminPerms14 = getPortalPermissions('admin', true); assert.equal(adminPerms14.canManageSettings, true, 'Admin must have canManageSettings'); // Member (non-admin) forbidden const memberPerms14 = getPortalPermissions('member', true); assert.equal(memberPerms14.canManageSettings, false, 'Member must NOT have canManageSettings'); // Unauthenticated forbidden const unauthPerms14 = getPortalPermissions('member', false); assert.equal(unauthPerms14.isAuthenticated, false, 'Unauth must not be authenticated'); assert.equal(unauthPerms14.canManageSettings, false, 'Unauth must NOT have canManageSettings'); // Verify page component inspects auth and permissions const profilePageSrc = fs.readFileSync(path.resolve(__dirname, '../app/clubs/[clubId]/manage/profile/page.tsx'), 'utf8'); assert(profilePageSrc.includes('!isDemoPreview && !currentUser'), 'Profile page must check authentication'); assert(profilePageSrc.includes('title="Authentication Required"'), 'Profile page must render Authentication Required error'); assert(profilePageSrc.includes("router.push('/login')"), 'Profile page must direct unauthenticated users to /login'); assert(profilePageSrc.includes('!isDemoPreview && !ctx.permissions.canManageSettings'), 'Profile page must check canManageSettings permission'); assert(profilePageSrc.includes('title="Management Access Restricted"'), 'Profile page must render Management Access Restricted error'); console.log(' PASS: Test A verified (Owner/Admin allowed; Member forbidden; Unauthenticated rejected with SafeErrorState -> /login).'); // ========================================================================= // TEST 15 (Test B): FP-13 Profile Query Gate (O(1) Point-Read Only) // ========================================================================= console.log('Testing: FP-13 Test B - Profile Query Gate (O(1) Point-Read Only)...'); // Extract fetchFounderClubContext body from club-data.ts source const fetchCtxMatch = clubDataSrc.match(/export async function fetchFounderClubContext[\s\S]*?^}/m); assert(fetchCtxMatch, 'fetchFounderClubContext must exist in club-data.ts'); const fetchCtxBody = fetchCtxMatch[0]; // Forbid collection queries in profile context assert(!fetchCtxBody.includes('group_rides'), 'fetchFounderClubContext must NOT query group_rides'); assert(!fetchCtxBody.includes('club_applications'), 'fetchFounderClubContext must NOT query club_applications'); assert(!fetchCtxBody.includes('collectionGroup'), 'fetchFounderClubContext must NOT perform collectionGroup queries'); assert(!fetchCtxBody.includes('getDocs('), 'fetchFounderClubContext must NOT call getDocs (strictly point-reads getDoc only)'); console.log(' PASS: Test B verified (Zero collection queries; zero group_rides; zero club_applications; strictly O(1) point-reads).'); // ========================================================================= // TEST 16 (Test C): FP-13 Profile Field Mutability & Whitelist Enforcement // ========================================================================= console.log('Testing: FP-13 Test C - Profile Field Mutability & Whitelist Enforcement...'); // Test input validations via updateClubProfile await assert.rejects( async () => updateClubProfile('test-club', '', { name: 'Valid Name', description: '', homeRegion: '', motorcycleFocus: '' }), /Authentication required/, 'Must require callerUid' ); await assert.rejects( async () => updateClubProfile('test-club', 'uid-1', { name: 'ab', description: '', homeRegion: '', motorcycleFocus: '' }), /Club name must be between 3 and 50 characters/, 'Must reject name shorter than 3 chars' ); await assert.rejects( async () => updateClubProfile('test-club', 'uid-1', { name: 'A'.repeat(51), description: '', homeRegion: '', motorcycleFocus: '' }), /Club name must be between 3 and 50 characters/, 'Must reject name longer than 50 chars' ); await assert.rejects( async () => updateClubProfile('test-club', 'uid-1', { name: 'Valid Club', description: 'A'.repeat(501), homeRegion: '', motorcycleFocus: '' }), /Club description must not exceed 500 characters/, 'Must reject description longer than 500 chars' ); await assert.rejects( async () => updateClubProfile('test-club', 'uid-1', { name: 'Valid Club', description: '', homeRegion: 'A'.repeat(101), motorcycleFocus: '' }), /Home region must not exceed 100 characters/, 'Must reject homeRegion longer than 100 chars' ); await assert.rejects( async () => updateClubProfile('test-club', 'uid-1', { name: 'Valid Club', description: '', homeRegion: '', motorcycleFocus: 'A'.repeat(101) }), /Motorcycle focus must not exceed 100 characters/, 'Must reject motorcycleFocus longer than 100 chars' ); // Verify updateClubProfile implementation in club-data.ts strictly writes whitelisted fields const updateMatch = clubDataSrc.match(/export async function updateClubProfile[\s\S]*?^}/m); assert(updateMatch, 'updateClubProfile must exist in club-data.ts'); const updateBody = updateMatch[0]; assert(updateBody.includes('updateDoc(clubRef, {'), 'updateClubProfile must call updateDoc'); assert(!updateBody.includes('slug:'), 'updateClubProfile MUST NOT write slug'); assert(!updateBody.includes('visibility:'), 'updateClubProfile MUST NOT write visibility'); assert(!updateBody.includes('admissionPolicy:'), 'updateClubProfile MUST NOT write admissionPolicy'); assert(!updateBody.includes('ownerUid:'), 'updateClubProfile MUST NOT write ownerUid'); assert(!updateBody.includes('memberCount:'), 'updateClubProfile MUST NOT write memberCount'); assert(!updateBody.includes('archivedAt:'), 'updateClubProfile MUST NOT write archivedAt'); console.log(' PASS: Test C verified (Strict input length bounds, whitelisted update, forbidden fields rejected).'); // ========================================================================= // TEST 17 (Test D): FP-13 Development Preview Fixture Safety // ========================================================================= console.log('Testing: FP-13 Test D - Development Preview Fixture Safety...'); // In development with allowDemoPreview: true -> returns fixture const prevEnv = process.env.NODE_ENV; process.env.NODE_ENV = 'development'; const demoCtx = await fetchFounderClubContext('any-id', undefined, { allowDemoPreview: true }); assert.equal(demoCtx.isDemoFixture, true, 'Must return isDemoFixture: true when opt-in in development'); assert.equal(demoCtx.club.name, FIXTURE_FOUNDER_CLUB.name); // In production with allowDemoPreview: true -> fixture MUST NOT be returned process.env.NODE_ENV = 'production'; let prodThrew = false; try { await fetchFounderClubContext('non-existent-club-id', undefined, { allowDemoPreview: true }); } catch { prodThrew = true; } assert.equal(prodThrew, true, 'Fixture MUST NEVER be returned in production, even if allowDemoPreview is set'); process.env.NODE_ENV = prevEnv; console.log(' PASS: Test D verified (Fixture returned strictly in development with explicit allowDemoPreview opt-in; never in production).'); // ========================================================================= // TEST 18 (Test E): FP-13 Shared Sub-Routing & Active Navigation State // ========================================================================= console.log('Testing: FP-13 Test E - Shared Sub-Routing & Active Navigation State...'); // Verify route links exist in FounderSidebar assert(sidebarSrc.includes('getRouteHref'), 'FounderSidebar must include getRouteHref'); assert(sidebarSrc.includes('/manage/profile'), 'FounderSidebar must route to /manage/profile'); assert(sidebarSrc.includes('/manage'), 'FounderSidebar must route to /manage'); // Verify exact active styling for profile assert(sidebarSrc.includes('bg-surface-container-high text-primary-container border-l-2 border-primary-container font-medium'), 'Profile item must have active highlight border and background'); // Verify profile page passes activeNav="profile" assert(profilePageSrc.includes('activeNav="profile"'), 'Profile page must pass activeNav="profile" to FounderPortalShell'); assert(profilePageSrc.includes(' { console.error('Test Suite Failure:', err); process.exit(1); });