UNPKG

@vertisanpro/flowbite-react

Version:

Non-Official React components built for Flowbite and Tailwind CSS

126 lines (125 loc) 7.14 kB
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { HiAdjustments, HiClipboardList, HiUserCircle } from '@vertisanpro/react-icons/hi'; import { MdDashboard } from '@vertisanpro/react-icons/md'; import React, { createRef, forwardRef } from 'react'; import { act } from 'react-dom/test-utils'; import { describe, expect, it, vi } from 'vitest'; import { Tabs } from './Tabs'; describe('Components / Tabs', () => { it('should open tab when clicked', async () => { const user = userEvent.setup(); render(React.createElement(TestTabs, null)); await user.click(firstTab()); expect(firstTab()).toHaveFocus(); const nextTab = tabs()[1]; await user.click(nextTab); expect(firstTab()).toHaveAttribute('aria-selected', 'false'); expect(nextTab).toHaveFocus(); expect(nextTab).toHaveAttribute('aria-selected', 'true'); }); it('should open focused tab when `Enter` is pressed', async () => { const user = userEvent.setup(); render(React.createElement(TestTabs, null)); await user.click(firstTab()); expect(firstTab()).toHaveFocus(); await user.keyboard('[ArrowRight]'); const nextTab = tabs()[1]; expect(nextTab).toHaveFocus(); await user.keyboard('[Enter]'); expect(nextTab).toHaveAttribute('aria-selected', 'true'); }); it('should do nothing when Left Arrow is pressed and first tab is already focused', async () => { const user = userEvent.setup(); render(React.createElement(TestTabs, null)); await user.click(firstTab()); expect(firstTab()).toHaveFocus(); await user.keyboard('[ArrowLeft]'); expect(firstTab()).toHaveFocus(); }); it('should focus previous tab when Left Arrow is pressed', async () => { const user = userEvent.setup(); render(React.createElement(TestTabsDifferentActiveItem, null)); await user.click(firstTab()); expect(activeTab()).toHaveFocus(); await user.keyboard('[ArrowLeft]'); expect(firstTab()).toHaveFocus(); }); it('should do nothing when Right Arrow is pressed and last tab is already focused', async () => { const user = userEvent.setup(); render(React.createElement(TestTabsLastActiveItem, null)); await user.click(lastTab()); expect(lastTab()).toHaveAttribute('aria-selected', 'true'); expect(lastTab()).toHaveFocus(); await user.keyboard('[ArrowRight]'); expect(lastTab()).toHaveFocus(); }); it('should focus next tab when Right Arrow is pressed', async () => { const user = userEvent.setup(); render(React.createElement(TestTabs, null)); await user.click(firstTab()); await user.keyboard('[ArrowRight]'); const nextTab = tabs()[1]; expect(nextTab).toHaveFocus(); }); it('should call onActiveTabChanged when clicked', async () => { const user = userEvent.setup(); const helper = { onActiveTabChange: () => void 0 }; const spy = vi.spyOn(helper, 'onActiveTabChange'); render(React.createElement(TestTabs, { onActiveTabChange: helper.onActiveTabChange })); await user.click(firstTab()); expect(firstTab()).toHaveFocus(); const nextTab = tabs()[1]; await user.click(nextTab); expect(firstTab()).toHaveAttribute('aria-selected', 'false'); expect(nextTab).toHaveFocus(); expect(nextTab).toHaveAttribute('aria-selected', 'true'); expect(spy).toHaveBeenCalledTimes(2); expect(spy).toHaveBeenCalledWith(1); }); it('should open tab and call onActiveTabChanged when setActiveTab is called', async () => { const ref = createRef(); const helper = { onActiveTabChange: () => void 0 }; const spy = vi.spyOn(helper, 'onActiveTabChange'); render(React.createElement(TestTabs, { ref: ref, onActiveTabChange: helper.onActiveTabChange })); expect(firstTab()).toHaveAttribute('aria-selected', 'true'); act(() => { ref.current?.setActiveTab(1); }); const nextTab = tabs()[1]; expect(firstTab()).toHaveAttribute('aria-selected', 'false'); expect(nextTab).toHaveAttribute('aria-selected', 'true'); expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith(1); }); it('should have no tab item rendered when condition is false', async () => { render(React.createElement(TestConditionalTabs, { condition: false })); const tabsLength = tabs().length; expect(tabsLength).toBe(0); }); }); // eslint-disable-next-line react/display-name const TestTabs = forwardRef(({ onActiveTabChange }, ref) => (React.createElement(Tabs, { "aria-label": "Test tabs", onActiveTabChange: onActiveTabChange, ref: ref }, React.createElement(Tabs.Item, { title: "Profile", icon: HiUserCircle }, "Profile content"), React.createElement(Tabs.Item, { title: "Dashboard", icon: MdDashboard }, "Dashboard content"), React.createElement(Tabs.Item, { title: "Settings", icon: HiAdjustments }, "Settings content"), React.createElement(Tabs.Item, { title: "Contacts", icon: HiClipboardList }, "Contacts content"), React.createElement(Tabs.Item, { disabled: true, title: "Disabled" }, "Disabled content")))); // eslint-disable-next-line react/display-name const TestConditionalTabs = forwardRef(({ condition }) => (React.createElement(Tabs, { "aria-label": "Test tabs" }, condition && (React.createElement(Tabs.Item, { title: "Profile", icon: HiUserCircle }, "Profile content"))))); const TestTabsDifferentActiveItem = () => (React.createElement(Tabs, { "aria-label": "Test tabs" }, React.createElement(Tabs.Item, { title: "Profile", icon: HiUserCircle }, "Profile content"), React.createElement(Tabs.Item, { active: true, title: "Dashboard", icon: MdDashboard }, "Dashboard content"), React.createElement(Tabs.Item, { title: "Settings", icon: HiAdjustments }, "Settings content"), React.createElement(Tabs.Item, { title: "Contacts", icon: HiClipboardList }, "Contacts content"), React.createElement(Tabs.Item, { disabled: true, title: "Disabled" }, "Disabled content"))); const TestTabsLastActiveItem = () => (React.createElement(Tabs, { "aria-label": "Test tabs" }, React.createElement(Tabs.Item, { title: "Profile", icon: HiUserCircle }, "Profile content"), React.createElement(Tabs.Item, { title: "Dashboard", icon: MdDashboard }, "Dashboard content"), React.createElement(Tabs.Item, { title: "Settings", icon: HiAdjustments }, "Settings content"), React.createElement(Tabs.Item, { title: "Contacts", icon: HiClipboardList }, "Contacts content"), React.createElement(Tabs.Item, { active: true, title: "Still working" }, "Completely functional content"))); const tabs = () => screen.queryAllByRole('tab'); const activeTab = () => tabs().find((tab) => tab.getAttribute('aria-selected') === 'true'); const firstTab = () => tabs()[0]; const lastTab = () => tabs()[tabs().length - 1];