Remove duplicate status matrix from Section 3.3 and consolidate to Section 11 as single source of truth. Fix all section number references throughout documentation. Changes: - Remove duplicate status matrix table from Section 3.3 - Update all references from "Section 3.3" and "Section 10" to "Section 11" - Fix phase directive paths to use consistent ../ prefix format - Fix P1 path typo (missing "directive" in filename) - Update Doc C status in matrix to reflect completion - Remove duplicate text in Doc B baseline scenarios - Remove self-referencing links in Doc B All status matrix references now point to Section 11, eliminating confusion about which matrix is authoritative.
24 KiB
Plugin Behavior Exploration: Alarm/Schedule/Notification Testing
Author: Matthew Raymer
Date: November 2025
Status: Active Exploration Template
Version: 1.1.0
Last Synced With Plugin Version: v1.1.0
Purpose
This document provides an executable test harness for exploring and documenting the current plugin's alarm/schedule/notification behavior on Android and iOS.
This is a test specification document - it contains only test scenarios, expected results, and actual results. It does NOT contain platform explanations or requirements.
Use this document to:
- Execute test scenarios
- Document actual vs expected results
- Identify gaps between current behavior and requirements
- Generate findings for the Plugin Requirements document
⚠️ RULE: This document contains NO platform explanations. All expected OS behavior must reference Doc A. All expected plugin behavior must reference Doc C.
Reference:
- Platform Capability Reference - OS-level facts (Doc A)
- Plugin Requirements - Plugin guarantees and requirements (Doc C)
0. Reproducibility Protocol
Each scenario MUST define:
- Device model & OS version: e.g., "Pixel 7, Android 14", "iPhone 15, iOS 17"
- App build hash: Git commit hash or build number
- Preconditions: State before test (alarms scheduled, app state, etc.)
- Steps: Exact sequence of actions
- Expected vs Actual: Clear comparison of expected vs observed behavior
Reproducibility Requirements:
- Test must be repeatable by another engineer
- All steps must be executable without special setup
- Results must be verifiable (logs, UI state, database state)
- Timing-sensitive tests must specify wait times
Failure Documentation:
- Capture logs immediately
- Screenshot UI state if relevant
- Record exact error messages
- Note any non-deterministic behavior
0.1 Quick Reference
For platform capabilities: See Doc A - Platform Capability Reference
For plugin requirements: See Doc C - Plugin Requirements
This document contains only test scenarios and results - no platform explanations or requirements.
1. Android Exploration
1.1 Code-Level Inspection Checklist
Source Locations:
- Plugin:
android/src/main/java/com/timesafari/dailynotification/ - Test App:
test-apps/android-test-app/ - Manifest:
test-apps/android-test-app/app/src/main/AndroidManifest.xml
| Task | File/Function | Line | Status | Notes |
|---|---|---|---|---|
| Locate main plugin class | DailyNotificationPlugin.kt |
1302 | ☐ | scheduleDailyNotification() |
| Identify alarm scheduling | NotifyReceiver.kt |
92 | ☐ | scheduleExactNotification() |
| Check AlarmManager usage | NotifyReceiver.kt |
219, 223, 231 | ☐ | setAlarmClock(), setExactAndAllowWhileIdle(), setExact() |
| Check WorkManager usage | FetchWorker.kt |
31 | ☐ | scheduleFetch() |
| Check notification display | DailyNotificationWorker.java |
200+ | ☐ | displayNotification() |
| Check boot receiver | BootReceiver.kt |
24 | ☐ | onReceive() handles BOOT_COMPLETED |
| Check persistence | DailyNotificationPlugin.kt |
1393+ | ☐ | Room database storage |
| Check exact alarm permission | DailyNotificationPlugin.kt |
1309 | ☐ | canScheduleExactAlarms() |
| Check manifest permissions | AndroidManifest.xml |
- | ☐ | RECEIVE_BOOT_COMPLETED, SCHEDULE_EXACT_ALARM |
1.2 Behavior Testing Matrix
Test 1: Base Case
| Step | Action | Trigger Source | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|---|---|---|---|---|---|---|
| 1 | Schedule alarm 2 minutes in future | Plugin | - | Alarm scheduled | ☐ | |
| 2 | Leave app in foreground/background | - | - | - | ☐ | |
| 3 | Wait for trigger time | OS | Alarm fires | Notification displayed | ☐ | |
| 4 | Check logs | - | - | No errors | ☐ |
Trigger Source Definitions:
- OS: Operating system initiates the action (alarm fires, boot completes, etc.)
- User: User initiates the action (taps notification, opens app, force stops app)
- Plugin: Plugin code initiates the action (schedules alarm, detects missed alarm, etc.)
Code Reference: NotifyReceiver.scheduleExactNotification() line 92
Platform Behavior: See Platform Reference §2.1.1
Test 2: Swipe from Recents
Preconditions:
- App installed and launched at least once
- Alarm scheduling permission granted (if required)
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Schedule alarm 2-5 minutes in future | Plugin | - | Alarm scheduled | ☐ | ☐ | |
| 2 | Swipe app away from recents | User | - | - | ☐ | ☐ | |
| 3 | Wait for trigger time | OS | ✅ Alarm fires (OS resurrects process) - Doc A §2.1.1 | ✅ Notification displayed - Doc C §1.1 | ☐ | ☐ | |
| 4 | Check app state on wake | OS | Cold start | App process recreated | ☐ | ☐ | |
| 5 | Check logs | - | - | No errors | ☐ | ☐ |
Code Reference: NotifyReceiver.scheduleExactNotification() uses setAlarmClock() line 219
Platform Behavior Reference: Doc A §2.1.1 - OS-guaranteed
Test 3: OS Kill (Memory Pressure)
Preconditions:
- App installed and launched at least once
- Alarm scheduled and verified in AlarmManager
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Schedule alarm 2-5 minutes in future | Plugin | - | Alarm scheduled | ☐ | ☐ | |
| 2 | Force kill via adb shell am kill <package> |
User/OS | - | - | ☐ | ☐ | |
| 3 | Wait for trigger time | OS | ✅ Alarm fires - Doc A §2.1.1 | ✅ Notification displayed - Doc C §1.1 | ☐ | ☐ | |
| 4 | Check logs | - | - | No errors | ☐ | ☐ |
Platform Behavior Reference: Doc A §2.1.1 - OS-guaranteed
Test 4: Device Reboot
Preconditions:
- App installed and launched at least once
- Alarm scheduled and verified in database
- Boot receiver registered in manifest
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Schedule alarm 10 minutes in future | Plugin | - | Alarm scheduled | ☐ | ☐ | |
| 2 | Reboot device | User | - | - | ☐ | ☐ | |
| 3 | Do NOT open app | - | ❌ Alarm does NOT fire - Doc A §2.1.2 | ❌ No notification | ☐ | ☐ | |
| 4 | Wait past scheduled time | - | ❌ No automatic firing | ❌ No notification | ☐ | ☐ | |
| 5 | Open app manually | User | - | Plugin detects missed alarm - Doc C §4.2 | ☐ | ☐ | |
| 6 | Check missed alarm handling | Plugin | - | ✅ Missed alarm detected - Doc C §4.3 | ☐ | ☐ | |
| 7 | Check rescheduling | Plugin | - | ✅ Future alarms rescheduled - Doc C §3.1.1 | ☐ | ☐ |
Code Reference:
- Boot receiver:
BootReceiver.ktline 24 - Rescheduling:
BootReceiver.ktline 38+
Platform Behavior Reference: Doc A §2.1.2 - Plugin-required
Plugin Requirement Reference: Doc C §3.1.1 - Boot event recovery
Test 5: Android Force Stop
Preconditions:
- App installed and launched at least once
- Multiple alarms scheduled (past and future)
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Schedule alarms (past and future) | Plugin | - | Alarms scheduled | ☐ | ☐ | |
| 2 | Go to Settings → Apps → [App] → Force Stop | User | ❌ All alarms removed - Doc A §2.2.1 | ❌ All alarms removed | ☐ | ☐ | |
| 3 | Wait for trigger time | - | ❌ Alarm does NOT fire - Doc A §2.2.1 | ❌ No notification | ☐ | ☐ | |
| 4 | Open app again | User | - | Plugin detects force stop scenario - Doc C §3.1.4 | ☐ | ☐ | |
| 5 | Check recovery | Plugin | - | ✅ All past alarms marked as missed - Doc C §3.1.4 | ☐ | ☐ | |
| 6 | Check rescheduling | Plugin | - | ✅ All future alarms rescheduled - Doc C §3.1.4 | ☐ | ☐ |
Platform Behavior Reference: Doc A §2.2.1 - Forbidden
Plugin Requirement Reference: Doc C §3.1.4 - Force stop recovery
Test 6: Exact Alarm Permission (Android 12+)
Preconditions:
- Android 12+ (API 31+) device
- App installed and launched at least once
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Revoke exact alarm permission | User | - | - | ☐ | ☐ | |
| 2 | Attempt to schedule alarm | Plugin | - | Plugin requests permission - Doc C §8.1.1 | ☐ | ☐ | |
| 3 | Check settings opened | Plugin | - | ✅ Settings opened | ☐ | ☐ | |
| 4 | Grant permission | User | - | - | ☐ | ☐ | |
| 5 | Schedule alarm | Plugin | - | ✅ Alarm scheduled | ☐ | ☐ | |
| 6 | Verify alarm fires | OS | ✅ Alarm fires - Doc A §5.2 | ✅ Notification displayed | ☐ | ☐ |
Code Reference: DailyNotificationPlugin.kt line 1309, 1314-1324
Platform Behavior Reference: Doc A §5.2 - Conditional
Plugin Requirement Reference: Doc C §8.1.1 - Permission handling
1.3 Persistence Investigation
| Item | Expected | Actual | Code Reference | Notes |
|---|---|---|---|---|
| Alarm ID stored | ✅ Yes | ☐ | DailyNotificationPlugin.kt line 1393+ |
|
| Trigger time stored | ✅ Yes | ☐ | Room database | |
| Repeat rule stored | ✅ Yes | ☐ | Schedule entity | |
| Channel/priority stored | ✅ Yes | ☐ | NotificationContentEntity | |
| Payload stored | ✅ Yes | ☐ | ContentCache | |
| Time created/modified | ✅ Yes | ☐ | Entity timestamps |
Storage Location: Room database (DailyNotificationDatabase)
1.4 Recovery Points Investigation
| Recovery Point | Expected Behavior | Actual Behavior | Code Reference | Notes |
|---|---|---|---|---|
| Boot event | ✅ Reschedule all alarms | ☐ | BootReceiver.kt line 24 |
|
| App cold start | ✅ Detect missed alarms | ☐ | Check plugin initialization | |
| App warm start | ✅ Verify active alarms | ☐ | Check plugin initialization | |
| Background fetch return | ⚠️ May reschedule | ☐ | FetchWorker.kt |
|
| User taps notification | ✅ Launch app | ☐ | Notification intent |
2. Required Baseline Scenarios
All six baseline scenarios MUST be tested:
- ✅ Swipe-kill - Test 2 (Android), Test 2 (iOS)
- ✅ OS low-RAM kill - Test 3 (Android)
- ✅ Reboot - Test 4 (Android), Test 3 (iOS)
- ✅ Force stop - Test 5 (Android only)
- ✅ Cold start - Test 4 Step 5 (Android), Test 4 (iOS)
- ✅ Notification-tap resume - Recovery Points §1.4 (Both)
3. iOS Exploration
3.1 Code-Level Inspection Checklist
Source Locations:
- Plugin:
ios/Plugin/ - Test App:
test-apps/ios-test-app/ - Alternative: Check
ios-2branch
| Task | File/Function | Line | Status | Notes |
|---|---|---|---|---|
| Locate main plugin class | DailyNotificationPlugin.swift |
506 | ☐ | scheduleUserNotification() |
| Identify notification scheduling | DailyNotificationScheduler.swift |
133 | ☐ | scheduleNotification() |
| Check UNUserNotificationCenter usage | DailyNotificationScheduler.swift |
185 | ☐ | notificationCenter.add() |
| Check trigger types | DailyNotificationScheduler.swift |
172 | ☐ | UNCalendarNotificationTrigger |
| Check BGTaskScheduler usage | DailyNotificationPlugin.swift |
495 | ☐ | scheduleBackgroundFetch() |
| Check persistence | DailyNotificationPlugin.swift |
35 | ☐ | storage: DailyNotificationStorage? |
| Check app launch recovery | DailyNotificationPlugin.swift |
42 | ☐ | load() method |
3.2 Behavior Testing Matrix
Test 1: Base Case
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|---|---|---|---|---|---|
| 1 | Schedule notification 2-5 minutes in future | - | Notification scheduled | ☐ | |
| 2 | Leave app backgrounded | - | - | ☐ | |
| 3 | Wait for trigger time | ✅ Notification fires | ✅ Notification displayed | ☐ | |
| 4 | Check logs | - | No errors | ☐ |
Code Reference: DailyNotificationScheduler.scheduleNotification() line 133
Platform Behavior: See Platform Reference §3.1.1
Test 2: Swipe App Away
Preconditions:
- App installed and launched at least once
- Notification scheduled and verified
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Schedule notification 2-5 minutes in future | Plugin | - | Notification scheduled | ☐ | ☐ | |
| 2 | Swipe app away from app switcher | User | - | - | ☐ | ☐ | |
| 3 | Wait for trigger time | OS | ✅ Notification fires (OS handles) - Doc A §3.1.1 | ✅ Notification displayed - Doc C §1.1 | ☐ | ☐ | |
| 4 | Check app state | OS | App terminated | App not running | ☐ | ☐ |
Platform Behavior Reference: Doc A §3.1.1 - OS-guaranteed
Test 3: Device Reboot
Preconditions:
- App installed and launched at least once
- Notification scheduled with calendar/time trigger
- Test device: [Device model, OS version]
- App build: [Git commit hash or build number]
| Step | Action | Trigger Source | Expected (OS) [Doc A] | Expected (Plugin) [Doc C] | Actual Result | Notes | Result |
|---|---|---|---|---|---|---|---|
| 1 | Schedule notification for future time | Plugin | - | Notification scheduled | ☐ | ☐ | |
| 2 | Reboot device | User | - | - | ☐ | ☐ | |
| 3 | Do NOT open app | OS | ✅ Notification fires (OS persists) - Doc A §3.1.2 | ✅ Notification displayed - Doc C §1.1 | ☐ | ☐ | |
| 4 | Check notification timing | OS | ✅ On time (±180s tolerance) - Doc A §6.1 | ✅ On time | ☐ | ☐ |
Platform Behavior Reference: Doc A §3.1.2 - OS-guaranteed
Note: Only calendar and time-based triggers persist. Location triggers do not - See Doc A §3.1.2
Test 4: Hard Termination & Relaunch
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|---|---|---|---|---|---|
| 1 | Schedule repeating notifications | - | Notifications scheduled | ☐ | |
| 2 | Terminate app via Xcode/switcher | - | - | ☐ | |
| 3 | Allow some triggers to occur | ✅ Notifications fire | ✅ Notifications displayed | ☐ | |
| 4 | Reopen app | - | Plugin checks for missed events | ☐ | |
| 5 | Check missed event detection | ⚠️ May detect | ☐ | Plugin-specific | |
| 6 | Check state recovery | ⚠️ May recover | ☐ | Plugin-specific |
Platform Behavior: OS-guaranteed for notifications; Plugin-guaranteed for missed event detection
Test 5: Background Execution Limits
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|---|---|---|---|---|---|
| 1 | Schedule BGTaskScheduler task | - | Task scheduled | ☐ | |
| 2 | Wait for system to execute | ⚠️ System-controlled | ⚠️ May not execute | ☐ | |
| 3 | Check execution timing | ⚠️ Not guaranteed | ⚠️ Not guaranteed | ☐ | |
| 4 | Check time budget | ⚠️ ~30 seconds | ⚠️ Limited time | ☐ |
Code Reference: DailyNotificationPlugin.scheduleBackgroundFetch() line 495
Platform Behavior: Conditional (see Platform Reference §3.1.3)
3.3 Persistence Investigation
| Item | Expected | Actual | Code Reference | Notes |
|---|---|---|---|---|
| Notification ID stored | ✅ Yes (in UNUserNotificationCenter) | ☐ | UNNotificationRequest |
|
| Plugin-side storage | ⚠️ May not exist | ☐ | DailyNotificationStorage? |
|
| Trigger time stored | ✅ Yes (in trigger) | ☐ | UNCalendarNotificationTrigger |
|
| Repeat rule stored | ✅ Yes (in trigger) | ☐ | repeats: true/false |
|
| Payload stored | ✅ Yes (in userInfo) | ☐ | notificationContent.userInfo |
Storage Location:
- Primary: UNUserNotificationCenter (OS-managed)
- Secondary: Plugin storage (if implemented)
3.4 Recovery Points Investigation
| Recovery Point | Expected Behavior | Actual Behavior | Code Reference | Notes |
|---|---|---|---|---|
| Boot event | ✅ Notifications fire automatically | ☐ | OS handles | |
| App cold start | ⚠️ May detect missed notifications | ☐ | Check load() method |
|
| App warm start | ⚠️ May verify pending notifications | ☐ | Check plugin initialization | |
| Background fetch | ⚠️ May reschedule | ☐ | BGTaskScheduler |
|
| User taps notification | ✅ App launched | ☐ | Notification action |
4. Cross-Platform Comparison
3.1 Observed Behavior Summary
| Scenario | Android (Observed) | iOS (Observed) | Platform Difference |
|---|---|---|---|
| Swipe/termination | ☐ | ☐ | Both should work |
| Reboot | ☐ | ☐ | iOS auto, Android manual |
| Force stop | ☐ | N/A | Android only |
| App code on trigger | ☐ | ☐ | Android yes, iOS no |
| Background execution | ☐ | ☐ | Android more flexible |
5. Findings & Gaps
4.1 Android Gaps
| Gap | Severity | Description | Recommendation |
|---|---|---|---|
| Boot recovery | ☐ Critical/Major/Minor/Expected | Does plugin reschedule on boot? | Implement if missing |
| Missed alarm detection | ☐ Critical/Major/Minor/Expected | Does plugin detect missed alarms? | Implement if missing |
| Force stop recovery | ☐ Critical/Major/Minor/Expected | Does plugin recover after force stop? | Implement if missing |
| Persistence completeness | ☐ Critical/Major/Minor/Expected | Are all required fields persisted? | Verify and add if missing |
Severity Classification:
- Critical: Breaks plugin guarantee (see Doc C §1.1)
- Major: Unexpected but recoverable (plugin works but behavior differs from expected)
- Minor: Non-blocking deviation (cosmetic or edge case)
- Expected: Platform limitation (documented in Doc A)
4.2 iOS Gaps
| Gap | Severity | Description | Recommendation |
|---|---|---|---|
| Missed notification detection | ☐ Critical/Major/Minor/Expected | Does plugin detect missed notifications? | Implement if missing |
| Plugin-side persistence | ☐ Critical/Major/Minor/Expected | Does plugin persist state separately? | Consider if needed |
| Background task reliability | ☐ Critical/Major/Minor/Expected | Can plugin rely on BGTaskScheduler? | Document limitations |
Severity Classification: Same as Android (see above).
6. Deliverables from This Exploration
After completing this exploration, generate:
- Completed test results - All checkboxes filled, actual results documented
- Gap analysis - Documented limitations and gaps
- Annotated code pointers - Code locations with findings
- Open Questions / TODOs - Unresolved issues
Related Documentation
- Platform Capability Reference - OS-level facts
- Plugin Requirements - Requirements based on findings
- Unified Alarm Directive - Master coordination document
Notes for Explorers
- Fill in checkboxes (☐) as you complete each test
- Document actual results in "Actual Result" columns
- Add notes for any unexpected behavior
- Reference code locations when documenting findings
- Update "Findings & Gaps" section as you discover issues
- Use platform capability reference to understand expected OS behavior
- Link to Platform Reference sections instead of duplicating platform facts