From 7d3393e1b9eafaa1fabd8586171a6df89186d1d7 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Tue, 16 Dec 2025 12:14:06 +0100 Subject: [PATCH] refactor --- .../logging}/ConsoleLogger.test.ts | 22 +-- adapters/tsconfig.json | 3 +- ....service.spec.ts => hello.service.test.ts} | 0 ...pec.ts => RecordEngagementUseCase.test.ts} | 0 ....spec.ts => RecordPageViewUseCase.test.ts} | 0 ...rService.spec.ts => DriverService.test.ts} | 0 ...ts => CompleteOnboardingPresenter.test.ts} | 0 ...DriverRegistrationStatusPresenter.test.ts} | 0 ...r.spec.ts => DriverStatsPresenter.test.ts} | 0 ...ts => DriversLeaderboardPresenter.test.ts} | 0 ...oller.spec.ts => LeagueController.test.ts} | 0 ...eService.spec.ts => LeagueService.test.ts} | 0 ...eamService.spec.ts => TeamService.test.ts} | 0 apps/api/tsconfig.json | 16 +- .../CheckoutConfirmationDialog.test.tsx | 0 .../RaceCreationSuccessScreen.test.tsx | 0 .../renderer}/SessionProgressMonitor.test.tsx | 0 .../value-objects/AnalyticsEntityId.test.ts | 0 .../value-objects/AnalyticsSessionId.test.ts | 0 .../domain/value-objects/PageViewId.test.ts | 0 .../CheckAuthenticationUseCase.test.ts | 0 .../CompleteDriverOnboardingUseCase.test.ts | 0 .../CompleteRaceCreationUseCase.test.ts | 0 .../ConfirmCheckoutUseCase.enhanced.test.ts | 0 .../ConfirmCheckoutUseCase.test.ts | 0 .../GetTotalDriversUseCase.test.ts | 0 .../ICheckoutConfirmationPort.test.ts | 0 .../application/OverlaySyncService.test.ts | 0 .../OverlaySyncService.timeout.test.ts | 0 ...culateChampionshipStandingsUseCase.test.ts | 0 .../StartAutomationSession.test.ts | 0 .../VerifyAuthenticatedPageUseCase.test.ts | 0 .../domain/entities/AutomationSession.test.ts | 0 .../services/PageStateValidator.test.ts | 0 .../services/StepTransitionValidator.test.ts | 0 core/automation/domain/shared/Result.ts | 78 ---------- .../BrowserAuthenticationState.test.ts | 0 .../CheckoutConfirmation.test.ts | 0 .../value-objects/CheckoutPrice.test.ts | 0 .../value-objects/CheckoutState.test.ts | 0 .../value-objects/CookieConfiguration.test.ts | 0 .../value-objects/RaceCreationResult.test.ts | 0 .../value-objects/SessionLifetime.test.ts | 0 .../domain/value-objects/SessionState.test.ts | 0 .../domain/value-objects/StepId.test.ts | 0 .../infrastructure/AutomationConfig.test.ts | 0 .../infrastructure/BrowserModeConfig.test.ts | 0 .../DemoImageServiceAdapter.test.ts | 0 ...lectronCheckoutConfirmationAdapter.test.ts | 0 .../WizardDismissalDetection.test.ts | 0 .../auth/AuthenticationGuard.test.ts | 0 ...nService.initiateLogin.browserMode.test.ts | 0 ...onService.verifyPageAuthentication.test.ts | 0 .../auth/SessionCookieStore.test.ts | 0 .../identity/EmailValidation.test.ts | 0 .../media/MediaUrl.test.ts | 0 .../notifications/NotificationId.test.ts | 0 .../notifications/QuietHours.test.ts | 0 .../ApproveLeagueJoinRequestUseCase.test.ts | 0 .../DashboardOverviewUseCase.test.ts | 0 .../GetLeagueJoinRequestsUseCase.test.ts | 0 .../application/MembershipUseCases.test.ts | 0 .../application/RaceDetailUseCases.test.ts | 0 .../application/RaceResultsUseCases.test.ts | 0 .../RegistrationAndTeamUseCases.test.ts | 0 .../RejectLeagueJoinRequestUseCase.test.ts | 0 .../RemoveLeagueMemberUseCase.test.ts | 0 .../racing/application/SeasonUseCases.test.ts | 0 .../UpdateLeagueMemberRoleUseCase.test.ts | 0 .../racing/domain/entities/Season.test.ts | 0 .../domain/services/DropScoreApplier.test.ts | 0 .../services/EventScoringService.test.ts | 0 .../services/ScheduleCalculator.test.ts | 0 core/tsconfig.json | 3 +- ...te-pages.spec.ts => website-pages.test.ts} | 0 ...es.spec.ts => PackageDependencies.test.ts} | 0 tests/unit/website/AlphaNav.test.tsx | 102 ------------- .../unit/website/InlinePenaltyButton.test.tsx | 123 ---------------- .../auth/DashboardAndLayoutAuth.test.tsx | 34 ----- .../CreateLeaguePage.wizardStep.test.tsx | 124 ---------------- tests/website/AlphaComponents.spec.ts | 32 ---- tests/website/ImportBoundaries.spec.ts | 81 ----------- tests/website/InMemoryAuthService.spec.ts | 63 -------- tests/website/IracingAuthPageImports.spec.ts | 17 --- tests/website/IracingRoutes.spec.ts | 85 ----------- tests/website/getAppMode.spec.ts | 63 -------- tests/website/signupRoute.spec.ts | 137 ------------------ tsconfig.base.json | 2 +- tsconfig.json | 2 +- vitest.config.ts | 7 +- 90 files changed, 20 insertions(+), 974 deletions(-) rename {tests/shared => adapters/logging}/ConsoleLogger.test.ts (72%) rename apps/api/src/application/hello/{hello.service.spec.ts => hello.service.test.ts} (100%) rename apps/api/src/modules/analytics/use-cases/{RecordEngagementUseCase.spec.ts => RecordEngagementUseCase.test.ts} (100%) rename apps/api/src/modules/analytics/use-cases/{RecordPageViewUseCase.spec.ts => RecordPageViewUseCase.test.ts} (100%) rename apps/api/src/modules/driver/{DriverService.spec.ts => DriverService.test.ts} (100%) rename apps/api/src/modules/driver/presenters/{CompleteOnboardingPresenter.spec.ts => CompleteOnboardingPresenter.test.ts} (100%) rename apps/api/src/modules/driver/presenters/{DriverRegistrationStatusPresenter.spec.ts => DriverRegistrationStatusPresenter.test.ts} (100%) rename apps/api/src/modules/driver/presenters/{DriverStatsPresenter.spec.ts => DriverStatsPresenter.test.ts} (100%) rename apps/api/src/modules/driver/presenters/{DriversLeaderboardPresenter.spec.ts => DriversLeaderboardPresenter.test.ts} (100%) rename apps/api/src/modules/league/{LeagueController.spec.ts => LeagueController.test.ts} (100%) rename apps/api/src/modules/league/{LeagueService.spec.ts => LeagueService.test.ts} (100%) rename apps/api/src/modules/team/{TeamService.spec.ts => TeamService.test.ts} (100%) rename {tests/unit => apps/companion}/renderer/CheckoutConfirmationDialog.test.tsx (100%) rename {tests/unit => apps/companion}/renderer/RaceCreationSuccessScreen.test.tsx (100%) rename {tests/unit/renderer/components => apps/companion/renderer}/SessionProgressMonitor.test.tsx (100%) rename tests/analytics/AnalyticsEntityId.spec.ts => core/analytics/domain/value-objects/AnalyticsEntityId.test.ts (100%) rename tests/analytics/AnalyticsSessionId.spec.ts => core/analytics/domain/value-objects/AnalyticsSessionId.test.ts (100%) rename tests/analytics/PageViewId.spec.ts => core/analytics/domain/value-objects/PageViewId.test.ts (100%) rename tests/application/CheckAuthenticationUseCase.spec.ts => core/automation/application/CheckAuthenticationUseCase.test.ts (100%) rename tests/application/CompleteDriverOnboardingUseCase.spec.ts => core/automation/application/CompleteDriverOnboardingUseCase.test.ts (100%) rename tests/application/CompleteRaceCreationUseCase.spec.ts => core/automation/application/CompleteRaceCreationUseCase.test.ts (100%) rename tests/application/ConfirmCheckoutUseCase.enhanced.spec.ts => core/automation/application/ConfirmCheckoutUseCase.enhanced.test.ts (100%) rename tests/application/ConfirmCheckoutUseCase.spec.ts => core/automation/application/ConfirmCheckoutUseCase.test.ts (100%) rename tests/application/GetTotalDriversUseCase.spec.ts => core/automation/application/GetTotalDriversUseCase.test.ts (100%) rename tests/application/ICheckoutConfirmationPort.spec.ts => core/automation/application/ICheckoutConfirmationPort.test.ts (100%) rename tests/application/OverlaySyncService.spec.ts => core/automation/application/OverlaySyncService.test.ts (100%) rename tests/application/OverlaySyncService.timeout.spec.ts => core/automation/application/OverlaySyncService.timeout.test.ts (100%) rename tests/application/RecalculateChampionshipStandingsUseCase.spec.ts => core/automation/application/RecalculateChampionshipStandingsUseCase.test.ts (100%) rename tests/application/StartAutomationSession.spec.ts => core/automation/application/StartAutomationSession.test.ts (100%) rename tests/application/VerifyAuthenticatedPageUseCase.spec.ts => core/automation/application/VerifyAuthenticatedPageUseCase.test.ts (100%) rename tests/domain/AutomationSession.spec.ts => core/automation/domain/entities/AutomationSession.test.ts (100%) rename tests/domain/PageStateValidator.spec.ts => core/automation/domain/services/PageStateValidator.test.ts (100%) rename tests/domain/StepTransitionValidator.spec.ts => core/automation/domain/services/StepTransitionValidator.test.ts (100%) delete mode 100644 core/automation/domain/shared/Result.ts rename tests/domain/BrowserAuthenticationState.spec.ts => core/automation/domain/value-objects/BrowserAuthenticationState.test.ts (100%) rename tests/domain/CheckoutConfirmation.spec.ts => core/automation/domain/value-objects/CheckoutConfirmation.test.ts (100%) rename tests/domain/CheckoutPrice.spec.ts => core/automation/domain/value-objects/CheckoutPrice.test.ts (100%) rename tests/domain/CheckoutState.spec.ts => core/automation/domain/value-objects/CheckoutState.test.ts (100%) rename tests/domain/CookieConfiguration.spec.ts => core/automation/domain/value-objects/CookieConfiguration.test.ts (100%) rename tests/domain/RaceCreationResult.spec.ts => core/automation/domain/value-objects/RaceCreationResult.test.ts (100%) rename tests/domain/SessionLifetime.spec.ts => core/automation/domain/value-objects/SessionLifetime.test.ts (100%) rename tests/domain/SessionState.spec.ts => core/automation/domain/value-objects/SessionState.test.ts (100%) rename tests/domain/StepId.spec.ts => core/automation/domain/value-objects/StepId.test.ts (100%) rename tests/infrastructure/AutomationConfig.spec.ts => core/automation/infrastructure/AutomationConfig.test.ts (100%) rename tests/infrastructure/BrowserModeConfig.spec.ts => core/automation/infrastructure/BrowserModeConfig.test.ts (100%) rename tests/infrastructure/DemoImageServiceAdapter.spec.ts => core/automation/infrastructure/DemoImageServiceAdapter.test.ts (100%) rename tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts => core/automation/infrastructure/ElectronCheckoutConfirmationAdapter.test.ts (100%) rename tests/infrastructure/WizardDismissalDetection.spec.ts => core/automation/infrastructure/WizardDismissalDetection.test.ts (100%) rename tests/infrastructure/AuthenticationGuard.spec.ts => core/automation/infrastructure/adapters/automation/auth/AuthenticationGuard.test.ts (100%) rename tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts => core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.initiateLogin.browserMode.test.ts (100%) rename tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts => core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.verifyPageAuthentication.test.ts (100%) rename tests/infrastructure/SessionCookieStore.spec.ts => core/automation/infrastructure/adapters/automation/auth/SessionCookieStore.test.ts (100%) rename tests/identity/EmailValidation.spec.ts => core/identity/EmailValidation.test.ts (100%) rename tests/media/MediaUrl.spec.ts => core/media/MediaUrl.test.ts (100%) rename tests/notifications/NotificationId.spec.ts => core/notifications/NotificationId.test.ts (100%) rename tests/notifications/QuietHours.spec.ts => core/notifications/QuietHours.test.ts (100%) rename tests/racing-application/ApproveLeagueJoinRequestUseCase.spec.ts => core/racing/application/ApproveLeagueJoinRequestUseCase.test.ts (100%) rename tests/racing-application/DashboardOverviewUseCase.spec.ts => core/racing/application/DashboardOverviewUseCase.test.ts (100%) rename tests/racing-application/GetLeagueJoinRequestsUseCase.spec.ts => core/racing/application/GetLeagueJoinRequestsUseCase.test.ts (100%) rename tests/racing-application/MembershipUseCases.spec.ts => core/racing/application/MembershipUseCases.test.ts (100%) rename tests/racing-application/RaceDetailUseCases.spec.ts => core/racing/application/RaceDetailUseCases.test.ts (100%) rename tests/racing-application/RaceResultsUseCases.spec.ts => core/racing/application/RaceResultsUseCases.test.ts (100%) rename tests/racing-application/RegistrationAndTeamUseCases.spec.ts => core/racing/application/RegistrationAndTeamUseCases.test.ts (100%) rename tests/racing-application/RejectLeagueJoinRequestUseCase.spec.ts => core/racing/application/RejectLeagueJoinRequestUseCase.test.ts (100%) rename tests/racing-application/RemoveLeagueMemberUseCase.spec.ts => core/racing/application/RemoveLeagueMemberUseCase.test.ts (100%) rename tests/racing-application/SeasonUseCases.spec.ts => core/racing/application/SeasonUseCases.test.ts (100%) rename tests/racing-application/UpdateLeagueMemberRoleUseCase.spec.ts => core/racing/application/UpdateLeagueMemberRoleUseCase.test.ts (100%) rename tests/racing/Season.spec.ts => core/racing/domain/entities/Season.test.ts (100%) rename tests/domain/DropScoreApplier.spec.ts => core/racing/domain/services/DropScoreApplier.test.ts (100%) rename tests/racing/EventScoringService.spec.ts => core/racing/domain/services/EventScoringService.test.ts (100%) rename tests/domain/ScheduleCalculator.spec.ts => core/racing/domain/services/ScheduleCalculator.test.ts (100%) rename tests/smoke/{website-pages.spec.ts => website-pages.test.ts} (100%) rename tests/structure/{PackageDependencies.spec.ts => PackageDependencies.test.ts} (100%) delete mode 100644 tests/unit/website/AlphaNav.test.tsx delete mode 100644 tests/unit/website/InlinePenaltyButton.test.tsx delete mode 100644 tests/unit/website/auth/DashboardAndLayoutAuth.test.tsx delete mode 100644 tests/unit/website/leagues/CreateLeaguePage.wizardStep.test.tsx delete mode 100644 tests/website/AlphaComponents.spec.ts delete mode 100644 tests/website/ImportBoundaries.spec.ts delete mode 100644 tests/website/InMemoryAuthService.spec.ts delete mode 100644 tests/website/IracingAuthPageImports.spec.ts delete mode 100644 tests/website/IracingRoutes.spec.ts delete mode 100644 tests/website/getAppMode.spec.ts delete mode 100644 tests/website/signupRoute.spec.ts diff --git a/tests/shared/ConsoleLogger.test.ts b/adapters/logging/ConsoleLogger.test.ts similarity index 72% rename from tests/shared/ConsoleLogger.test.ts rename to adapters/logging/ConsoleLogger.test.ts index fbc6eada7..1be54f2dd 100644 --- a/tests/shared/ConsoleLogger.test.ts +++ b/adapters/logging/ConsoleLogger.test.ts @@ -1,13 +1,12 @@ -import { vi } from 'vitest'; -import { ConsoleLogger } from '../../../logging/ConsoleLogger'; // Assuming ConsoleLogger is here +import { vi, type Mock } from 'vitest'; +import { ConsoleLogger } from './ConsoleLogger'; describe('ConsoleLogger', () => { let logger: ConsoleLogger; - let consoleDebugSpy: vi.SpyInstance; - let consoleInfoSpy: vi.SpyInstance; - let consoleWarnSpy: vi.SpyInstance; - let consoleErrorSpy: vi.SpyInstance; - let consoleLogSpy: vi.SpyInstance; + let consoleDebugSpy: Mock; + let consoleInfoSpy: Mock; + let consoleWarnSpy: Mock; + let consoleErrorSpy: Mock; beforeEach(() => { logger = new ConsoleLogger(); @@ -15,7 +14,6 @@ describe('ConsoleLogger', () => { consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(() => {}); consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); - consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); }); afterEach(() => { @@ -23,7 +21,6 @@ describe('ConsoleLogger', () => { consoleInfoSpy.mockRestore(); consoleWarnSpy.mockRestore(); consoleErrorSpy.mockRestore(); - consoleLogSpy.mockRestore(); }); it('should call console.debug with the correct arguments when debug is called', () => { @@ -59,11 +56,4 @@ describe('ConsoleLogger', () => { expect(consoleErrorSpy).toHaveBeenCalledWith(message, error, context); }); - it('should call console.log with the correct arguments when log is called', () => { - const message = 'Log message'; - const context = { key: 'value' }; - logger.log(message, context); - expect(consoleLogSpy).toHaveBeenCalledTimes(1); - expect(consoleLogSpy).toHaveBeenCalledWith(message, context); - }); }); \ No newline at end of file diff --git a/adapters/tsconfig.json b/adapters/tsconfig.json index c5c3fbcd0..f5c4367ba 100644 --- a/adapters/tsconfig.json +++ b/adapters/tsconfig.json @@ -8,6 +8,7 @@ "declaration": true, "declarationMap": true, "sourceMap": true, + "types": ["vitest/globals"], "paths": { "@/*": ["./*"], "@core/*": ["../core/*"], @@ -16,5 +17,5 @@ } }, "include": ["**/*.ts"], - "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] + "exclude": ["node_modules", "dist"] } \ No newline at end of file diff --git a/apps/api/src/application/hello/hello.service.spec.ts b/apps/api/src/application/hello/hello.service.test.ts similarity index 100% rename from apps/api/src/application/hello/hello.service.spec.ts rename to apps/api/src/application/hello/hello.service.test.ts diff --git a/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.spec.ts b/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.test.ts similarity index 100% rename from apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.spec.ts rename to apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.test.ts diff --git a/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.spec.ts b/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.test.ts similarity index 100% rename from apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.spec.ts rename to apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.test.ts diff --git a/apps/api/src/modules/driver/DriverService.spec.ts b/apps/api/src/modules/driver/DriverService.test.ts similarity index 100% rename from apps/api/src/modules/driver/DriverService.spec.ts rename to apps/api/src/modules/driver/DriverService.test.ts diff --git a/apps/api/src/modules/driver/presenters/CompleteOnboardingPresenter.spec.ts b/apps/api/src/modules/driver/presenters/CompleteOnboardingPresenter.test.ts similarity index 100% rename from apps/api/src/modules/driver/presenters/CompleteOnboardingPresenter.spec.ts rename to apps/api/src/modules/driver/presenters/CompleteOnboardingPresenter.test.ts diff --git a/apps/api/src/modules/driver/presenters/DriverRegistrationStatusPresenter.spec.ts b/apps/api/src/modules/driver/presenters/DriverRegistrationStatusPresenter.test.ts similarity index 100% rename from apps/api/src/modules/driver/presenters/DriverRegistrationStatusPresenter.spec.ts rename to apps/api/src/modules/driver/presenters/DriverRegistrationStatusPresenter.test.ts diff --git a/apps/api/src/modules/driver/presenters/DriverStatsPresenter.spec.ts b/apps/api/src/modules/driver/presenters/DriverStatsPresenter.test.ts similarity index 100% rename from apps/api/src/modules/driver/presenters/DriverStatsPresenter.spec.ts rename to apps/api/src/modules/driver/presenters/DriverStatsPresenter.test.ts diff --git a/apps/api/src/modules/driver/presenters/DriversLeaderboardPresenter.spec.ts b/apps/api/src/modules/driver/presenters/DriversLeaderboardPresenter.test.ts similarity index 100% rename from apps/api/src/modules/driver/presenters/DriversLeaderboardPresenter.spec.ts rename to apps/api/src/modules/driver/presenters/DriversLeaderboardPresenter.test.ts diff --git a/apps/api/src/modules/league/LeagueController.spec.ts b/apps/api/src/modules/league/LeagueController.test.ts similarity index 100% rename from apps/api/src/modules/league/LeagueController.spec.ts rename to apps/api/src/modules/league/LeagueController.test.ts diff --git a/apps/api/src/modules/league/LeagueService.spec.ts b/apps/api/src/modules/league/LeagueService.test.ts similarity index 100% rename from apps/api/src/modules/league/LeagueService.spec.ts rename to apps/api/src/modules/league/LeagueService.test.ts diff --git a/apps/api/src/modules/team/TeamService.spec.ts b/apps/api/src/modules/team/TeamService.test.ts similarity index 100% rename from apps/api/src/modules/team/TeamService.spec.ts rename to apps/api/src/modules/team/TeamService.test.ts diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index 9888c05e5..9f87fb3fe 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -5,19 +5,8 @@ "module": "commonjs", "lib": ["es2022", "dom"], "moduleResolution": "node", - "esModuleInterop": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "strict": false, - "noImplicitAny": false, - "noImplicitThis": false, - "strictNullChecks": false, - "alwaysStrict": false, - "exactOptionalPropertyTypes": false, - "noUncheckedIndexedAccess": false, - "assumeChangesOnlyAffectDirectDependencies": true, "noEmit": false, "declaration": true, "declarationMap": true, @@ -26,8 +15,7 @@ "outDir": "./dist", "incremental": true, "baseUrl": ".", - "types": ["node", "express", "jest"], - "strictPropertyInitialization": false, + "types": ["node", "express", "vitest/globals"], "paths": { "@/*": ["./*"], "@core/*": ["../../core/*"], @@ -36,5 +24,5 @@ } }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "**/*.mock.ts", "**/*.spec.ts", "**/*.test.ts"] + "exclude": ["node_modules", "dist", "**/*.mock.ts"] } diff --git a/tests/unit/renderer/CheckoutConfirmationDialog.test.tsx b/apps/companion/renderer/CheckoutConfirmationDialog.test.tsx similarity index 100% rename from tests/unit/renderer/CheckoutConfirmationDialog.test.tsx rename to apps/companion/renderer/CheckoutConfirmationDialog.test.tsx diff --git a/tests/unit/renderer/RaceCreationSuccessScreen.test.tsx b/apps/companion/renderer/RaceCreationSuccessScreen.test.tsx similarity index 100% rename from tests/unit/renderer/RaceCreationSuccessScreen.test.tsx rename to apps/companion/renderer/RaceCreationSuccessScreen.test.tsx diff --git a/tests/unit/renderer/components/SessionProgressMonitor.test.tsx b/apps/companion/renderer/SessionProgressMonitor.test.tsx similarity index 100% rename from tests/unit/renderer/components/SessionProgressMonitor.test.tsx rename to apps/companion/renderer/SessionProgressMonitor.test.tsx diff --git a/tests/analytics/AnalyticsEntityId.spec.ts b/core/analytics/domain/value-objects/AnalyticsEntityId.test.ts similarity index 100% rename from tests/analytics/AnalyticsEntityId.spec.ts rename to core/analytics/domain/value-objects/AnalyticsEntityId.test.ts diff --git a/tests/analytics/AnalyticsSessionId.spec.ts b/core/analytics/domain/value-objects/AnalyticsSessionId.test.ts similarity index 100% rename from tests/analytics/AnalyticsSessionId.spec.ts rename to core/analytics/domain/value-objects/AnalyticsSessionId.test.ts diff --git a/tests/analytics/PageViewId.spec.ts b/core/analytics/domain/value-objects/PageViewId.test.ts similarity index 100% rename from tests/analytics/PageViewId.spec.ts rename to core/analytics/domain/value-objects/PageViewId.test.ts diff --git a/tests/application/CheckAuthenticationUseCase.spec.ts b/core/automation/application/CheckAuthenticationUseCase.test.ts similarity index 100% rename from tests/application/CheckAuthenticationUseCase.spec.ts rename to core/automation/application/CheckAuthenticationUseCase.test.ts diff --git a/tests/application/CompleteDriverOnboardingUseCase.spec.ts b/core/automation/application/CompleteDriverOnboardingUseCase.test.ts similarity index 100% rename from tests/application/CompleteDriverOnboardingUseCase.spec.ts rename to core/automation/application/CompleteDriverOnboardingUseCase.test.ts diff --git a/tests/application/CompleteRaceCreationUseCase.spec.ts b/core/automation/application/CompleteRaceCreationUseCase.test.ts similarity index 100% rename from tests/application/CompleteRaceCreationUseCase.spec.ts rename to core/automation/application/CompleteRaceCreationUseCase.test.ts diff --git a/tests/application/ConfirmCheckoutUseCase.enhanced.spec.ts b/core/automation/application/ConfirmCheckoutUseCase.enhanced.test.ts similarity index 100% rename from tests/application/ConfirmCheckoutUseCase.enhanced.spec.ts rename to core/automation/application/ConfirmCheckoutUseCase.enhanced.test.ts diff --git a/tests/application/ConfirmCheckoutUseCase.spec.ts b/core/automation/application/ConfirmCheckoutUseCase.test.ts similarity index 100% rename from tests/application/ConfirmCheckoutUseCase.spec.ts rename to core/automation/application/ConfirmCheckoutUseCase.test.ts diff --git a/tests/application/GetTotalDriversUseCase.spec.ts b/core/automation/application/GetTotalDriversUseCase.test.ts similarity index 100% rename from tests/application/GetTotalDriversUseCase.spec.ts rename to core/automation/application/GetTotalDriversUseCase.test.ts diff --git a/tests/application/ICheckoutConfirmationPort.spec.ts b/core/automation/application/ICheckoutConfirmationPort.test.ts similarity index 100% rename from tests/application/ICheckoutConfirmationPort.spec.ts rename to core/automation/application/ICheckoutConfirmationPort.test.ts diff --git a/tests/application/OverlaySyncService.spec.ts b/core/automation/application/OverlaySyncService.test.ts similarity index 100% rename from tests/application/OverlaySyncService.spec.ts rename to core/automation/application/OverlaySyncService.test.ts diff --git a/tests/application/OverlaySyncService.timeout.spec.ts b/core/automation/application/OverlaySyncService.timeout.test.ts similarity index 100% rename from tests/application/OverlaySyncService.timeout.spec.ts rename to core/automation/application/OverlaySyncService.timeout.test.ts diff --git a/tests/application/RecalculateChampionshipStandingsUseCase.spec.ts b/core/automation/application/RecalculateChampionshipStandingsUseCase.test.ts similarity index 100% rename from tests/application/RecalculateChampionshipStandingsUseCase.spec.ts rename to core/automation/application/RecalculateChampionshipStandingsUseCase.test.ts diff --git a/tests/application/StartAutomationSession.spec.ts b/core/automation/application/StartAutomationSession.test.ts similarity index 100% rename from tests/application/StartAutomationSession.spec.ts rename to core/automation/application/StartAutomationSession.test.ts diff --git a/tests/application/VerifyAuthenticatedPageUseCase.spec.ts b/core/automation/application/VerifyAuthenticatedPageUseCase.test.ts similarity index 100% rename from tests/application/VerifyAuthenticatedPageUseCase.spec.ts rename to core/automation/application/VerifyAuthenticatedPageUseCase.test.ts diff --git a/tests/domain/AutomationSession.spec.ts b/core/automation/domain/entities/AutomationSession.test.ts similarity index 100% rename from tests/domain/AutomationSession.spec.ts rename to core/automation/domain/entities/AutomationSession.test.ts diff --git a/tests/domain/PageStateValidator.spec.ts b/core/automation/domain/services/PageStateValidator.test.ts similarity index 100% rename from tests/domain/PageStateValidator.spec.ts rename to core/automation/domain/services/PageStateValidator.test.ts diff --git a/tests/domain/StepTransitionValidator.spec.ts b/core/automation/domain/services/StepTransitionValidator.test.ts similarity index 100% rename from tests/domain/StepTransitionValidator.spec.ts rename to core/automation/domain/services/StepTransitionValidator.test.ts diff --git a/core/automation/domain/shared/Result.ts b/core/automation/domain/shared/Result.ts deleted file mode 100644 index 0b3d837ee..000000000 --- a/core/automation/domain/shared/Result.ts +++ /dev/null @@ -1,78 +0,0 @@ -export class Result { - private constructor( - private readonly _value?: T, - private readonly _error?: E, - private readonly _isSuccess: boolean = true - ) {} - - static ok(value: T): Result { - return new Result(value, undefined, true); - } - - static err(error: E): Result { - return new Result(undefined, error, false); - } - - isOk(): boolean { - return this._isSuccess; - } - - isErr(): boolean { - return !this._isSuccess; - } - - unwrap(): T { - if (!this._isSuccess) { - throw new Error('Called unwrap on an error result'); - } - return this._value!; - } - - unwrapOr(defaultValue: T): T { - return this._isSuccess ? this._value! : defaultValue; - } - - unwrapErr(): E { - if (this._isSuccess) { - throw new Error('Called unwrapErr on a success result'); - } - return this._error!; - } - - map(fn: (value: T) => U): Result { - if (this._isSuccess) { - return Result.ok(fn(this._value!)); - } - return Result.err(this._error!); - } - - mapErr(fn: (error: E) => F): Result { - if (!this._isSuccess) { - return Result.err(fn(this._error!)); - } - return Result.ok(this._value!); - } - - andThen(fn: (value: T) => Result): Result { - if (this._isSuccess) { - return fn(this._value!); - } - return Result.err(this._error!); - } - - /** - * Direct access to the value (for testing convenience). - * Prefer using unwrap() in production code. - */ - get value(): T | undefined { - return this._value; - } - - /** - * Direct access to the error (for testing convenience). - * Prefer using unwrapErr() in production code. - */ - get error(): E | undefined { - return this._error; - } -} \ No newline at end of file diff --git a/tests/domain/BrowserAuthenticationState.spec.ts b/core/automation/domain/value-objects/BrowserAuthenticationState.test.ts similarity index 100% rename from tests/domain/BrowserAuthenticationState.spec.ts rename to core/automation/domain/value-objects/BrowserAuthenticationState.test.ts diff --git a/tests/domain/CheckoutConfirmation.spec.ts b/core/automation/domain/value-objects/CheckoutConfirmation.test.ts similarity index 100% rename from tests/domain/CheckoutConfirmation.spec.ts rename to core/automation/domain/value-objects/CheckoutConfirmation.test.ts diff --git a/tests/domain/CheckoutPrice.spec.ts b/core/automation/domain/value-objects/CheckoutPrice.test.ts similarity index 100% rename from tests/domain/CheckoutPrice.spec.ts rename to core/automation/domain/value-objects/CheckoutPrice.test.ts diff --git a/tests/domain/CheckoutState.spec.ts b/core/automation/domain/value-objects/CheckoutState.test.ts similarity index 100% rename from tests/domain/CheckoutState.spec.ts rename to core/automation/domain/value-objects/CheckoutState.test.ts diff --git a/tests/domain/CookieConfiguration.spec.ts b/core/automation/domain/value-objects/CookieConfiguration.test.ts similarity index 100% rename from tests/domain/CookieConfiguration.spec.ts rename to core/automation/domain/value-objects/CookieConfiguration.test.ts diff --git a/tests/domain/RaceCreationResult.spec.ts b/core/automation/domain/value-objects/RaceCreationResult.test.ts similarity index 100% rename from tests/domain/RaceCreationResult.spec.ts rename to core/automation/domain/value-objects/RaceCreationResult.test.ts diff --git a/tests/domain/SessionLifetime.spec.ts b/core/automation/domain/value-objects/SessionLifetime.test.ts similarity index 100% rename from tests/domain/SessionLifetime.spec.ts rename to core/automation/domain/value-objects/SessionLifetime.test.ts diff --git a/tests/domain/SessionState.spec.ts b/core/automation/domain/value-objects/SessionState.test.ts similarity index 100% rename from tests/domain/SessionState.spec.ts rename to core/automation/domain/value-objects/SessionState.test.ts diff --git a/tests/domain/StepId.spec.ts b/core/automation/domain/value-objects/StepId.test.ts similarity index 100% rename from tests/domain/StepId.spec.ts rename to core/automation/domain/value-objects/StepId.test.ts diff --git a/tests/infrastructure/AutomationConfig.spec.ts b/core/automation/infrastructure/AutomationConfig.test.ts similarity index 100% rename from tests/infrastructure/AutomationConfig.spec.ts rename to core/automation/infrastructure/AutomationConfig.test.ts diff --git a/tests/infrastructure/BrowserModeConfig.spec.ts b/core/automation/infrastructure/BrowserModeConfig.test.ts similarity index 100% rename from tests/infrastructure/BrowserModeConfig.spec.ts rename to core/automation/infrastructure/BrowserModeConfig.test.ts diff --git a/tests/infrastructure/DemoImageServiceAdapter.spec.ts b/core/automation/infrastructure/DemoImageServiceAdapter.test.ts similarity index 100% rename from tests/infrastructure/DemoImageServiceAdapter.spec.ts rename to core/automation/infrastructure/DemoImageServiceAdapter.test.ts diff --git a/tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts b/core/automation/infrastructure/ElectronCheckoutConfirmationAdapter.test.ts similarity index 100% rename from tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts rename to core/automation/infrastructure/ElectronCheckoutConfirmationAdapter.test.ts diff --git a/tests/infrastructure/WizardDismissalDetection.spec.ts b/core/automation/infrastructure/WizardDismissalDetection.test.ts similarity index 100% rename from tests/infrastructure/WizardDismissalDetection.spec.ts rename to core/automation/infrastructure/WizardDismissalDetection.test.ts diff --git a/tests/infrastructure/AuthenticationGuard.spec.ts b/core/automation/infrastructure/adapters/automation/auth/AuthenticationGuard.test.ts similarity index 100% rename from tests/infrastructure/AuthenticationGuard.spec.ts rename to core/automation/infrastructure/adapters/automation/auth/AuthenticationGuard.test.ts diff --git a/tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts b/core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.initiateLogin.browserMode.test.ts similarity index 100% rename from tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts rename to core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.initiateLogin.browserMode.test.ts diff --git a/tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts b/core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.verifyPageAuthentication.test.ts similarity index 100% rename from tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts rename to core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.verifyPageAuthentication.test.ts diff --git a/tests/infrastructure/SessionCookieStore.spec.ts b/core/automation/infrastructure/adapters/automation/auth/SessionCookieStore.test.ts similarity index 100% rename from tests/infrastructure/SessionCookieStore.spec.ts rename to core/automation/infrastructure/adapters/automation/auth/SessionCookieStore.test.ts diff --git a/tests/identity/EmailValidation.spec.ts b/core/identity/EmailValidation.test.ts similarity index 100% rename from tests/identity/EmailValidation.spec.ts rename to core/identity/EmailValidation.test.ts diff --git a/tests/media/MediaUrl.spec.ts b/core/media/MediaUrl.test.ts similarity index 100% rename from tests/media/MediaUrl.spec.ts rename to core/media/MediaUrl.test.ts diff --git a/tests/notifications/NotificationId.spec.ts b/core/notifications/NotificationId.test.ts similarity index 100% rename from tests/notifications/NotificationId.spec.ts rename to core/notifications/NotificationId.test.ts diff --git a/tests/notifications/QuietHours.spec.ts b/core/notifications/QuietHours.test.ts similarity index 100% rename from tests/notifications/QuietHours.spec.ts rename to core/notifications/QuietHours.test.ts diff --git a/tests/racing-application/ApproveLeagueJoinRequestUseCase.spec.ts b/core/racing/application/ApproveLeagueJoinRequestUseCase.test.ts similarity index 100% rename from tests/racing-application/ApproveLeagueJoinRequestUseCase.spec.ts rename to core/racing/application/ApproveLeagueJoinRequestUseCase.test.ts diff --git a/tests/racing-application/DashboardOverviewUseCase.spec.ts b/core/racing/application/DashboardOverviewUseCase.test.ts similarity index 100% rename from tests/racing-application/DashboardOverviewUseCase.spec.ts rename to core/racing/application/DashboardOverviewUseCase.test.ts diff --git a/tests/racing-application/GetLeagueJoinRequestsUseCase.spec.ts b/core/racing/application/GetLeagueJoinRequestsUseCase.test.ts similarity index 100% rename from tests/racing-application/GetLeagueJoinRequestsUseCase.spec.ts rename to core/racing/application/GetLeagueJoinRequestsUseCase.test.ts diff --git a/tests/racing-application/MembershipUseCases.spec.ts b/core/racing/application/MembershipUseCases.test.ts similarity index 100% rename from tests/racing-application/MembershipUseCases.spec.ts rename to core/racing/application/MembershipUseCases.test.ts diff --git a/tests/racing-application/RaceDetailUseCases.spec.ts b/core/racing/application/RaceDetailUseCases.test.ts similarity index 100% rename from tests/racing-application/RaceDetailUseCases.spec.ts rename to core/racing/application/RaceDetailUseCases.test.ts diff --git a/tests/racing-application/RaceResultsUseCases.spec.ts b/core/racing/application/RaceResultsUseCases.test.ts similarity index 100% rename from tests/racing-application/RaceResultsUseCases.spec.ts rename to core/racing/application/RaceResultsUseCases.test.ts diff --git a/tests/racing-application/RegistrationAndTeamUseCases.spec.ts b/core/racing/application/RegistrationAndTeamUseCases.test.ts similarity index 100% rename from tests/racing-application/RegistrationAndTeamUseCases.spec.ts rename to core/racing/application/RegistrationAndTeamUseCases.test.ts diff --git a/tests/racing-application/RejectLeagueJoinRequestUseCase.spec.ts b/core/racing/application/RejectLeagueJoinRequestUseCase.test.ts similarity index 100% rename from tests/racing-application/RejectLeagueJoinRequestUseCase.spec.ts rename to core/racing/application/RejectLeagueJoinRequestUseCase.test.ts diff --git a/tests/racing-application/RemoveLeagueMemberUseCase.spec.ts b/core/racing/application/RemoveLeagueMemberUseCase.test.ts similarity index 100% rename from tests/racing-application/RemoveLeagueMemberUseCase.spec.ts rename to core/racing/application/RemoveLeagueMemberUseCase.test.ts diff --git a/tests/racing-application/SeasonUseCases.spec.ts b/core/racing/application/SeasonUseCases.test.ts similarity index 100% rename from tests/racing-application/SeasonUseCases.spec.ts rename to core/racing/application/SeasonUseCases.test.ts diff --git a/tests/racing-application/UpdateLeagueMemberRoleUseCase.spec.ts b/core/racing/application/UpdateLeagueMemberRoleUseCase.test.ts similarity index 100% rename from tests/racing-application/UpdateLeagueMemberRoleUseCase.spec.ts rename to core/racing/application/UpdateLeagueMemberRoleUseCase.test.ts diff --git a/tests/racing/Season.spec.ts b/core/racing/domain/entities/Season.test.ts similarity index 100% rename from tests/racing/Season.spec.ts rename to core/racing/domain/entities/Season.test.ts diff --git a/tests/domain/DropScoreApplier.spec.ts b/core/racing/domain/services/DropScoreApplier.test.ts similarity index 100% rename from tests/domain/DropScoreApplier.spec.ts rename to core/racing/domain/services/DropScoreApplier.test.ts diff --git a/tests/racing/EventScoringService.spec.ts b/core/racing/domain/services/EventScoringService.test.ts similarity index 100% rename from tests/racing/EventScoringService.spec.ts rename to core/racing/domain/services/EventScoringService.test.ts diff --git a/tests/domain/ScheduleCalculator.spec.ts b/core/racing/domain/services/ScheduleCalculator.test.ts similarity index 100% rename from tests/domain/ScheduleCalculator.spec.ts rename to core/racing/domain/services/ScheduleCalculator.test.ts diff --git a/core/tsconfig.json b/core/tsconfig.json index 512f0a4df..56f097f19 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -8,6 +8,7 @@ "declaration": true, "declarationMap": true, "sourceMap": true, + "types": ["vitest/globals"], "paths": { "@/*": ["./*"], "@core/*": ["./*"], @@ -16,5 +17,5 @@ } }, "include": ["**/*.ts"], - "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] + "exclude": ["node_modules", "dist"] } \ No newline at end of file diff --git a/tests/smoke/website-pages.spec.ts b/tests/smoke/website-pages.test.ts similarity index 100% rename from tests/smoke/website-pages.spec.ts rename to tests/smoke/website-pages.test.ts diff --git a/tests/structure/PackageDependencies.spec.ts b/tests/structure/PackageDependencies.test.ts similarity index 100% rename from tests/structure/PackageDependencies.spec.ts rename to tests/structure/PackageDependencies.test.ts diff --git a/tests/unit/website/AlphaNav.test.tsx b/tests/unit/website/AlphaNav.test.tsx deleted file mode 100644 index af37396bd..000000000 --- a/tests/unit/website/AlphaNav.test.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import React from 'react'; -import { render, screen } from '@testing-library/react'; - -vi.mock('next/navigation', () => ({ - usePathname: () => '/', - useRouter: () => ({ - push: () => {}, - replace: () => {}, - prefetch: () => {}, - }), -})); - -vi.mock('next/link', () => { - const ActualLink = ({ href, children, ...rest }: any) => ( - - {children} - - ); - return { default: ActualLink }; -}); - -vi.mock('../../../apps/website/components/profile/UserPill', () => { - return { - __esModule: true, - default: function MockUserPill() { - return ( -
- Sign In - Get Started - -
- ); - }, - }; -}); - -vi.mock('../../../apps/website/lib/auth/AuthContext', () => { - const React = require('react'); - const AuthContext = React.createContext({ - session: null, - loading: false, - login: () => {}, - logout: async () => {}, - refreshSession: async () => {}, - }); - - const AuthProvider = ({ initialSession, children }: { initialSession?: any; children: React.ReactNode }) => ( - {}, logout: async () => {}, refreshSession: async () => {} }}>{children} - ); - - const useAuth = () => React.useContext(AuthContext); - - return { - __esModule: true, - AuthProvider, - useAuth, - }; -}); - -import { AuthProvider } from '../../../apps/website/lib/auth/AuthContext'; -import { AlphaNav } from '../../../apps/website/components/alpha/AlphaNav'; - -describe('AlphaNav', () => { - it('hides Dashboard link and uses Home when unauthenticated', () => { - render( - - - , - ); - - const dashboardLinks = screen.queryAllByText('Dashboard'); - expect(dashboardLinks.length).toBe(0); - - const homeLink = screen.getByText('Home'); - expect(homeLink).toBeInTheDocument(); - }); - - it('shows Dashboard link and hides Home when authenticated', () => { - render( - - - , - ); - - const dashboard = screen.getByText('Dashboard'); - expect(dashboard).toBeInTheDocument(); - expect((dashboard as HTMLAnchorElement).getAttribute('href')).toBe('/dashboard'); - - const homeLink = screen.queryByText('Home'); - expect(homeLink).toBeNull(); - }); -}); \ No newline at end of file diff --git a/tests/unit/website/InlinePenaltyButton.test.tsx b/tests/unit/website/InlinePenaltyButton.test.tsx deleted file mode 100644 index 148e295ff..000000000 --- a/tests/unit/website/InlinePenaltyButton.test.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; - -// Mock() Button component -vi.mock('../../../apps/website/components/ui/Button', () => ({ - default: ({ onClick, children, className, title, variant }: any) => ( - - ), -})); - -import InlinePenaltyButton from '../../../apps/website/components/races/InlinePenaltyButton'; - -describe('InlinePenaltyButton', () => { - const mockDriver = { id: 'driver-1', name: 'Test Driver' }; - const mockOnPenaltyClick = vi.fn(); - - it('should not render when user is not admin', () => { - render( - - ); - - const button = screen.queryByTestId('penalty-button'); - expect(button).not.toBeInTheDocument(); - }); - - it('should render when user is admin', () => { - render( - - ); - - const button = screen.getByTestId('penalty-button'); - expect(button).toBeInTheDocument(); - expect(button).toHaveAttribute('title', 'Issue penalty to Test Driver'); - expect(button).toHaveAttribute('data-variant', 'danger'); - }); - - it('should call onPenaltyClick when button is clicked', () => { - render( - - ); - - const button = screen.getByTestId('penalty-button'); - fireEvent.click(button); - - expect(mockOnPenaltyClick).toHaveBeenCalledTimes(1); - expect(mockOnPenaltyClick).toHaveBeenCalledWith(mockDriver); - }); - - it('should not crash when onPenaltyClick is not provided', () => { - render( - - ); - - const button = screen.getByTestId('penalty-button'); - - // Should not crash when clicked without onPenaltyClick - expect(() => fireEvent.click(button)).not.toThrow(); - }); - - it('should have proper button styling for spacing', () => { - render( - - ); - - const button = screen.getByTestId('penalty-button'); - - // Check that button has proper spacing classes - expect(button).toHaveClass('p-1.5'); - expect(button).toHaveClass('min-h-[32px]'); - expect(button).toHaveClass('w-8'); - expect(button).toHaveClass('h-8'); - expect(button).toHaveClass('rounded-full'); - expect(button).toHaveClass('flex'); - expect(button).toHaveClass('items-center'); - expect(button).toHaveClass('justify-center'); - }); - - it('should render AlertTriangle icon with proper sizing', () => { - render( - - ); - - const button = screen.getByTestId('penalty-button'); - const icon = button.querySelector('svg'); - - expect(icon).toBeInTheDocument(); - expect(icon).toHaveClass('w-4'); - expect(icon).toHaveClass('h-4'); - expect(icon).toHaveClass('flex-shrink-0'); - }); -}); \ No newline at end of file diff --git a/tests/unit/website/auth/DashboardAndLayoutAuth.test.tsx b/tests/unit/website/auth/DashboardAndLayoutAuth.test.tsx deleted file mode 100644 index 393b32b7d..000000000 --- a/tests/unit/website/auth/DashboardAndLayoutAuth.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -/** - * Auth + caching behavior for RootLayout and Dashboard. - * - * These tests assert that: - * - RootLayout is marked dynamic so it re-evaluates cookies per request. - * - DashboardPage is also dynamic (no static caching of auth state). - */ - -describe('RootLayout auth caching behavior', () => { - it('is configured as dynamic to avoid static auth caching', async () => { - const layoutModule = (await import( - '../../../../apps/website/app/layout', - )) as { dynamic?: string }; - - // Next.js dynamic routing flag - const dynamic = layoutModule.dynamic; - - expect(dynamic).toBe('force-dynamic'); - }); -}); - -describe('Dashboard auth caching behavior', () => { - it('is configured as dynamic to evaluate auth per request', async () => { - const dashboardModule = (await import( - '../../../../apps/website/app/dashboard/page', - )) as { dynamic?: string }; - - const dynamic = dashboardModule.dynamic; - - expect(dynamic).toBe('force-dynamic'); - }); -}); \ No newline at end of file diff --git a/tests/unit/website/leagues/CreateLeaguePage.wizardStep.test.tsx b/tests/unit/website/leagues/CreateLeaguePage.wizardStep.test.tsx deleted file mode 100644 index 41dfb99a6..000000000 --- a/tests/unit/website/leagues/CreateLeaguePage.wizardStep.test.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import React from 'react'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; - -// --- Mocks for Next.js navigation --- - -const useSearchParamsMock = vi.fn(); -const useRouterMock = vi.fn(); - -const routerInstance = { - push: vi.fn(), - replace: vi.fn(), - prefetch: vi.fn(), -}; - -vi.mock('next/navigation', () => { - return { - useSearchParams: () => useSearchParamsMock(), - useRouter: () => { - return useRouterMock() ?? routerInstance; - }, - }; -}); - -// Minimal next/link mock to keep existing patterns consistent -vi.mock('next/link', () => { - const ActualLink = ({ href, children, ...rest }: any) => ( - - {children} - - ); - return { default: ActualLink }; -}); - -import CreateLeaguePage from '../../../../apps/website/app/leagues/create/page'; - -// Helper to build a searchParams-like object -function createSearchParams(stepValue: string | null) { - return { - get: (key: string) => { - if (key === 'step') { - return stepValue; - } - return null; - }, - } as URLSearchParams; -} - -describe('CreateLeaguePage - URL-bound wizard steps', () => { - beforeEach(() => { - useSearchParamsMock.mockReset(); - useRouterMock.mockReset(); - routerInstance.push.mockReset(); - routerInstance.replace.mockReset(); - }); - - it('defaults to basics step when step param is missing', () => { - useSearchParamsMock.mockReturnValue(createSearchParams(null)); - - render(); - - // Basics step title from the wizard - expect(screen.getByText('Name your league')).toBeInTheDocument(); - }); - - it('treats invalid step value as basics', () => { - useSearchParamsMock.mockReturnValue(createSearchParams('invalid-step')); - - render(); - - expect(screen.getByText('Name your league')).toBeInTheDocument(); - }); - - it('mounts directly on scoring step when step=scoring', () => { - useSearchParamsMock.mockReturnValue(createSearchParams('scoring')); - - render(); - - // Step 4 title in the wizard - expect(screen.getByText('Scoring & championships')).toBeInTheDocument(); - }); - - it('renders a Continue button on the basics step that can trigger navigation when the form is valid', () => { - useSearchParamsMock.mockReturnValue(createSearchParams(null)); - useRouterMock.mockReturnValue(routerInstance); - - render(); - - const continueButton = screen.getByRole('button', { name: /continue/i }); - // The underlying wizard only enables this button when the form is valid. - // This smoke-test just confirms the button is present and clickable without asserting navigation, - // leaving detailed navigation behavior to more focused integration tests. - fireEvent.click(continueButton); - }); - - it('clicking Back from schedule navigates to step=structure via router', () => { - useSearchParamsMock.mockReturnValue(createSearchParams('schedule')); - useRouterMock.mockReturnValue(routerInstance); - - render(); - - const backButton = screen.getByRole('button', { name: /back/i }); - fireEvent.click(backButton); - - expect(routerInstance.push).toHaveBeenCalledTimes(1); - const call = routerInstance.push.mock.calls[0]; - expect(call).toBeDefined(); - const callArg = (call as [string])[0]; - expect(callArg).toContain('/leagues/create'); - expect(callArg).toContain('step=structure'); - }); - - it('derives current step solely from URL so a "reload" keeps the same step', () => { - useSearchParamsMock.mockReturnValueOnce(createSearchParams('scoring')); - useSearchParamsMock.mockReturnValueOnce(createSearchParams('scoring')); - - render(); - expect(screen.getAllByText('Scoring & championships').length).toBeGreaterThanOrEqual(1); - - // Simulate a logical reload by re-rendering with the same URL state - render(); - expect(screen.getAllByText('Scoring & championships').length).toBeGreaterThanOrEqual(1); - }); -}); \ No newline at end of file diff --git a/tests/website/AlphaComponents.spec.ts b/tests/website/AlphaComponents.spec.ts deleted file mode 100644 index c16a8cf3c..000000000 --- a/tests/website/AlphaComponents.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import fs from 'node:fs'; -import path from 'node:path'; - -const alphaDir = path.resolve(__dirname, '../../../../apps/website/components/alpha'); - -const metaAllowlist = new Set([ - 'FeatureLimitationTooltip.tsx', - 'CompanionInstructions.tsx', - 'CompanionStatus.tsx', - 'AlphaBanner.tsx', - 'AlphaFooter.tsx', - 'AlphaNav.tsx', - // Temporary passthrough wrapper that re-exports the real schedule form - 'ScheduleRaceForm.tsx', -]); - -describe('Alpha components structure', () => { - it('contains only alpha chrome and meta components', () => { - const entries = fs.readdirSync(alphaDir); - const tsxFiles = entries.filter((file) => file.endsWith('.tsx')); - - const violations = tsxFiles.filter((file) => { - if (metaAllowlist.has(file)) { - return false; - } - return !file.startsWith('Alpha'); - }); - - expect(violations).toEqual([]); - }); -}); \ No newline at end of file diff --git a/tests/website/ImportBoundaries.spec.ts b/tests/website/ImportBoundaries.spec.ts deleted file mode 100644 index 742760c03..000000000 --- a/tests/website/ImportBoundaries.spec.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import fs from 'node:fs'; -import path from 'node:path'; - -const websiteRoot = path.resolve(__dirname, '../../../../apps/website'); - -const forbiddenImportPrefixes = [ - "@/lib/demo-data", - "@/lib/inmemory", - "@/lib/social", - "@/lib/email-validation", - "@/lib/membership-data", - "@/lib/registration-data", - "@/lib/team-data", -]; - -function collectTsFiles(dir: string): string[] { - const entries = fs.readdirSync(dir, { withFileTypes: true }); - const files: string[] = []; - - for (const entry of entries) { - const fullPath = path.join(dir, entry.name); - if (entry.isDirectory()) { - // Skip Next.js build output if present - if (entry.name === '.next') continue; - files.push(...collectTsFiles(fullPath)); - } else if (entry.isFile()) { - if ( - entry.name.endsWith('.ts') || - entry.name.endsWith('.tsx') - ) { - files.push(fullPath); - } - } - } - - return files; -} - -describe('Website import boundaries', () => { - it('does not import forbidden website lib modules directly', () => { - const files = collectTsFiles(websiteRoot); - - const violations: { file: string; line: number; content: string }[] = []; - - for (const file of files) { - const content = fs.readFileSync(file, 'utf8'); - const lines = content.split(/\r?\n/); - - lines.forEach((line, index) => { - const trimmed = line.trim(); - if (!trimmed.startsWith('import')) return; - - for (const prefix of forbiddenImportPrefixes) { - if (trimmed.includes(`"${prefix}`) || trimmed.includes(`'${prefix}`)) { - violations.push({ - file, - line: index + 1, - content: line, - }); - } - } - }); - } - - if (violations.length > 0) { - const message = - 'Found forbidden imports in apps/website:\n' + - violations - .map( - (v) => - `- ${v.file}:${v.line} :: ${v.content.trim()}`, - ) - .join('\n'); - // Fail with detailed message so we can iterate while RED - expect(message).toBe(''); // Intentionally impossible when violations exist - } else { - expect(violations).toEqual([]); - } - }); -}); \ No newline at end of file diff --git a/tests/website/InMemoryAuthService.spec.ts b/tests/website/InMemoryAuthService.spec.ts deleted file mode 100644 index 0d3b95f55..000000000 --- a/tests/website/InMemoryAuthService.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; - -const cookieStore = { - get: vi.fn(), - set: vi.fn(), - delete: vi.fn(), -}; - -vi.mock('next/headers', () => ({ - cookies: () => cookieStore, -})); - -import { InMemoryAuthService } from '../../../../apps/website/lib/auth/InMemoryAuthService'; - -describe('InMemoryAuthService', () => { - beforeEach(() => { - cookieStore.get.mockReset(); - cookieStore.set.mockReset(); - cookieStore.delete.mockReset(); - }); - - it('startIracingAuthRedirect returns redirectUrl with returnTo and state without touching cookies', async () => { - const service = new InMemoryAuthService(); - - const { redirectUrl, state } = await service.startIracingAuthRedirect('some'); - - expect(typeof state).toBe('string'); - expect(state.length).toBeGreaterThan(0); - - const url = new URL(redirectUrl, 'http://localhost'); - expect(url.pathname).toBe('/auth/iracing/callback'); - expect(url.searchParams.get('returnTo')).toBe('some'); - expect(url.searchParams.get('state')).toBe(state); - expect(url.searchParams.get('code')).toBeTruthy(); - - expect(cookieStore.get).not.toHaveBeenCalled(); - expect(cookieStore.set).not.toHaveBeenCalled(); - expect(cookieStore.delete).not.toHaveBeenCalled(); - }); - - it('loginWithIracingCallback returns deterministic demo session', async () => { - const service = new InMemoryAuthService(); - - const session = await service.loginWithIracingCallback({ - code: 'dummy-code', - state: 'any-state', - }); - - expect(session.user.id).toBe('demo-user'); - expect(session.user.primaryDriverId).toBeDefined(); - expect(session.user.primaryDriverId).not.toBe(''); - }); - - it('logout clears the demo session cookie via adapter', async () => { - const service = new InMemoryAuthService(); - - await service.logout(); - - expect(cookieStore.get).not.toHaveBeenCalled(); - expect(cookieStore.set).not.toHaveBeenCalled(); - expect(cookieStore.delete).toHaveBeenCalledWith('gp_demo_session'); - }); -}); \ No newline at end of file diff --git a/tests/website/IracingAuthPageImports.spec.ts b/tests/website/IracingAuthPageImports.spec.ts deleted file mode 100644 index 626aa29b3..000000000 --- a/tests/website/IracingAuthPageImports.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import fs from 'node:fs'; -import path from 'node:path'; - -describe('IracingAuthPage imports', () => { - it('does not import cookies or getAuthService', () => { - const filePath = path.resolve( - __dirname, - '../../../../apps/website/app/auth/iracing/page.tsx', - ); - const source = fs.readFileSync(filePath, 'utf-8'); - - expect(source.includes("from 'next/headers'")).toBe(false); - expect(source.includes('cookies(')).toBe(false); - expect(source.includes('getAuthService')).toBe(false); - }); -}); \ No newline at end of file diff --git a/tests/website/IracingRoutes.spec.ts b/tests/website/IracingRoutes.spec.ts deleted file mode 100644 index fc1e4c453..000000000 --- a/tests/website/IracingRoutes.spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; - -const cookieStore = { - get: vi.fn(), - set: vi.fn(), - delete: vi.fn(), -}; - -vi.mock('next/headers', () => { - return { - cookies: () => cookieStore, - }; -}); - -import { GET as startGet } from '../../../../apps/website/app/auth/iracing/start/route'; -import { GET as callbackGet } from '../../../../apps/website/app/auth/iracing/callback/route'; -import { POST as logoutPost } from '../../../../apps/website/app/auth/logout/route'; - -describe('iRacing auth route handlers', () => { - beforeEach(() => { - cookieStore.get.mockReset(); - cookieStore.set.mockReset(); - cookieStore.delete.mockReset(); - }); - - it('start route redirects to auth URL and sets state cookie', async () => { - const req = new Request('http://localhost/auth/iracing/start?returnTo=/dashboard'); - - const res = await startGet(req); - - expect(res.status).toBe(307); - const location = res.headers.get('location') ?? ''; - expect(location).toContain('/auth/iracing/callback'); - expect(location).toContain('returnTo=%2Fdashboard'); - expect(location).toMatch(/state=/); - - expect(cookieStore.set).toHaveBeenCalled(); - const call = cookieStore.set.mock.calls[0]; - expect(call).toBeDefined(); - const [name] = call as [string, string]; - expect(name).toBe('gp_demo_auth_state'); - }); - - it('callback route creates session cookie and redirects to returnTo', async () => { - cookieStore.get.mockImplementation((name: string) => { - if (name === 'gp_demo_auth_state') { - return { value: 'valid-state' }; - } - return undefined; - }); - - const req = new Request( - 'http://localhost/auth/iracing/callback?code=demo-code&state=valid-state&returnTo=/dashboard', - ); - - const res = await callbackGet(req); - - expect(res.status).toBe(307); - const location = res.headers.get('location'); - expect(location).toBe('http://localhost/dashboard'); - - expect(cookieStore.set).toHaveBeenCalled(); - const call = cookieStore.set.mock.calls[0]; - expect(call).toBeDefined(); - const [sessionName, sessionValue] = call as [string, string]; - expect(sessionName).toBe('gp_demo_session'); - expect(typeof sessionValue).toBe('string'); - - expect(cookieStore.delete).toHaveBeenCalledWith('gp_demo_auth_state'); - }); - - it('logout route deletes session cookie and redirects home using request origin', async () => { - const req = new Request('http://example.com/auth/logout', { - method: 'POST', - }); - - const res = await logoutPost(req); - - expect(res.status).toBe(307); - const location = res.headers.get('location'); - expect(location).toBe('http://example.com/'); - - expect(cookieStore.delete).toHaveBeenCalledWith('gp_demo_session'); - }); -}); \ No newline at end of file diff --git a/tests/website/getAppMode.spec.ts b/tests/website/getAppMode.spec.ts deleted file mode 100644 index e76a036d3..000000000 --- a/tests/website/getAppMode.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach } from 'vitest'; - -import { getAppMode, AppMode } from '../../../apps/website/lib/mode'; - -const ORIGINAL_NODE_ENV = process.env.NODE_ENV; - -describe('getAppMode', () => { - const originalEnv = process.env; - - beforeEach(() => { - process.env = { ...originalEnv }; - (process.env as any).NODE_ENV = 'production'; - }); - - afterEach(() => { - process.env = originalEnv; - (process.env as any).NODE_ENV = ORIGINAL_NODE_ENV; - }); - - it('returns "pre-launch" when NEXT_PUBLIC_GRIDPILOT_MODE is undefined', () => { - delete process.env.NEXT_PUBLIC_GRIDPILOT_MODE; - - const mode = getAppMode(); - - expect(mode).toBe('pre-launch'); - }); - - it('returns "pre-launch" when NEXT_PUBLIC_GRIDPILOT_MODE is explicitly set to "pre-launch"', () => { - process.env.NEXT_PUBLIC_GRIDPILOT_MODE = 'pre-launch'; - - const mode = getAppMode(); - - expect(mode).toBe('pre-launch'); - }); - - it('returns "alpha" when NEXT_PUBLIC_GRIDPILOT_MODE is set to "alpha"', () => { - process.env.NEXT_PUBLIC_GRIDPILOT_MODE = 'alpha'; - - const mode = getAppMode(); - - expect(mode).toBe('alpha'); - }); - - it('falls back to "pre-launch" and logs when NEXT_PUBLIC_GRIDPILOT_MODE is invalid in production', () => { - const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {}); - - process.env.NEXT_PUBLIC_GRIDPILOT_MODE = 'invalid-mode' as any; - - const mode = getAppMode(); - - expect(mode).toBe('pre-launch'); - expect(consoleError).toHaveBeenCalled(); - - consoleError.mockRestore(); - }); - - it('throws in development when NEXT_PUBLIC_GRIDPILOT_MODE is invalid', () => { - (process.env as any).NODE_ENV = 'development'; - process.env.NEXT_PUBLIC_GRIDPILOT_MODE = 'invalid-mode' as any; - - expect(() => getAppMode()).toThrowError(/Invalid NEXT_PUBLIC_GRIDPILOT_MODE/); - }); -}); \ No newline at end of file diff --git a/tests/website/signupRoute.spec.ts b/tests/website/signupRoute.spec.ts deleted file mode 100644 index 3723e2f48..000000000 --- a/tests/website/signupRoute.spec.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { describe, it, expect, beforeEach, vi } from 'vitest'; - -type RateLimitResult = { - allowed: boolean; - remaining: number; - resetAt: number; -}; - -const mockCheckRateLimit = vi.fn(() => Promise.resolve({ allowed: true, remaining: 4, resetAt: 0 })); -const mockGetClientIp = vi.fn(() => '127.0.0.1'); - -vi.mock('../../../apps/website/lib/rate-limit', () => ({ - checkRateLimit: mockCheckRateLimit, - getClientIp: mockGetClientIp, -})); - -async function getPostHandler() { - const routeModule = (await import( - '../../../apps/website/app/api/signup/route' - )) as { POST: (request: Request) => Promise }; - return routeModule.POST; -} - -function createJsonRequest(body: unknown): Request { - return new Request('http://localhost/api/signup', { - method: 'POST', - headers: { - 'content-type': 'application/json', - }, - body: JSON.stringify(body), - }); -} - -describe('/api/signup POST', () => { - beforeEach(() => { - vi.resetModules(); - mockCheckRateLimit.mockReset(); - mockGetClientIp.mockReset(); - - mockGetClientIp.mockReturnValue('127.0.0.1'); - mockCheckRateLimit.mockResolvedValue({ - allowed: true, - remaining: 4, - resetAt: Date.now() + 60 * 60 * 1000, - }); - }); - - it('accepts a valid email within rate limits and returns success payload', async () => { - const POST = await getPostHandler(); - - const response = await POST( - createJsonRequest({ - email: 'user@example.com', - }), - ); - - expect(response.status).toBeGreaterThanOrEqual(200); - expect(response.status).toBeLessThan(300); - - const data = (await response.json()) as { message: unknown; ok: unknown }; - - expect(data).toHaveProperty('message'); - expect(typeof data.message).toBe('string'); - expect(data).toHaveProperty('ok', true); - }); - - it('rejects an invalid email with 400 and error message', async () => { - const POST = await getPostHandler(); - - const response = await POST( - createJsonRequest({ - email: 'not-an-email', - }), - ); - - expect(response.status).toBe(400); - - const data = (await response.json()) as { error: unknown }; - expect(typeof data.error).toBe('string'); - expect(typeof data.error === 'string' && data.error.toLowerCase()).toContain('email'); - }); - - it('rejects disposable email domains with 400 and error message', async () => { - const POST = await getPostHandler(); - - const response = await POST( - createJsonRequest({ - email: 'foo@mailinator.com', - }), - ); - - expect(response.status).toBe(400); - - const data = (await response.json()) as { error: unknown }; - expect(typeof data.error).toBe('string'); - }); - - it('returns 409 and friendly message when email is already subscribed', async () => { - const POST = await getPostHandler(); - - const email = 'duplicate@example.com'; - - const first = await POST(createJsonRequest({ email })); - expect(first.status).toBeGreaterThanOrEqual(200); - expect(first.status).toBeLessThan(300); - - const second = await POST(createJsonRequest({ email })); - - expect(second.status).toBe(409); - - const data = (await second.json()) as { error: unknown }; - expect(typeof data.error).toBe('string'); - expect(typeof data.error === 'string' && data.error.toLowerCase()).toContain('already'); - }); - - it('returns 429 with retryAfter when rate limit is exceeded', async () => { - mockCheckRateLimit.mockResolvedValueOnce({ - allowed: false, - remaining: 0, - resetAt: Date.now() + 30_000, - }); - - const POST = await getPostHandler(); - - const response = await POST( - createJsonRequest({ - email: 'limited@example.com', - }), - ); - - expect(response.status).toBe(429); - - const data = (await response.json()) as { error: unknown; retryAfter?: unknown }; - expect(typeof data.error).toBe('string'); - expect(data).toHaveProperty('retryAfter'); - }); -}); \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index d2bc9de34..b069069d9 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -30,5 +30,5 @@ "@testing/*": ["./testing/*"] } }, - "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] + "exclude": ["node_modules", "dist"] } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 4cbd07220..bbbee1f53 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,7 @@ "core/**/*", "apps/**/*", "tests/**/*" - ], +, "adapters/logging/ConsoleLogger.test.ts" ], "exclude": [ "node_modules", "dist", diff --git a/vitest.config.ts b/vitest.config.ts index b54ae7d6d..c158f457f 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,7 +7,12 @@ export default defineConfig({ watch: false, environment: 'jsdom', setupFiles: ['tests/setup/vitest.setup.ts'], - include: ['tests/**/*.{test,spec}.?(c|m)[jt]s?(x)', 'core/**/*.{test,spec}.?(c|m)[jt]s?(x)'], + include: [ + 'tests/**/*.{test,spec}.?(c|m)[jt]s?(x)', + 'core/**/*.{test,spec}.?(c|m)[jt]s?(x)', + 'adapters/**/*.{test,spec}.?(c|m)[jt]s?(x)', + 'apps/**/*.{test,spec}.?(c|m)[jt]s?(x)', + ], exclude: [ 'node_modules/**', 'tests/smoke/website-pages.spec.ts',