Files
insta-recipe/src/tests/notification-auto-subscribe.svelte.spec.ts

121 lines
3.2 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import HomePage from '../routes/+page.svelte';
import { pushNotificationManager } from '$lib/client/PushNotificationManager';
// Mock $app/environment
vi.mock('$app/environment', () => ({
browser: true
}));
// Mock fetch for queue API calls
globalThis.fetch = vi.fn(() =>
Promise.resolve({
ok: true,
json: () => Promise.resolve({ items: [], stats: { total: 0, pending: 0, in_progress: 0, completed: 0, error: 0 } })
} as Response)
);
// Mock EventSource for SSE
globalThis.EventSource = vi.fn(() => ({
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
close: vi.fn(),
onerror: null,
onmessage: null,
onopen: null,
readyState: 0,
url: '',
withCredentials: false,
CONNECTING: 0,
OPEN: 1,
CLOSED: 2,
dispatchEvent: vi.fn()
})) as any;
vi.mock('$lib/client/PushNotificationManager', () => ({
pushNotificationManager: {
getState: vi.fn(),
subscribe: vi.fn(),
onStateChange: vi.fn(() => () => {})
}
}));
describe('Automatic Notification Subscription', () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(pushNotificationManager.getState).mockReturnValue({
supported: true,
permission: 'default',
subscribed: false,
loading: false,
error: null
});
});
it('should auto-subscribe on first user click when supported and not subscribed', async () => {
render(HomePage);
// Wait for component to mount and set up event listeners
await new Promise(resolve => setTimeout(resolve, 100));
// Simulate user click anywhere on page
document.body.click();
// Wait for event handlers to process
await new Promise(resolve => setTimeout(resolve, 50));
expect(pushNotificationManager.subscribe).toHaveBeenCalledTimes(1);
});
it('should not auto-subscribe if permission denied', async () => {
vi.mocked(pushNotificationManager.getState).mockReturnValue({
supported: true,
permission: 'denied',
subscribed: false,
loading: false,
error: null
});
render(HomePage);
await new Promise(resolve => setTimeout(resolve, 100));
document.body.click();
await new Promise(resolve => setTimeout(resolve, 50));
expect(pushNotificationManager.subscribe).not.toHaveBeenCalled();
});
it('should not auto-subscribe if already subscribed', async () => {
vi.mocked(pushNotificationManager.getState).mockReturnValue({
supported: true,
permission: 'granted',
subscribed: true,
loading: false,
error: null
});
render(HomePage);
await new Promise(resolve => setTimeout(resolve, 100));
document.body.click();
await new Promise(resolve => setTimeout(resolve, 50));
expect(pushNotificationManager.subscribe).not.toHaveBeenCalled();
});
it('should only attempt subscription once', async () => {
render(HomePage);
await new Promise(resolve => setTimeout(resolve, 100));
document.body.click();
document.body.click();
document.body.click();
await new Promise(resolve => setTimeout(resolve, 50));
expect(pushNotificationManager.subscribe).toHaveBeenCalledTimes(1);
});
});