Add durable toasts with an inline action button

This commit is contained in:
2026-06-07 20:37:55 +03:00
parent 50d3079b24
commit 5dc5ef8724
4 changed files with 95 additions and 5 deletions
+39
View File
@@ -171,6 +171,45 @@ describe('Toaster exit animation (two-phase dismiss)', () => {
vi.useRealTimers();
});
test('a durable toast does not auto-dismiss, and its action runs then dismisses it', () => {
vi.useFakeTimers();
const onClick = vi.fn();
let id: string;
act(() => {
id = useNotificationStore.getState().notify({
kind: 'info',
title: 'Update available',
message: 'A new version is ready.',
durable: true,
action: { label: 'Reload', onClick },
});
root.render(<Toaster />);
});
// Well past the auto-dismiss window — still present (durable).
act(() => {
vi.advanceTimersByTime(60000);
});
expect(useNotificationStore.getState().notifications.some((n) => n.id === id!)).toBe(true);
// The action button runs the handler, then the toast exits.
const actionBtn = Array.from(container.querySelectorAll('button')).find(
(b) => b.textContent === 'Reload',
);
expect(actionBtn).toBeTruthy();
act(() => {
actionBtn!.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
expect(onClick).toHaveBeenCalledTimes(1);
act(() => {
vi.advanceTimersByTime(TOAST_EXIT_MS);
});
expect(useNotificationStore.getState().notifications.some((n) => n.id === id!)).toBe(false);
vi.useRealTimers();
});
test('clicking close twice does not reset the exit timer', () => {
vi.useFakeTimers();
let id: string;