Files
daily-notification-plugin/docs/testing/IOS_PHASE1_TESTING_GUIDE.md
Matthew Raymer c39bd7cec6 docs: Consolidate documentation structure (139 files, zero information loss)
Consolidate all markdown documentation into organized structure per
CONSOLIDATION_DIRECTIVE. All files preserved (canonical, merged, or archived).

- docs/integration/ - Integration documentation (7 files)
- docs/platform/ios/ - iOS platform docs (12 files)
- docs/platform/android/ - Android platform docs (9 files)
- docs/testing/ - Testing documentation (15 files)
- docs/design/ - Design & research (5 files)
- docs/ai/ - AI/ChatGPT artifacts (7 files)
- docs/archive/2025-legacy-doc/ - Historical docs (17 files)

- Integration: Root INTEGRATION_GUIDE.md → docs/integration/
- Platform: Separated iOS and Android into platform/ subdirectories
- Testing: Consolidated all testing docs to docs/testing/
- Legacy: Archived entire doc/ directory to archive/
- AI: Moved all ChatGPT artifacts to docs/ai/

- Added docs/00-INDEX.md - Central navigation hub
- Added docs/CONSOLIDATION_SOURCE_MAP.md - Complete audit trail
- Added docs/CONSOLIDATION_COMPLETE.md - Consolidation summary
- Updated README.md with links to documentation index

- All 139 files have destinations (see CONSOLIDATION_SOURCE_MAP.md)
- Zero information loss (all files preserved)
- Archive preserves original structure
- Index provides clear navigation

- 87 files moved/created/updated
- Root-level docs consolidated
- Legacy doc/ directory archived
- Test app docs remain with test apps (indexed)

Ref: CONSOLIDATION_DIRECTIVE
Author: Matthew Raymer
2025-12-18 09:13:18 +00:00

14 KiB

iOS Phase 1 Testing Guide

Status: READY FOR TESTING
Phase: Phase 1 - Core Infrastructure Parity
Target: iOS Simulator (primary) or Physical Device


Quick Start Testing

Prerequisites

  • Xcode Version: 15.0 or later
  • macOS Version: 13.0 (Ventura) or later
  • iOS Deployment Target: iOS 15.0 or later
  • Test App: test-apps/ios-test-app/ (to be created)

Testing Environment Setup

  1. Build Test App:

    # From repo root
    ./scripts/build-ios-test-app.sh --simulator
    

    Note: If build script doesn't exist yet, see "Manual Build Steps" below.

  2. Open in Xcode:

    cd test-apps/ios-test-app
    open App.xcworkspace  # or App.xcodeproj
    
  3. Run on Simulator:

    • Select target device (iPhone 15, iPhone 15 Pro, etc.)
    • Press Cmd+R to build and run
    • Or use Xcode menu: Product → Run

Phase 1 Test Cases

Test Case 1: Plugin Initialization

Objective: Verify plugin loads and initializes correctly

Steps:

  1. Launch test app on iOS Simulator
  2. Check Console.app logs for: DNP-PLUGIN: Daily Notification Plugin loaded on iOS
  3. Verify no initialization errors

Expected Results:

  • Plugin loads without errors
  • Storage and scheduler components initialized
  • State actor created (iOS 13+)

Logs to Check:

DNP-PLUGIN: Daily Notification Plugin loaded on iOS
DailyNotificationStorage: Database opened successfully at [path]
DailyNotificationScheduler: Notification category setup complete

Test Case 2: Configure Method

Objective: Test plugin configuration

JavaScript Test Code:

import { DailyNotification } from '@capacitor-community/daily-notification';

// Test configure
await DailyNotification.configure({
  options: {
    storage: 'tiered',
    ttlSeconds: 3600,
    prefetchLeadMinutes: 5,
    maxNotificationsPerDay: 1,
    retentionDays: 7
  }
});

Steps:

  1. Call configure() with options
  2. Check Console.app for: DNP-PLUGIN: Plugin configuration completed successfully
  3. Verify settings stored in UserDefaults

Expected Results:

  • Configuration succeeds without errors
  • Settings stored correctly
  • Database path set correctly

Verification:

// In Xcode debugger or Console.app
po UserDefaults.standard.dictionary(forKey: "DailyNotificationPrefs")

Test Case 3: Schedule Daily Notification

Objective: Test main scheduling method with prefetch

JavaScript Test Code:

// Schedule notification for 5 minutes from now
const now = new Date();
const scheduleTime = new Date(now.getTime() + 5 * 60 * 1000);
const hour = scheduleTime.getHours();
const minute = scheduleTime.getMinutes();
const timeString = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;

await DailyNotification.scheduleDailyNotification({
  options: {
    time: timeString,
    title: "Test Notification",
    body: "This is a Phase 1 test notification",
    sound: true,
    url: null
  }
});

Steps:

  1. Schedule notification 5 minutes from now
  2. Verify prefetch scheduled 5 minutes before notification time
  3. Check Console.app logs
  4. Wait for notification to appear

