import { test, expect, vi } from 'vitest'; import { render, screen, within, fireEvent } from '@testing-library/react'; import DatePicker from './DatePicker'; const LABEL_TEXT = 'Date of birth'; const DATE_PICKER_ID = 'date-picker'; test('date picker renders correctly', () => { render( ); // a little hacky. maybe testid would be better? const datePicker = screen.getAllByRole('generic')[1]; const label = within(datePicker).getByText(LABEL_TEXT); const textInput = within(datePicker).getByRole('textbox'); expect(datePicker).toHaveClass('ds_datepicker'); expect(label).toHaveClass('ds_label'); expect(label).toHaveAttribute('for', textInput.id); expect(label.tagName).toEqual('LABEL'); expect(textInput).toHaveClass('ds_input', 'ds_input--fixed-10'); expect(textInput.id).toEqual(DATE_PICKER_ID); }); test('date picker with disabled dates', () => { const DISABLED_DATES = '18/05/2023 19/05/2023' render( ); const datePicker = screen.getAllByRole('generic')[1]; expect(datePicker).toHaveAttribute('data-disableddates', DISABLED_DATES); }); test('date picker with hint text', () => { const HINT_TEXT = 'My hint text' render( ); const datePicker = screen.getAllByRole('generic')[1]; const hintTextEl = screen.getByText(HINT_TEXT); const textInput = within(datePicker).getByRole('textbox'); expect(hintTextEl).toBeInTheDocument(); expect(textInput).toHaveAttribute('aria-describedby', hintTextEl.id); }); test('date picker with max date', () => { const MAX_DATE = '28/05/2023' render( ); const datePicker = screen.getAllByRole('generic')[1]; expect(datePicker).toHaveAttribute('data-maxDate', MAX_DATE); }); test('date picker with min date', () => { const MIN_DATE = '28/05/2023' render( ); const datePicker = screen.getAllByRole('generic')[1]; expect(datePicker).toHaveAttribute('data-mindate', MIN_DATE); }); test('date picker with blur fn', () => { const ONBLUR_FUNCTION = vi.fn(); render( ); const datePicker = screen.getAllByRole('generic')[1]; const textInput = within(datePicker).getByRole('textbox'); fireEvent.blur(textInput); expect(ONBLUR_FUNCTION).toHaveBeenCalled(); }); test('date picker with change fn', () => { const ONCHANGE_FUNCTION = vi.fn(); render( ); const datePicker = screen.getAllByRole('generic')[1]; const textInput = within(datePicker).getByRole('textbox'); fireEvent.change(textInput, {target: {value: 'foo'}}); expect(ONCHANGE_FUNCTION).toHaveBeenCalled(); }); test('date picker with onBlur that is not a function', () => { render( ); const datePicker = screen.getAllByRole('generic')[1]; const textInput = within(datePicker).getByRole('textbox'); fireEvent.blur(textInput); // todo: assertion // success indicated by no errors thrown // error would be thrown on an untestable thread }); test('date picker with onChange that is not a function', () => { render( ); const datePicker = screen.getAllByRole('generic')[1]; const textInput = within(datePicker).getByRole('textbox'); fireEvent.change(textInput, { target: { value: 'foo' } }); // todo: assertion // success indicated by no errors thrown // error would be thrown on an untestable thread }); test('date picker with initial value', () => { const INITIAL_VALUE = '28/05/2023'; render( ); const datePicker = screen.getAllByRole('generic')[1]; const textInput = within(datePicker).getByRole('textbox'); expect(textInput).toHaveValue(INITIAL_VALUE); }); test('date picker with multiple inputs', () => { const INITIAL_VALUE = '28/05/2023'; render( ); const datePicker = screen.getAllByRole('generic')[1]; const textInputs = within(datePicker).getAllByRole('textbox'); const dateInput = textInputs[0]; const monthInput = textInputs[1]; const yearInput = textInputs[2]; const dateLabel = within(datePicker).getByText('Day'); const monthLabel = within(datePicker).getByText('Month'); const yearLabel = within(datePicker).getByText('Year'); expect(textInputs.length).toEqual(3); expect(dateInput).toHaveValue(INITIAL_VALUE.split('/')[0]); expect(monthInput).toHaveValue(INITIAL_VALUE.split('/')[1]); expect(yearInput).toHaveValue(INITIAL_VALUE.split('/')[2]); expect(dateInput).toHaveAttribute('id', `${DATE_PICKER_ID}-day`); expect(monthInput).toHaveAttribute('id', `${DATE_PICKER_ID}-month`); expect(yearInput).toHaveAttribute('id', `${DATE_PICKER_ID}-year`); expect(dateInput).toHaveClass('ds_input', 'ds_input--fixed-2', 'js-datepicker-date'); expect(monthInput).toHaveClass('ds_input', 'ds_input--fixed-2', 'js-datepicker-month'); expect(yearInput).toHaveClass('ds_input', 'ds_input--fixed-4', 'js-datepicker-year'); expect(dateLabel).toHaveClass('ds_label'); expect(monthLabel).toHaveClass('ds_label'); expect(yearLabel).toHaveClass('ds_label'); expect(dateLabel).toHaveAttribute('for', dateInput.id); expect(monthLabel).toHaveAttribute('for', monthInput.id); expect(yearLabel).toHaveAttribute('for', yearInput.id); }); test('date picker with error message', () => { const ERROR_MESSAGE_TEXT = 'This is a required field'; render( ); const textInput = screen.getByRole('textbox'); const errorMessageElement = screen.getByText(ERROR_MESSAGE_TEXT); expect(textInput).toHaveClass('ds_input--error') expect(textInput).toHaveAttribute('aria-describedby', errorMessageElement.id); expect(textInput).toHaveAttribute('aria-invalid', 'true'); expect(errorMessageElement).toBeInTheDocument(); expect(errorMessageElement).toHaveClass('ds_question__error-message'); }); test('instantiating/initialising DS component script', () => { render( ) const datePicker = screen.getAllByRole('generic')[1]; expect(datePicker).toHaveClass('js-initialised'); expect(datePicker).toHaveClass('js-instantiated'); }); test('passing additional props', () => { render( ) const datePicker = screen.getAllByRole('generic')[1]; expect(datePicker?.dataset.test).toEqual('foo'); }); test('passing additional CSS classes', () => { render( ) const datePicker = screen.getAllByRole('generic')[1]; expect(datePicker).toHaveClass('foo', 'ds_datepicker'); });