From 48617fddf4493bf7438083946edd493961dd57d8 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Sat, 4 Oct 2025 05:44:26 +0000 Subject: [PATCH] feat(test-apps): update iOS test app with Phase 4 TimeSafari components - Added Phase 4 imports: EndorserAPIClient, SecurityManager, TimeSafariNotificationManager - Updated TimeSafariIOSTestApp class with Phase 4 component integration - Added comprehensive Phase 4 test methods: - testSecurityManager(): JWT generation/verification testing - testEndorserAPIClient(): Endorser.ch API integration testing - testTimeSafariNotificationManager(): Notification generation testing - testPhase4Integration(): Complete workflow testing - Added Phase 4 initialization in constructor and setupEventListeners - Updated HTML with Phase 4 test buttons and UI sections - Enhanced iOS-specific testing with Phase 4 components - Added TimeSafari user configuration and preferences support iOS test app now fully supports Phase 4 TimeSafari integration testing --- test-apps/ios-test/src/index.html | 11 ++ test-apps/ios-test/src/index.ts | 269 +++++++++++++++++++++++++++++- 2 files changed, 278 insertions(+), 2 deletions(-) diff --git a/test-apps/ios-test/src/index.html b/test-apps/ios-test/src/index.html index 89585e2..e1dad73 100644 --- a/test-apps/ios-test/src/index.html +++ b/test-apps/ios-test/src/index.html @@ -392,6 +392,17 @@ + +
+

🚀 Phase 4: TimeSafari Components

+
+ + + + +
+
+

⚠️ Error Handling

