Files
Sportstime/SportsTimeTests/Domain/SportTests.swift
Trey T a6f538dfed Audit and fix 52 test correctness issues across 22 files
Systematic audit of 1,191 tests found tests written to pass rather than
verify correctness. Key fixes:

Infrastructure:
- TestClock: fixed timezone from .current to America/New_York (deterministic)
- TestFixtures: added 1.3x road routing factor to match production
- ItineraryTestHelpers: real per-city coordinates instead of hardcoded (40,-80)

Planning tests:
- Added missing Scenario E factory dispatch tests
- Tightened 12 loose assertions (>= 1 → == 8.0, > 0 → range checks)
- Fixed 4 no-op tests that accepted both success and failure
- Fixed wrong repeat-city invariant (was checking same-day, not different-day)
- Fixed tautological assertion in missing-stadium edge case

Services/Domain/Export tests:
- Replaced 4 placeholder tests (#expect(true)) with real assertions
- Fixed tautological assertions in POISearchServiceTests
- Fixed Chicago coordinate in RegionMapSelectorTests (-89 → -87.6553)
- Added sort order verification to ItineraryRowFlatteningTests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:00:46 -05:00

206 lines
7.0 KiB
Swift

//
// SportTests.swift
// SportsTimeTests
//
// TDD specification tests for Sport enum.
//
import Testing
import Foundation
@testable import SportsTime
@Suite("Sport")
struct SportTests {
// MARK: - Specification Tests: Season Months
@Test("MLB season: March (3) to October (10)")
func mlb_seasonMonths() {
let (start, end) = Sport.mlb.seasonMonths
#expect(start == 3)
#expect(end == 10)
}
@Test("NBA season: October (10) to June (6) - wraps around year")
func nba_seasonMonths() {
let (start, end) = Sport.nba.seasonMonths
#expect(start == 10)
#expect(end == 6)
}
@Test("NHL season: October (10) to June (6) - wraps around year")
func nhl_seasonMonths() {
let (start, end) = Sport.nhl.seasonMonths
#expect(start == 10)
#expect(end == 6)
}
@Test("NFL season: September (9) to February (2) - wraps around year")
func nfl_seasonMonths() {
let (start, end) = Sport.nfl.seasonMonths
#expect(start == 9)
#expect(end == 2)
}
@Test("MLS season: February (2) to December (12)")
func mls_seasonMonths() {
let (start, end) = Sport.mls.seasonMonths
#expect(start == 2)
#expect(end == 12)
}
@Test("WNBA season: May (5) to October (10)")
func wnba_seasonMonths() {
let (start, end) = Sport.wnba.seasonMonths
#expect(start == 5)
#expect(end == 10)
}
@Test("NWSL season: March (3) to November (11)")
func nwsl_seasonMonths() {
let (start, end) = Sport.nwsl.seasonMonths
#expect(start == 3)
#expect(end == 11)
}
// MARK: - Specification Tests: isInSeason (Normal Range)
@Test("MLB: isInSeason returns true for months 3-10")
func mlb_isInSeason_normalRange() {
let calendar = TestClock.calendar
// In season: March through October
for month in 3...10 {
let date = calendar.date(from: DateComponents(year: 2026, month: month, day: 15))!
#expect(Sport.mlb.isInSeason(for: date), "MLB should be in season in month \(month)")
}
// Out of season: January, February, November, December
for month in [1, 2, 11, 12] {
let date = calendar.date(from: DateComponents(year: 2026, month: month, day: 15))!
#expect(!Sport.mlb.isInSeason(for: date), "MLB should NOT be in season in month \(month)")
}
}
// MARK: - Specification Tests: isInSeason (Wrap-Around)
@Test("NBA: isInSeason returns true for months 10-12 and 1-6 (wrap-around)")
func nba_isInSeason_wrapAround() {
let calendar = TestClock.calendar
// In season: October through June (wraps)
let inSeasonMonths = [10, 11, 12, 1, 2, 3, 4, 5, 6]
for month in inSeasonMonths {
let date = calendar.date(from: DateComponents(year: 2026, month: month, day: 15))!
#expect(Sport.nba.isInSeason(for: date), "NBA should be in season in month \(month)")
}
// Out of season: July, August, September
for month in [7, 8, 9] {
let date = calendar.date(from: DateComponents(year: 2026, month: month, day: 15))!
#expect(!Sport.nba.isInSeason(for: date), "NBA should NOT be in season in month \(month)")
}
}
@Test("NFL: isInSeason returns true for months 9-12 and 1-2 (wrap-around)")
func nfl_isInSeason_wrapAround() {
let calendar = TestClock.calendar
// In season: September through February (wraps)
let inSeasonMonths = [9, 10, 11, 12, 1, 2]
for month in inSeasonMonths {
let date = calendar.date(from: DateComponents(year: 2026, month: month, day: 15))!
#expect(Sport.nfl.isInSeason(for: date), "NFL should be in season in month \(month)")
}
// Out of season: March through August
for month in 3...8 {
let date = calendar.date(from: DateComponents(year: 2026, month: month, day: 15))!
#expect(!Sport.nfl.isInSeason(for: date), "NFL should NOT be in season in month \(month)")
}
}
// MARK: - Specification Tests: Boundary Values
@Test("isInSeason boundary: first and last day of season month")
func isInSeason_boundaryDays() {
// Production isInSeason uses Calendar.current to extract month.
// Use noon (hour: 12) so the date stays in the correct calendar day
// regardless of system timezone across the US.
// MLB: First day of March (in season)
let marchFirst = TestFixtures.date(year: 2026, month: 3, day: 1, hour: 12)
#expect(Sport.mlb.isInSeason(for: marchFirst))
// MLB: Last day of October (in season)
let octLast = TestFixtures.date(year: 2026, month: 10, day: 31, hour: 12)
#expect(Sport.mlb.isInSeason(for: octLast))
// MLB: First day of November (out of season)
let novFirst = TestFixtures.date(year: 2026, month: 11, day: 1, hour: 12)
#expect(!Sport.mlb.isInSeason(for: novFirst))
// MLB: Last day of February (out of season)
let febLast = TestFixtures.date(year: 2026, month: 2, day: 28, hour: 12)
#expect(!Sport.mlb.isInSeason(for: febLast))
}
// MARK: - Specification Tests: Supported Sports
@Test("supported returns all 7 sports")
func supported_returnsAllSports() {
let supported = Sport.supported
#expect(supported.count == 7)
#expect(supported.contains(.mlb))
#expect(supported.contains(.nba))
#expect(supported.contains(.nhl))
#expect(supported.contains(.nfl))
#expect(supported.contains(.mls))
#expect(supported.contains(.wnba))
#expect(supported.contains(.nwsl))
}
@Test("CaseIterable matches supported")
func caseIterable_matchesSupported() {
let allCases = Set(Sport.allCases)
let supported = Set(Sport.supported)
#expect(allCases == supported)
}
// MARK: - Invariant Tests
@Test("Invariant: seasonMonths values are always 1-12")
func invariant_seasonMonthsValidRange() {
for sport in Sport.allCases {
let (start, end) = sport.seasonMonths
#expect(start >= 1 && start <= 12, "\(sport) start month must be 1-12")
#expect(end >= 1 && end <= 12, "\(sport) end month must be 1-12")
}
}
@Test("Invariant: each sport has unique displayName")
func invariant_uniqueDisplayNames() {
var displayNames: Set<String> = []
for sport in Sport.allCases {
#expect(!displayNames.contains(sport.displayName), "Duplicate displayName: \(sport.displayName)")
displayNames.insert(sport.displayName)
}
}
// MARK: - Property Tests
@Test("Property: id equals rawValue")
func property_idEqualsRawValue() {
for sport in Sport.allCases {
#expect(sport.id == sport.rawValue)
}
}
@Test("Property: sportId equals rawValue (AnySport conformance)")
func property_sportIdEqualsRawValue() {
for sport in Sport.allCases {
#expect(sport.sportId == sport.rawValue)
}
}
}