# XCUITest Authoring Guide This guide documents the current SportsTime UI test foundation and how to add new tests safely. ## Current Foundation ## Layout - Test target: `SportsTimeUITests` - Base setup/helpers: `SportsTimeUITests/Framework/BaseUITestCase.swift` - Page objects + shared flows: `SportsTimeUITests/Framework/Screens.swift` - Suite files: `SportsTimeUITests/Tests/*.swift` - Legacy mixed tests: `SportsTimeUITests/SportsTimeUITests.swift` and `SportsTimeUITests/SportsTimeUITestsLaunchTests.swift` ## Existing Suite Coverage - `AppLaunchTests` - `HomeTests` - `TabNavigationTests` - `ScheduleTests` - `TripWizardFlowTests` - `TripOptionsTests` - `TripSavingTests` - `ProgressTests` - `SettingsTests` - `AccessibilityTests` - `StabilityTests` ## Key Conventions - Inherit from `BaseUITestCase`. - Use `@MainActor` test methods. - Prefer page-object actions over direct element taps. - Prefer existing high-level flows (`TestFlows.planDateRangeTrip`, `TestFlows.planAndSelectFirstTrip`) for shared setup. - Use deterministic selectors with accessibility identifiers. - Use `waitForExistenceOrFail` and `waitUntilHittable` instead of arbitrary sleeps. ## Adding a New UI Test 1. Pick the closest existing suite in `SportsTimeUITests/Tests/`. 2. If none fits, create a new suite using `XCUITestSuiteTemplate.swift`. 3. Add/extend page-object methods in `Screens.swift` before writing raw element code. 4. Reuse `TestFlows` when setup overlaps existing end-to-end flows. 5. Keep assertion messages explicit and behavior-focused. 6. Capture screenshot(s) for key milestone state in longer flows. 7. Run targeted tests, then full UI tests. ## When to Edit `Screens.swift` Edit page objects when: - A new screen element needs a stable selector. - The interaction is reused across multiple tests. - The flow can be standardized (especially wizard planning flow). Do not add one-off test-only branching logic unless it removes a real flake. ## Running Tests ## Fast Loop (single test) ```bash xcodebuild test-without-building \ -project SportsTime.xcodeproj \ -scheme SportsTime \ -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \ -parallel-testing-enabled NO \ -only-testing:SportsTimeUITests/TripWizardFlowTests/testF026_DateRangeSelection ``` ## Per Class ```bash xcodebuild test-without-building \ -project SportsTime.xcodeproj \ -scheme SportsTime \ -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \ -parallel-testing-enabled NO \ -only-testing:SportsTimeUITests/TripOptionsTests ``` ## Full UI Suite ```bash xcodebuild test-without-building \ -project SportsTime.xcodeproj \ -scheme SportsTime \ -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \ -parallel-testing-enabled NO \ -only-testing:SportsTimeUITests ``` ## Full Scheme Validation (unit + UI) ```bash xcodebuild test-without-building \ -project SportsTime.xcodeproj \ -scheme SportsTime \ -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \ -parallel-testing-enabled NO ``` ## Flake Prevention Notes - Keep simulator orientation consistent (portrait baseline from `BaseUITestCase`). - For wizard date selection, navigate by month/year first and use day-cell fallback when specific IDs are unavailable. - For cross-season planning tests, prefer deterministic fallback sports if selected sport has no viable schedule for current test data. - Increase waits only where planning computation is the actual bottleneck.