diff --git a/test-apps/ios-test/src/index.ts b/test-apps/ios-test/src/index.ts index f1beac3..93cfcb0 100644 --- a/test-apps/ios-test/src/index.ts +++ b/test-apps/ios-test/src/index.ts @@ -1,6 +1,17 @@ import { Capacitor } from '@capacitor/core'; import { ConfigLoader, MockDailyNotificationService, TestLogger } from '../shared/config-loader'; +// Phase 4: Import TimeSafari components +import { EndorserAPIClient, TIMESAFARI_ENDSORER_CONFIG } from '../../../src/typescript/EndorserAPIClient'; +import { SecurityManager, TIMESAFARI_SECURITY_CONFIG } from '../../../src/typescript/SecurityManager'; +import { TimeSafariNotificationManager, DEFAULT_TIMESAFARI_PREFERENCES } from '../../../src/typescript/TimeSafariNotificationManager'; +import { + TimeSafariUser, + TimeSafariPreferences, + EnhancedTimeSafariNotification, + TimeSafariNotificationType +} from '../../../src/definitions'; + // Enhanced UI components for iOS testing class PermissionManager { private container: HTMLElement; @@ -236,7 +247,7 @@ class ErrorDisplay { } } -// Enhanced test interface for TimeSafari iOS integration +// Enhanced test interface for TimeSafari iOS integration with Phase 4 components class TimeSafariIOSTestApp { private statusElement: HTMLElement; private logElement: HTMLElement; @@ -244,6 +255,11 @@ class TimeSafariIOSTestApp { private notificationService: MockDailyNotificationService; private logger: TestLogger; + // Phase 4: TimeSafari components + private endorserAPIClient: EndorserAPIClient; + private securityManager: SecurityManager; + private timeSafariNotificationManager: TimeSafariNotificationManager; + // UI Components private permissionManager: PermissionManager; private settingsPanel: SettingsPanel; @@ -257,6 +273,11 @@ class TimeSafariIOSTestApp { this.logger = new TestLogger('debug'); this.notificationService = new MockDailyNotificationService(this.configLoader.getConfig()); + // Phase 4: Initialize TimeSafari components + this.endorserAPIClient = new EndorserAPIClient(this.configLoader.getEndorserAPIConfig()); + this.securityManager = new SecurityManager(this.configLoader.getSecurityConfig()); + this.timeSafariNotificationManager = new TimeSafariNotificationManager(); + // Initialize UI components this.permissionManager = new PermissionManager( document.getElementById('permission-status-container')!, @@ -268,7 +289,8 @@ class TimeSafariIOSTestApp { this.setupEventListeners(); this.initializeUI(); - this.log('TimeSafari iOS Test app initialized with enhanced UI'); + this.initializePhase4Components(); + this.log('TimeSafari iOS Test app initialized with Phase 4 components'); } private setupEventListeners() { @@ -290,6 +312,12 @@ class TimeSafariIOSTestApp { document.getElementById('refresh-status')?.addEventListener('click', () => this.refreshStatus()); document.getElementById('background-refresh-status')?.addEventListener('click', () => this.checkBackgroundRefresh()); document.getElementById('bg-task-status')?.addEventListener('click', () => this.checkBGTaskStatus()); + + // Phase 4: TimeSafari component testing + document.getElementById('test-security-manager')?.addEventListener('click', () => this.testSecurityManager()); + document.getElementById('test-endorser-api-client')?.addEventListener('click', () => this.testEndorserAPIClient()); + document.getElementById('test-notification-manager')?.addEventListener('click', () => this.testTimeSafariNotificationManager()); + document.getElementById('test-phase4-integration')?.addEventListener('click', () => this.testPhase4Integration()); } private async initializeUI(): Promise { @@ -306,6 +334,49 @@ class TimeSafariIOSTestApp { } } + // Phase 4: Initialize TimeSafari components + private async initializePhase4Components(): Promise { + try { + this.log('Initializing Phase 4 TimeSafari components...'); + + // Initialize SecurityManager with test DID + const timeSafariUser = this.configLoader.getTimeSafariUser(); + const securityInitialized = await this.securityManager.initialize(timeSafariUser.activeDid); + + if (securityInitialized) { + this.log('✅ SecurityManager initialized successfully'); + + // Generate JWT token for API authentication + const jwt = await this.securityManager.generateJWT({ + scope: 'notifications', + audience: 'endorser-api' + }); + + if (jwt) { + this.endorserAPIClient.setAuthToken(jwt); + this.log('✅ JWT token generated and set for EndorserAPI'); + } + } else { + this.log('❌ SecurityManager initialization failed'); + } + + // Initialize TimeSafariNotificationManager + const managerInitialized = await this.timeSafariNotificationManager.initialize(timeSafariUser); + + if (managerInitialized) { + this.log('✅ TimeSafariNotificationManager initialized successfully'); + } else { + this.log('❌ TimeSafariNotificationManager initialization failed'); + } + + this.log('Phase 4 components initialization completed'); + + } catch (error) { + this.log('Error initializing Phase 4 components:', error); + this.errorDisplay.showError(error as Error); + } + } + // Enhanced UI methods private async checkPermissions(): Promise { try { @@ -695,6 +766,200 @@ class TimeSafariIOSTestApp { private updateStatus(status: string) { this.statusElement.textContent = status; } + + // Phase 4: TimeSafari component test methods + private async testSecurityManager(): Promise { + try { + this.log('🔐 Testing SecurityManager (iOS)...'); + + const timeSafariUser = this.configLoader.getTimeSafariUser(); + + // Test JWT generation + const jwt = await this.securityManager.generateJWT({ + scope: 'test', + audience: 'test-api' + }); + + if (jwt) { + this.log('✅ JWT generation successful'); + this.log('JWT token:', jwt.substring(0, 50) + '...'); + + // Test JWT verification + const claims = await this.securityManager.verifyJWT(jwt); + if (claims) { + this.log('✅ JWT verification successful'); + this.log('Claims:', claims); + } else { + this.log('❌ JWT verification failed'); + } + } else { + this.log('❌ JWT generation failed'); + } + + // Test operation history + const history = this.securityManager.getOperationHistory(); + this.log(`Security operations performed: ${history.length}`); + + this.log('SecurityManager test completed'); + + } catch (error) { + this.log('SecurityManager test failed:', error); + this.errorDisplay.showError(error as Error); + } + } + + private async testEndorserAPIClient(): Promise { + try { + this.log('🌐 Testing EndorserAPIClient (iOS)...'); + + const timeSafariUser = this.configLoader.getTimeSafariUser(); + + // Test offers to person + this.log('Testing offers to person...'); + const offersResponse = await this.endorserAPIClient.fetchOffersToPerson( + timeSafariUser.activeDid, + timeSafariUser.lastKnownOfferId, + undefined + ); + + this.log(`✅ Offers fetched: ${offersResponse.data.length} offers`); + if (offersResponse.data.length > 0) { + this.log('Sample offer:', offersResponse.data[0]); + } + + // Test offers to projects + this.log('Testing offers to projects...'); + const projectsResponse = await this.endorserAPIClient.fetchOffersToProjectsOwnedByMe( + timeSafariUser.lastKnownOfferId + ); + + this.log(`✅ Project offers fetched: ${projectsResponse.data.length} offers`); + + // Test project updates + if (timeSafariUser.starredPlanIds && timeSafariUser.starredPlanIds.length > 0) { + this.log('Testing project updates...'); + const updatesResponse = await this.endorserAPIClient.fetchProjectsLastUpdated( + timeSafariUser.starredPlanIds, + timeSafariUser.lastKnownPlanId, + undefined + ); + + this.log(`✅ Project updates fetched: ${updatesResponse.data.length} updates`); + } + + this.log('EndorserAPIClient test completed'); + + } catch (error) { + this.log('EndorserAPIClient test failed:', error); + this.errorDisplay.showError(error as Error); + } + } + + private async testTimeSafariNotificationManager(): Promise { + try { + this.log('📱 Testing TimeSafariNotificationManager (iOS)...'); + + // Test notification generation + this.log('Generating TimeSafari notifications...'); + const notifications = await this.timeSafariNotificationManager.generateNotifications({ + forceFetch: false, + includeMetadata: true, + filterByPriority: true, + maxNotifications: 10, + cacheTtl: 300000 + }); + + this.log(`✅ Generated ${notifications.length} notifications`); + + // Display notification details + notifications.forEach((notification, index) => { + this.log(`Notification ${index + 1}:`, { + type: notification.type, + subtype: notification.subtype, + priority: notification.notificationPriority, + timestamp: new Date(notification.timestamp).toISOString(), + disabled: notification.disabled, + sound: notification.sound, + vibration: notification.vibration + }); + }); + + // Test statistics + const stats = this.timeSafariNotificationManager.getStatistics(); + this.log('Manager statistics:', stats); + + this.log('TimeSafariNotificationManager test completed'); + + } catch (error) { + this.log('TimeSafariNotificationManager test failed:', error); + this.errorDisplay.showError(error as Error); + } + } + + private async testPhase4Integration(): Promise { + try { + this.log('🚀 Testing complete Phase 4 integration (iOS)...'); + + const timeSafariUser = this.configLoader.getTimeSafariUser(); + + // Test complete workflow + this.log('Step 1: Security authentication...'); + const jwt = await this.securityManager.generateJWT({ + scope: 'notifications', + audience: 'endorser-api' + }); + + if (!jwt) { + throw new Error('JWT generation failed'); + } + + this.endorserAPIClient.setAuthToken(jwt); + this.log('✅ Authentication successful'); + + this.log('Step 2: Fetching TimeSafari data...'); + const bundle = await this.endorserAPIClient.fetchAllTimeSafariNotifications({ + activeDid: timeSafariUser.activeDid, + starredPlanIds: timeSafariUser.starredPlanIds || [], + lastKnownOfferId: timeSafariUser.lastKnownOfferId, + lastKnownPlanId: timeSafariUser.lastKnownPlanId, + fetchOffersToPerson: true, + fetchOffersToProjects: true, + fetchProjectUpdates: true, + notificationPreferences: { + offers: true, + projects: true, + people: false, + items: true + } + }); + + this.log(`✅ Data fetched successfully: ${bundle.success}`); + this.log('Bundle metadata:', bundle.metadata); + + this.log('Step 3: Generating notifications...'); + const notifications = await this.timeSafariNotificationManager.generateNotifications({ + forceFetch: true, + includeMetadata: true, + maxNotifications: 20 + }); + + this.log(`✅ Generated ${notifications.length} notifications`); + + // Summary + this.log('🎉 Phase 4 integration test completed successfully!'); + this.log('Summary:', { + securityInitialized: this.securityManager.isInitialized(), + apiClientReady: !!this.endorserAPIClient, + managerInitialized: this.timeSafariNotificationManager.isInitialized(), + notificationsGenerated: notifications.length, + bundleSuccess: bundle.success + }); + + } catch (error) { + this.log('Phase 4 integration test failed:', error); + this.errorDisplay.showError(error as Error); + } + } } // Initialize app when DOM is ready