Expected Results:

  • Notification scheduled successfully
  • Prefetch BGTask scheduled 5 minutes before notification
  • Notification appears at scheduled time (±180s tolerance)

Logs to Check:

DNP-PLUGIN: Scheduling daily notification
DNP-PLUGIN: Daily notification scheduled successfully
DNP-FETCH-SCHEDULE: Background fetch scheduled for [date]
DailyNotificationScheduler: Notification scheduled successfully for [date]

Verification Commands:

# Check pending notifications (in Xcode debugger)
po UNUserNotificationCenter.current().pendingNotificationRequests()

# Check BGTask scheduling (simulator only)
# Use LLDB command in Xcode debugger:
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.timesafari.dailynotification.fetch"]

Test Case 4: Get Last Notification

Objective: Test last notification retrieval

JavaScript Test Code:

const lastNotification = await DailyNotification.getLastNotification();
console.log('Last notification:', lastNotification);

Steps:

  1. Schedule a notification
  2. Wait for it to fire (or manually trigger)
  3. Call getLastNotification()
  4. Verify returned data structure

Expected Results:

  • Returns notification object with: id, title, body, timestamp, url
  • Returns empty object {} if no notifications exist
  • Thread-safe retrieval via state actor

Expected Response:

{
  "id": "daily_1234567890",
  "title": "Test Notification",
  "body": "This is a Phase 1 test notification",
  "timestamp": 1234567890000,
  "url": null
}

Test Case 5: Cancel All Notifications

Objective: Test cancellation of all scheduled notifications

JavaScript Test Code:

// Schedule multiple notifications first
await DailyNotification.scheduleDailyNotification({...});
await DailyNotification.scheduleDailyNotification({...});

// Then cancel all
await DailyNotification.cancelAllNotifications();

Steps:

  1. Schedule 2-3 notifications
  2. Verify they're scheduled: getNotificationStatus()
  3. Call cancelAllNotifications()
  4. Verify all cancelled

Expected Results:

  • All notifications cancelled
  • Storage cleared
  • Pending count = 0

Logs to Check:

DNP-PLUGIN: All notifications cancelled successfully
DailyNotificationScheduler: All notifications cancelled
DailyNotificationStorage: All notifications cleared

Test Case 6: Get Notification Status

Objective: Test status retrieval

JavaScript Test Code:

const status = await DailyNotification.getNotificationStatus();
console.log('Status:', status);

Steps:

  1. Call getNotificationStatus()
  2. Verify response structure
  3. Check permission status
  4. Check pending count

Expected Results:

  • Returns complete status object
  • Permission status accurate
  • Pending count accurate
  • Next notification time calculated

Expected Response:

{
  "isEnabled": true,
  "isScheduled": true,
  "lastNotificationTime": 1234567890000,
  "nextNotificationTime": 1234567895000,
  "pending": 1,
  "settings": {
    "storageMode": "tiered",
    "ttlSeconds": 3600
  }
}

Test Case 7: Update Settings

Objective: Test settings update

JavaScript Test Code:

await DailyNotification.updateSettings({
  settings: {
    sound: false,
    priority: "high",
    timezone: "America/New_York"
  }
});

Steps:

  1. Call updateSettings() with new settings
  2. Verify settings stored
  3. Retrieve settings and verify changes

Expected Results:

  • Settings updated successfully
  • Changes persisted
  • Thread-safe update via state actor

Test Case 8: BGTask Miss Detection

Objective: Test BGTask miss detection and rescheduling

Steps:

  1. Schedule a notification with prefetch
  2. Note the BGTask earliestBeginDate from logs
  3. Simulate missing the BGTask window:
    • Wait 15+ minutes after earliestBeginDate
    • Ensure no successful run recorded
  4. Launch app (triggers checkForMissedBGTask())
  5. Verify BGTask rescheduled

Expected Results:

  • Miss detection triggers on app launch
  • BGTask rescheduled for 1 minute from now
  • Logs show: DNP-FETCH: BGTask missed window; rescheduling

Logs to Check:

DNP-FETCH: BGTask missed window; rescheduling
DNP-FETCH: BGTask rescheduled for [date]

Manual Trigger (Simulator Only):

# In Xcode debugger (LLDB)
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.timesafari.dailynotification.fetch"]

Test Case 9: Permission Auto-Healing

Objective: Test automatic permission request

Steps:

  1. Reset notification permissions (Settings → [App] → Notifications → Off)
  2. Call scheduleDailyNotification()
  3. Verify permission request dialog appears
  4. Grant permissions
  5. Verify scheduling succeeds

Expected Results:

  • Permission request dialog appears automatically
  • Scheduling succeeds after granting
  • Error returned if permissions denied

Logs to Check:

DailyNotificationScheduler: Permission request result: true
DailyNotificationScheduler: Scheduling notification: [id]

Test Case 10: Error Handling

Objective: Test error code responses

