// 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 = `

PWA Offline Test Results

Overall Score
${passedTests}/${totalTests} tests passed
${successRate}%
${this.testResults.map(test => `
${test.name}
${test.message}
`).join('')}

Recommendations:

    ${this.getRecommendations().map(rec => `
  • • ${rec}
  • `).join('')}
`; document.body.appendChild(modal); } getRecommendations() { const recommendations = []; const failedTests = this.testResults.filter(test => !test.passed); if (failedTests.some(test => test.name.includes('Service Worker'))) { recommendations.push('Ensure service worker is properly registered and active'); } if (failedTests.some(test => test.name.includes('Cache'))) { recommendations.push('Check cache configuration and ensure resources are being cached'); } if (failedTests.some(test => test.name.includes('Network'))) { recommendations.push('Verify network connectivity and server availability'); } if (recommendations.length === 0) { recommendations.push('All tests passed! Your PWA offline functionality is working correctly.'); } return recommendations; } // Public API getTestResults() { return this.testResults; } clearResults() { this.testResults = []; } } // Singleton pattern let instance = null; const PWAOfflineTesterAPI = { getInstance() { if (!instance) { instance = new PWAOfflineTester(); } return instance; }, runTests() { return this.getInstance().runTests(); } }; // Export for module use if (typeof module !== 'undefined' && module.exports) { module.exports = PWAOfflineTesterAPI; } else if (typeof window !== 'undefined' && !window.PWAOfflineTester) { window.PWAOfflineTester = PWAOfflineTesterAPI; } // Auto-initialize if (typeof window !== 'undefined' && !window.pwaOfflineTester) { window.pwaOfflineTester = PWAOfflineTesterAPI.getInstance(); // Add global function for easy access window.testPWAOffline = () => { window.pwaOfflineTester.runTests(); }; }