// // StadiumTests.swift // SportsTimeTests // // TDD specification tests for Stadium model. // import Testing import CoreLocation @testable import SportsTime @Suite("Stadium") struct StadiumTests { // MARK: - Test Data private let nycCoord = CLLocationCoordinate2D(latitude: 40.7580, longitude: -73.9855) private let bostonCoord = CLLocationCoordinate2D(latitude: 42.3467, longitude: -71.0972) private let chicagoCoord = CLLocationCoordinate2D(latitude: 41.8827, longitude: -87.6233) private let laCoord = CLLocationCoordinate2D(latitude: 34.0430, longitude: -118.2673) private func makeStadium( id: String = "stadium1", latitude: Double, longitude: Double ) -> Stadium { Stadium( id: id, name: "Test Stadium", city: "Test City", state: "XX", latitude: latitude, longitude: longitude, capacity: 40000, sport: .mlb ) } // MARK: - Specification Tests: region @Test("region: NYC longitude returns .east") func region_nycEast() { let stadium = makeStadium(latitude: nycCoord.latitude, longitude: nycCoord.longitude) #expect(stadium.region == .east) } @Test("region: Boston longitude returns .east") func region_bostonEast() { let stadium = makeStadium(latitude: bostonCoord.latitude, longitude: bostonCoord.longitude) #expect(stadium.region == .east) } @Test("region: Chicago longitude returns .central") func region_chicagoCentral() { let stadium = makeStadium(latitude: chicagoCoord.latitude, longitude: chicagoCoord.longitude) #expect(stadium.region == .central) } @Test("region: LA longitude returns .west") func region_laWest() { let stadium = makeStadium(latitude: laCoord.latitude, longitude: laCoord.longitude) #expect(stadium.region == .west) } // MARK: - Specification Tests: coordinate @Test("coordinate returns CLLocationCoordinate2D from lat/long") func coordinate_returnsCorrectValue() { let stadium = makeStadium(latitude: 40.7580, longitude: -73.9855) #expect(stadium.coordinate.latitude == 40.7580) #expect(stadium.coordinate.longitude == -73.9855) } @Test("location returns CLLocation from lat/long") func location_returnsCorrectValue() { let stadium = makeStadium(latitude: 40.7580, longitude: -73.9855) #expect(stadium.location.coordinate.latitude == 40.7580) #expect(stadium.location.coordinate.longitude == -73.9855) } // MARK: - Specification Tests: distance @Test("distance between NYC and Boston stadiums") func distance_nycToBoston() { let nycStadium = makeStadium(id: "nyc", latitude: nycCoord.latitude, longitude: nycCoord.longitude) let bostonStadium = makeStadium(id: "boston", latitude: bostonCoord.latitude, longitude: bostonCoord.longitude) let distance = nycStadium.distance(to: bostonStadium) // NYC to Boston is approximately 298-300 km / ~186 miles with these coordinates #expect(distance > 295_000, "NYC to Boston should be > 295km") #expect(distance < 310_000, "NYC to Boston should be < 310km") } @Test("distance to self is zero") func distance_toSelf() { let stadium = makeStadium(latitude: nycCoord.latitude, longitude: nycCoord.longitude) let distance = stadium.distance(to: stadium) #expect(distance == 0) } @Test("distance from coordinate") func distance_fromCoordinate() { let stadium = makeStadium(latitude: nycCoord.latitude, longitude: nycCoord.longitude) let distance = stadium.distance(from: bostonCoord) // Same as NYC to Boston (~298-300 km depending on exact coordinates) #expect(distance > 295_000) #expect(distance < 310_000) } // MARK: - Specification Tests: Equality @Test("equality based on id only") func equality_basedOnId() { let stadium1 = Stadium( id: "stadium1", name: "Stadium A", city: "City A", state: "AA", latitude: 40.0, longitude: -70.0, capacity: 40000, sport: .mlb ) let stadium2 = Stadium( id: "stadium1", name: "Different Name", city: "Different City", state: "BB", latitude: 30.0, longitude: -80.0, capacity: 50000, sport: .nba ) #expect(stadium1 == stadium2, "Stadiums with same id should be equal") } @Test("inequality when ids differ") func inequality_differentIds() { let stadium1 = makeStadium(id: "stadium1", latitude: 40.0, longitude: -70.0) let stadium2 = makeStadium(id: "stadium2", latitude: 40.0, longitude: -70.0) #expect(stadium1 != stadium2, "Stadiums with different ids should not be equal") } // MARK: - Invariant Tests @Test("Invariant: region is consistent with Region.classify") func invariant_regionConsistentWithClassify() { let testCases: [(lat: Double, lon: Double)] = [ (40.7580, -73.9855), // NYC (41.8827, -87.6233), // Chicago (34.0430, -118.2673), // LA (42.3467, -71.0972), // Boston (33.4484, -112.0740), // Phoenix ] for (lat, lon) in testCases { let stadium = makeStadium(latitude: lat, longitude: lon) let expected = Region.classify(longitude: lon) #expect(stadium.region == expected, "Stadium at \(lon) should be in \(expected)") } } @Test("Invariant: location and coordinate match lat/long") func invariant_locationAndCoordinateMatch() { let stadium = makeStadium(latitude: 40.7580, longitude: -73.9855) #expect(stadium.location.coordinate.latitude == stadium.latitude) #expect(stadium.location.coordinate.longitude == stadium.longitude) #expect(stadium.coordinate.latitude == stadium.latitude) #expect(stadium.coordinate.longitude == stadium.longitude) } // MARK: - Property Tests @Test("Property: fullAddress combines city and state") func property_fullAddress() { let stadium = Stadium( id: "test", name: "Test Stadium", city: "New York", state: "NY", latitude: 40.0, longitude: -74.0, capacity: 40000, sport: .mlb ) #expect(stadium.fullAddress == "New York, NY") } @Test("Property: timeZone returns nil when identifier is nil") func property_timeZoneNil() { let stadium = Stadium( id: "test", name: "Test Stadium", city: "Test", state: "XX", latitude: 40.0, longitude: -74.0, capacity: 40000, sport: .mlb, timeZoneIdentifier: nil ) #expect(stadium.timeZone == nil) } @Test("Property: timeZone returns TimeZone when identifier is valid") func property_timeZoneValid() { let stadium = Stadium( id: "test", name: "Test Stadium", city: "Test", state: "XX", latitude: 40.0, longitude: -74.0, capacity: 40000, sport: .mlb, timeZoneIdentifier: "America/New_York" ) #expect(stadium.timeZone?.identifier == "America/New_York") } }