Files
Sportstime/SportsTimeTests/Services/VisitPhotoServiceTests.swift
Trey t 8162b4a029 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>
2026-01-16 14:07:41 -06:00

109 lines
4.3 KiB
Swift

//
// 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))
}
}