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