import { describe, it, expect } from 'vitest'; import { getWebsiteRouteContracts, ScenarioRole } from '../../shared/website/RouteContractSpec'; import { WebsiteRouteManager } from '../../shared/website/WebsiteRouteManager'; import { RouteScenarioMatrix } from '../../shared/website/RouteScenarioMatrix'; describe('RouteContractSpec', () => { const contracts = getWebsiteRouteContracts(); const manager = new WebsiteRouteManager(); const inventory = manager.getWebsiteRouteInventory(); it('should cover all inventory routes', () => { expect(contracts.length).toBe(inventory.length); const inventoryPaths = inventory.map(def => manager.resolvePathTemplate(def.pathTemplate, def.params) ); const contractPaths = contracts.map(c => c.path); // Ensure every path in inventory has a corresponding contract inventoryPaths.forEach(path => { expect(contractPaths).toContain(path); }); }); it('should have expectedStatus set for every contract', () => { contracts.forEach(contract => { expect(contract.expectedStatus).toBeDefined(); expect(['ok', 'redirect', 'forbidden', 'notFoundAllowed', 'errorRoute']).toContain(contract.expectedStatus); }); }); it('should have required scenarios based on access level', () => { contracts.forEach(contract => { const scenarios = Object.keys(contract.scenarios) as ScenarioRole[]; // All routes must have unauth, auth, admin, sponsor scenarios expect(scenarios).toContain('unauth'); expect(scenarios).toContain('auth'); expect(scenarios).toContain('admin'); expect(scenarios).toContain('sponsor'); // Admin and Sponsor routes must also have wrong-role scenario if (contract.accessLevel === 'admin' || contract.accessLevel === 'sponsor') { expect(scenarios).toContain('wrong-role'); } }); }); it('should have correct scenario expectations for admin routes', () => { const adminContracts = contracts.filter(c => c.accessLevel === 'admin'); adminContracts.forEach(contract => { expect(contract.scenarios.unauth?.expectedStatus).toBe('redirect'); expect(contract.scenarios.auth?.expectedStatus).toBe('redirect'); expect(contract.scenarios.admin?.expectedStatus).toBe('ok'); expect(contract.scenarios.sponsor?.expectedStatus).toBe('redirect'); expect(contract.scenarios['wrong-role']?.expectedStatus).toBe('redirect'); }); }); it('should have correct scenario expectations for sponsor routes', () => { const sponsorContracts = contracts.filter(c => c.accessLevel === 'sponsor'); sponsorContracts.forEach(contract => { expect(contract.scenarios.unauth?.expectedStatus).toBe('redirect'); expect(contract.scenarios.auth?.expectedStatus).toBe('redirect'); expect(contract.scenarios.admin?.expectedStatus).toBe('redirect'); expect(contract.scenarios.sponsor?.expectedStatus).toBe('ok'); expect(contract.scenarios['wrong-role']?.expectedStatus).toBe('redirect'); }); }); it('should have expectedRedirectTo set for protected routes (unauth scenario)', () => { const protectedContracts = contracts.filter(c => c.accessLevel !== 'public'); // Filter out routes that might have overrides to not be 'redirect' const redirectingContracts = protectedContracts.filter(c => c.expectedStatus === 'redirect'); expect(redirectingContracts.length).toBeGreaterThan(0); redirectingContracts.forEach(contract => { expect(contract.expectedRedirectTo).toBeDefined(); expect(contract.expectedRedirectTo).toMatch(/^\//); }); }); it('should include default SSR sanity markers', () => { contracts.forEach(contract => { expect(contract.ssrMustContain).toContain(''); expect(contract.ssrMustContain).toContain(' { it('should match the number of contracts', () => { expect(RouteScenarioMatrix.length).toBe(contracts.length); }); it('should correctly identify routes with param edge cases', () => { const edgeCaseRoutes = RouteScenarioMatrix.filter(m => m.hasParamEdgeCases); // Based on WebsiteRouteManager.getParamEdgeCases(), we expect at least /races/[id] and /leagues/[id] expect(edgeCaseRoutes.length).toBeGreaterThanOrEqual(2); const paths = edgeCaseRoutes.map(m => m.path); expect(paths.some(p => p.startsWith('/races/'))).toBe(true); expect(paths.some(p => p.startsWith('/leagues/'))).toBe(true); }); }); });