refactor(tests): TDD rewrite of all unit tests with spec documentation

Complete rewrite of unit test suite using TDD methodology:

Planning Engine Tests:
- GameDAGRouterTests: Beam search, anchor games, transitions
- ItineraryBuilderTests: Stop connection, validators, EV enrichment
- RouteFiltersTests: Region, time window, scoring filters
- ScenarioA/B/C/D PlannerTests: All planning scenarios
- TravelEstimatorTests: Distance, duration, travel days
- TripPlanningEngineTests: Orchestration, caching, preferences

Domain Model Tests:
- AchievementDefinitionsTests, AnySportTests, DivisionTests
- GameTests, ProgressTests, RegionTests, StadiumTests
- TeamTests, TravelSegmentTests, TripTests, TripPollTests
- TripPreferencesTests, TripStopTests, SportTests

Service Tests:
- FreeScoreAPITests, RouteDescriptionGeneratorTests
- SuggestedTripsGeneratorTests

Export Tests:
- ShareableContentTests (card types, themes, dimensions)

Bug fixes discovered through TDD:
- ShareCardDimensions: mapSnapshotSize exceeded available width (960x480)
- ScenarioBPlanner: Added anchor game validation filter

All tests include:
- Specification tests (expected behavior)
- Invariant tests (properties that must always hold)
- Edge case tests (boundary conditions)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-16 14:07:41 -06:00
parent 035dd6f5de
commit 8162b4a029
102 changed files with 13409 additions and 9883 deletions

View File

@@ -9,6 +9,11 @@
import Foundation
/// Result of building an itinerary from stops.
///
/// - Invariants:
/// - travelSegments.count == stops.count - 1 (or 0 if stops.count <= 1)
/// - totalDrivingHours >= 0
/// - totalDistanceMiles >= 0
struct BuiltItinerary {
let stops: [ItineraryStop]
let travelSegments: [TravelSegment]
@@ -17,6 +22,20 @@ struct BuiltItinerary {
}
/// Shared logic for building itineraries across all scenario planners.
///
/// Connects stops with travel segments and validates feasibility.
///
/// - Expected Behavior:
/// - Empty stops empty itinerary (no travel)
/// - Single stop single-stop itinerary (no travel)
/// - Multiple stops segments between each consecutive pair
/// - Infeasible segment (exceeds driving limits) returns nil
/// - Validator returns false returns nil
///
/// - Invariants:
/// - travelSegments.count == stops.count - 1 for successful builds
/// - All segments pass TravelEstimator feasibility check
/// - All segments pass optional custom validator
enum ItineraryBuilder {
/// Validation that can be performed on each travel segment.
@@ -40,6 +59,15 @@ enum ItineraryBuilder {
///
/// - Returns: Built itinerary if successful, nil if any segment fails
///
/// - Expected Behavior:
/// - Empty stops BuiltItinerary with empty segments
/// - Single stop BuiltItinerary with empty segments
/// - Two stops one segment connecting them
/// - N stops N-1 segments
/// - TravelEstimator returns nil returns nil
/// - Validator returns false returns nil
/// - totalDrivingHours = sum of segment.estimatedDrivingHours
/// - totalDistanceMiles = sum of segment.estimatedDistanceMiles
static func build(
stops: [ItineraryStop],
constraints: DrivingConstraints,