// PWA Offline Test Script for SecureBit.chat // Enhanced Security Edition v4.3.120 // Tests offline functionality and cache status class PWAOfflineTester { constructor() { this.testResults = []; this.isRunning = false; } async runTests() { if (this.isRunning) { console.warn('⚠️ Tests already running'); return; } this.isRunning = true; this.testResults = []; console.log('🧪 Starting PWA Offline Tests...'); try { await this.testServiceWorkerRegistration(); await this.testCacheStatus(); await this.testOfflineResources(); await this.testOnlineResources(); this.showTestResults(); } catch (error) { console.error('❌ Test failed:', error); this.addTestResult('Test Suite', false, `Test suite failed: ${error.message}`); } finally { this.isRunning = false; } } async testServiceWorkerRegistration() { try { if ('serviceWorker' in navigator) { const registration = await navigator.serviceWorker.getRegistration(); if (registration) { this.addTestResult('Service Worker Registration', true, 'Service worker is registered'); } else { this.addTestResult('Service Worker Registration', false, 'No service worker found'); } } else { this.addTestResult('Service Worker Support', false, 'Service worker not supported'); } } catch (error) { this.addTestResult('Service Worker Registration', false, `Error: ${error.message}`); } } async testCacheStatus() { try { if ('caches' in window) { const cacheNames = await caches.keys(); const totalCached = 0; for (const cacheName of cacheNames) { const cache = await caches.open(cacheName); const keys = await cache.keys(); totalCached += keys.length; } if (totalCached > 0) { this.addTestResult('Cache Status', true, `${totalCached} resources cached`); } else { this.addTestResult('Cache Status', false, 'No resources cached'); } } else { this.addTestResult('Cache API Support', false, 'Cache API not supported'); } } catch (error) { this.addTestResult('Cache Status', false, `Error: ${error.message}`); } } async testOfflineResources() { const criticalResources = [ '/', '/index.html', '/manifest.json', '/dist/app.js', '/dist/app-boot.js', '/libs/react/react.production.min.js', '/libs/react-dom/react-dom.production.min.js', '/assets/tailwind.css' ]; let cachedCount = 0; for (const resource of criticalResources) { try { const cached = await caches.match(resource); if (cached) { cachedCount++; } } catch (error) { console.warn(`⚠️ Failed to check cache for ${resource}:`, error); } } const success = cachedCount >= criticalResources.length * 0.8; // 80% success rate this.addTestResult('Critical Resources Cached', success, `${cachedCount}/${criticalResources.length} critical resources cached`); } async testOnlineResources() { try { // Test if we can fetch a simple resource const response = await fetch('/favicon.ico', { method: 'HEAD', cache: 'no-cache' }); if (response.ok) { this.addTestResult('Network Connectivity', true, 'Network is accessible'); } else { this.addTestResult('Network Connectivity', false, `Network error: ${response.status}`); } } catch (error) { this.addTestResult('Network Connectivity', false, `Network error: ${error.message}`); } } addTestResult(testName, passed, message) { this.testResults.push({ name: testName, passed, message, timestamp: new Date().toISOString() }); console.log(`${passed ? '✅' : '❌'} ${testName}: ${message}`); } showTestResults() { const passedTests = this.testResults.filter(test => test.passed).length; const totalTests = this.testResults.length; const successRate = Math.round((passedTests / totalTests) * 100); const modal = document.createElement('div'); modal.className = 'fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4 backdrop-blur-sm'; modal.innerHTML = `