veza/apps/web/src/context/ToastContext.test.tsx

147 lines
3.5 KiB
TypeScript
Raw Normal View History

import { renderHook, act, render, screen } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { ToastProvider, useToast } from '../components/feedback/ToastProvider';
import { ReactNode } from 'react';
// Mock toast to avoid react-hot-toast dynamic import issues in Vitest
vi.mock('@/utils/toast', () => {
const mockFn = (msg: string) => {
const el = document.createElement('div');
el.textContent = msg;
el.setAttribute('data-testid', 'toast-message');
document.body.appendChild(el);
};
return {
default: Object.assign(mockFn, {
success: mockFn,
error: mockFn,
warning: mockFn,
loading: mockFn,
custom: mockFn,
dismiss: vi.fn(),
remove: vi.fn(),
promise: vi.fn(() => Promise.resolve()),
}),
};
});
const wrapper = ({ children }: { children: ReactNode }) => (
<ToastProvider>{children}</ToastProvider>
);
describe('ToastContext', () => {
beforeEach(() => {
vi.clearAllMocks();
document.querySelectorAll('[data-testid="toast-message"]').forEach((el) => el.remove());
});
it('should provide toast context', () => {
const { result } = renderHook(() => useToast(), { wrapper });
expect(result.current).toBeDefined();
expect(result.current).toHaveProperty('addToast');
expect(typeof result.current.addToast).toBe('function');
});
it('should add toast', () => {
const TestComponent = () => {
const { addToast } = useToast();
return (
<div>
<button onClick={() => addToast('Test message', 'info')}>
Add Toast
</button>
</div>
);
};
render(
<ToastProvider>
<TestComponent />
</ToastProvider>,
);
const button = screen.getByText('Add Toast');
act(() => {
button.click();
});
// Toast should be added to the DOM
expect(screen.getByText('Test message')).toBeInTheDocument();
});
it('should add success toast', () => {
const TestComponent = () => {
const { addToast } = useToast();
return (
<div>
<button onClick={() => addToast('Success!', 'success')}>
Add Success
</button>
</div>
);
};
render(
<ToastProvider>
<TestComponent />
</ToastProvider>,
);
const button = screen.getByText('Add Success');
act(() => {
button.click();
});
expect(screen.getByText('Success!')).toBeInTheDocument();
});
it('should add error toast', () => {
const TestComponent = () => {
const { addToast } = useToast();
return (
<div>
<button onClick={() => addToast('Error!', 'error')}>Add Error</button>
</div>
);
};
render(
<ToastProvider>
<TestComponent />
</ToastProvider>,
);
const button = screen.getByText('Add Error');
act(() => {
button.click();
});
expect(screen.getByText('Error!')).toBeInTheDocument();
});
it('should use default type info when type not provided', () => {
const TestComponent = () => {
const { addToast } = useToast();
return (
<div>
<button onClick={() => addToast('Info message')}>Add Info</button>
</div>
);
};
render(
<ToastProvider>
<TestComponent />
</ToastProvider>,
);
const button = screen.getByText('Add Info');
act(() => {
button.click();
});
expect(screen.getByText('Info message')).toBeInTheDocument();
});
});