## TL;DR

XCUITest found the element but could not compute a tappable point, usually because it is covered, offscreen, or has zero size. Wait for hittability and scroll it into view before tapping; if it is still not hittable, tap by coordinate as a last resort.

## Error

```text
testTapSaveButton: Unable to find hit point for element XCUIElementTypeButton "Save"
```

## Steps

1. Wait for the element to exist AND be hittable before acting. Expected: the wait passes; if it times out, the element is genuinely not hittable.
```swift
let save = app.buttons["Save"]
let pred = NSPredicate(format: "exists == true AND hittable == true")
expectation(for: pred, evaluatedWith: save, handler: nil)
waitForExpectations(timeout: 5)
```
2. Scroll it into view: swipe on the containing scroll view until `save.isHittable` becomes true. Expected: the hittability check flips to true.
3. Check for overlays: a toast, banner, or the keyboard covering the button. Dismiss it first. Expected: the hit point resolves once the covering view is gone.
4. Verify the frame is not zero-size in the failure snapshot (element exists but width or height is 0). Expected: a real frame; zero means a layout bug, not a test bug.
5. Last resort: tap the coordinate directly: `save.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()`. Expected: the tap lands even when hit-testing fails.

## When to use

- The element query finds the element but the tap fails.
- It happens after animations or when the keyboard appears.
- It fails on small screens but passes on large ones (layout pushes the button under an edge).

## When not to use

- `No matches found` (the element does not exist at all).
- The tap succeeds but the app does not react (an app bug, not a hit-test bug).
- The failure is in typeText, not tap (that is the keyboard-focus variant).

## Tool compatibility

- XCUITest with Xcode 14, 15, and 16; iOS 16, 17, and 18 simulators and devices.

## Variant phrasings

### Neither element nor any descendant has keyboard focus

The typeText cousin of this error: the field exists but cannot take focus. Tap it first, then type.

### fails only on small screens

Layout pushes the button under the home indicator or keyboard. Scroll or adjust the layout.

### passes locally, fails on CI

Animation timing differs. Wait for hittability instead of sleeping a fixed time.

## Why it happens

XCUITest computes the tap point by hit-testing the element's frame against the visible hierarchy. Anything covering it (keyboard, alert, another view), a frame outside the screen, or a zero-size frame leaves no valid point, even though the element query matched.

## Edge cases

- isHittable is false for elements behind a transparent overlay too, not just opaque ones.
- Animations need a hittability wait plus a beat; existence alone is not enough.
- Coordinate taps bypass hit-testing, so they can mask real overlay bugs; prefer fixing the overlay.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_MOD6eXlaMRSo_yrktL14LA
