Files
honeyDueKMP/iosApp/CaseraUITests/README.md
Trey t 7444f73b46 Close all 25 codex audit findings across KMP, iOS, and Android
Remediate all P0-S priority findings from cross-platform architecture audit:
- Harden token storage with EncryptedSharedPreferences (Android) and Keychain (iOS)
- Add SSL pinning and certificate validation to API clients
- Fix subscription cache race conditions and add thread-safe access
- Add input validation for document uploads and file type restrictions
- Refactor DocumentApi to use proper multipart upload flow
- Add rate limiting awareness and retry logic to API layer
- Harden subscription tier enforcement in SubscriptionHelper
- Add biometric prompt for sensitive actions (Login, Onboarding)
- Fix notification permission handling and device registration
- Add UI test infrastructure (page objects, fixtures, smoke tests)
- Add CI workflow for mobile builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:15:34 -06:00

3.7 KiB

Casera iOS UI Testing Architecture

Directory Structure

CaseraUITests/
├── PageObjects/           # Screen abstractions (Page Object pattern)
│   ├── BaseScreen.swift   # Common wait/assert utilities
│   ├── LoginScreen.swift  # Login screen elements and actions
│   ├── RegisterScreen.swift
│   └── MainTabScreen.swift
├── TestConfiguration/     # Launch config, environment setup
│   └── TestLaunchConfig.swift
├── Fixtures/              # Test data builders
│   └── TestFixtures.swift
├── CriticalPath/          # Must-pass tests for CI gating
│   └── SmokeTests.swift   # Fast smoke suite (<2 min)
├── Suite0-10_*.swift      # Existing comprehensive test suites
├── UITestHelpers.swift    # Legacy shared helpers
├── AccessibilityIdentifiers.swift # UI element IDs
└── README.md              # This file

Test Suites

Suite Purpose CI Gate Target Time
SmokeTests App launches, auth, navigation Every PR <2 min
Suite0-2 Onboarding, registration, auth Nightly <5 min
Suite3-8 Feature CRUD (residence, task, etc) Nightly <15 min
Suite9-10 E2E integration Weekly <30 min

Patterns

Page Object Pattern

Every screen has a corresponding PageObject in PageObjects/. Use these instead of raw XCUIElement queries in tests. Page objects encapsulate element lookups and common actions, making tests more readable and easier to maintain when the UI changes.

Wait Helpers

NEVER use sleep() or Thread.sleep(). Use waitForElement(), waitForElementToDisappear(), or waitForHittable() from BaseScreen. These are condition-based waits that return as soon as the condition is met, making tests both faster and more reliable.

Test Data

Use TestFixtures builders for consistent, unique test data. Random numbers and UUIDs ensure test isolation so tests can run in any order without interfering with each other.

Launch Configuration

Use TestLaunchConfig.launchApp() for standard launches. Use launchAuthenticated() to skip login when the app supports test authentication bypass. The standard configuration disables animations and forces English locale.

Accessibility Identifiers

All interactive elements must have identifiers defined in AccessibilityIdentifiers.swift. Use .accessibilityIdentifier() in SwiftUI views. Page objects reference these identifiers for element lookup.

CI Configuration

Smoke Suite (every PR)

xcodebuild test -project iosApp.xcodeproj -scheme iosApp \
  -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 17' \
  -only-testing:CaseraUITests/SmokeTests

Full Regression (nightly)

xcodebuild test -project iosApp.xcodeproj -scheme iosApp \
  -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 17' \
  -only-testing:CaseraUITests

Flake Reduction

  • Target: <2% flake rate on critical-path suite
  • All waits use condition-based predicates (no fixed sleeps)
  • Test data uses unique identifiers to prevent cross-test interference
  • UI animations disabled via launch arguments
  • Element lookups use accessibility identifiers where possible, with predicate-based fallbacks

Adding New Tests

  1. If the screen does not have a page object yet, create one in PageObjects/ that extends BaseScreen.
  2. Define accessibility identifiers in AccessibilityIdentifiers.swift for any new UI elements.
  3. Add test data builders to TestFixtures.swift if needed.
  4. Write the test in the appropriate suite file, or create a new suite if the feature is new.
  5. For critical-path tests (must pass on every PR), add to CriticalPath/SmokeTests.swift.