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 { MenuSelect, MenuSelectDerivedElement, } from '.'; expect.extend(matchers); describe('MenuSelect', () => { afterEach(() => { cleanup(); }); it('renders a listbox', () => { render(); const listbox = screen.getByRole('listbox'); expect(listbox).toBeInTheDocument(); }); it('renders a border', () => { render( , ); const border = screen.getByTestId('border'); expect(border).toBeInTheDocument(); }); it('renders a label', () => { render( , ); const listbox = screen.getByLabelText('foo'); expect(listbox).toBeInTheDocument(); const label = screen.getByTestId('label'); expect(label).toHaveTextContent('foo'); }); it('renders a hidden label', () => { render( , ); const listbox = screen.getByLabelText('foo'); expect(listbox).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('render options with implicit values', () => { render( , ); const listbox = screen.getByRole('listbox'); expect(listbox.children).toHaveLength(2); }); it('renders valid options', () => { render( , ); const listbox = screen.getByRole('listbox'); expect(listbox.children).toHaveLength(2); }); it('renders option groups', () => { render( , ); const listbox = screen.getByRole('listbox'); expect(listbox.children).toHaveLength(2); expect(listbox.children[0].children).toHaveLength(1); expect(listbox.children[1].children).toHaveLength(2); }); describe.each` size | inputClassNames | hintClassNames | indicatorClassNames ${'small'} | ${'min-h-10'} | ${'pr-10'} | ${'w-10'} ${'medium'} | ${'min-h-12'} | ${'pr-12'} | ${'w-12'} ${'large'} | ${'min-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 listbox = screen.getByRole('listbox'); expect(listbox).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-5'} | ${'top-0.5'} `('on $variant variant', ({ variant, inputClassNames, hintClassNames, }: { variant: TextControl.Variant, inputClassNames: string, hintClassNames: string, }) => { it('renders input styles', () => { render( , ); const listbox = screen.getByRole('listbox'); expect(listbox).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 listbox: HTMLSelectElement = screen.getByRole('listbox'); const [, secondOption] = screen.getAllByRole('option'); await userEvent.selectOptions(listbox, secondOption); expect(onChange).toBeCalled(); }); });