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>
115 lines
4.3 KiB
Swift
115 lines
4.3 KiB
Swift
//
|
|
// PollServiceTests.swift
|
|
// SportsTimeTests
|
|
//
|
|
// TDD specification tests for PollService types.
|
|
//
|
|
|
|
import Testing
|
|
import Foundation
|
|
@testable import SportsTime
|
|
|
|
// MARK: - PollError Tests
|
|
|
|
@Suite("PollError")
|
|
struct PollErrorTests {
|
|
|
|
// MARK: - Specification Tests: errorDescription
|
|
|
|
/// - Expected Behavior: notSignedIn explains iCloud requirement
|
|
@Test("errorDescription: notSignedIn mentions iCloud")
|
|
func errorDescription_notSignedIn() {
|
|
let error = PollError.notSignedIn
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.lowercased().contains("icloud") || error.errorDescription!.lowercased().contains("sign in"))
|
|
}
|
|
|
|
/// - Expected Behavior: pollNotFound explains poll doesn't exist
|
|
@Test("errorDescription: pollNotFound mentions not found")
|
|
func errorDescription_pollNotFound() {
|
|
let error = PollError.pollNotFound
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.lowercased().contains("not found") || error.errorDescription!.lowercased().contains("deleted"))
|
|
}
|
|
|
|
/// - Expected Behavior: alreadyVoted explains duplicate vote
|
|
@Test("errorDescription: alreadyVoted mentions already voted")
|
|
func errorDescription_alreadyVoted() {
|
|
let error = PollError.alreadyVoted
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.lowercased().contains("already voted"))
|
|
}
|
|
|
|
/// - Expected Behavior: notPollOwner explains ownership requirement
|
|
@Test("errorDescription: notPollOwner mentions owner")
|
|
func errorDescription_notPollOwner() {
|
|
let error = PollError.notPollOwner
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.lowercased().contains("owner"))
|
|
}
|
|
|
|
/// - Expected Behavior: networkUnavailable explains connection issue
|
|
@Test("errorDescription: networkUnavailable mentions connection")
|
|
func errorDescription_networkUnavailable() {
|
|
let error = PollError.networkUnavailable
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.lowercased().contains("connect") || error.errorDescription!.lowercased().contains("internet"))
|
|
}
|
|
|
|
/// - Expected Behavior: encodingError explains save failure
|
|
@Test("errorDescription: encodingError mentions save")
|
|
func errorDescription_encodingError() {
|
|
let error = PollError.encodingError
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.lowercased().contains("save") || error.errorDescription!.lowercased().contains("failed"))
|
|
}
|
|
|
|
/// - Expected Behavior: unknown includes underlying error message
|
|
@Test("errorDescription: unknown includes underlying error")
|
|
func errorDescription_unknown() {
|
|
let underlyingError = NSError(domain: "TestDomain", code: 123, userInfo: [NSLocalizedDescriptionKey: "Test underlying error"])
|
|
let error = PollError.unknown(underlyingError)
|
|
#expect(error.errorDescription != nil)
|
|
#expect(error.errorDescription!.contains("Test underlying error") || error.errorDescription!.lowercased().contains("error"))
|
|
}
|
|
|
|
// MARK: - Invariant Tests
|
|
|
|
/// - Invariant: All errors have non-empty descriptions
|
|
@Test("Invariant: all errors have descriptions")
|
|
func invariant_allHaveDescriptions() {
|
|
let errors: [PollError] = [
|
|
.notSignedIn,
|
|
.pollNotFound,
|
|
.alreadyVoted,
|
|
.notPollOwner,
|
|
.networkUnavailable,
|
|
.encodingError,
|
|
.unknown(NSError(domain: "", code: 0))
|
|
]
|
|
|
|
for error in errors {
|
|
#expect(error.errorDescription != nil)
|
|
#expect(!error.errorDescription!.isEmpty)
|
|
}
|
|
}
|
|
|
|
/// - Invariant: All non-unknown errors have distinct descriptions
|
|
@Test("Invariant: non-unknown errors have distinct descriptions")
|
|
func invariant_distinctDescriptions() {
|
|
let errors: [PollError] = [
|
|
.notSignedIn,
|
|
.pollNotFound,
|
|
.alreadyVoted,
|
|
.notPollOwner,
|
|
.networkUnavailable,
|
|
.encodingError
|
|
]
|
|
|
|
let descriptions = errors.compactMap { $0.errorDescription }
|
|
let uniqueDescriptions = Set(descriptions)
|
|
|
|
#expect(descriptions.count == uniqueDescriptions.count)
|
|
}
|
|
}
|