docs(ios): add comprehensive testing guide and refine iOS parity directive
Add iOS prefetch testing guide with detailed procedures, log checklists, and behavior classification. Enhance iOS test app requirements with security constraints, sign-off checklists, and changelog structure. Update main directive with testing strategy and method behavior mapping. Changes: - Add IOS_PREFETCH_TESTING.md with simulator/device test plans, log diagnostics, telemetry expectations, and test run templates - Add DailyNotificationBackgroundTaskTestHarness.swift as reference implementation for BGTaskScheduler testing - Enhance IOS_TEST_APP_REQUIREMENTS.md with security/privacy constraints, review checklists, CI hints, and glossary cross-links - Update 0003-iOS-Android-Parity-Directive.md with testing strategy section, method behavior classification, and validation matrix updates All documents now include changelog stubs, cross-references, and completion criteria for Phase 1 implementation and testing.
This commit is contained in:
@@ -1,16 +1,58 @@
|
||||
# iOS Test App Requirements
|
||||
|
||||
**Purpose:** What the iOS test app must provide so that the testing guide can be executed with parity vs Android
|
||||
|
||||
**Plugin Target:** DailyNotificationPlugin v3.x (iOS)
|
||||
**Phase:** Phase 1 – Prefetch MVP
|
||||
**Status:** 📋 **REQUIRED FOR PHASE 1**
|
||||
**Date:** 2025-01-XX
|
||||
**Date:** 2025-11-15
|
||||
**Author:** Matthew Raymer
|
||||
**Directive Reference:** `doc/directives/0003-iOS-Android-Parity-Directive.md`
|
||||
|
||||
**Note:** This app exists to support the prefetch testing scenarios in `doc/test-app-ios/IOS_PREFETCH_TESTING.md`.
|
||||
|
||||
**Android parity:** Behavior is aligned with `test-apps/android-test-app` where platform constraints allow. Timing and BGTask heuristics **will differ** from Android's exact alarms:
|
||||
- **Android:** Exact alarms via AlarmManager / WorkManager
|
||||
- **iOS:** Heuristic BGTaskScheduler (see glossary); no hard guarantee of 5-min prefetch
|
||||
|
||||
**Glossary:** See glossary in `IOS_PREFETCH_TESTING.md` for terminology.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This document defines the requirements for the iOS test app (`test-apps/ios-test-app/`) that must be created as part of Phase 1 implementation. The iOS test app must provide UI parity with the Android test app (`test-apps/android-test-app/`) while respecting iOS-specific constraints and capabilities.
|
||||
|
||||
## Non-Goals (Phase 1)
|
||||
|
||||
**Out of scope for Phase 1:**
|
||||
|
||||
- ❌ No full UX polish (color, branding)
|
||||
- ❌ No localization / accessibility guarantees (text only for internal QA)
|
||||
- ❌ No production signing / App Store deployment
|
||||
- ❌ No advanced UI features beyond basic functionality testing
|
||||
|
||||
## Security & Privacy Constraints
|
||||
|
||||
**Critical requirements for test app implementation:**
|
||||
|
||||
- Test app MUST use **non-production** endpoints and credentials
|
||||
- JWT / API keys used here are **test-only** and may be rotated or revoked at any time
|
||||
- Logs MUST NOT include real user PII (names, emails, phone numbers)
|
||||
- Any screenshots or shared logs should be scrubbed of secrets before external sharing
|
||||
- Test app should clearly indicate it's a development/testing build (not production)
|
||||
|
||||
## If You Only Have 30 Minutes
|
||||
|
||||
Quick setup checklist:
|
||||
|
||||
1. Copy HTML/JS from Android test app (`test-apps/android-test-app/app/src/main/assets/public/index.html`)
|
||||
2. Wire plugin into Capacitor (`capacitor.config.json`)
|
||||
3. Add Info.plist keys (BGTask identifiers, background modes, notification permissions)
|
||||
4. Build/run (`./scripts/build-ios-test-app.sh --simulator` or Xcode)
|
||||
5. Press buttons: Check Plugin Status → Request Permissions → Schedule Test Notification
|
||||
6. See logs with prefixes `DNP-PLUGIN`, `DNP-FETCH`, `DNP-SCHEDULER`
|
||||
|
||||
---
|
||||
|
||||
## UI Parity Requirements
|
||||
@@ -54,6 +96,20 @@ The test app UI must support:
|
||||
- Show pending notification count
|
||||
- Display error messages if any
|
||||
|
||||
### UI Elements to Plugin Methods Mapping
|
||||
|
||||
| UI Element / Button | Plugin Method / API Call | Notes |
|
||||
|---------------------|-------------------------|-------|
|
||||
| "Check Plugin Status" | `DailyNotification.configure()` or status call | Verify plugin load & config |
|
||||
| "Check Permissions" | `getNotificationStatus()` | Maps to permission state |
|
||||
| "Request Permissions" | `requestPermissions()` | Drives iOS UNUserNotificationCenter |
|
||||
| "Schedule Test Notification" | `scheduleDailyNotification()` | Should schedule prefetch + notify |
|
||||
| "Show Last Notification" | `getLastNotification()` | Uses deterministic path (Bucket A) |
|
||||
| "Cancel All Notifications" | `cancelAllNotifications()` | Uses deterministic path (Bucket A) |
|
||||
| "Get Notification Status" | `getNotificationStatus()` | Uses deterministic path (Bucket A) |
|
||||
|
||||
**See `IOS_PREFETCH_TESTING.md` Behavior Classification for deterministic vs heuristic methods.**
|
||||
|
||||
---
|
||||
|
||||
## iOS Permissions Configuration
|
||||
@@ -64,10 +120,11 @@ The test app's `Info.plist` **MUST** include:
|
||||
|
||||
```xml
|
||||
<!-- Background Task Identifiers -->
|
||||
<!-- These identifiers MUST match exactly the values used in IOS_PREFETCH_TESTING.md and the plugin Swift code, otherwise BGTaskScheduler (see glossary) will silently fail -->
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.timesafari.dailynotification.fetch</string>
|
||||
<string>com.timesafari.dailynotification.notify</string>
|
||||
<string>com.timesafari.dailynotification.fetch</string> <!-- Prefetch task (BGAppRefreshTask - see glossary) -->
|
||||
<string>com.timesafari.dailynotification.notify</string> <!-- Notification maintenance task (if applicable) -->
|
||||
</array>
|
||||
|
||||
<!-- Background Modes -->
|
||||
@@ -121,12 +178,29 @@ Use the build script:
|
||||
./scripts/build-ios-test-app.sh --device
|
||||
```
|
||||
|
||||
### Future CI Integration (Optional)
|
||||
|
||||
**Note for Phase 2+:** Consider adding `xcodebuild`-based CI job that:
|
||||
- Builds `test-apps/ios-test-app` for simulator
|
||||
- Runs a minimal UI test that:
|
||||
- Launches app
|
||||
- Calls `configure()` and `getNotificationStatus()`
|
||||
- This ensures test app remains buildable as plugin evolves
|
||||
|
||||
**Phase 1:** Manual testing only; CI integration is out of scope.
|
||||
|
||||
### Build Requirements
|
||||
|
||||
**Required Tools:**
|
||||
- **Xcode:** 15.0 or later
|
||||
- **macOS:** 13.0 (Ventura) or later
|
||||
- **iOS Deployment Target:** iOS 15.0 or later
|
||||
- **CocoaPods:** Must run `pod install` before first build
|
||||
- **CocoaPods:** >= 1.13 (must run `pod install` before first build)
|
||||
- **Node.js:** 20.x (recommended)
|
||||
- **npm:** Latest stable (comes with Node.js)
|
||||
- **Xcode Command Line Tools:** Must run `xcode-select --install` if not already installed
|
||||
|
||||
**Note:** Mismatched versions are **out of scope** for Phase 1 support. Use recommended versions to avoid compatibility issues.
|
||||
|
||||
---
|
||||
|
||||
@@ -167,6 +241,8 @@ npx cap sync ios
|
||||
|
||||
## Debugging Strategy
|
||||
|
||||
**When executing the scenarios in `IOS_PREFETCH_TESTING.md`, use the following commands while looking for logs with prefixes `DNP-PLUGIN`, `DNP-FETCH`, `DNP-SCHEDULER`.**
|
||||
|
||||
### Xcode Debugger
|
||||
|
||||
**Check Pending Notifications:**
|
||||
@@ -193,21 +269,27 @@ e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWith
|
||||
**Key Log Prefixes:**
|
||||
- `DNP-PLUGIN:` - Main plugin operations
|
||||
- `DNP-FETCH:` - Background fetch operations
|
||||
- `DNP-FETCH-SCHEDULE:` - BGTask scheduling
|
||||
- `DailyNotificationStorage:` - Storage operations
|
||||
- `DailyNotificationScheduler:` - Scheduling operations
|
||||
- `DNP-SCHEDULER:` - Scheduling operations
|
||||
- `DNP-STORAGE:` - Storage operations
|
||||
|
||||
### Common Debugging Scenarios
|
||||
|
||||
**Scenario: BGTask not running when expected → follow this checklist:**
|
||||
|
||||
1. **BGTask Not Running:**
|
||||
- Check Info.plist has `BGTaskSchedulerPermittedIdentifiers`
|
||||
- Verify task registered in AppDelegate
|
||||
- Verify identifiers match code exactly (case-sensitive)
|
||||
- Verify task registered in AppDelegate before app finishes launching
|
||||
- Check Background App Refresh enabled in Settings → [Your App]
|
||||
- Verify app not force-quit (iOS won't run BGTask for force-quit apps)
|
||||
- Use simulator-only LLDB command to manually trigger
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Log Checklist: Section 3`
|
||||
|
||||
2. **Notifications Not Delivering:**
|
||||
- Check notification permissions
|
||||
- Verify notification scheduled
|
||||
- Check notification permissions: `UNUserNotificationCenter.current().getNotificationSettings()`
|
||||
- Verify notification scheduled: `UNUserNotificationCenter.current().getPendingNotificationRequests()`
|
||||
- Check notification category registered
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Log Checklist: Section 4`
|
||||
|
||||
3. **Build Failures:**
|
||||
- Run `pod install`
|
||||
@@ -278,56 +360,172 @@ test-apps/ios-test-app/
|
||||
|
||||
### Basic Functionality
|
||||
|
||||
1. **Plugin Registration**
|
||||
**Happy Path Example:**
|
||||
|
||||
When everything is working correctly, your first run should produce logs like this:
|
||||
|
||||
```text
|
||||
[DNP-PLUGIN] configure() called
|
||||
[DNP-PLUGIN] status = ready
|
||||
[DNP-PLUGIN] requestPermissions() → granted
|
||||
[DNP-SCHEDULER] scheduleDailyNotification() → notificationTime=2025-11-15T05:53:00Z
|
||||
[DNP-FETCH] Scheduling prefetch for notification at 2025-11-15T05:53:00Z
|
||||
[DNP-FETCH] BGAppRefreshTask scheduled (earliestBeginDate=2025-11-15T05:48:00Z)
|
||||
[DNP-SCHEDULER] Scheduling notification for 2025-11-15T05:53:00Z
|
||||
[DNP-STORAGE] Persisted schedule to DB (id=..., type=DAILY, ...)
|
||||
```
|
||||
|
||||
**If your first run doesn't look roughly like this, fix that before proceeding to BGTask tests.**
|
||||
|
||||
1. **Plugin Registration** `[P1-Core][SIM+DEV]`
|
||||
- Launch app
|
||||
- Verify plugin status shows "Plugin is loaded and ready!"
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Simulator Test Plan: Step 2`
|
||||
|
||||
2. **Permission Management**
|
||||
2. **Permission Management** `[P1-Core][SIM+DEV]`
|
||||
- Check permissions
|
||||
- Request permissions
|
||||
- Verify permissions granted
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Simulator Test Plan: Step 6 (Negative-Path Tests)`
|
||||
|
||||
3. **Notification Scheduling**
|
||||
3. **Notification Scheduling** `[P1-Prefetch][SIM+DEV]`
|
||||
- Schedule test notification
|
||||
- Verify notification scheduled
|
||||
- Wait for notification to appear
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Simulator Test Plan: Steps 3-5`
|
||||
|
||||
### Background Tasks
|
||||
|
||||
1. **BGTask Scheduling**
|
||||
**Sim vs Device Behavior:**
|
||||
|
||||
- `[SIM+DEV]` – can be fully tested on simulator and device (logic correctness)
|
||||
- `[DEV-ONLY]` – timing / heuristic behavior, must be verified on real hardware
|
||||
|
||||
1. **BGTask Scheduling** `[P1-Prefetch][SIM+DEV]`
|
||||
- Schedule notification with prefetch
|
||||
- Verify BGTask scheduled 5 minutes before notification
|
||||
- Manually trigger BGTask (simulator only)
|
||||
- Verify content fetched
|
||||
- **Note:** Logic and logs on sim; real timing on device
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Simulator Test Plan: Steps 3-4`
|
||||
|
||||
2. **BGTask Miss Detection**
|
||||
2. **BGTask Miss Detection** `[P1-Prefetch][DEV-ONLY]`
|
||||
- Schedule notification
|
||||
- Wait 15+ minutes
|
||||
- Launch app
|
||||
- Verify BGTask rescheduled
|
||||
- **Note:** Only meaningful on device (heuristic timing)
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Real Device Test Plan: Step 4`
|
||||
|
||||
### Error Handling
|
||||
|
||||
1. **Permission Denied**
|
||||
1. **Permission Denied** `[P1-Core]`
|
||||
- Deny notification permissions
|
||||
- Try to schedule notification
|
||||
- Verify error returned
|
||||
- **See also:** `IOS_PREFETCH_TESTING.md – Simulator Test Plan: Step 6 (Negative-Path Tests)`
|
||||
|
||||
2. **Invalid Parameters**
|
||||
2. **Invalid Parameters** `[P1-Core]`
|
||||
- Try to schedule with invalid time format
|
||||
- Verify error returned
|
||||
|
||||
### Advanced Features `[P2-Advanced]`
|
||||
|
||||
1. **Rolling Window** `[P2-Advanced]`
|
||||
- Schedule multiple notifications
|
||||
- Verify rolling window maintenance
|
||||
- Check notification limits (64 max on iOS)
|
||||
|
||||
2. **TTL Enforcement** `[P2-Advanced]`
|
||||
- Schedule notification with prefetch
|
||||
- Wait for TTL to expire
|
||||
- Verify stale content discarded at delivery
|
||||
|
||||
---
|
||||
|
||||
## Developer/Test Harness Features (Optional but Recommended)
|
||||
|
||||
Since this test app is for internal testing, it can expose more tools:
|
||||
|
||||
### Dev-Only Toggles
|
||||
|
||||
1. **Force Schedule Notification N Minutes from Now**
|
||||
- Bypass normal scheduling UI
|
||||
- Directly call `scheduleDailyNotification()` with calculated time
|
||||
- Useful for quick testing scenarios
|
||||
|
||||
2. **Force "Prefetch-Only" Task**
|
||||
- Trigger BGTask without scheduling notification
|
||||
- Useful for testing prefetch logic in isolation
|
||||
- Display raw JSON returned from API (last fetched payload)
|
||||
|
||||
3. **Display Raw API Response**
|
||||
- Show last fetched payload as JSON
|
||||
- Useful for debugging API responses
|
||||
- Can be referenced from `IOS_PREFETCH_TESTING.md` as shortcuts for specific scenarios
|
||||
|
||||
4. **Manual BGTask Trigger (Dev Build Only)**
|
||||
- Button to manually trigger BGTask (simulator only)
|
||||
- Wraps the LLDB command in UI for convenience
|
||||
|
||||
These features can then be referenced from `IOS_PREFETCH_TESTING.md` as shortcuts for specific test scenarios.
|
||||
|
||||
## Risks & Gotchas
|
||||
|
||||
**Common pitfalls when working with the test app:**
|
||||
|
||||
1. **Accidentally editing shared HTML/JS in iOS test app instead of Android canonical source**
|
||||
- Always edit Android test app HTML/JS first, then copy to iOS
|
||||
- Keep iOS test app HTML/JS as a copy, not the source of truth
|
||||
|
||||
2. **Forgetting `npx cap sync ios` after plugin or asset changes**
|
||||
- Run `npx cap sync ios` after any plugin code changes
|
||||
- Run `npx cap sync ios` after any web asset changes
|
||||
- Check `capacitor.config.json` is up to date
|
||||
|
||||
3. **Running with stale Pods**
|
||||
- Run `pod repo update` periodically
|
||||
- Run `pod install` after dependency changes
|
||||
- Clean build folder (Cmd+Shift+K) if Pods seem stale
|
||||
|
||||
4. **Changing BGTask identifiers in one place but not the other**
|
||||
- Info.plist `BGTaskSchedulerPermittedIdentifiers` must match Swift code exactly (case-sensitive)
|
||||
- Check both places when updating identifiers
|
||||
- See `IOS_PREFETCH_TESTING.md` for identifier requirements
|
||||
|
||||
5. **Mismatched tooling versions**
|
||||
- Use recommended versions (Node 20.x, CocoaPods >= 1.13, Xcode 15.0+)
|
||||
- Mismatched versions are out of scope for Phase 1 support
|
||||
|
||||
## References
|
||||
|
||||
- **Directive:** `doc/directives/0003-iOS-Android-Parity-Directive.md`
|
||||
- **Testing Guide:** `doc/test-app-ios/IOS_PREFETCH_TESTING.md` - Comprehensive prefetch testing procedures
|
||||
- **Android Test App:** `test-apps/android-test-app/`
|
||||
- **Build Script:** `scripts/build-ios-test-app.sh`
|
||||
- **Testing Guide:** `doc/IOS_PHASE1_TESTING_GUIDE.md`
|
||||
|
||||
---
|
||||
|
||||
## Review & Sign-Off Checklist (Phase 1)
|
||||
|
||||
**Use this checklist to verify Phase 1 iOS test app is complete:**
|
||||
|
||||
- [ ] Test app builds on simulator with recommended toolchain (Node 20.x, CocoaPods >= 1.13, Xcode 15.0+)
|
||||
- [ ] Test app builds on at least one real device
|
||||
- [ ] All UI buttons map to plugin methods as per the **UI Elements to Plugin Methods Mapping** table
|
||||
- [ ] Happy-path log sequence matches the example in **Testing Scenarios → Basic Functionality**
|
||||
- [ ] BGTask identifiers are consistent (Info.plist ↔ Swift ↔ docs)
|
||||
- [ ] Risks & Gotchas section has been read and acknowledged by the implementer
|
||||
- [ ] Security & Privacy Constraints have been followed (non-production endpoints, no PII in logs)
|
||||
|
||||
---
|
||||
|
||||
## Changelog (high-level)
|
||||
|
||||
- 2025-11-15 — Initial Phase 1 version (prefetch MVP, Android parity)
|
||||
|
||||
---
|
||||
|
||||
**Status:** 📋 **REQUIRED FOR PHASE 1**
|
||||
**Last Updated:** 2025-01-XX
|
||||
**Last Updated:** 2025-11-15
|
||||
|
||||
|
||||
Reference in New Issue
Block a user