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

81 lines
3.7 KiB
Markdown

# 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)
```bash
xcodebuild test -project iosApp.xcodeproj -scheme iosApp \
-sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 17' \
-only-testing:CaseraUITests/SmokeTests
```
### Full Regression (nightly)
```bash
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`.