All 7 authenticated-flow XCTestCase classes logged out for real in
tearDown, forcing a real OTP round trip against the production backend
on the next authenticated test. Under CI's back-to-back suite run this
produced ~9 real logins to the same QA phone number in ~9 minutes -
the first few succeeded (~30-40s each) but every one after that failed
to complete within timeout, cascading into 'Login never completed'
across CartCheckoutFlowTests, HomeFiltersFlowTests,
OrderDetailsFlowTests, SavedCardsFlowTests, UserProfileFlowTests.
Removed the per-test logout so the QA account's Keychain-backed session
persists across the whole suite (ensureLoggedIn already no-ops when
already authenticated). Moved the 'must start logged out' guarantee to
the two classes that actually need it - HomeGuestFlowTests and
ProfileLoggedOutFlowTests now force logout themselves right after
app.launch() via a small launch helper, instead of relying on whichever
authenticated class happened to run last.
See decisions/2026-09-11-ui-test-shared-login-session.md.
FiltersModalView.swift was 0% covered. Reaching it via guest mode hit
the backend's App Attest simulator-bypass rejection (403
APP_ATTEST_VERIFICATION_FAILED on /api/public/session, confirmed via
curl - a pre-existing, out-of-repo backend issue already documented in
decisions/2026-08-06-ui-test-account-and-app-attest-bypass.md), which
kept the guest address picker stuck showing a load-error sub-screen.
While chasing that, found a real bug in ContentView.swift:
.sheet(item: $appState.activeModal) had no onDismiss, so an
interactive swipe-to-dismiss never reset the bound item to nil -
anyone who swipes the address picker away without picking a location
leaves appState.activeModal stuck non-nil, silently breaking the next
modal presentation app-wide. Fixed with
onDismiss: { appState.activeModal = nil }.
Rewrote HomeFiltersFlowTests to use the authenticated QA account
instead of guest mode, routing around the backend-blocked guest wall
entirely. Also fixed a separate, real XCUITest issue: a plain .tap()
on the filter icon (inside Home's .offset()-transformed collapsing
header) reliably produced "Computed hit point {-1, -1}" - fixed via
coordinate(withNormalizedOffset:).tap().
Verified: HomeFiltersFlowTests passed clean across 2 consecutive
isolated runs. Full-suite regression run could not be completed this
round - the local environment stopped completing any instrumented
test launch afterward (reproduced across background/foreground,
clean DerivedData, simulator reboot, decoupled build/test, process
cleanup), unrelated to these changes. Documented in
decisions/2026-08-11-coverage-push-to-85-percent-status.md, with a
next-session TODO to run the full suite once the environment recovers.