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>
165 lines
5.3 KiB
Swift
165 lines
5.3 KiB
Swift
//
|
|
// RegionTests.swift
|
|
// SportsTimeTests
|
|
//
|
|
// TDD specification tests for Region enum.
|
|
//
|
|
|
|
import Testing
|
|
@testable import SportsTime
|
|
|
|
@Suite("Region")
|
|
struct RegionTests {
|
|
|
|
// MARK: - Specification Tests: classify(longitude:)
|
|
|
|
@Test("classify: longitude > -85 returns .east")
|
|
func classify_east() {
|
|
// NYC: -73.9855
|
|
#expect(Region.classify(longitude: -73.9855) == .east)
|
|
|
|
// Boston: -71.0972
|
|
#expect(Region.classify(longitude: -71.0972) == .east)
|
|
|
|
// Miami: -80.1918
|
|
#expect(Region.classify(longitude: -80.1918) == .east)
|
|
|
|
// Toronto: -79.3832
|
|
#expect(Region.classify(longitude: -79.3832) == .east)
|
|
|
|
// Atlanta: -84.3880
|
|
#expect(Region.classify(longitude: -84.3880) == .east)
|
|
|
|
// Just above boundary
|
|
#expect(Region.classify(longitude: -84.9999) == .east)
|
|
}
|
|
|
|
@Test("classify: longitude in -110...-85 returns .central")
|
|
func classify_central() {
|
|
// Chicago: -87.6233
|
|
#expect(Region.classify(longitude: -87.6233) == .central)
|
|
|
|
// Houston: -95.3698
|
|
#expect(Region.classify(longitude: -95.3698) == .central)
|
|
|
|
// Dallas: -96.7970
|
|
#expect(Region.classify(longitude: -96.7970) == .central)
|
|
|
|
// Minneapolis: -93.2650
|
|
#expect(Region.classify(longitude: -93.2650) == .central)
|
|
|
|
// Denver: -104.9903
|
|
#expect(Region.classify(longitude: -104.9903) == .central)
|
|
|
|
// Boundary: exactly -85
|
|
#expect(Region.classify(longitude: -85.0) == .central)
|
|
|
|
// Boundary: exactly -110
|
|
#expect(Region.classify(longitude: -110.0) == .central)
|
|
}
|
|
|
|
@Test("classify: longitude < -110 returns .west")
|
|
func classify_west() {
|
|
// Los Angeles: -118.2673
|
|
#expect(Region.classify(longitude: -118.2673) == .west)
|
|
|
|
// San Francisco: -122.4194
|
|
#expect(Region.classify(longitude: -122.4194) == .west)
|
|
|
|
// Seattle: -122.3321
|
|
#expect(Region.classify(longitude: -122.3321) == .west)
|
|
|
|
// Phoenix: -112.0740
|
|
#expect(Region.classify(longitude: -112.0740) == .west)
|
|
|
|
// Las Vegas: -115.1398
|
|
#expect(Region.classify(longitude: -115.1398) == .west)
|
|
|
|
// Just below boundary
|
|
#expect(Region.classify(longitude: -110.0001) == .west)
|
|
}
|
|
|
|
// MARK: - Specification Tests: Boundary Values
|
|
|
|
@Test("classify boundary: -85 is central, -84.9999 is east")
|
|
func classify_eastCentralBoundary() {
|
|
#expect(Region.classify(longitude: -85.0) == .central)
|
|
#expect(Region.classify(longitude: -84.9999) == .east)
|
|
#expect(Region.classify(longitude: -85.0001) == .central)
|
|
}
|
|
|
|
@Test("classify boundary: -110 is central, -110.0001 is west")
|
|
func classify_centralWestBoundary() {
|
|
#expect(Region.classify(longitude: -110.0) == .central)
|
|
#expect(Region.classify(longitude: -109.9999) == .central)
|
|
#expect(Region.classify(longitude: -110.0001) == .west)
|
|
}
|
|
|
|
// MARK: - Specification Tests: Edge Cases
|
|
|
|
@Test("classify: extreme east longitude (positive) returns .east")
|
|
func classify_extremeEast() {
|
|
#expect(Region.classify(longitude: 0.0) == .east)
|
|
#expect(Region.classify(longitude: 50.0) == .east)
|
|
}
|
|
|
|
@Test("classify: extreme west longitude returns .west")
|
|
func classify_extremeWest() {
|
|
#expect(Region.classify(longitude: -180.0) == .west)
|
|
#expect(Region.classify(longitude: -150.0) == .west)
|
|
}
|
|
|
|
// MARK: - Invariant Tests
|
|
|
|
@Test("Invariant: classify never returns .crossCountry")
|
|
func invariant_classifyNeverReturnsCrossCountry() {
|
|
let testLongitudes: [Double] = [-180, -150, -120, -110.0001, -110, -100, -85.0001, -85, -70, 0, 50]
|
|
for lon in testLongitudes {
|
|
let region = Region.classify(longitude: lon)
|
|
#expect(region != .crossCountry, "classify should never return crossCountry for longitude \(lon)")
|
|
}
|
|
}
|
|
|
|
@Test("Invariant: every longitude maps to exactly one region")
|
|
func invariant_everyLongitudeMapsToOneRegion() {
|
|
// Test a range of longitudes
|
|
for lon in stride(from: -180.0, through: 50.0, by: 10.0) {
|
|
let region = Region.classify(longitude: lon)
|
|
#expect([Region.east, .central, .west].contains(region), "Longitude \(lon) should map to east, central, or west")
|
|
}
|
|
}
|
|
|
|
// MARK: - Property Tests
|
|
|
|
@Test("Property: id equals rawValue")
|
|
func property_idEqualsRawValue() {
|
|
for region in Region.allCases {
|
|
#expect(region.id == region.rawValue)
|
|
}
|
|
}
|
|
|
|
@Test("Property: displayName equals rawValue")
|
|
func property_displayNameEqualsRawValue() {
|
|
for region in Region.allCases {
|
|
#expect(region.displayName == region.rawValue)
|
|
}
|
|
}
|
|
|
|
@Test("Property: all regions have iconName")
|
|
func property_allRegionsHaveIconName() {
|
|
for region in Region.allCases {
|
|
#expect(!region.iconName.isEmpty)
|
|
}
|
|
}
|
|
|
|
// MARK: - Specification Tests: Display Properties
|
|
|
|
@Test("shortName values are correct")
|
|
func shortName_values() {
|
|
#expect(Region.east.shortName == "East")
|
|
#expect(Region.central.shortName == "Central")
|
|
#expect(Region.west.shortName == "West")
|
|
#expect(Region.crossCountry.shortName == "Coast to Coast")
|
|
}
|
|
}
|