import { test, expect, vi } from 'vitest'; import { render, screen, within } from '@testing-library/react'; import SiteSearch from './SiteSearch'; const SITE_SEARCH_ID = 'site-search'; const LABEL_TEXT = 'Search'; const PLACEHOLDER_TEXT = 'Search'; test('site search renders correctly', () => { render( ); const searchForm = screen.getByRole('search'); const searchFormContainer = searchForm.parentElement; const searchLabel = document.querySelector('label'); const searchInput = within(searchForm).getByRole('searchbox'); const inputWrapper = searchInput.parentElement; const searchButton = within(searchForm).getByRole('button'); expect(searchFormContainer).toHaveClass('ds_site-search'); expect(searchFormContainer?.tagName).toEqual('DIV'); expect(searchFormContainer).not.toHaveAttribute('id', 'site-search-autocomplete'); expect(searchForm).toHaveClass('ds_site-search__form'); expect(searchForm).toHaveAttribute('method', 'GET'); expect(searchForm).toHaveAttribute('action', '/search'); expect(searchLabel?.textContent).toEqual(LABEL_TEXT); expect(searchLabel).toHaveAttribute('for', SITE_SEARCH_ID); expect(searchLabel).toHaveAttribute('id', `${SITE_SEARCH_ID}-label`); expect(searchLabel).toHaveClass('ds_label', 'visually-hidden'); expect(inputWrapper).toHaveClass('ds_input__wrapper ds_input__wrapper--has-icon'); expect(inputWrapper?.tagName).toEqual('DIV'); expect(searchInput).toHaveClass('ds_input', 'ds_site-search__input'); expect(searchInput).toHaveAttribute('id', SITE_SEARCH_ID); expect(searchInput).toHaveAttribute('placeholder', PLACEHOLDER_TEXT); expect(searchInput).toHaveAttribute('required'); expect(searchInput).toHaveAttribute('spellcheck', 'false'); expect(searchInput).toHaveAttribute('type', 'search'); expect(searchInput).toHaveAttribute('name', 'q'); expect(searchInput).not.toHaveAttribute('autocomplete'); expect(searchButton).toHaveClass('ds_button'); expect(searchButton).toHaveAttribute('type', 'submit'); expect(searchButton.textContent).toEqual('Search'); }); test('custom action', () => { render( ); const searchForm = screen.getByRole('search'); expect(searchForm).toHaveAttribute('action', '/foo'); }); test('custom id', () => { render( ); const searchForm = screen.getByRole('search'); const searchInput = within(searchForm).getByRole('searchbox'); expect(searchInput).toHaveAttribute('id', 'foo'); }); test('custom method', () => { render( ); const searchForm = screen.getByRole('search'); expect(searchForm).toHaveAttribute('method', 'POST'); }); test('custom name', () => { render( ); const searchForm = screen.getByRole('search'); const searchInput = within(searchForm).getByRole('searchbox'); expect(searchInput).toHaveAttribute('name', 'foo'); }); test('custom placeholder', () => { render( ); const searchForm = screen.getByRole('search'); const searchInput = within(searchForm).getByRole('searchbox'); expect(searchInput).toHaveAttribute('placeholder', 'foo'); }); test('autocomplete', () => { const AUTOCOMPLETE_SUGGESTION_MAPPING_FUNCTION = vi.fn(); const SUGGESTIONS_ID = 'autocomplete-suggestions'; render( ) const searchForm = screen.getByRole('search'); const searchFormContainer = searchForm.parentElement; const searchInput = within(searchForm).getByRole('searchbox'); const autocompleteStatus = within(searchForm).getByRole('status'); const suggestionsContainer = document.querySelector('.ds_autocomplete__suggestions'); const suggestionsList = within(searchForm).getByRole('listbox'); expect(searchFormContainer).toHaveClass('ds_autocomplete'); expect(searchFormContainer).toHaveAttribute('id', `${SITE_SEARCH_ID}-autocomplete`); expect(autocompleteStatus).toBeInTheDocument(); expect(autocompleteStatus).toHaveClass('visually-hidden'); expect(autocompleteStatus).toHaveAttribute('aria-live', 'polite'); expect(autocompleteStatus).toHaveAttribute('id', 'autocomplete-status'); expect(autocompleteStatus.tagName).toEqual('DIV'); expect(searchInput).toHaveAttribute('aria-autocomplete', 'list'); expect(searchInput).toHaveAttribute('aria-owns', SUGGESTIONS_ID); expect(searchInput).toHaveAttribute('autocomplete', 'off'); expect(searchInput).toHaveClass('js-autocomplete-input'); expect(suggestionsContainer).toHaveAttribute('id', SUGGESTIONS_ID); expect(suggestionsContainer?.tagName).toEqual('DIV'); expect(suggestionsList).toHaveClass('ds_autocomplete__suggestions-list'); expect(suggestionsList).toHaveAttribute('aria-labelledby', `${SITE_SEARCH_ID}-label`); expect(suggestionsList.tagName).toEqual('OL'); }); test('instantiating/initialising DS component script: autocomplete', () => { render( ); const searchForm = screen.getByRole('search'); const searchFormContainer = searchForm.parentElement; expect(searchFormContainer).toHaveClass('js-initialised'); expect(searchFormContainer).toHaveClass('js-instantiated'); }); test('instantiating/initialising DS component script: no autocomplete', () => { render( ); const searchForm = screen.getByRole('search'); const searchFormContainer = searchForm.parentElement; expect(searchFormContainer).not.toHaveClass('js-initialised'); expect(searchFormContainer).not.toHaveClass('js-instantiated'); }); test('passing additional props', () => { render( ); const searchForm = screen.getByRole('search'); const searchFormContainer = searchForm.parentElement; expect(searchFormContainer?.dataset.test).toEqual('foo'); }); test('passing additional CSS classes', () => { render( ); const searchForm = screen.getByRole('search'); const searchFormContainer = searchForm.parentElement; expect(searchFormContainer).toHaveClass('foo', 'ds_site-search'); });