veza/apps/web/src/components/ui/focus-trap.test.tsx

99 lines
2.5 KiB
TypeScript
Raw Normal View History

import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { FocusTrap } from './focus-trap';
describe('FocusTrap Component', () => {
beforeEach(() => {
// Reset focus before each test
document.body.focus();
});
it('renders children', () => {
render(
<FocusTrap>
<button>Button 1</button>
<button>Button 2</button>
</FocusTrap>,
);
expect(screen.getByText('Button 1')).toBeInTheDocument();
expect(screen.getByText('Button 2')).toBeInTheDocument();
});
it('focuses first element when active', () => {
render(
<FocusTrap active={true}>
<button>Button 1</button>
<button>Button 2</button>
</FocusTrap>,
);
const button1 = screen.getByText('Button 1');
expect(document.activeElement).toBe(button1);
});
it('traps focus with Tab key', () => {
render(
<FocusTrap active={true}>
<button>Button 1</button>
<button>Button 2</button>
</FocusTrap>,
);
const button1 = screen.getByText('Button 1');
const button2 = screen.getByText('Button 2');
// Focus the last element
button2.focus();
expect(document.activeElement).toBe(button2);
// Tab from last element should wrap to first
fireEvent.keyDown(document, { key: 'Tab' });
expect(document.activeElement).toBe(button1);
});
it('traps focus with Shift+Tab key', () => {
render(
<FocusTrap active={true}>
<button>Button 1</button>
<button>Button 2</button>
</FocusTrap>,
);
const button1 = screen.getByText('Button 1');
const button2 = screen.getByText('Button 2');
button1.focus();
fireEvent.keyDown(document, { key: 'Tab', shiftKey: true });
// Should wrap to last button
expect(document.activeElement).toBe(button2);
});
it('calls onEscape when Escape key is pressed', () => {
const mockOnEscape = vi.fn();
render(
<FocusTrap active={true} onEscape={mockOnEscape}>
<button>Button 1</button>
</FocusTrap>,
);
fireEvent.keyDown(document, { key: 'Escape' });
expect(mockOnEscape).toHaveBeenCalled();
});
it('does not trap focus when active is false', () => {
render(
<FocusTrap active={false}>
<button>Button 1</button>
</FocusTrap>,
);
const button1 = screen.getByText('Button 1');
// Focus should not be automatically set
expect(document.activeElement).not.toBe(button1);
});
});