Add F-010, F-017 UI tests and update QA test plan with 24 automation mappings

- F-010: Tap active tab scrolls to top (TabNavigationTests)
- F-017: Recent trips section with saved trips (HomeTests)
- Update SportsTime_QA_Test_Plan.xlsx with all 60 automated test mappings
- Green highlight on automated cells for visual tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-18 23:18:00 -06:00
parent d0cbf75fc4
commit dad3270be7
4 changed files with 165 additions and 34 deletions

View File

@@ -2,8 +2,8 @@
// HomeTests.swift
// SportsTimeUITests
//
// Tests for the Home tab: hero card, start planning, and toolbar button.
// QA Sheet: F-012, F-013, F-020
// Tests for the Home tab: hero card, start planning, toolbar button, and recent trips.
// QA Sheet: F-012, F-013, F-014, F-017, F-019, F-020
//
import XCTest
@@ -79,6 +79,48 @@ final class HomeTests: BaseUITestCase {
captureScreenshot(named: "F014-FeaturedTrips")
}
/// F-017: Recent trips section shows saved trips with "See All" link on Home tab.
@MainActor
func testF017_RecentTripsSectionWithSavedTrips() {
// Plan a trip and select the first option
let (_, detail) = TestFlows.planAndSelectFirstTrip(app: app)
// Save the trip
detail.assertSaveState(isSaved: false)
detail.tapFavorite()
detail.assertSaveState(isSaved: true)
captureScreenshot(named: "F017-TripSaved")
// Navigate back: Detail Options Wizard Cancel (dismiss sheet)
app.navigationBars.buttons.firstMatch.tap()
app.navigationBars.buttons.firstMatch
.waitUntilHittable(timeout: BaseUITestCase.shortTimeout).tap()
TripWizardScreen(app: app).tapCancel()
// We're back on Home tab. Wait for it to load.
let home = HomeScreen(app: app)
home.waitForLoad()
// Scroll to find the recent trips section
let recentTrips = home.recentTripsSection
var scrollAttempts = 0
while !recentTrips.exists && scrollAttempts < 15 {
app.swipeUp(velocity: .slow)
scrollAttempts += 1
}
XCTAssertTrue(recentTrips.exists,
"Recent trips section should appear after saving a trip")
// Verify "See All" link is visible
let seeAllText = app.staticTexts["See All"]
XCTAssertTrue(seeAllText.exists,
"'See All' link should be visible in recent trips section")
captureScreenshot(named: "F017-RecentTripsSection")
}
/// F-019: Planning tips section is visible at bottom of home tab.
@MainActor
func testF019_PlanningTipsSectionVisible() {

View File

@@ -44,6 +44,39 @@ final class TabNavigationTests: BaseUITestCase {
captureScreenshot(named: "F008-TabNavigation-ReturnHome")
}
/// F-010: Tapping the active tab scrolls the view back to the top.
@MainActor
func testF010_TapActiveTabScrollsToTop() {
let home = HomeScreen(app: app)
home.waitForLoad()
// Verify "Adventure Awaits" hero card is hittable at the top
XCTAssertTrue(home.adventureAwaitsText.isHittable,
"Adventure Awaits should be hittable initially")
// Scroll down until the hero card is off-screen
for _ in 0..<8 {
app.swipeUp(velocity: .slow)
}
// Verify the hero card is no longer hittable (scrolled off-screen)
XCTAssertFalse(home.adventureAwaitsText.isHittable,
"Adventure Awaits should not be hittable after scrolling down")
captureScreenshot(named: "F010-ScrolledDown")
// Tap the Home tab (already the active tab) to trigger scroll-to-top
home.homeTab.waitUntilHittable(timeout: BaseUITestCase.shortTimeout).tap()
// Hero card should scroll back into view and become hittable
home.adventureAwaitsText.waitUntilHittable(
timeout: BaseUITestCase.defaultTimeout,
"Adventure Awaits should be hittable after tapping active tab (scroll to top)"
)
captureScreenshot(named: "F010-ScrolledToTop")
}
/// F-009: Tab state preserved Schedule filters survive tab switch.
@MainActor
func testF009_TabStatePreservedOnSwitch() {

Binary file not shown.

View File

@@ -1,49 +1,105 @@
# UI Test Prompt Template
# SportsTime UI Test Prompt (Paste Into Claude)
Use this prompt when asking an agent to add or modify SportsTime UI tests.
Use this when you want Claude to pick and implement the 3 easiest UI tests from QA IDs/names you provide.
Replace the `INPUT` section, then paste the whole prompt.
---
You are updating SportsTime UI tests.
You are an iOS UI test engineer working in the SportsTime repo.
## Goal
## Mission
- [Describe the behavior to test or fix.]
From the provided QA cases (IDs/names from `docs/SportsTime_QA_Test_Plan.xlsx`), pick the **3 easiest, lowest-flake cases** and implement solid UI tests for them using the **existing SportsTime UI test architecture**.
## Scope
## Non-Negotiable Rules
- Update/add tests under `SportsTimeUITests/Tests/`.
- Reuse page objects in `SportsTimeUITests/Framework/Screens.swift`.
- Reuse shared setup in `SportsTimeUITests/Framework/BaseUITestCase.swift`.
- Reuse existing `TestFlows` where possible.
1. Do not reinvent the test framework.
2. Reuse existing architecture:
- `SportsTimeUITests/Framework/BaseUITestCase.swift`
- `SportsTimeUITests/Framework/Screens.swift`
- existing `TestFlows` helpers
- existing suites under `SportsTimeUITests/Tests/`
3. Prefer updating existing suites over creating new ones.
4. Use stable accessibility IDs already used in the app/tests (`home.*`, `wizard.*`, `tripOptions.*`, `tripDetail.*`, `schedule.*`, `settings.*`, `progress.*`, etc.).
5. Prefer robust waits (`waitForExistenceOrFail`, `waitUntilHittable`) and page-object methods.
6. Avoid `sleep` unless there is no reliable alternative; if used, justify it.
7. Keep tests deterministic with current local test data.
8. Follow naming conventions (`testF###_...`, `testP###_...`, etc.).
9. Do not change product code unless absolutely required for testability (and explain why).
10. Change only what is needed for these 3 tests.
## Required Changes
## Required Reading Before Coding
- [List test suites to modify.]
- [List new test names.]
- [List selectors/page-object methods to add if needed.]
1. `AGENTS.md`
2. `XCUITest-Authoring.md`
3. Existing tests in `SportsTimeUITests/Tests/` for patterns and style
## Constraints
## Selection Strategy (Pick Exactly 3)
- Do not add raw sleeps unless strictly necessary.
- Prefer `waitForExistenceOrFail` and `waitUntilHittable`.
- Keep tests deterministic with current local test data.
- Keep existing naming style (`testF###_...`, `testP###_...`, etc.).
Choose the 3 easiest cases using this priority order:
## Validation
1. Already mostly covered by existing screen objects/flows.
2. Requires minimal or no new selectors.
3. No unstable backend/timing dependency.
4. No complex multi-screen setup unless reusable via existing `TestFlows`.
5. Highest confidence of passing consistently on current simulator baseline.
Run these before finishing:
If a candidate looks flaky/high-risk, skip it and explain why.
1. Targeted class or test:
- `xcodebuild test-without-building -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -parallel-testing-enabled NO -only-testing:SportsTimeUITests/<SuiteOrTest>`
2. Full UI suite:
- `xcodebuild test-without-building -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -parallel-testing-enabled NO -only-testing:SportsTimeUITests`
3. If requested, full scheme:
- `xcodebuild test-without-building -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -parallel-testing-enabled NO`
## Implementation Workflow
## Output Format
1. Evaluate all candidate QA cases.
2. Output a short ranked list with reason for each.
3. Confirm the chosen 3.
4. Implement tests:
- Put tests in existing or appropriate suite(s) in `SportsTimeUITests/Tests/`.
- Add page-object helpers in `Screens.swift` only when reusable.
- Keep assertions behavior-focused and explicit.
- Capture screenshots at key checkpoints for longer flows.
5. Run only the 3 selected tests first.
6. Fix failures.
7. Re-run each selected test at least 2 times to catch flake.
8. Stop only when all 3 are green and stable, or clearly blocked.
- Summarize files changed.
- Summarize root causes fixed.
- Include exact commands run and pass/fail outcomes.
- Call out any remaining flaky behavior or follow-up work.
## Validation Commands
Use this destination:
`-destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2'`
Run each selected test explicitly:
`xcodebuild test-without-building -project SportsTime.xcodeproj -scheme SportsTime -parallel-testing-enabled NO -only-testing:SportsTimeUITests/<SuiteName>/test<ID>_<Name> <destination>`
If needed, run selected suite only:
`xcodebuild test-without-building -project SportsTime.xcodeproj -scheme SportsTime -parallel-testing-enabled NO -only-testing:SportsTimeUITests/<SuiteName> <destination>`
Do not run the full suite unless I ask.
## Output Contract
Return:
1. Chosen 3 QA cases and why they were selected.
2. Files changed and what changed in each.
3. Exact commands run.
4. Test results for each selected test (including repeat runs).
5. Any residual risk or blocker.
6. Optional next 2-3 QA cases to implement next (ranked by ease/confidence).
## INPUT (Replace This Block)
Candidate QA cases from `docs/SportsTime_QA_Test_Plan.xlsx`:
- [F-___]
- [F-___]
- [F-___]
- [F-___]
- [F-___]
Extra constraints:
- [Example: Do not edit `SportsTimeUITests/Tests/TripSavingTests.swift`]
- [Example: Only use existing `TestFlows`]