import { h } from 'preact'; import { render, fireEvent, waitFor } from '@testing-library/preact'; import userEvent from '@testing-library/user-event'; import { axe } from 'jest-axe'; import { Search } from '../Search'; import { locale } from '../../utilities/locale'; describe('', () => { beforeEach(() => { global.filterXSS = jest.fn(); global.InstantClick = jest.fn(() => ({ on: jest.fn(), off: jest.fn(), preload: jest.fn(), display: jest.fn(), }))(); global.instantClick = jest.fn(() => ({}))(); }); it('should have no a11y violations', async () => { const props = { searchTerm: 'fish', setSearchTerm: jest.fn(), }; const { container } = render(); const results = await axe(container); expect(results).toHaveNoViolations(); }); it('should have a search textbox', () => { const props = { searchTerm: 'fish', setSearchTerm: jest.fn(), }; const { getByRole } = render(); const searchInput = getByRole('textbox', { name: /search/i }); expect(searchInput.value).toEqual('fish'); expect(searchInput.getAttribute('placeholder')).toEqual(`${locale('core.search')}...`); expect(searchInput.getAttribute('autocomplete')).toEqual('off'); }); it('should contain text the user entered in the search textbox', async () => { const props = { searchTerm: 'fish', setSearchTerm: jest.fn(), }; const { getByRole, findByRole } = render(); let searchInput = getByRole('textbox', { name: /search/i }); expect(searchInput.value).toEqual('fish'); fireEvent.change(searchInput, { target: { value: 'hello' } }); searchInput = await findByRole('textbox', { name: /search/i }); expect(searchInput.value).toEqual('hello'); }); it('should set the search term', async () => { const props = { searchTerm: '', setSearchTerm: jest.fn(), }; const { getByRole } = render(); const searchInput = getByRole('textbox', { name: /search/i }); expect(searchInput.value).toEqual(''); userEvent.type(searchInput, 'hello'); waitFor(() => { expect(searchInput.value).toEqual('hello'); expect(props.setSearchTerm).toHaveBeenCalledWith('hello'); }); }); it('should submit the search form', async () => { const props = { searchTerm: '', setSearchTerm: jest.fn(), onSubmitSearch: jest.fn(), }; const { getByRole, findByRole } = render(); let searchInput = getByRole('textbox', { name: /search/i }); expect(searchInput.value).toEqual(''); userEvent.type(searchInput, 'hello'); fireEvent.submit(getByRole('search')); searchInput = await findByRole('textbox', { name: /search/i }); waitFor(() => { expect(searchInput.value).toEqual('hello'); expect(props.onSubmitSearch).toHaveBeenCalledWith('hello'); }); }); it('should be listening for history state changes', async () => { // This is an implementation detail, but I want to make sure that this // listener is registered as it affects the UI. jest.spyOn(window, 'addEventListener'); const props = { searchTerm: '', setSearchTerm: jest.fn(), }; render(); expect(window.addEventListener).toHaveBeenNthCalledWith( 1, 'popstate', expect.any(Function), ); }); it('should stop listening for history state changes when the component is destroyed', async () => { // This is an implementation detail, but I want to make sure that this // listener is unregistered as it affects the UI. jest.spyOn(window, 'removeEventListener'); const props = { searchTerm: '', setSearchTerm: jest.fn(), }; const { unmount } = render(); unmount(); expect(window.removeEventListener).toHaveBeenNthCalledWith( 1, 'popstate', expect.any(Function), ); }); });