fix(ios): UITest tapAndType waits for keyboard focus (#288)#300
Conversation
Add XCUIElement.tapAndType(in:) that taps, waits for app.keyboard and hasKeyboardFocus before typeText to fix CI flake on auth screens. Use it in password-reset and login/history tests plus keyboard overlap test. Document iOS E2E lane retry count (MAX_RETRIES=1 via package.json) in e2e-ios workflow. Closes #288 Co-authored-by: Bretton Auerbach <auerbachb@users.noreply.github.com>
|
CodeAnt AI is reviewing your PR. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📝 WalkthroughWalkthroughAdds an XCUIElement extension Changes
Sequence Diagram(s)sequenceDiagram
participant Test as XCTest
participant App as XCUIApplication
participant Keyboard as Simulator Keyboard
rect rgba(200,230,255,0.5)
Test->>App: tap(element)
App->>Keyboard: request first responder / present keyboard
Keyboard-->>App: keyboard appears
App-->>Test: element.hasKeyboardFocus == true
Test->>App: typeText(text)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📋 Issue PlannerBuilt with CodeRabbit's Coding Plans for faster development and fewer bugs. View plan used: ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ios/StillPointAppUITests/Helpers/XCUIElement`+TapAndType.swift:
- Around line 18-23: Replace the non-fatal XCTAssertTrue check for keyboard
presence with a guard that returns early: call
keyboard.waitForExistence(timeout: timeout) in a guard statement, and on failure
call XCTFail with the same message ("Keyboard did not appear after tapping text
field", include file and line) then return to prevent continuing to
focus/typing; update the helper in XCUIElement+TapAndType.swift (the method that
performs the tap/focus and typing) to use guard + XCTFail + return instead of
XCTAssertTrue so the helper behavior is deterministic even when
continueAfterFailure = true.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c563e19e-1b15-4c06-a84c-144cd1aa6bde
📒 Files selected for processing (3)
.github/workflows/e2e-ios.ymlios/StillPointAppUITests/Helpers/XCUIElement+TapAndType.swiftios/StillPointAppUITests/StillPointAppUITests.swift
|
CodeAnt AI finished reviewing your PR. |
|
@CodeAnt-AI review |
|
CodeAnt AI is running the review. |
|
@cursor review |
|
@graphite-app re-review |
Sequence DiagramThis PR adds a UITest helper that taps an auth text field, waits for the software keyboard and keyboard focus, then types text to eliminate flaky keyboard-focus failures in iOS end-to-end tests. sequenceDiagram
participant UITest
participant TextField
participant App
participant Keyboard
UITest->>TextField: tapAndType(text, in app)
TextField->>TextField: Tap field
TextField->>App: Wait for keyboard existence
App-->>Keyboard: Show keyboard
Keyboard-->>TextField: Keyboard visible
TextField->>TextField: Wait for keyboard focus then type text
Generated by CodeAnt AI |
|
CodeAnt AI finished running the review. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7b3b51a. Configure here.
…te, VoiceOver session - tapAndType: wait for hasKeyboardFocus first (software keyboard optional for hardware-keyboard sims); use XCTWaiter instance for clear timeout failures; optional short keyboard wait + focus retry - testLaunchLoginCompleteSessionAndHistoryPersistence: terminateAppReliably with polling for .notRunning to absorb flaky terminate on CI - testVoiceOverLabelsForTimerAndPrimaryButton: 600s virtual session at 0.05x so slow CI cannot complete before timer label assertion Addresses PR #300 iOS e2e smoke/critical failures and review feedback. Co-authored-by: Bretton Auerbach <auerbachb@users.noreply.github.com>
XCTWaiter(delegate:delegateQueue:) is unavailable / mismatched on Xcode 26; plain XCTWaiter() avoids SwiftCompile failure on ios-e2e-smoke. Co-authored-by: Bretton Auerbach <auerbachb@users.noreply.github.com>
…r wait Critical lane failed: confirmation never appeared after forgot-password tap. Dismiss keyboard after email entry, use tapByStableCenter on forgot button, extend passwordResetMessage wait to 20s. Co-authored-by: Bretton Auerbach <auerbachb@users.noreply.github.com>
|
CodeAnt AI is running Incremental review |
|
CodeAnt AI Incremental review completed. |
|
CodeAnt AI is running the review. |
Sequence DiagramThis PR updates iOS UI tests to use a tap-and-type helper that waits for keyboard focus before typing into auth fields and adds a terminate helper that reliably stops the app before relaunch, reducing flaky CI failures. sequenceDiagram
participant UITest
participant Field
participant App
participant Waiter
UITest->>Field: tapAndType(text, in app)
Field->>Field: Tap element
Field->>Waiter: Wait for keyboard focus on field
alt Focus becomes active
Waiter-->>Field: Focus ready
else Focus delayed
Field->>App: Optionally wait for keyboard and retry focus
Waiter-->>Field: Focus ready or timeout
end
alt Focus acquired
Field->>Field: Type text into field
else Focus not acquired
Field-->>UITest: Fail test with focus timeout
end
UITest->>App: terminateAppReliably()
loop Up to N attempts
App->>App: Call terminate
App->>App: Poll until state is notRunning
end
alt App stopped
App-->>UITest: Ready for relaunch
else Still running
App-->>UITest: Fail test app did not stop
end
Generated by CodeAnt AI |
| let keyboard = app.keyboards.firstMatch | ||
| if keyboard.waitForExistence(timeout: min(2.0, timeout)) { | ||
| let retryFocus = XCTNSPredicateExpectation(predicate: focusPredicate, object: self) | ||
| outcome = waiter.wait(for: [retryFocus], timeout: min(3.0, timeout)) |
There was a problem hiding this comment.
Suggestion: The retry path is incorrectly gated on software keyboard existence. In hardware-keyboard CI runs, app.keyboards.firstMatch may never exist, so the code skips the second focus check entirely and can still fail with focus-related typing errors even when focus would be obtained shortly after. Retry the focus predicate independently of keyboard existence (or always perform a short delayed re-check). [logic error]
Severity Level: Major ⚠️
- ⚠️ Login UI tests may flake on hardware-keyboard CI configs.
- ⚠️ Password reset discovery test reliability reduced by focus gating.Steps of Reproduction ✅
1. Run the iOS UI test suite that includes
`testLaunchLoginCompleteSessionAndHistoryPersistence()` and
`testKeyboardOverlapKeepsSubmitReachable()` in
`ios/StillPointAppUITests/StillPointAppUITests.swift:27-47` and `143-162`, where
`emailField.tapAndType(..., in: app)` and `passwordField.tapAndType(..., in: app)` are
invoked using the default timeout.
2. These calls enter `XCUIElement.tapAndType(_:in:timeout:file:line:)` in
`ios/StillPointAppUITests/Helpers/XCUIElement+TapAndType.swift:9-45`, which taps the field
(`line 16`), then waits for `hasKeyboardFocus == true` using `XCTWaiter` and
`XCTNSPredicateExpectation` (`lines 18-23`), storing the result in `outcome`.
3. In a CI configuration using a hardware keyboard where no software keyboard view appears
(matching the helper's documented support for "hardware keyboard / CI variants" at lines
6-7), if `hasKeyboardFocus` does not become true within the initial `timeout`, `outcome`
becomes `.timedOut`, the code enters the retry block (`line 25`), but the retry is
conditioned on `keyboard.waitForExistence(...)` (`lines 28-29`) which returns false when
`app.keyboards.firstMatch` never materializes, so the focus retry at `lines 30-31` is
skipped and `outcome` remains `.timedOut`.
4. Control then hits the `guard outcome == .completed` at `lines 35-42`, which triggers
`XCTFail("Field did not become keyboard first responder...")` and returns early instead of
performing a short delayed re-check of the focus predicate; any case where focus would be
obtained shortly after the initial timeout but with no software keyboard present will
cause `tapAndType` to fail these login/password-reset UI tests prematurely, even though an
unconditional retry would have allowed the tests to proceed.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** ios/StillPointAppUITests/Helpers/XCUIElement+TapAndType.swift
**Line:** 28:31
**Comment:**
*Logic Error: The retry path is incorrectly gated on software keyboard existence. In hardware-keyboard CI runs, `app.keyboards.firstMatch` may never exist, so the code skips the second focus check entirely and can still fail with focus-related typing errors even when focus would be obtained shortly after. Retry the focus predicate independently of keyboard existence (or always perform a short delayed re-check).
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix|
CodeAnt AI finished running the review. |
|
CodeAnt AI is running the review. |
Sequence DiagramThis PR updates iOS UI tests to use a focus-first tapAndType helper for auth fields and a terminateAppReliably helper before relaunch, reducing keyboard focus flakes and unstable terminate failures in CI. sequenceDiagram
participant UITest
participant App
participant Keyboard
UITest->>App: Launch app for auth flow
UITest->>App: tapAndType email field
App-->>UITest: Email field gains keyboard focus
UITest->>App: tapAndType password field
UITest->>App: Submit auth form
UITest->>App: terminateAppReliably before relaunch
App-->>UITest: App reaches notRunning state
UITest->>App: Relaunch and verify home or session screen
Generated by CodeAnt AI |
|
A review was recently triggered for this PR. Please wait 9s before retriggering. |
1 similar comment
|
A review was recently triggered for this PR. Please wait 9s before retriggering. |
|
A review was recently triggered for this PR. Please wait 3s before retriggering. |
1 similar comment
|
A review was recently triggered for this PR. Please wait 3s before retriggering. |
|
CodeAnt AI finished running the review. |
|
CodeAnt AI is running the review. |
Sequence DiagramThis PR adds a keyboard focus helper that taps an auth field, waits for it to gain keyboard focus, then types, and also introduces a reliable terminate helper that retries app termination until the app is fully stopped before relaunch. sequenceDiagram
participant UITest
participant App
participant KeyboardFocusHelper
UITest->>App: Launch app for auth flow
UITest->>KeyboardFocusHelper: tapAndType on auth field
KeyboardFocusHelper->>App: Tap field and wait for keyboard focus
App-->>KeyboardFocusHelper: Field has keyboard focus
KeyboardFocusHelper-->>UITest: Text entered into field
UITest->>App: terminateAppReliably
App->>App: Retry terminate and poll for notRunning
App-->>UITest: App fully stopped, ready for relaunch
Generated by CodeAnt AI |
|
CodeAnt AI finished running the review. |
|
CodeAnt AI is running the review. |
Sequence DiagramThis PR adds a tapAndType helper that waits for keyboard focus before typing into auth fields and a terminateAppReliably helper that ensures the app fully stops before relaunch, reducing flaky iOS UI tests. sequenceDiagram
participant UITest
participant AuthField
participant App
UITest->>AuthField: tapAndType with text and app
AuthField->>AuthField: tap and wait for keyboard focus
AuthField-->>UITest: field ready for typing
AuthField->>AuthField: type text into field
UITest->>App: terminateAppReliably
App->>App: terminate and poll until notRunning
App-->>UITest: app fully terminated
UITest->>App: launch for next step
Generated by CodeAnt AI |
|
CodeAnt AI finished running the review. |
|
CodeAnt AI is running the review. |
Sequence DiagramThis PR updates iOS UI tests to use a tapAndType helper that waits for keyboard focus before typing into auth fields and adds a terminateAppReliably helper to stabilize app termination and relaunch flows in CI. sequenceDiagram
participant UITest
participant App
participant AuthField
UITest->>App: Launch auth flow
UITest->>AuthField: tapAndType credentials
AuthField->>App: Tap field and wait for keyboard focus
App-->>AuthField: Field has keyboard focus
AuthField-->>UITest: Type text into field completes
UITest->>App: Request reliable termination
App->>App: Retry terminate until state notRunning
App-->>UITest: App terminated and ready for relaunch
Generated by CodeAnt AI |
|
CodeAnt AI finished running the review. |

User description
Test plan
ios-e2e-smokeCI lane passes (smoke auth + basic navigation)ios-e2e-criticalCI lane passes (VoiceOver timer, password reset flow)tapAndTypewaits for keyboard focus before typing — no "neither element nor any descendant has keyboard focus" failuresterminateAppReliablyis stable under repeat runsXCTWaiter()instance init compiles on Xcode 26Summary
UITest keyboard/focus helper and CI hardening for PR #288 / #300.
Recent fixes
XCTWaiter()default init on Xcode 26.terminateAppReliablyfor flakyterminate().tapByStableCenteron forgot-password, 20s wait for confirmation.Closes #288
Summary by CodeRabbit
Tests
Chores
CodeAnt-AI Description
Make iOS UI tests wait for focus and handle flaky CI runs
What Changed
Impact
✅ Fewer auth test failures✅ More stable iOS CI runs✅ Clearer password reset verification🔄 Retrigger CodeAnt AI Review
Details
💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.