import * as React from 'react'; import { cleanup, render, screen, } from '@testing-library/react'; import { TextControl } from '@tesseract-design/web-base'; import userEvent from '@testing-library/user-event'; import { afterEach, expect, vi, describe, it, } from 'vitest'; import matchers from '@testing-library/jest-dom/matchers'; import { PluginAPI } from 'tailwindcss/types/config'; import { DropdownSelect, DropdownSelectDerivedElement, dropdownSelectPlugin, } from '.'; expect.extend(matchers); describe('dropdownSelectPlugin', () => { it('adds component styles', () => { const pluginApi = { addComponents: vi.fn(), } as unknown as PluginAPI; dropdownSelectPlugin(pluginApi); expect(pluginApi.addComponents).toBeCalledTimes(1); }); }); describe('DropdownSelect', () => { afterEach(() => { cleanup(); }); it('renders a combobox', () => { render(); const combobox = screen.getByRole('combobox'); expect(combobox).toBeInTheDocument(); }); it('renders a border', () => { render( , ); const border = screen.getByTestId('border'); expect(border).toBeInTheDocument(); }); it('renders a label', () => { render( , ); const combobox = screen.getByLabelText('foo'); expect(combobox).toBeInTheDocument(); const label = screen.getByTestId('label'); expect(label).toHaveTextContent('foo'); }); it('renders a hidden label', () => { render( , ); const combobox = screen.getByLabelText('foo'); expect(combobox).toBeInTheDocument(); const label = screen.getByTestId('label'); expect(label).toHaveClass('sr-only'); }); it('renders a hint', () => { render( , ); const hint = screen.getByTestId('hint'); expect(hint).toBeInTheDocument(); }); it('renders an indicator', () => { render( , ); const indicator = screen.getByTestId('indicator'); expect(indicator).toBeInTheDocument(); }); it('render options with implicit values', () => { render( , ); const combobox = screen.getByRole('combobox'); expect(combobox.children).toHaveLength(2); }); it('renders valid options', () => { render( , ); const combobox = screen.getByRole('combobox'); expect(combobox.children).toHaveLength(2); }); it('renders option groups', () => { render( , ); const combobox = screen.getByRole('combobox'); expect(combobox.children).toHaveLength(2); expect(combobox.children[0].children).toHaveLength(1); expect(combobox.children[1].children).toHaveLength(2); }); describe.each` size | inputClassNames | hintClassNames | indicatorClassNames ${'small'} | ${'h-10'} | ${'pr-10'} | ${'w-10'} ${'medium'} | ${'h-12'} | ${'pr-12'} | ${'w-12'} ${'large'} | ${'h-16'} | ${'pr-16'} | ${'w-16'} `('on $size size', ({ size, inputClassNames, hintClassNames, indicatorClassNames, }: { size: TextControl.Size, inputClassNames: string, hintClassNames: string, indicatorClassNames: string, }) => { it('renders input styles', () => { render( , ); const combobox = screen.getByRole('combobox'); expect(combobox).toHaveClass(inputClassNames); }); it('renders hint styles with indicator', () => { render( , ); const hint = screen.getByTestId('hint'); expect(hint).toHaveClass(hintClassNames); }); it('renders indicator styles', () => { render( , ); const indicator = screen.getByTestId('indicator'); expect(indicator).toHaveClass(indicatorClassNames); }); it('renders indicator styles for label', () => { render( , ); const label = screen.getByTestId('label'); expect(label).toHaveClass(hintClassNames); }); }); it('renders a block input', () => { render( , ); const base = screen.getByTestId('base'); expect(base).toHaveClass('block'); }); describe.each` variant | inputClassNames | hintClassNames ${'default'} | ${'pl-4'} | ${'bottom-0 pl-4 pb-1'} ${'alternate'} | ${'pl-1.5 pt-4'} | ${'top-0.5'} `('on $variant variant', ({ variant, inputClassNames, hintClassNames, }: { variant: TextControl.Variant, inputClassNames: string, hintClassNames: string, }) => { it('renders input styles', () => { render( , ); const combobox = screen.getByRole('combobox'); expect(combobox).toHaveClass(inputClassNames); }); it('renders hint styles', () => { render( , ); const hint = screen.getByTestId('hint'); expect(hint).toHaveClass(hintClassNames); }); }); it('handles change events', async () => { const onChange = vi.fn().mockImplementationOnce( (e: React.ChangeEvent) => { e.preventDefault(); }, ); render( , ); const combobox: HTMLSelectElement = screen.getByRole('combobox'); const [, secondOption] = screen.getAllByRole('option'); await userEvent.selectOptions(combobox, secondOption); expect(onChange).toBeCalled(); }); });