test(pwa): add comprehensive PWA and Vitest test suite

- Install Vitest and React Testing Library for frontend tests
- Configure Vitest with jsdom environment and coverage
- Add test setup file with global mocks (matchMedia, IntersectionObserver)
- Write InstallPWA component tests (14 tests):
  - iOS detection and manual installation instructions
  - Android/Chrome beforeinstallprompt event handling
  - Install and dismiss functionality
  - 7-day dismissal persistence (localStorage)
  - Installed state detection (standalone mode)
- Write PWA configuration tests (28 tests):
  - App icons existence (PNG and SVG)
  - iOS splash screens for multiple devices
  - Vite PWA plugin configuration
  - index.html meta tags (iOS PWA support)
  - Manifest schema validation
  - Service worker configuration (Workbox)
- Write service worker tests (24 tests):
  - Service worker registration and lifecycle
  - Workbox integration
  - Cache Storage API operations
- Migrate existing WebRTC tests from Jest to Vitest (25 tests):
  - Update imports to use Vitest (vi.fn, describe, it, expect)
  - Fix WebRTCWarning and webrtcDetection test expectations
- Add test scripts to package.json (test, test:watch, test:ui, test:coverage)

All 91 tests passing (InstallPWA: 14, PWA config: 28, Service Worker: 24,
WebRTC: 25 total across 2 files)
This commit is contained in:
Radosław Gierwiało
2025-11-19 21:24:34 +01:00
parent f0a1bfb31a
commit 9d1af60f30
9 changed files with 2332 additions and 11 deletions

View File

@@ -0,0 +1,42 @@
import '@testing-library/jest-dom';
import { cleanup } from '@testing-library/react';
import { afterEach } from 'vitest';
// Cleanup after each test
afterEach(() => {
cleanup();
});
// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: (query) => ({
matches: false,
media: query,
onchange: null,
addListener: () => {},
removeListener: () => {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => {},
}),
});
// Mock IntersectionObserver
global.IntersectionObserver = class IntersectionObserver {
constructor() {}
disconnect() {}
observe() {}
takeRecords() {
return [];
}
unobserve() {}
};
// Mock ResizeObserver
global.ResizeObserver = class ResizeObserver {
constructor() {}
disconnect() {}
observe() {}
unobserve() {}
};