import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { syncSitePush } from '@/components/notifications/push-client'; beforeEach(() => vi.stubGlobal('localStorage', { getItem: vi.fn().mockReturnValue(null) })); afterEach(() => vi.unstubAllGlobals()); describe('shared site push subscriptions', () => { for (const admin of [false, true]) it(`registers comments and commission with one ${admin ? 'admin' : 'customer'} browser subscription`, async () => { const json = { endpoint: 'https://fcm.googleapis.com/fcm/send/test', keys: { auth: 'test', p256dh: 'test' } }; const register = vi.fn().mockResolvedValue({ pushManager: { getSubscription: async () => ({ toJSON: () => json }) } }); const setItem = vi.fn(); const fetcher = vi.fn(async (_url: string, options?: RequestInit) => options?.method === "POST" ? new Response(null, { status: 204 }) : Response.json({ publicKey: 'key', canAdmin: admin })); vi.stubGlobal('navigator', { serviceWorker: { register } }); vi.stubGlobal('fetch', fetcher); vi.stubGlobal('sessionStorage', { setItem }); await syncSitePush('user'); expect(register).toHaveBeenCalledTimes(1); expect(fetcher.mock.calls[1][0]).toBe('/api/comments/push-subscription'); expect(JSON.parse(fetcher.mock.calls[1][1]!.body as string)).toEqual(json); expect(JSON.parse(fetcher.mock.calls[2][1]!.body as string)).toEqual({ ...json, scope: admin ? 'admin' : 'customer' }); expect(setItem).toHaveBeenCalledWith('site-push-synced-user', '1'); }); it('keeps failed registration retryable', async () => { const setItem = vi.fn(); vi.stubGlobal('navigator', { serviceWorker: { register: async () => ({ pushManager: { getSubscription: async () => ({ toJSON: () => ({ endpoint: 'endpoint' }) }) } }) } }); vi.stubGlobal('sessionStorage', { setItem }); vi.stubGlobal('fetch', vi.fn(async (url: string, options?: RequestInit) => options?.method === "POST" ? new Response(null, { status: url.includes('comments') ? 503 : 204 }) : Response.json({ publicKey: 'key', canAdmin: false }))); await expect(syncSitePush('user')).rejects.toThrow('push-subscription-failed'); expect(setItem).not.toHaveBeenCalled(); }); });