import { act, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { ARROW_DOWN, ENTER, ESCAPE } from '../../jest/keys';
import { SilkeAutocompleteField } from './silke-autocomplete-field';
type Item = {
label: string;
value: string;
};
const makeItem = (value: string): Item => ({ label: value, value });
const items: Item[] = [
makeItem('cure'),
makeItem('cat'),
makeItem('lion'),
makeItem('bear'),
makeItem('deer'),
];
describe('silke-autocomplete-field', () => {
beforeAll(() => {
window.HTMLElement.prototype.scrollIntoView = function () {};
});
it('Displays all options when clicking input field', async () => {
const user = userEvent.setup();
render();
const input = screen.getByLabelText('Animal');
await act(async () => await user.click(input));
const list = screen.getByRole('listbox');
items.forEach((item) => {
expect(list.textContent).toContain(item.label);
});
});
it('Hides all options when pressing ESC key', async () => {
const user = userEvent.setup();
render();
const input = screen.getByLabelText('Animal');
await act(async () => await user.click(input));
const list = screen.getByRole('listbox');
items.forEach((item) => {
expect(list.textContent).toContain(item.label);
});
await act(async () => await user.keyboard(ESCAPE));
const list2 = await screen.queryAllByRole('listbox');
expect(list2).toHaveLength(0);
});
it('It is possible to search for item', async () => {
const user = userEvent.setup();
render();
const input = screen.getByLabelText('Animal');
act(() => input.focus());
await act(async () => await user.keyboard(ARROW_DOWN));
await act(async () => await user.keyboard('C'));
const listbox = screen.getByRole('listbox');
['cat', 'cure'].forEach((label) => {
expect(listbox.textContent).toContain(label);
});
['lion', 'beer', 'deer'].forEach((label) => {
expect(listbox.textContent).not.toContain(label);
});
await act(async () => await user.keyboard('A'));
['cat'].forEach((label) => {
expect(listbox.textContent).toContain(label);
});
['lion', 'beer', 'deer', 'cure'].forEach((label) => {
expect(listbox.textContent).not.toContain(label);
});
});
it('Is possible to add new items when clicking add button', async () => {
const user = userEvent.setup();
const onChange = jest.fn();
const onAdd = jest.fn();
render(
,
);
const input = screen.getByLabelText('Animal');
act(() => input.focus());
await act(async () => await user.keyboard('banana'));
const addButton = screen.getByText('+ Add item "banana"');
await act(async () => await user.click(addButton));
expect(onAdd).toHaveBeenCalledWith('banana');
});
it('Is possible to add new items by typing the item and then press ENTER', async () => {
const user = userEvent.setup();
const onChange = jest.fn();
const onAdd = jest.fn();
render(
,
);
const input = screen.getByLabelText('Animal');
act(() => input.focus());
await act(async () => await user.keyboard('banana'));
await act(async () => await user.keyboard(ENTER));
expect(onAdd).toHaveBeenCalledWith('banana');
});
it('Is possible to select item by clicking on it', async () => {
const user = userEvent.setup();
const onChange = jest.fn();
render();
const input = screen.getByLabelText('Animal');
await act(async () => await user.click(input));
const bearItem = screen.getByText('bear');
await act(async () => await user.click(bearItem));
expect(onChange).toHaveBeenCalledWith('bear');
});
it('Is possible to select item by using keyboard only', async () => {
const user = userEvent.setup();
const onChange = jest.fn();
render();
const input = screen.getByLabelText('Animal');
act(() => input.focus());
await act(async () => await user.keyboard(ARROW_DOWN));
await act(async () => await user.keyboard(ARROW_DOWN));
await act(async () => await user.keyboard(ARROW_DOWN));
await act(async () => await user.keyboard(ENTER));
expect(onChange).toHaveBeenCalledWith('bear');
});
});