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:
@@ -10,7 +10,13 @@ import CoreLocation
|
||||
|
||||
// MARK: - Planning Scenario
|
||||
|
||||
/// Exactly one scenario per request. No blending.
|
||||
/// Planning scenario types - exactly one per request.
|
||||
///
|
||||
/// - Expected Behavior:
|
||||
/// - scenarioA: User provides date range only, system finds games
|
||||
/// - scenarioB: User selects specific games + date range
|
||||
/// - scenarioC: User provides start/end locations, system plans route
|
||||
/// - scenarioD: User follows a team's schedule
|
||||
enum PlanningScenario: Equatable {
|
||||
case scenarioA // Date range only
|
||||
case scenarioB // Selected games + date range
|
||||
@@ -195,10 +201,19 @@ struct ItineraryOption: Identifiable {
|
||||
/// - leisureLevel: The user's leisure preference
|
||||
/// - Returns: Sorted and ranked options (all options, no limit)
|
||||
///
|
||||
/// Sorting behavior:
|
||||
/// - Packed: Most games first, then least driving
|
||||
/// - Moderate: Best efficiency (games per driving hour)
|
||||
/// - Relaxed: Least driving first, then fewer games
|
||||
/// - Expected Behavior:
|
||||
/// - Empty options → empty result
|
||||
/// - All options are returned (no filtering)
|
||||
/// - Ranks are reassigned 1, 2, 3... after sorting
|
||||
///
|
||||
/// Sorting behavior by leisure level:
|
||||
/// - Packed: Most games first, then least driving (maximize games)
|
||||
/// - Moderate: Best efficiency (games/hour), then most games (balance)
|
||||
/// - Relaxed: Least driving first, then fewer games (minimize driving)
|
||||
///
|
||||
/// - Invariants:
|
||||
/// - Output count == input count
|
||||
/// - Ranks are sequential starting at 1
|
||||
static func sortByLeisure(
|
||||
_ options: [ItineraryOption],
|
||||
leisureLevel: LeisureLevel
|
||||
@@ -270,7 +285,19 @@ struct ItineraryStop: Identifiable, Hashable {
|
||||
|
||||
// MARK: - Driving Constraints
|
||||
|
||||
/// Driving feasibility constraints.
|
||||
/// Driving feasibility constraints based on number of drivers.
|
||||
///
|
||||
/// - Expected Behavior:
|
||||
/// - numberOfDrivers < 1 → clamped to 1
|
||||
/// - maxHoursPerDriverPerDay < 1.0 → clamped to 1.0
|
||||
/// - maxDailyDrivingHours = numberOfDrivers * maxHoursPerDriverPerDay
|
||||
/// - Default: 1 driver, 8 hours/day = 8 total hours
|
||||
/// - 2 drivers, 8 hours each = 16 total hours
|
||||
///
|
||||
/// - Invariants:
|
||||
/// - numberOfDrivers >= 1
|
||||
/// - maxHoursPerDriverPerDay >= 1.0
|
||||
/// - maxDailyDrivingHours >= 1.0
|
||||
struct DrivingConstraints {
|
||||
let numberOfDrivers: Int
|
||||
let maxHoursPerDriverPerDay: Double
|
||||
|
||||
Reference in New Issue
Block a user