Files
Sportstime/SportsTimeUITests/Tests/TripOptionsTests.swift
Trey t ab1d7bc6b6 Add F-015, F-076, F-094 UI tests for home refresh, trip detail, diagnostics
- F-015: Featured trips refresh button works without crash
- F-076: Trip detail loads correctly with single-stop trip
- F-094: Schedule diagnostics sheet opens from filter menu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:03:12 -06:00

152 lines
4.7 KiB
Swift

//
// TripOptionsTests.swift
// SportsTimeUITests
//
// Tests the Trip Options results screen: sorting, selection, navigation.
// QA Sheet: F-051, F-052, F-053, F-054, F-055, F-058, F-059, F-076
//
import XCTest
final class TripOptionsTests: BaseUITestCase {
// MARK: - Helpers
/// Plans a trip and returns the options screen ready for sorting tests.
@MainActor
private func planTripAndGetOptions() -> TripOptionsScreen {
let (_, options) = TestFlows.planDateRangeTrip(app: app)
options.assertHasResults()
return options
}
// MARK: - Results Display (F-051)
/// F-051: Trip options listed with city count, game count, distance, and preview.
@MainActor
func testF051_ResultsDisplayAfterPlanning() {
let options = planTripAndGetOptions()
// At least one trip card should be visible
let firstCard = options.tripCard(0)
XCTAssertTrue(firstCard.exists, "First trip card should be visible")
// Sort dropdown should be visible (proves results header rendered)
XCTAssertTrue(options.sortDropdown.exists, "Sort dropdown should be visible on results screen")
captureScreenshot(named: "F051-ResultsDisplay")
}
// MARK: - Sort Options (F-052, F-053, F-054, F-055)
/// F-052: Sort by Recommended reorders trip options.
@MainActor
func testF052_SortByRecommended() {
let options = planTripAndGetOptions()
// Sort option IDs are rawValue.lowercased() with spaces removed
options.sort(by: "recommended")
// Results should still exist after sorting
options.assertHasResults()
captureScreenshot(named: "F052-SortByRecommended")
}
/// F-053: Sort by Most Games reorders trip options.
@MainActor
func testF053_SortByMostGames() {
let options = planTripAndGetOptions()
options.sort(by: "mostgames")
options.assertHasResults()
captureScreenshot(named: "F053-SortByMostGames")
}
/// F-054: Sort by Least Miles reorders trip options.
@MainActor
func testF054_SortByLeastMiles() {
let options = planTripAndGetOptions()
options.sort(by: "leastmiles")
options.assertHasResults()
captureScreenshot(named: "F054-SortByLeastMiles")
}
/// F-055: Sort by Best Efficiency reorders trip options.
@MainActor
func testF055_SortByBestEfficiency() {
let options = planTripAndGetOptions()
options.sort(by: "bestefficiency")
options.assertHasResults()
captureScreenshot(named: "F055-SortByBestEfficiency")
}
// MARK: - Select Trip (F-058)
/// F-058: Tapping a trip option card opens TripDetailView with full itinerary.
@MainActor
func testF058_SelectTripOpensDetail() {
let options = planTripAndGetOptions()
// Tap first trip card
options.selectTrip(at: 0)
// Trip detail should open with itinerary
let detail = TripDetailScreen(app: app)
detail.waitForLoad()
detail.assertItineraryVisible()
captureScreenshot(named: "F058-SelectTripOpensDetail")
}
// MARK: - Trip Detail Variants (F-076)
/// F-076: Trip detail works correctly with a single-stop (minimal) trip.
@MainActor
func testF076_TripDetailWithSingleStop() {
let options = planTripAndGetOptions()
// Select the first trip option
options.selectTrip(at: 0)
// Trip detail should load with itinerary
let detail = TripDetailScreen(app: app)
detail.waitForLoad()
detail.assertItineraryVisible()
// Verify the detail screen is functional (favorite button exists)
XCTAssertTrue(detail.favoriteButton.waitForExistence(
timeout: BaseUITestCase.shortTimeout),
"Favorite button should exist on trip detail")
captureScreenshot(named: "F076-TripDetailSingleStop")
}
// MARK: - Back Navigation (F-059)
/// F-059: Back button on Trip Options returns to wizard with selections preserved.
@MainActor
func testF059_BackToWizardFromOptions() {
_ = planTripAndGetOptions()
// Tap back button to return to wizard
app.navigationBars.buttons.firstMatch.tap()
// Wizard should reappear with its navigation title or planning mode buttons
let wizard = TripWizardScreen(app: app)
let wizardVisible = wizard.navigationTitle.waitForExistence(timeout: BaseUITestCase.defaultTimeout)
|| wizard.planningModeButton("dateRange").waitForExistence(timeout: BaseUITestCase.defaultTimeout)
XCTAssertTrue(wizardVisible, "Wizard should be visible after tapping back from options")
captureScreenshot(named: "F059-BackToWizard")
}
}