mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
e1219a166a
Both presenters ran their own queue behind the window toast bus. The queue, the auto dismiss and the exit delay now live in useToastQueue; each presenter keeps its markup, its exit timing and its unmount handover.
87 lines
3.3 KiB
TypeScript
87 lines
3.3 KiB
TypeScript
// FE-COMP-TOASTQUEUE-001 to -006: the toast queue both toast presenters share.
|
|
import { act, renderHook } from '@testing-library/react';
|
|
|
|
import { useToastQueue } from './useToastQueue';
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
delete window.__addToast;
|
|
});
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
delete window.__addToast;
|
|
});
|
|
|
|
describe('useToastQueue', () => {
|
|
it('FE-COMP-TOASTQUEUE-001: registers the bus and queues a toast with the default type and duration', () => {
|
|
const { result } = renderHook(() => useToastQueue({ exitMs: 400, restorePrevious: false }));
|
|
let id = 0;
|
|
act(() => {
|
|
id = window.__addToast!('Saved');
|
|
});
|
|
expect(id).toBeGreaterThan(0);
|
|
expect(result.current.toasts).toEqual([{ id, message: 'Saved', type: 'info', duration: 3000, removing: false }]);
|
|
});
|
|
|
|
it('FE-COMP-TOASTQUEUE-002: auto-dismisses after the duration, then drops the toast after the exit time', () => {
|
|
const { result } = renderHook(() => useToastQueue({ exitMs: 220, restorePrevious: true }));
|
|
act(() => {
|
|
window.__addToast!('Done', 'success', 1000);
|
|
});
|
|
act(() => vi.advanceTimersByTime(999));
|
|
expect(result.current.toasts[0].removing).toBe(false);
|
|
act(() => vi.advanceTimersByTime(1));
|
|
expect(result.current.toasts[0].removing).toBe(true);
|
|
act(() => vi.advanceTimersByTime(219));
|
|
expect(result.current.toasts).toHaveLength(1);
|
|
act(() => vi.advanceTimersByTime(1));
|
|
expect(result.current.toasts).toEqual([]);
|
|
});
|
|
|
|
it('FE-COMP-TOASTQUEUE-003: a duration of zero keeps the toast until it is dismissed', () => {
|
|
const { result } = renderHook(() => useToastQueue({ exitMs: 400, restorePrevious: false }));
|
|
act(() => {
|
|
window.__addToast!('Sticky', 'warning', 0);
|
|
});
|
|
act(() => vi.advanceTimersByTime(60_000));
|
|
expect(result.current.toasts).toHaveLength(1);
|
|
expect(result.current.toasts[0].removing).toBe(false);
|
|
|
|
act(() => result.current.dismissToast(result.current.toasts[0].id));
|
|
expect(result.current.toasts[0].removing).toBe(true);
|
|
act(() => vi.advanceTimersByTime(400));
|
|
expect(result.current.toasts).toEqual([]);
|
|
});
|
|
|
|
it('FE-COMP-TOASTQUEUE-004: the desktop mode deletes the bus on unmount', () => {
|
|
const previous = vi.fn(() => 1);
|
|
window.__addToast = previous;
|
|
const { unmount } = renderHook(() => useToastQueue({ exitMs: 400, restorePrevious: false }));
|
|
expect(window.__addToast).not.toBe(previous);
|
|
unmount();
|
|
expect(window.__addToast).toBeUndefined();
|
|
});
|
|
|
|
it('FE-COMP-TOASTQUEUE-005: the phone mode hands the bus back to the previous holder on unmount', () => {
|
|
const previous = vi.fn(() => 1);
|
|
window.__addToast = previous;
|
|
const { unmount } = renderHook(() => useToastQueue({ exitMs: 220, restorePrevious: true }));
|
|
expect(window.__addToast).not.toBe(previous);
|
|
unmount();
|
|
expect(window.__addToast).toBe(previous);
|
|
});
|
|
|
|
it('FE-COMP-TOASTQUEUE-006: pending timers are cleared on unmount', () => {
|
|
const clear = vi.spyOn(globalThis, 'clearTimeout');
|
|
const { unmount } = renderHook(() => useToastQueue({ exitMs: 400, restorePrevious: false }));
|
|
act(() => {
|
|
window.__addToast!('One', 'info', 1000);
|
|
window.__addToast!('Two', 'error', 2000);
|
|
});
|
|
const before = clear.mock.calls.length;
|
|
unmount();
|
|
expect(clear.mock.calls.length - before).toBe(2);
|
|
clear.mockRestore();
|
|
});
|
|
});
|