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>
203 lines
5.0 KiB
Swift
203 lines
5.0 KiB
Swift
//
|
|
// TeamTests.swift
|
|
// SportsTimeTests
|
|
//
|
|
// TDD specification tests for Team model.
|
|
//
|
|
|
|
import Testing
|
|
import Foundation
|
|
@testable import SportsTime
|
|
|
|
@Suite("Team")
|
|
@MainActor
|
|
struct TeamTests {
|
|
|
|
// MARK: - Specification Tests: fullName
|
|
|
|
@Test("fullName: returns 'city name' when city is non-empty")
|
|
func fullName_withCity() {
|
|
let team = Team(
|
|
id: "team1",
|
|
name: "Red Sox",
|
|
abbreviation: "BOS",
|
|
sport: .mlb,
|
|
city: "Boston",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
#expect(team.fullName == "Boston Red Sox")
|
|
}
|
|
|
|
@Test("fullName: returns just name when city is empty")
|
|
func fullName_emptyCity() {
|
|
let team = Team(
|
|
id: "team1",
|
|
name: "Guardians",
|
|
abbreviation: "CLE",
|
|
sport: .mlb,
|
|
city: "",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
#expect(team.fullName == "Guardians")
|
|
}
|
|
|
|
@Test("fullName: handles city with spaces")
|
|
func fullName_cityWithSpaces() {
|
|
let team = Team(
|
|
id: "team1",
|
|
name: "Lakers",
|
|
abbreviation: "LAL",
|
|
sport: .nba,
|
|
city: "Los Angeles",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
#expect(team.fullName == "Los Angeles Lakers")
|
|
}
|
|
|
|
@Test("fullName: handles team name with spaces")
|
|
func fullName_teamNameWithSpaces() {
|
|
let team = Team(
|
|
id: "team1",
|
|
name: "Red Sox",
|
|
abbreviation: "BOS",
|
|
sport: .mlb,
|
|
city: "Boston",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
#expect(team.fullName == "Boston Red Sox")
|
|
}
|
|
|
|
// MARK: - Specification Tests: Equality
|
|
|
|
@Test("equality based on id only")
|
|
func equality_basedOnId() {
|
|
let team1 = Team(
|
|
id: "team1",
|
|
name: "Name A",
|
|
abbreviation: "AAA",
|
|
sport: .mlb,
|
|
city: "City A",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
let team2 = Team(
|
|
id: "team1",
|
|
name: "Different Name",
|
|
abbreviation: "BBB",
|
|
sport: .nba,
|
|
city: "Different City",
|
|
stadiumId: "different-stadium"
|
|
)
|
|
|
|
#expect(team1 == team2, "Teams with same id should be equal")
|
|
}
|
|
|
|
@Test("inequality when ids differ")
|
|
func inequality_differentIds() {
|
|
let team1 = Team(
|
|
id: "team1",
|
|
name: "Same Name",
|
|
abbreviation: "AAA",
|
|
sport: .mlb,
|
|
city: "Same City",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
let team2 = Team(
|
|
id: "team2",
|
|
name: "Same Name",
|
|
abbreviation: "AAA",
|
|
sport: .mlb,
|
|
city: "Same City",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
#expect(team1 != team2, "Teams with different ids should not be equal")
|
|
}
|
|
|
|
// MARK: - Invariant Tests
|
|
|
|
@Test("Invariant: fullName is never empty")
|
|
func invariant_fullNameNeverEmpty() {
|
|
// Team with name only
|
|
let team1 = Team(
|
|
id: "team1",
|
|
name: "Team",
|
|
abbreviation: "TM",
|
|
sport: .mlb,
|
|
city: "",
|
|
stadiumId: "stadium1"
|
|
)
|
|
#expect(!team1.fullName.isEmpty)
|
|
|
|
// Team with city and name
|
|
let team2 = Team(
|
|
id: "team2",
|
|
name: "Team",
|
|
abbreviation: "TM",
|
|
sport: .mlb,
|
|
city: "City",
|
|
stadiumId: "stadium1"
|
|
)
|
|
#expect(!team2.fullName.isEmpty)
|
|
}
|
|
|
|
// MARK: - Property Tests
|
|
|
|
@Test("Property: id is Identifiable conformance")
|
|
func property_identifiable() {
|
|
let team = Team(
|
|
id: "unique-id",
|
|
name: "Team",
|
|
abbreviation: "TM",
|
|
sport: .mlb,
|
|
city: "City",
|
|
stadiumId: "stadium1"
|
|
)
|
|
|
|
#expect(team.id == "unique-id")
|
|
}
|
|
|
|
@Test("Property: optional fields can be nil")
|
|
func property_optionalFieldsNil() {
|
|
let team = Team(
|
|
id: "team1",
|
|
name: "Team",
|
|
abbreviation: "TM",
|
|
sport: .mlb,
|
|
city: "City",
|
|
stadiumId: "stadium1",
|
|
logoURL: nil,
|
|
primaryColor: nil,
|
|
secondaryColor: nil
|
|
)
|
|
|
|
#expect(team.logoURL == nil)
|
|
#expect(team.primaryColor == nil)
|
|
#expect(team.secondaryColor == nil)
|
|
}
|
|
|
|
@Test("Property: optional fields can have values")
|
|
func property_optionalFieldsWithValues() {
|
|
let team = Team(
|
|
id: "team1",
|
|
name: "Team",
|
|
abbreviation: "TM",
|
|
sport: .mlb,
|
|
city: "City",
|
|
stadiumId: "stadium1",
|
|
logoURL: URL(string: "https://example.com/logo.png"),
|
|
primaryColor: "#FF0000",
|
|
secondaryColor: "#0000FF"
|
|
)
|
|
|
|
#expect(team.logoURL?.absoluteString == "https://example.com/logo.png")
|
|
#expect(team.primaryColor == "#FF0000")
|
|
#expect(team.secondaryColor == "#0000FF")
|
|
}
|
|
}
|