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();
});
});