refactor(tests): TDD rewrite of all unit tests with spec documentation
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>
This commit is contained in:
108
SportsTimeTests/Services/VisitPhotoServiceTests.swift
Normal file
108
SportsTimeTests/Services/VisitPhotoServiceTests.swift
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// VisitPhotoServiceTests.swift
|
||||
// SportsTimeTests
|
||||
//
|
||||
// TDD specification tests for VisitPhotoService types.
|
||||
//
|
||||
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import SportsTime
|
||||
|
||||
// MARK: - PhotoServiceError Tests
|
||||
|
||||
@Suite("PhotoServiceError")
|
||||
struct PhotoServiceErrorTests {
|
||||
|
||||
// MARK: - Specification Tests: errorDescription
|
||||
|
||||
/// - Expected Behavior: notSignedIn explains iCloud requirement
|
||||
@Test("errorDescription: notSignedIn mentions iCloud")
|
||||
func errorDescription_notSignedIn() {
|
||||
let error = PhotoServiceError.notSignedIn
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.lowercased().contains("icloud") || error.errorDescription!.lowercased().contains("sign in"))
|
||||
}
|
||||
|
||||
/// - Expected Behavior: uploadFailed includes the message
|
||||
@Test("errorDescription: uploadFailed includes message")
|
||||
func errorDescription_uploadFailed() {
|
||||
let error = PhotoServiceError.uploadFailed("Network timeout")
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.contains("Network timeout") || error.errorDescription!.lowercased().contains("upload"))
|
||||
}
|
||||
|
||||
/// - Expected Behavior: downloadFailed includes the message
|
||||
@Test("errorDescription: downloadFailed includes message")
|
||||
func errorDescription_downloadFailed() {
|
||||
let error = PhotoServiceError.downloadFailed("Connection lost")
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.contains("Connection lost") || error.errorDescription!.lowercased().contains("download"))
|
||||
}
|
||||
|
||||
/// - Expected Behavior: thumbnailGenerationFailed explains the issue
|
||||
@Test("errorDescription: thumbnailGenerationFailed mentions thumbnail")
|
||||
func errorDescription_thumbnailGenerationFailed() {
|
||||
let error = PhotoServiceError.thumbnailGenerationFailed
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.lowercased().contains("thumbnail"))
|
||||
}
|
||||
|
||||
/// - Expected Behavior: invalidImage explains invalid data
|
||||
@Test("errorDescription: invalidImage mentions invalid")
|
||||
func errorDescription_invalidImage() {
|
||||
let error = PhotoServiceError.invalidImage
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.lowercased().contains("invalid"))
|
||||
}
|
||||
|
||||
/// - Expected Behavior: assetNotFound explains missing photo
|
||||
@Test("errorDescription: assetNotFound mentions not found")
|
||||
func errorDescription_assetNotFound() {
|
||||
let error = PhotoServiceError.assetNotFound
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.lowercased().contains("not found") || error.errorDescription!.lowercased().contains("photo"))
|
||||
}
|
||||
|
||||
/// - Expected Behavior: quotaExceeded explains storage limit
|
||||
@Test("errorDescription: quotaExceeded mentions quota")
|
||||
func errorDescription_quotaExceeded() {
|
||||
let error = PhotoServiceError.quotaExceeded
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(error.errorDescription!.lowercased().contains("quota") || error.errorDescription!.lowercased().contains("storage"))
|
||||
}
|
||||
|
||||
// MARK: - Invariant Tests
|
||||
|
||||
/// - Invariant: All errors have non-empty descriptions
|
||||
@Test("Invariant: all errors have descriptions")
|
||||
func invariant_allHaveDescriptions() {
|
||||
let errors: [PhotoServiceError] = [
|
||||
.notSignedIn,
|
||||
.uploadFailed("test"),
|
||||
.downloadFailed("test"),
|
||||
.thumbnailGenerationFailed,
|
||||
.invalidImage,
|
||||
.assetNotFound,
|
||||
.quotaExceeded
|
||||
]
|
||||
|
||||
for error in errors {
|
||||
#expect(error.errorDescription != nil)
|
||||
#expect(!error.errorDescription!.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
/// - Invariant: uploadFailed and downloadFailed preserve their messages
|
||||
@Test("Invariant: parameterized errors preserve message")
|
||||
func invariant_parameterizedErrorsPreserveMessage() {
|
||||
let testMessage = "Test error message 12345"
|
||||
|
||||
let uploadError = PhotoServiceError.uploadFailed(testMessage)
|
||||
let downloadError = PhotoServiceError.downloadFailed(testMessage)
|
||||
|
||||
// The message should appear somewhere in the description
|
||||
#expect(uploadError.errorDescription!.contains(testMessage))
|
||||
#expect(downloadError.errorDescription!.contains(testMessage))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user