|
|
@ -1,6 +1,18 @@ |
|
|
|
import { Capacitor } from '@capacitor/core'; |
|
|
|
|
|
|
|
// Mock classes for testing when shared utilities aren't available
|
|
|
|
import { DailyNotificationPlugin } from '@timesafari/daily-notification-plugin'; |
|
|
|
|
|
|
|
// 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 ConfigLoader for Phase 4
|
|
|
|
class ConfigLoader { |
|
|
|
private static instance: ConfigLoader; |
|
|
|
private config: any; |
|
|
@ -25,13 +37,28 @@ class ConfigLoader { |
|
|
|
}, |
|
|
|
endorser: { |
|
|
|
baseUrl: 'http://10.0.2.2:3001/api/v2/report', |
|
|
|
apiKey: 'test-api-key' |
|
|
|
apiKey: 'test-api-key', |
|
|
|
// Phase 4: Enhanced EndorserAPI configuration
|
|
|
|
timeoutMs: 15000, |
|
|
|
maxRetries: 3, |
|
|
|
enableParallel: true, |
|
|
|
maxConcurrent: 3 |
|
|
|
}, |
|
|
|
security: { |
|
|
|
// Phase 4: Security configuration
|
|
|
|
enableCryptoSigning: true, |
|
|
|
enableJWTGeneration: true, |
|
|
|
jwtExpirationMinutes: 60, |
|
|
|
signatureAlgorithm: 'ES256K', |
|
|
|
credentialStorage: 'secure_element' |
|
|
|
}, |
|
|
|
testData: { |
|
|
|
userDid: 'user:test', |
|
|
|
userDid: 'did:example:android-test-user', |
|
|
|
lastKnownOfferId: '0', |
|
|
|
lastKnownPlanId: '0', |
|
|
|
starredPlanIds: ['plan:test'] |
|
|
|
starredPlanIds: ['plan:test-1', 'plan:test-2'], |
|
|
|
favoritePersonIds: ['person:test-1'], |
|
|
|
favoriteItemIds: ['item:test-1'] |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
@ -50,6 +77,39 @@ class ConfigLoader { |
|
|
|
return `${this.config.endorser.baseUrl}${endpoints[endpoint] || endpoint}`; |
|
|
|
} |
|
|
|
|
|
|
|
// Phase 4: Enhanced configuration methods
|
|
|
|
getEndorserAPIConfig() { |
|
|
|
return { |
|
|
|
baseUrl: this.config.endorser.baseUrl.replace('/api/v2/report', ''), |
|
|
|
timeoutMs: this.config.endorser.timeoutMs, |
|
|
|
maxRetries: this.config.endorser.maxRetries, |
|
|
|
enableParallel: this.config.endorser.enableParallel, |
|
|
|
maxConcurrent: this.config.endorser.maxConcurrent |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
getSecurityConfig() { |
|
|
|
return { |
|
|
|
enableCryptoSigning: this.config.security.enableCryptoSigning, |
|
|
|
enableJWTGeneration: this.config.security.enableJWTGeneration, |
|
|
|
jwtExpirationMinutes: this.config.security.jwtExpirationMinutes, |
|
|
|
signatureAlgorithm: this.config.security.signatureAlgorithm, |
|
|
|
credentialStorage: this.config.security.credentialStorage |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
getTimeSafariUser(): TimeSafariUser { |
|
|
|
return { |
|
|
|
activeDid: this.config.testData.userDid, |
|
|
|
preferences: DEFAULT_TIMESAFARI_PREFERENCES, |
|
|
|
starredPlanIds: this.config.testData.starredPlanIds, |
|
|
|
favoritePersonIds: this.config.testData.favoritePersonIds, |
|
|
|
favoriteItemIds: this.config.testData.favoriteItemIds, |
|
|
|
lastKnownOfferId: this.config.testData.lastKnownOfferId, |
|
|
|
lastKnownPlanId: this.config.testData.lastKnownPlanId |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
getAuthHeaders(): any { |
|
|
|
return { |
|
|
|
'Authorization': `Bearer ${this.config.endorser.apiKey}`, |
|
|
@ -338,7 +398,7 @@ class ErrorDisplay { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Enhanced test interface for TimeSafari Android integration
|
|
|
|
// Enhanced test interface for TimeSafari Android integration with Phase 4 components
|
|
|
|
class TimeSafariAndroidTestApp { |
|
|
|
private statusElement: HTMLElement; |
|
|
|
private logElement: HTMLElement; |
|
|
@ -346,6 +406,11 @@ class TimeSafariAndroidTestApp { |
|
|
|
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; |
|
|
@ -359,6 +424,11 @@ class TimeSafariAndroidTestApp { |
|
|
|
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')!, |
|
|
@ -370,7 +440,8 @@ class TimeSafariAndroidTestApp { |
|
|
|
|
|
|
|
this.setupEventListeners(); |
|
|
|
this.initializeUI(); |
|
|
|
this.log('TimeSafari Android Test app initialized with enhanced UI'); |
|
|
|
this.initializePhase4Components(); |
|
|
|
this.log('TimeSafari Android Test app initialized with Phase 4 components'); |
|
|
|
} |
|
|
|
|
|
|
|
private setupEventListeners() { |
|
|
@ -392,6 +463,12 @@ class TimeSafariAndroidTestApp { |
|
|
|
document.getElementById('battery-status')?.addEventListener('click', () => this.checkBatteryStatus()); |
|
|
|
document.getElementById('exact-alarm-status')?.addEventListener('click', () => this.checkExactAlarmStatus()); |
|
|
|
document.getElementById('reboot-recovery')?.addEventListener('click', () => this.checkRebootRecovery()); |
|
|
|
|
|
|
|
// 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<void> { |
|
|
@ -408,6 +485,49 @@ class TimeSafariAndroidTestApp { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Phase 4: Initialize TimeSafari components
|
|
|
|
private async initializePhase4Components(): Promise<void> { |
|
|
|
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<void> { |
|
|
|
try { |
|
|
@ -802,6 +922,200 @@ class TimeSafariAndroidTestApp { |
|
|
|
private updateStatus(status: string) { |
|
|
|
this.statusElement.textContent = status; |
|
|
|
} |
|
|
|
|
|
|
|
// Phase 4: TimeSafari component test methods
|
|
|
|
private async testSecurityManager(): Promise<void> { |
|
|
|
try { |
|
|
|
this.log('🔐 Testing SecurityManager...'); |
|
|
|
|
|
|
|
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<void> { |
|
|
|
try { |
|
|
|
this.log('🌐 Testing EndorserAPIClient...'); |
|
|
|
|
|
|
|
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<void> { |
|
|
|
try { |
|
|
|
this.log('📱 Testing TimeSafariNotificationManager...'); |
|
|
|
|
|
|
|
// 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<void> { |
|
|
|
try { |
|
|
|
this.log('🚀 Testing complete Phase 4 integration...'); |
|
|
|
|
|
|
|
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
|
|
|
|