Make dashboard event toasts persistent

This commit is contained in:
Jamie Brunton committed 2026-08-14 09:08:13 +01:00
1 parent 4798385d8b
commit c75e71f26e
4 files changed
+91 -14

No files matched your search

+56
View File
@@ -11,6 +11,7 @@ import {
NotificationProvider,
NotificationViewport,
notificationForEvent,
shouldToastForEvent,
} from '../../apps/dashboard/src/app/notifications.js';
class FakeRealtime {
@@ -28,7 +29,9 @@ class FakeRealtime {
afterEach(() => {
cleanup();
globalThis.localStorage.clear();
vi.restoreAllMocks();
vi.useRealTimers();
});
describe('dashboard notifications', () => {
@@ -90,4 +93,57 @@ describe('dashboard notifications', () => {
await user.click(within(centre).getByRole('button', { name: 'Clear all' }));
expect(within(centre).getByText('All quiet')).toBeInTheDocument();
});
it('keeps routine sync completions in the notification centre without showing a toast', async () => {
const realtime = new FakeRealtime();
const user = userEvent.setup();
render(
<MemoryRouter>
<NotificationProvider realtime={realtime}>
<NotificationBell />
<NotificationViewport />
</NotificationProvider>
</MemoryRouter>,
);
const syncEvent: DashboardEvent = {
id: 'sync-1',
occurredAt: '2026-08-09T09:30:00.000Z',
type: 'sync.completed',
payload: { syncId: 'conversation-sync-1', kind: 'conversations', processed: 12 },
};
expect(shouldToastForEvent(syncEvent)).toBe(false);
act(() => realtime.emit(syncEvent));
expect(screen.queryByRole('status')).not.toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Notifications, 1 unread' }));
expect(within(screen.getByLabelText('Notifications', { selector: 'aside' })).getByText('Conversations sync complete'))
.toBeInTheDocument();
});
it('keeps important event toasts visible until they are dismissed', async () => {
vi.useFakeTimers();
const realtime = new FakeRealtime();
render(
<MemoryRouter>
<NotificationProvider realtime={realtime}>
<NotificationViewport />
</NotificationProvider>
</MemoryRouter>,
);
act(() => realtime.emit({
id: 'media-1',
occurredAt: '2026-08-09T09:30:00.000Z',
type: 'media.received',
payload: { conversationId: 'conversation-1', sender: 'alice', count: 1 },
}));
expect(screen.getByRole('status')).toHaveTextContent('Image received from u/alice');
act(() => vi.advanceTimersByTime(60_000));
expect(screen.getByRole('status')).toBeInTheDocument();
act(() => screen.getByRole('button', { name: 'Dismiss Image received from u/alice' }).click());
expect(screen.queryByRole('status')).not.toBeInTheDocument();
});
});