@vertisanpro/flowbite-react
Version:
Non-Official React components built for Flowbite and Tailwind CSS
126 lines (125 loc) • 7.14 kB
JavaScript
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];