Files
Sportstime/SportsTimeUITests/Tests/TripSavingTests.swift
Trey t dc142bd14b feat: expand XCUITest coverage to 54 QA scenarios with accessibility IDs and fix test failures
Add 22 new UI tests across 8 test files covering Home, Schedule, Progress,
Settings, TabNavigation, TripSaving, and TripOptions. Add accessibility
identifiers to 11 view files for test element discovery. Fix sport chip
assertion logic (all sports start selected, tap deselects), scroll container
issues on iOS 26 nested ScrollViews, toggle interaction, and delete trip flow.
Update QA coverage map from 32 to 54 automated test cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 19:44:22 -06:00

172 lines
5.0 KiB
Swift

//
// TripSavingTests.swift
// SportsTimeUITests
//
// Tests the end-to-end trip saving flow: plan select save verify in My Trips.
// QA Sheet: F-064, F-065, F-077, F-078, F-079, F-080
//
import XCTest
final class TripSavingTests: BaseUITestCase {
// MARK: - Helpers
/// Plans a trip, saves it, navigates back to My Trips, and returns the screens.
@MainActor
private func planSaveAndReturnToMyTrips() -> (home: HomeScreen, myTrips: MyTripsScreen) {
let (wizard, detail) = TestFlows.planAndSelectFirstTrip(app: app)
detail.assertSaveState(isSaved: false)
detail.tapFavorite()
detail.assertSaveState(isSaved: true)
// Navigate back: Detail Options Wizard Cancel
app.navigationBars.buttons.firstMatch.tap()
let wizardBackBtn = app.navigationBars.buttons.firstMatch
wizardBackBtn.waitUntilHittable(timeout: BaseUITestCase.shortTimeout).tap()
wizard.tapCancel()
let home = HomeScreen(app: app)
home.switchToTab(home.myTripsTab)
let myTrips = MyTripsScreen(app: app)
return (home, myTrips)
}
// MARK: - Save Trip (F-043)
/// F-043/F-044: Plans a trip, selects an option, saves it, and verifies it appears in My Trips.
@MainActor
func testF043_SaveTripAppearsInMyTrips() {
let (_, myTrips) = planSaveAndReturnToMyTrips()
myTrips.assertHasTrips()
captureScreenshot(named: "F043-TripSaving-InMyTrips")
}
// MARK: - Save/Unsave Toggle (F-048, F-049)
/// F-048: Save trip unsaved trip shows "Save to favorites", tap changes to "Remove from favorites".
@MainActor
func testF048_SaveTrip() {
let (_, detail) = TestFlows.planAndSelectFirstTrip(app: app)
detail.assertSaveState(isSaved: false)
detail.tapFavorite()
detail.assertSaveState(isSaved: true)
captureScreenshot(named: "F048-TripSaved")
}
/// F-049: Unsave trip saved trip can be un-favorited by tapping again.
@MainActor
func testF049_UnsaveTrip() {
let (_, detail) = TestFlows.planAndSelectFirstTrip(app: app)
// Save first
detail.assertSaveState(isSaved: false)
detail.tapFavorite()
detail.assertSaveState(isSaved: true)
// Unsave
detail.tapFavorite()
detail.assertSaveState(isSaved: false)
captureScreenshot(named: "F049-TripUnsaved")
}
// MARK: - Saved Trips List (F-059)
/// F-059: Saved trips list shows trip card after saving.
@MainActor
func testF059_SavedTripsList() {
let (_, myTrips) = planSaveAndReturnToMyTrips()
myTrips.assertHasTrips()
// First trip card should exist
let firstTrip = myTrips.tripCard(0)
XCTAssertTrue(
firstTrip.waitForExistence(timeout: BaseUITestCase.defaultTimeout),
"First saved trip card should be visible"
)
captureScreenshot(named: "F059-SavedTripsList")
}
// MARK: - Empty State (F-058)
/// F-058: My Trips empty state when no trips saved.
@MainActor
func testF058_MyTripsEmptyState() {
let home = HomeScreen(app: app)
home.waitForLoad()
home.switchToTab(home.myTripsTab)
let myTrips = MyTripsScreen(app: app)
myTrips.assertEmpty()
captureScreenshot(named: "F058-MyTrips-Empty")
}
// MARK: - Tap Saved Trip Opens Detail (F-079)
/// F-079: Tapping a saved trip card opens the detail view.
@MainActor
func testF079_TapSavedTripOpensDetail() {
let (_, myTrips) = planSaveAndReturnToMyTrips()
myTrips.assertHasTrips()
// Tap the first saved trip
myTrips.tapTrip(at: 0)
// Trip detail should open
let detail = TripDetailScreen(app: app)
detail.waitForLoad()
detail.assertItineraryVisible()
captureScreenshot(named: "F079-TapSavedTripOpensDetail")
}
// MARK: - Remove Saved Trip (F-080)
/// F-080: Unfavoriting a trip removes it from My Trips.
@MainActor
func testF080_DeleteSavedTrip() {
let (_, myTrips) = planSaveAndReturnToMyTrips()
myTrips.assertHasTrips()
// Tap into the saved trip detail
myTrips.tapTrip(at: 0)
let detail = TripDetailScreen(app: app)
detail.waitForLoad()
// Unfavorite to remove from saved trips
detail.assertSaveState(isSaved: true)
detail.tapFavorite()
detail.assertSaveState(isSaved: false)
// Navigate back to My Trips
app.navigationBars.buttons.firstMatch.tap()
// After unfavoriting, should show empty state
myTrips.assertEmpty()
captureScreenshot(named: "F080-DeleteSavedTrip")
}
// MARK: - Stats Row (F-061)
/// F-061: Trip detail stats row shows city count, game count, distance, driving time.
@MainActor
func testF061_StatsRowDisplaysCorrectly() {
let (_, detail) = TestFlows.planAndSelectFirstTrip(app: app)
detail.assertStatsRowVisible()
captureScreenshot(named: "F061-StatsRow")
}
}