Files
insta-recipe/src/tests/push-notifications.e2e.spec.ts
Giancarmine Salucci 49bccf8f15 simplify
2026-02-18 01:21:44 +01:00

207 lines
6.3 KiB
TypeScript

/**
* E2E Tests for Push Notifications
*
* Tests the complete push notification workflow using Playwright:
* - Permission granting
* - Subscription creation
* - Server registration
* - Manual test notifications
* - Unsubscribe flow
* - localStorage persistence
*
* Note: These tests require the dev server to be running.
*/
import { test, expect, type BrowserContext } from '@playwright/test';
test.describe('Push Notifications E2E', () => {
let context: BrowserContext;
test.beforeEach(async ({ browser }) => {
// Create new context with notification permissions granted
context = await browser.newContext();
await context.grantPermissions(['notifications']);
});
test.afterEach(async () => {
await context?.close();
});
test('should subscribe to push notifications', async () => {
const page = await context.newPage();
await page.goto('/');
await page.waitForLoadState('networkidle');
// Wait for service worker to be registered
await page.waitForFunction(() => 'serviceWorker' in navigator && 'PushManager' in window);
// Find the notification toggle button
const toggleButton = page.getByRole('button', { name: /enable notifications/i });
await expect(toggleButton).toBeVisible();
// Click to enable notifications
await toggleButton.click();
// Wait for subscription to complete
await page.waitForTimeout(2000);
// Verify subscription was created in browser
const subscription = await page.evaluate(async () => {
const registration = await navigator.serviceWorker.ready;
const sub = await registration.pushManager.getSubscription();
return sub
? {
endpoint: sub.endpoint,
hasKeys: !!(sub as any).keys
}
: null;
});
expect(subscription).not.toBeNull();
expect(subscription?.endpoint).toBeTruthy();
expect(subscription?.endpoint).toContain('https://');
expect(subscription?.hasKeys).toBe(true);
// Verify button text changed to "Disable Notifications"
await expect(toggleButton).toHaveText(/disable notifications/i);
await page.close();
});
test('should show test notification buttons when subscribed', async () => {
const page = await context.newPage();
await page.goto('/');
await page.waitForLoadState('networkidle');
// Wait for service worker
await page.waitForFunction(() => 'serviceWorker' in navigator);
// Enable notifications first
const toggleButton = page.getByRole('button', { name: /enable notifications/i });
await toggleButton.click();
await page.waitForTimeout(2000);
// Verify test buttons are visible
const testSuccessButton = page.getByRole('button', { name: /test success/i });
const testErrorButton = page.getByRole('button', { name: /test error/i });
const testProgressButton = page.getByRole('button', { name: /test progress/i });
await expect(testSuccessButton).toBeVisible();
await expect(testErrorButton).toBeVisible();
await expect(testProgressButton).toBeVisible();
await page.close();
});
test('should send test notifications', async () => {
const page = await context.newPage();
await page.goto('/');
await page.waitForLoadState('networkidle');
// Wait for service worker
await page.waitForFunction(() => 'serviceWorker' in navigator);
// Enable notifications first
const toggleButton = page.getByRole('button', { name: /enable notifications/i });
await toggleButton.click();
await page.waitForTimeout(2000);
// Mock the test notification API response
await page.route('/api/notifications/test', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ success: true, subscriberCount: 1 })
});
});
// Click test success button
const testSuccessButton = page.getByRole('button', { name: /test success/i });
await testSuccessButton.click();
// Wait for and verify success message
const successMessage = page.getByText(/✓ test success notification sent/i);
await expect(successMessage).toBeVisible({ timeout: 5000 });
// Verify message contains subscriber count
await expect(successMessage).toContainText('1 subscriber');
// Wait for auto-dismiss
await expect(successMessage).not.toBeVisible({ timeout: 4000 });
await page.close();
});
test('should unsubscribe from push notifications', async () => {
const page = await context.newPage();
await page.goto('/');
await page.waitForLoadState('networkidle');
// Wait for service worker
await page.waitForFunction(() => 'serviceWorker' in navigator);
// First subscribe
const toggleButton = page.getByRole('button', { name: /enable notifications/i });
await toggleButton.click();
await page.waitForTimeout(2000);
// Verify subscribed
await expect(toggleButton).toHaveText(/disable notifications/i);
// Now unsubscribe
await toggleButton.click();
await page.waitForTimeout(2000);
// Verify subscription was removed
const subscription = await page.evaluate(async () => {
const registration = await navigator.serviceWorker.ready;
return await registration.pushManager.getSubscription();
});
expect(subscription).toBeNull();
// Verify button text changed back
await expect(toggleButton).toHaveText(/enable notifications/i);
// Verify test buttons are no longer visible
const testSuccessButton = page.getByRole('button', { name: /test success/i });
await expect(testSuccessButton).not.toBeVisible();
await page.close();
});
test('should persist clientId in localStorage', async () => {
const page = await context.newPage();
await page.goto('/');
await page.waitForLoadState('networkidle');
// Wait for service worker
await page.waitForFunction(() => 'serviceWorker' in navigator);
// Enable notifications
const toggleButton = page.getByRole('button', { name: /enable notifications/i });
await toggleButton.click();
await page.waitForTimeout(2000);
// Verify clientId is stored in localStorage
const clientId = await page.evaluate(() => {
return localStorage.getItem('push-client-id');
});
expect(clientId).toBeTruthy();
expect(clientId).toMatch(/^client_[a-f0-9-]+$/);
// Reload page and verify clientId persists
await page.reload();
await page.waitForLoadState('networkidle');
const persistedClientId = await page.evaluate(() => {
return localStorage.getItem('push-client-id');
});
expect(persistedClientId).toBe(clientId);
await page.close();
});
});