Task 5.24: PWA — vite-plugin-pwa with autoUpdate, manifest, workbox caching, PWAInstallPrompt component, notification helper, SVG icons, 6 tests

This commit is contained in:
Agent Zero
2026-07-24 00:01:53 +02:00
parent d54a87cf84
commit 96e183bab2
11 changed files with 4034 additions and 3 deletions
@@ -0,0 +1,96 @@
/**
* PWA Install Prompt tests — Task 5.24.
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { PWAInstallPrompt } from '@/components/PWAInstallPrompt';
import { getNotificationPermission, isPWAInstalled } from '@/utils/notifications';
// Mock i18n
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key }),
}));
describe('PWAInstallPrompt', () => {
beforeEach(() => {
localStorage.clear();
vi.restoreAllMocks();
});
it('renders nothing when no beforeinstallprompt event fires', () => {
render(<PWAInstallPrompt />);
expect(screen.queryByTestId('pwa-install-prompt')).toBeNull();
});
it('shows install prompt when beforeinstallprompt fires', async () => {
render(<PWAInstallPrompt />);
const event = new Event('beforeinstallprompt');
Object.assign(event, {
prompt: vi.fn().mockResolvedValue(undefined),
userChoice: Promise.resolve({ outcome: 'accepted' }),
});
window.dispatchEvent(event);
await waitFor(() => {
expect(screen.getByTestId('pwa-install-prompt')).toBeInTheDocument();
});
expect(screen.getByTestId('pwa-install-btn')).toBeInTheDocument();
expect(screen.getByTestId('pwa-dismiss-btn')).toBeInTheDocument();
});
it('hides when dismiss button is clicked', async () => {
render(<PWAInstallPrompt />);
const event = new Event('beforeinstallprompt');
Object.assign(event, {
prompt: vi.fn().mockResolvedValue(undefined),
userChoice: Promise.resolve({ outcome: 'dismissed' }),
});
window.dispatchEvent(event);
await waitFor(() => {
expect(screen.getByTestId('pwa-install-prompt')).toBeInTheDocument();
});
fireEvent.click(screen.getByTestId('pwa-dismiss-btn'));
await waitFor(() => {
expect(screen.queryByTestId('pwa-install-prompt')).toBeNull();
});
// Should not show again after dismiss (localStorage)
expect(localStorage.getItem('leocrm_pwa_install_dismissed')).toBe('1');
});
it('does not show when already dismissed', () => {
localStorage.setItem('leocrm_pwa_install_dismissed', '1');
render(<PWAInstallPrompt />);
const event = new Event('beforeinstallprompt');
Object.assign(event, {
prompt: vi.fn(),
userChoice: Promise.resolve({ outcome: 'dismissed' }),
});
window.dispatchEvent(event);
expect(screen.queryByTestId('pwa-install-prompt')).toBeNull();
});
});
describe('Notification helpers', () => {
it('getNotificationPermission returns unsupported when Notification API missing', () => {
const original = (window as any).Notification;
delete (window as any).Notification;
expect(getNotificationPermission()).toBe('unsupported');
(window as any).Notification = original;
});
it('isPWAInstalled returns false in browser mode', () => {
expect(isPWAInstalled()).toBe(false);
});
});