the-tip-top-frontend/__tests__/hooks/useClickOutside.test.ts
soufiane 0dd11b572d test: add unit tests for new components to improve coverage
- Add tests for useClickOutside hook
- Add tests for UserDropdown component
- Add tests for TicketPrizeDisplay component
- Add tests for TicketTableRow component
- Increase test count from 181 to 222

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:52:04 +01:00

104 lines
3.0 KiB
TypeScript

/**
* Tests for the useClickOutside hook
* @jest-environment jsdom
*/
import { renderHook } from '@testing-library/react';
import { useClickOutside } from '@/hooks/useClickOutside';
import { createRef } from 'react';
describe('useClickOutside', () => {
let callback: jest.Mock;
let ref: React.RefObject<HTMLDivElement>;
let element: HTMLDivElement;
beforeEach(() => {
callback = jest.fn();
element = document.createElement('div');
document.body.appendChild(element);
ref = { current: element };
});
afterEach(() => {
document.body.removeChild(element);
jest.clearAllMocks();
});
it('should call callback when clicking outside the element', () => {
renderHook(() => useClickOutside(ref, callback, true));
const outsideElement = document.createElement('div');
document.body.appendChild(outsideElement);
const event = new MouseEvent('mousedown', { bubbles: true });
outsideElement.dispatchEvent(event);
expect(callback).toHaveBeenCalledTimes(1);
document.body.removeChild(outsideElement);
});
it('should not call callback when clicking inside the element', () => {
renderHook(() => useClickOutside(ref, callback, true));
const event = new MouseEvent('mousedown', { bubbles: true });
element.dispatchEvent(event);
expect(callback).not.toHaveBeenCalled();
});
it('should not call callback when disabled', () => {
renderHook(() => useClickOutside(ref, callback, false));
const outsideElement = document.createElement('div');
document.body.appendChild(outsideElement);
const event = new MouseEvent('mousedown', { bubbles: true });
outsideElement.dispatchEvent(event);
expect(callback).not.toHaveBeenCalled();
document.body.removeChild(outsideElement);
});
it('should handle null ref gracefully', () => {
const nullRef = createRef<HTMLDivElement>();
// Should not throw when ref is null
expect(() => {
renderHook(() => useClickOutside(nullRef, callback, true));
const event = new MouseEvent('mousedown', { bubbles: true });
document.body.dispatchEvent(event);
}).not.toThrow();
// Callback should NOT be called when ref is null (ref.current is falsy)
expect(callback).not.toHaveBeenCalled();
});
it('should remove event listener on unmount', () => {
const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener');
const { unmount } = renderHook(() => useClickOutside(ref, callback, true));
unmount();
expect(removeEventListenerSpy).toHaveBeenCalledWith('mousedown', expect.any(Function));
removeEventListenerSpy.mockRestore();
});
it('should use default enabled value of true', () => {
renderHook(() => useClickOutside(ref, callback));
const outsideElement = document.createElement('div');
document.body.appendChild(outsideElement);
const event = new MouseEvent('mousedown', { bubbles: true });
outsideElement.dispatchEvent(event);
expect(callback).toHaveBeenCalledTimes(1);
document.body.removeChild(outsideElement);
});
});