Files
Sportstime/SportsTimeTests/Helpers/MockServices.swift
Trey t 8162b4a029 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>
2026-01-16 14:07:41 -06:00

103 lines
3.5 KiB
Swift

//
// MockServices.swift
// SportsTimeTests
//
// Mock implementations of services for testing. These mocks allow tests
// to control service behavior and verify interactions.
//
import Foundation
import CoreLocation
@testable import SportsTime
// MARK: - Mock Data Provider
/// Mock data provider for testing components that depend on game/stadium/team data.
@MainActor
final class MockDataProvider {
var games: [Game] = []
var stadiums: [String: Stadium] = [:]
var teams: [String: Team] = [:]
var shouldFail = false
var failureError: Error = NSError(domain: "MockError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Mock failure"])
func configure(games: [Game], stadiums: [Stadium], teams: [Team]) {
self.games = games
self.stadiums = Dictionary(uniqueKeysWithValues: stadiums.map { ($0.id, $0) })
self.teams = Dictionary(uniqueKeysWithValues: teams.map { ($0.id, $0) })
}
func stadium(for id: String) -> Stadium? {
stadiums[id]
}
func team(for id: String) -> Team? {
teams[id]
}
func filterGames(sports: Set<Sport>, startDate: Date, endDate: Date) throws -> [Game] {
if shouldFail { throw failureError }
return games.filter { game in
sports.contains(game.sport) &&
game.dateTime >= startDate &&
game.dateTime <= endDate
}
}
}
// MARK: - Mock Location Service
/// Mock location service for testing distance and travel time calculations.
@MainActor
final class MockLocationService {
var stubbedDistances: [String: Double] = [:] // "from_to" -> meters
var stubbedTravelTimes: [String: TimeInterval] = [:] // "from_to" -> seconds
var defaultDistanceMeters: Double = 100_000 // ~62 miles
var defaultTravelTimeSeconds: TimeInterval = 3600 // 1 hour
var shouldFail = false
var failureError: Error = NSError(domain: "LocationError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Location unavailable"])
var calculateDistanceCalls: [(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D)] = []
var calculateTravelTimeCalls: [(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D)] = []
func stubDistance(from: String, to: String, meters: Double) {
stubbedDistances["\(from)_\(to)"] = meters
}
func stubTravelTime(from: String, to: String, seconds: TimeInterval) {
stubbedTravelTimes["\(from)_\(to)"] = seconds
}
func calculateDistance(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D) async throws -> Double {
calculateDistanceCalls.append((from: from, to: to))
if shouldFail { throw failureError }
return defaultDistanceMeters
}
func calculateTravelTime(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D) async throws -> TimeInterval {
calculateTravelTimeCalls.append((from: from, to: to))
if shouldFail { throw failureError }
return defaultTravelTimeSeconds
}
}
// MARK: - Mock Route Service
/// Mock route service for testing route optimization.
@MainActor
final class MockRouteService {
var shouldFail = false
var failureError: Error = NSError(domain: "RouteError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Route unavailable"])
var optimizeRouteCalls: [[CLLocationCoordinate2D]] = []
var stubbedRoute: [Int]? // Indices in order
func optimizeRoute(waypoints: [CLLocationCoordinate2D]) async throws -> [Int] {
optimizeRouteCalls.append(waypoints)
if shouldFail { throw failureError }
return stubbedRoute ?? Array(0..<waypoints.count)
}
}