import { render, screen, userEvent } from '../test-utils'; import Tabs, { TabsProps } from './Tabs'; const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTimeAsync }); if (typeof performance === 'undefined') { global.performance = { now: () => Date.now() } as Performance; } const defaultTabsStatus = [false, true, false]; function generateTabs(tabsStatus = defaultTabsStatus) { return tabsStatus.map((disabled, index) => ({ disabled, title: `Title ${index}`, content:

Content {index}

, })); } describe('Tabs', () => { const initialProps: TabsProps = { tabs: generateTabs(), changeTabOnSwipe: true, name: 'testName', headerWidth: 'block', selected: 0, onTabSelect: jest.fn(), className: 'custom-class-name', }; beforeEach(() => { jest.clearAllMocks(); jest.useFakeTimers(); }); afterEach(async () => { jest.runOnlyPendingTimers(); jest.useRealTimers(); }); it('should render a tablist', () => { render(); expect(screen.getByRole('tablist')).toBeInTheDocument(); }); it('should respect className', () => { render(); expect(screen.getByRole('tablist').parentNode).toHaveClass(String(initialProps.className)); }); it('should respect `name` prop', () => { render(); const controlsTarget = screen .getByRole('tab', { selected: true }) .getAttribute('aria-controls'); expect(screen.getByRole('tabpanel')).toHaveAttribute('id', controlsTarget); }); it('should render correct number of tabs', () => { render(); expect(screen.getAllByRole('tab')).toHaveLength(defaultTabsStatus.length); initialProps.tabs.forEach(({ title }) => { expect(screen.getByText(title)).toBeInTheDocument(); }); }); it('should show first tab content by default', () => { render(); expect(screen.getAllByRole('tabpanel')).toHaveLength(1); expect(screen.getByTestId('content-0')).toBeInTheDocument(); }); describe('tab switch', () => { it('should call onTabSelecton on click', async () => { render(); const thirdTab = screen.getAllByRole('tab')[2]; await user.click(thirdTab); // It's called on mount first, that's why the count is at 2 expect(initialProps.onTabSelect).toHaveBeenCalledTimes(2); expect(initialProps.onTabSelect).toHaveBeenCalledWith(2); }); it('should call onTabSelecton when navigating with keyboard', async () => { render(); await user.keyboard('{Tab}{Tab}{Tab}{Enter}'); // It's called on mount first, that's why the count is at 2 expect(initialProps.onTabSelect).toHaveBeenCalledTimes(2); expect(initialProps.onTabSelect).toHaveBeenCalledWith(2); }); it('should call onTabSelecton on swipe', async () => { render(); await user.keyboard('{Tab}{Tab}{Tab}{Enter}'); // It's called on mount first, that's why the count is at 2 expect(initialProps.onTabSelect).toHaveBeenCalledTimes(2); expect(initialProps.onTabSelect).toHaveBeenCalledWith(2); }); it('should highlight selected tab', async () => { const { rerender } = render(); rerender(); expect(screen.getByRole('tab', { selected: true })).toHaveTextContent('Title 2'); }); it('should switch content tab', async () => { const { rerender } = render(); rerender(); expect(screen.getByRole('tabpanel')).toHaveTextContent('Content 2'); }); }); });