diff --git a/components/settings/__tests__/multi-account-push.test.tsx b/components/settings/__tests__/multi-account-push.test.tsx new file mode 100644 index 000000000..1c3f01eaf --- /dev/null +++ b/components/settings/__tests__/multi-account-push.test.tsx @@ -0,0 +1,47 @@ +import { render, waitFor } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; +import { MultiAccountPushSettings } from '../multi-account-push'; +import { useAccountStore } from '@/stores/account-store'; +import { useAuthStore } from '@/stores/auth-store'; +import * as webPush from '@/lib/web-push'; + +vi.mock('next-intl', () => ({ + useTranslations: () => (key: string) => key, +})); + +vi.mock('../settings-section', async (importOriginal) => ({ + ...(await importOriginal()), + SettingsSection: ({ children }: { children: React.ReactNode }) =>
{children}
, +})); + +// Push state is stored under the JMAP account id the server assigned: only +// "jmap-a" has a registration here. +vi.mock('@/lib/web-push', () => ({ + isWebPushSupported: () => true, + isWebPushEnabled: vi.fn(async (id: string) => id === 'jmap-a'), + enableWebPushForAccounts: vi.fn(), + disableWebPush: vi.fn(), +})); + +describe('MultiAccountPushSettings', () => { + it('reads each login\'s push state under its JMAP account id', async () => { + const clients: Record string }> = { + 'a@mail.example.com': { getAccountId: () => 'jmap-a' }, + 'b@mail.example.com': { getAccountId: () => 'jmap-b' }, + }; + useAccountStore.setState({ + accounts: [ + { id: 'a@mail.example.com', username: 'a', email: 'a@example.com', isConnected: true }, + { id: 'b@mail.example.com', username: 'b', email: 'b@example.com', isConnected: true }, + ] as never, + }); + useAuthStore.setState({ getClientForAccount: ((id: string) => clients[id]) as never }); + + const { container } = render(); + + await waitFor(() => expect(container.textContent).toContain('a@example.com · state_on')); + expect(container.textContent).toContain('b@example.com · state_off'); + expect(webPush.isWebPushEnabled).toHaveBeenCalledWith('jmap-a'); + expect(webPush.isWebPushEnabled).not.toHaveBeenCalledWith('a@mail.example.com'); + }); +}); diff --git a/components/settings/multi-account-push.tsx b/components/settings/multi-account-push.tsx index cb025b3e7..d431a36b7 100644 --- a/components/settings/multi-account-push.tsx +++ b/components/settings/multi-account-push.tsx @@ -31,8 +31,13 @@ export function MultiAccountPushSettings({ relayBaseUrl }: { relayBaseUrl?: stri const connected = accounts.filter(a => a.isConnected && useAuthStore.getState().getClientForAccount(a.id)); const refresh = useCallback(async () => { + // Push state is stored under the JMAP account id the server assigned (see + // enableWebPush), not under the login's own id: read it back the same way. const entries = await Promise.all( - useAccountStore.getState().accounts.map(async a => [a.id, await isWebPushEnabled(a.id)] as const), + useAccountStore.getState().accounts.map(async (a) => { + const jmapAccountId = useAuthStore.getState().getClientForAccount(a.id)?.getAccountId(); + return [a.id, jmapAccountId ? await isWebPushEnabled(jmapAccountId) : false] as const; + }), ); setEnabled(Object.fromEntries(entries)); }, []);