Files
Sportstime/SportsTimeTests/Domain/GameTests.swift
2026-02-18 13:00:15 -06:00

212 lines
6.0 KiB
Swift

//
// GameTests.swift
// SportsTimeTests
//
// TDD specification tests for Game model.
//
import Testing
import Foundation
@testable import SportsTime
@Suite("Game")
@MainActor
struct GameTests {
// MARK: - Test Data
private func makeGame(dateTime: Date) -> Game {
Game(
id: "game1",
homeTeamId: "team1",
awayTeamId: "team2",
stadiumId: "stadium1",
dateTime: dateTime,
sport: .mlb,
season: "2026",
isPlayoff: false
)
}
// MARK: - Specification Tests: gameDate
@Test("gameDate returns start of day for dateTime")
func gameDate_returnsStartOfDay() {
let calendar = TestClock.calendar
// Game at 7:05 PM
let dateTime = calendar.date(from: DateComponents(
year: 2026, month: 6, day: 15,
hour: 19, minute: 5, second: 0
))!
let game = makeGame(dateTime: dateTime)
let expectedStart = calendar.startOfDay(for: dateTime)
#expect(game.gameDate == expectedStart)
// Verify it's at midnight
let components = calendar.dateComponents([.hour, .minute, .second], from: game.gameDate)
#expect(components.hour == 0)
#expect(components.minute == 0)
#expect(components.second == 0)
}
@Test("gameDate is same for games on same calendar day")
func gameDate_sameDay() {
let calendar = TestClock.calendar
// Morning game
let morningTime = calendar.date(from: DateComponents(
year: 2026, month: 6, day: 15,
hour: 10, minute: 0
))!
// Evening game
let eveningTime = calendar.date(from: DateComponents(
year: 2026, month: 6, day: 15,
hour: 20, minute: 0
))!
let morningGame = makeGame(dateTime: morningTime)
let eveningGame = makeGame(dateTime: eveningTime)
#expect(morningGame.gameDate == eveningGame.gameDate)
}
@Test("gameDate differs for games on different calendar days")
func gameDate_differentDays() {
let calendar = TestClock.calendar
let day1 = calendar.date(from: DateComponents(
year: 2026, month: 6, day: 15, hour: 19
))!
let day2 = calendar.date(from: DateComponents(
year: 2026, month: 6, day: 16, hour: 19
))!
let game1 = makeGame(dateTime: day1)
let game2 = makeGame(dateTime: day2)
#expect(game1.gameDate != game2.gameDate)
}
// MARK: - Specification Tests: startTime Alias
@Test("startTime is alias for dateTime")
func startTime_isAliasForDateTime() {
let dateTime = TestClock.now
let game = makeGame(dateTime: dateTime)
#expect(game.startTime == game.dateTime)
}
// MARK: - Specification Tests: Equality
@Test("equality based on id only")
func equality_basedOnId() {
let dateTime = TestClock.now
let game1 = Game(
id: "game1",
homeTeamId: "team1",
awayTeamId: "team2",
stadiumId: "stadium1",
dateTime: dateTime,
sport: .mlb,
season: "2026",
isPlayoff: false
)
// Same id, different fields
let game2 = Game(
id: "game1",
homeTeamId: "different-team",
awayTeamId: "different-team2",
stadiumId: "different-stadium",
dateTime: dateTime.addingTimeInterval(3600),
sport: .nba,
season: "2027",
isPlayoff: true
)
#expect(game1 == game2, "Games with same id should be equal")
}
@Test("inequality when ids differ")
func inequality_differentIds() {
let dateTime = TestClock.now
let game1 = Game(
id: "game1",
homeTeamId: "team1",
awayTeamId: "team2",
stadiumId: "stadium1",
dateTime: dateTime,
sport: .mlb,
season: "2026",
isPlayoff: false
)
let game2 = Game(
id: "game2",
homeTeamId: "team1",
awayTeamId: "team2",
stadiumId: "stadium1",
dateTime: dateTime,
sport: .mlb,
season: "2026",
isPlayoff: false
)
#expect(game1 != game2, "Games with different ids should not be equal")
}
// MARK: - Invariant Tests
@Test("Invariant: gameDate is always at midnight")
func invariant_gameDateAtMidnight() {
let calendar = TestClock.calendar
// Test various times throughout the day
let times = [0, 6, 12, 18, 23].map { hour in
calendar.date(from: DateComponents(year: 2026, month: 6, day: 15, hour: hour))!
}
for time in times {
let game = makeGame(dateTime: time)
let components = calendar.dateComponents([.hour, .minute, .second], from: game.gameDate)
#expect(components.hour == 0, "gameDate hour should be 0")
#expect(components.minute == 0, "gameDate minute should be 0")
#expect(components.second == 0, "gameDate second should be 0")
}
}
@Test("Invariant: startTime equals dateTime")
func invariant_startTimeEqualsDateTime() {
for _ in 0..<10 {
let dateTime = TestClock.now.addingTimeInterval(Double.random(in: -86400...86400))
let game = makeGame(dateTime: dateTime)
#expect(game.startTime == game.dateTime)
}
}
// MARK: - Property Tests
@Test("Property: gameDate is in same calendar day as dateTime")
func property_gameDateSameCalendarDay() {
let calendar = TestClock.calendar
let dateTime = calendar.date(from: DateComponents(
year: 2026, month: 7, day: 4, hour: 19, minute: 5
))!
let game = makeGame(dateTime: dateTime)
let dateTimeDay = calendar.component(.day, from: dateTime)
let gameDateDay = calendar.component(.day, from: game.gameDate)
#expect(dateTimeDay == gameDateDay)
}
}