// // SportsTimeUITests.swift // SportsTimeUITests // // Created by Trey Tartt on 1/6/26. // import XCTest final class SportsTimeUITests: XCTestCase { override func setUpWithError() throws { // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false } override func tearDownWithError() throws { // Put teardown code here. } // MARK: - Demo Flow Test (Continuous Scroll Mode) /// Complete trip planning demo with continuous smooth scrolling. /// /// In demo mode, the app auto-selects each step as it appears on screen: /// - Planning Mode: "By Dates" /// - Dates: June 11-16, 2026 /// - Sport: MLB /// - Region: Central US /// - Sort: Most Games /// - Trip: 4th option /// - Action: Auto-favorite /// /// The test just needs to: /// 1. Launch with -DemoMode argument /// 2. Tap "Start Planning" /// 3. Continuously scroll - items auto-select as they appear /// 4. Wait for transitions to complete @MainActor func testTripPlanningDemoFlow() throws { let app = XCUIApplication() app.launchArguments = ["-DemoMode"] app.launch() // Wait for app to fully load sleep(2) // MARK: Step 1 - Tap "Start Planning" let startPlanningButton = app.buttons["home.startPlanningButton"] XCTAssertTrue(startPlanningButton.waitForExistence(timeout: 10), "Start Planning button should exist") startPlanningButton.tap() // Wait for demo mode to auto-select planning mode sleep(2) // MARK: Step 2 - Continuous scroll through wizard // Demo mode auto-selects: Date Range → June 11-16 → MLB → Central // Each step auto-selects 0.5s after appearing, so we scroll slowly for _ in 1...8 { slowSwipeUp(app: app) sleep(2) // Give time for auto-selections } // MARK: Step 3 - Click "Plan My Trip" let planTripButton = app.buttons["wizard.planTripButton"] XCTAssertTrue(planTripButton.waitForExistence(timeout: 5), "Plan My Trip button should exist") planTripButton.tap() // Wait for planning to complete sleep(6) // MARK: Step 4 - Demo mode auto-selects "Most Games" and navigates to 4th trip // Wait for TripOptionsView to load and auto-selections to complete let sortDropdown = app.buttons["tripOptions.sortDropdown"] XCTAssertTrue(sortDropdown.waitForExistence(timeout: 15), "Sort dropdown should exist") // Wait for demo mode to auto-select sort and navigate to trip detail sleep(3) // MARK: Step 5 - Scroll through trip detail (demo mode auto-favorites) // Wait for TripDetailView to appear let favoriteButton = app.buttons["tripDetail.favoriteButton"] if favoriteButton.waitForExistence(timeout: 10) { // Demo mode will auto-favorite, but we scroll to show the itinerary for _ in 1...6 { slowSwipeUp(app: app) sleep(2) } // Scroll back up to show the favorited state for _ in 1...4 { slowSwipeDown(app: app) sleep(1) } } // Wait to display final state sleep(3) // Test complete - demo flow finished with trip favorited } // MARK: - Manual Demo Flow Test (Original) /// Original manual test flow for comparison or when demo mode is not desired @MainActor func testTripPlanningManualFlow() throws { let app = XCUIApplication() app.launch() // Wait for app to fully load sleep(2) // MARK: Step 1 - Tap "Start Planning" let startPlanningButton = app.buttons["home.startPlanningButton"] XCTAssertTrue(startPlanningButton.waitForExistence(timeout: 10), "Start Planning button should exist") startPlanningButton.tap() sleep(1) // MARK: Step 2 - Choose "By Dates" mode let dateRangeMode = app.buttons["wizard.planningMode.dateRange"] XCTAssertTrue(dateRangeMode.waitForExistence(timeout: 5), "Date Range mode should exist") dateRangeMode.tap() sleep(1) // Scroll down to see dates step app.swipeUp() sleep(1) // MARK: Step 3 - Select June 11-16, 2026 // Navigate to June 2026 let nextMonthButton = app.buttons["wizard.dates.nextMonth"] XCTAssertTrue(nextMonthButton.waitForExistence(timeout: 5), "Next month button should exist") let monthLabel = app.staticTexts["wizard.dates.monthLabel"] var attempts = 0 while !monthLabel.label.contains("June 2026") && attempts < 12 { nextMonthButton.tap() Thread.sleep(forTimeInterval: 0.3) attempts += 1 } // Select June 11 let june11 = app.buttons["wizard.dates.day.2026-06-11"] XCTAssertTrue(june11.waitForExistence(timeout: 5), "June 11 should exist") june11.tap() Thread.sleep(forTimeInterval: 0.5) // Select June 16 let june16 = app.buttons["wizard.dates.day.2026-06-16"] XCTAssertTrue(june16.waitForExistence(timeout: 5), "June 16 should exist") june16.tap() sleep(1) // Scroll down to see sports step app.swipeUp(velocity: .slow) sleep(1) // MARK: Step 4 - Pick MLB let mlbButton = app.buttons["wizard.sports.mlb"] XCTAssertTrue(mlbButton.waitForExistence(timeout: 5), "MLB button should exist") mlbButton.tap() sleep(1) // Scroll down to see regions step app.swipeUp(velocity: .slow) sleep(1) // MARK: Step 5 - Select Central US region let centralRegion = app.buttons["wizard.regions.central"] XCTAssertTrue(centralRegion.waitForExistence(timeout: 5), "Central region should exist") centralRegion.tap() sleep(1) // Scroll down to see remaining steps app.swipeUp(velocity: .slow) sleep(1) // Keep scrolling for defaults app.swipeUp(velocity: .slow) sleep(1) // MARK: Step 8 - Click "Plan My Trip" let planTripButton = app.buttons["wizard.planTripButton"] XCTAssertTrue(planTripButton.waitForExistence(timeout: 5), "Plan My Trip button should exist") planTripButton.tap() // Wait for planning to complete sleep(5) // MARK: Step 9 - Select "Most Games" from dropdown let sortDropdown = app.buttons["tripOptions.sortDropdown"] XCTAssertTrue(sortDropdown.waitForExistence(timeout: 15), "Sort dropdown should exist") sortDropdown.tap() Thread.sleep(forTimeInterval: 0.5) let mostGamesOption = app.buttons["tripOptions.sortOption.mostgames"] if mostGamesOption.waitForExistence(timeout: 3) { mostGamesOption.tap() } else { app.buttons["Most Games"].tap() } Thread.sleep(forTimeInterval: 1) // MARK: Step 10 - Scroll and select 4th trip for _ in 1...3 { slowSwipeUp(app: app) sleep(1) } let fourthTrip = app.buttons["tripOptions.trip.3"] if fourthTrip.waitForExistence(timeout: 5) { fourthTrip.tap() } else { slowSwipeUp(app: app) sleep(1) if fourthTrip.waitForExistence(timeout: 3) { fourthTrip.tap() } else { let anyTrip = app.buttons.matching(NSPredicate(format: "identifier BEGINSWITH 'tripOptions.trip.'")).firstMatch XCTAssertTrue(anyTrip.waitForExistence(timeout: 5), "At least one trip option should exist") anyTrip.tap() } } sleep(2) // MARK: Step 12 - Scroll through itinerary for _ in 1...5 { slowSwipeUp(app: app) Thread.sleep(forTimeInterval: 1.5) } // MARK: Step 13 - Favorite the trip for _ in 1...5 { slowSwipeDown(app: app) Thread.sleep(forTimeInterval: 0.5) } let favoriteButton = app.buttons["tripDetail.favoriteButton"] XCTAssertTrue(favoriteButton.waitForExistence(timeout: 5), "Favorite button should exist") favoriteButton.tap() sleep(2) } // MARK: - Helper Methods /// Performs a slow swipe up gesture for smooth scrolling private func slowSwipeUp(app: XCUIApplication) { let start = app.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.7)) let end = app.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.3)) start.press(forDuration: 0.1, thenDragTo: end, withVelocity: .slow, thenHoldForDuration: 0.1) } /// Performs a slow swipe down gesture for smooth scrolling private func slowSwipeDown(app: XCUIApplication) { let start = app.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.3)) let end = app.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.7)) start.press(forDuration: 0.1, thenDragTo: end, withVelocity: .slow, thenHoldForDuration: 0.1) } // MARK: - Basic Tests @MainActor func testExample() throws { let app = XCUIApplication() app.launch() } @MainActor func testLaunchPerformance() throws { measure(metrics: [XCTApplicationLaunchMetric()]) { XCUIApplication().launch() } } }