- Implement performance dashboard with real-time metrics tracking - Add React hooks for smart polling, debouncing, and active source lookup - Create Jest testing framework with comprehensive test suites for components, API endpoints, and utilities - Enhance UI components with optimized rendering and memoization - Improve polling efficiency with visibility detection and adaptive intervals 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
226 lines
No EOL
6.1 KiB
TypeScript
226 lines
No EOL
6.1 KiB
TypeScript
import { renderHook, act } from '@testing-library/react';
|
|
import { useToast } from '../useToast';
|
|
|
|
describe('useToast', () => {
|
|
let mockRandom: jest.SpyInstance;
|
|
|
|
beforeEach(() => {
|
|
// Reset Math.random to ensure consistent IDs in tests
|
|
mockRandom = jest.spyOn(Math, 'random').mockReturnValue(0.5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
mockRandom.mockRestore();
|
|
});
|
|
|
|
it('starts with empty toasts array', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
expect(result.current.toasts).toEqual([]);
|
|
});
|
|
|
|
it('adds a toast with addToast', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.addToast('info', 'Test Title', 'Test message');
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(1);
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'info',
|
|
title: 'Test Title',
|
|
message: 'Test message',
|
|
duration: 5000,
|
|
});
|
|
expect(result.current.toasts[0].id).toBeDefined();
|
|
});
|
|
|
|
it('adds error toast with longer duration', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.addToast('error', 'Error Title');
|
|
});
|
|
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'error',
|
|
title: 'Error Title',
|
|
duration: 7000, // Errors stay longer
|
|
});
|
|
});
|
|
|
|
it('adds toast with custom duration', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.addToast('success', 'Success Title', 'Success message', 3000);
|
|
});
|
|
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'success',
|
|
title: 'Success Title',
|
|
message: 'Success message',
|
|
duration: 3000,
|
|
});
|
|
});
|
|
|
|
it('removes a toast by ID', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
let toastId: string;
|
|
|
|
act(() => {
|
|
toastId = result.current.addToast('info', 'Test Title');
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(1);
|
|
|
|
act(() => {
|
|
result.current.removeToast(toastId);
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(0);
|
|
});
|
|
|
|
it('clears all toasts', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.addToast('info', 'Toast 1');
|
|
result.current.addToast('error', 'Toast 2');
|
|
result.current.addToast('success', 'Toast 3');
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(3);
|
|
|
|
act(() => {
|
|
result.current.clearAllToasts();
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(0);
|
|
});
|
|
|
|
it('supports multiple toasts', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.addToast('info', 'Toast 1');
|
|
result.current.addToast('error', 'Toast 2');
|
|
result.current.addToast('success', 'Toast 3');
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(3);
|
|
expect(result.current.toasts[0].title).toBe('Toast 1');
|
|
expect(result.current.toasts[1].title).toBe('Toast 2');
|
|
expect(result.current.toasts[2].title).toBe('Toast 3');
|
|
});
|
|
|
|
describe('convenience methods', () => {
|
|
it('showSuccess creates success toast', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.showSuccess('Success!', 'Operation completed');
|
|
});
|
|
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'success',
|
|
title: 'Success!',
|
|
message: 'Operation completed',
|
|
});
|
|
});
|
|
|
|
it('showError creates error toast', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.showError('Error!', 'Something went wrong');
|
|
});
|
|
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'error',
|
|
title: 'Error!',
|
|
message: 'Something went wrong',
|
|
duration: 7000,
|
|
});
|
|
});
|
|
|
|
it('showWarning creates warning toast', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.showWarning('Warning!', 'Be careful');
|
|
});
|
|
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'warning',
|
|
title: 'Warning!',
|
|
message: 'Be careful',
|
|
});
|
|
});
|
|
|
|
it('showInfo creates info toast', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
act(() => {
|
|
result.current.showInfo('Info', 'Helpful information');
|
|
});
|
|
|
|
expect(result.current.toasts[0]).toMatchObject({
|
|
type: 'info',
|
|
title: 'Info',
|
|
message: 'Helpful information',
|
|
});
|
|
});
|
|
});
|
|
|
|
it('returns unique IDs for each toast', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
let id1: string, id2: string;
|
|
|
|
act(() => {
|
|
// Mock different random values for unique IDs
|
|
mockRandom
|
|
.mockReturnValueOnce(0.1)
|
|
.mockReturnValueOnce(0.9);
|
|
|
|
id1 = result.current.addToast('info', 'Toast 1');
|
|
id2 = result.current.addToast('info', 'Toast 2');
|
|
});
|
|
|
|
expect(id1).not.toBe(id2);
|
|
expect(result.current.toasts[0].id).toBe(id1);
|
|
expect(result.current.toasts[1].id).toBe(id2);
|
|
});
|
|
|
|
it('removes only the specified toast when multiple exist', () => {
|
|
const { result } = renderHook(() => useToast());
|
|
|
|
let id1: string, id2: string, id3: string;
|
|
|
|
act(() => {
|
|
// Mock different random values for unique IDs
|
|
mockRandom
|
|
.mockReturnValueOnce(0.1)
|
|
.mockReturnValueOnce(0.5)
|
|
.mockReturnValueOnce(0.9);
|
|
|
|
id1 = result.current.addToast('info', 'Toast 1');
|
|
id2 = result.current.addToast('error', 'Toast 2');
|
|
id3 = result.current.addToast('success', 'Toast 3');
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(3);
|
|
|
|
act(() => {
|
|
result.current.removeToast(id2);
|
|
});
|
|
|
|
expect(result.current.toasts).toHaveLength(2);
|
|
expect(result.current.toasts.find(t => t.id === id1)).toBeDefined();
|
|
expect(result.current.toasts.find(t => t.id === id2)).toBeUndefined();
|
|
expect(result.current.toasts.find(t => t.id === id3)).toBeDefined();
|
|
});
|
|
}); |