Test Scenarios:

  1. Missing Parameters:

    await DailyNotification.scheduleDailyNotification({
      options: {} // Missing 'time' parameter
    });
    

    Expected Error:

    {
      "error": "missing_required_parameter",
      "message": "Missing required parameter: time"
    }
    
  2. Invalid Time Format:

    await DailyNotification.scheduleDailyNotification({
      options: { time: "invalid" }
    });
    

    Expected Error:

    {
      "error": "invalid_time_format",
      "message": "Invalid time format. Use HH:mm"
    }
    
  3. Notifications Denied:

    • Deny notification permissions
    • Try to schedule notification
    • Verify error code returned

Expected Error:

{
  "error": "notifications_denied",
  "message": "Notification permissions denied"
}

Manual Build Steps (If Build Script Not Available)

Step 1: Install Dependencies

cd ios
pod install

Step 2: Open in Xcode

open DailyNotificationPlugin.xcworkspace
# or
open DailyNotificationPlugin.xcodeproj

Step 3: Configure Build Settings

  1. Select project in Xcode
  2. Go to Signing & Capabilities
  3. Add Background Modes:
    • Background fetch
    • Background processing
  4. Add to Info.plist:
    <key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
      <string>com.timesafari.dailynotification.fetch</string>
      <string>com.timesafari.dailynotification.notify</string>
    </array>
    

Step 4: Build and Run

  • Select target device (Simulator or Physical Device)
  • Press Cmd+R or Product → Run

Debugging Tools

Console.app Logging

View Logs:

  1. Open Console.app (Applications → Utilities)
  2. Select your device/simulator
  3. Filter by: DNP- or DailyNotification

Key Log Prefixes:

  • DNP-PLUGIN: - Main plugin operations
  • DNP-FETCH: - Background fetch operations
  • DNP-FETCH-SCHEDULE: - BGTask scheduling
  • DailyNotificationStorage: - Storage operations
  • DailyNotificationScheduler: - Scheduling operations

Xcode Debugger Commands

Check Pending Notifications:

po UNUserNotificationCenter.current().pendingNotificationRequests()

Check Permission Status:

po await UNUserNotificationCenter.current().notificationSettings()

Check BGTask Status (Simulator Only):

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.timesafari.dailynotification.fetch"]

Check Storage:

po UserDefaults.standard.dictionary(forKey: "DailyNotificationPrefs")

Common Issues & Solutions

Issue 1: BGTaskScheduler Not Running

Symptoms:

  • BGTask never executes
  • No logs from handleBackgroundFetch()

Solutions:

  1. Verify Info.plist has BGTaskSchedulerPermittedIdentifiers
  2. Check task registered in setupBackgroundTasks()
  3. Simulator workaround: Use LLDB command to manually trigger (see above)

Issue 2: Notifications Not Delivering

Symptoms:

  • Notification scheduled but never appears
  • No notification in notification center

Solutions:

  1. Check permissions: UNUserNotificationCenter.current().getNotificationSettings()
  2. Verify notification scheduled: getPendingNotificationRequests()
  3. Check notification category registered
  4. Verify time hasn't passed (iOS may deliver immediately if time passed)

Issue 3: Build Failures

Symptoms:

  • Xcode build errors
  • Missing dependencies

Solutions:

  1. Run pod install in ios/ directory
  2. Clean build folder: Product → Clean Build Folder (Cmd+Shift+K)
  3. Verify Capacitor plugin path in capacitor.plugins.json
  4. Check Xcode scheme matches workspace

Issue 4: Background Tasks Expiring

Symptoms:

  • BGTask starts but expires before completion
  • Logs show: Background fetch task expired

Solutions:

  1. Ensure task.setTaskCompleted(success:) called before expiration
  2. Keep processing efficient (< 30 seconds)
  3. Schedule next task immediately after completion

Testing Checklist

Phase 1 Core Methods

  • configure() - Configuration succeeds
  • scheduleDailyNotification() - Notification schedules correctly
  • getLastNotification() - Returns correct notification
  • cancelAllNotifications() - All notifications cancelled
  • getNotificationStatus() - Status accurate
  • updateSettings() - Settings updated correctly

Background Tasks

  • BGTask scheduled 5 minutes before notification
  • BGTask executes successfully
  • BGTask miss detection works
  • BGTask rescheduling works

Error Handling

  • Missing parameter errors returned
  • Invalid time format errors returned
  • Permission denied errors returned
  • Error codes match Android format

Thread Safety

  • No race conditions observed
  • State actor used for all storage operations
  • Background tasks use state actor

Next Steps After Testing

  1. Document Issues: Create GitHub issues for any bugs found
  2. Update Test Cases: Add test cases for edge cases discovered
  3. Performance Testing: Test with multiple notifications
  4. Phase 2 Preparation: Begin Phase 2 advanced features

References

  • Directive: doc/directives/0003-iOS-Android-Parity-Directive.md
  • Phase 1 Summary: doc/PHASE1_COMPLETION_SUMMARY.md
  • Android Testing: docs/notification-testing-procedures.md
  • Comprehensive Testing: docs/comprehensive-testing-guide-v2.md

Status: READY FOR TESTING
Last Updated: 2025-01-XX