import { fireEvent, render, screen } from '@testing-library/react' import { default as MultiSelect, MultiSelectGroup } from '.' describe('MultiSelect', () => { describe('in development mode', () => { beforeEach(() => { process.env.NODE_ENV = 'development' }) describe('when `` is used without ``', () => { beforeEach(() => { // eslint-disable-next-line no-console console.error = vi.fn() render() }) it('emits error message', () => { // eslint-disable-next-line no-console expect(console.error).toHaveBeenCalledWith( expect.stringMatching( /Perhaps you forgot to wrap with /u, ), ) }) }) }) describe('none of the options selected', () => { let option1: HTMLInputElement let option2: HTMLInputElement let option3: HTMLInputElement let allOptions: HTMLInputElement[] let parent: HTMLDivElement const childOnChange = vi.fn() const parentOnChange = vi.fn() beforeEach(() => { render( , ) option1 = screen.getByDisplayValue('option1') option2 = screen.getByDisplayValue('option2') option3 = screen.getByDisplayValue('option3') allOptions = [option1, option2, option3] parent = screen.getByTestId('SelectGroup') }) it('options have correct name', () => { allOptions.forEach((element) => expect(element.name).toBe('defaultName')) }) it('parent have correct aria-label', () => { expect(parent.getAttribute('aria-label')).toBe('defaultAriaLabel') }) it('none of the options are selected', () => { allOptions.forEach((element) => expect(element.checked).toBeFalsy()) }) describe('selecting option1', () => { it('childOnChange is called', () => { fireEvent.click(option1) expect(childOnChange).toHaveBeenCalledWith({ value: 'option1', selected: true, }) }) it('parentOnChange is called', () => { fireEvent.click(option1) expect(parentOnChange).toHaveBeenCalledWith(['option1']) }) }) }) describe('option2 is selected', () => { let option1: HTMLInputElement let option2: HTMLInputElement let option3: HTMLInputElement const childOnChange = vi.fn() const parentOnChange = vi.fn() beforeEach(() => { render( , ) option1 = screen.getByDisplayValue('option1') option2 = screen.getByDisplayValue('option2') option3 = screen.getByDisplayValue('option3') }) it('only option2 is selected', () => { expect(option2.checked).toBeTruthy() ;[option1, option3].forEach((element) => expect(element.checked).toBeFalsy(), ) }) describe('selecting option1', () => { it('parentOnChange is called', () => { fireEvent.click(option1) expect(parentOnChange).toHaveBeenCalledWith(['option2', 'option1']) }) }) describe('de-selecting option2', () => { it('childOnChange is called', () => { fireEvent.click(option2) expect(childOnChange).toHaveBeenCalledWith({ value: 'option2', selected: false, }) }) it('parentOnChange is called', () => { fireEvent.click(option2) expect(parentOnChange).toHaveBeenCalledWith([]) }) }) }) describe('the group is disabled', () => { let option1: HTMLInputElement let option2: HTMLInputElement let option3: HTMLInputElement let allOptions: HTMLInputElement[] beforeEach(() => { render() option1 = screen.getByDisplayValue('option1') option2 = screen.getByDisplayValue('option2') option3 = screen.getByDisplayValue('option3') allOptions = [option1, option2, option3] }) it('all the options are disabled', () => { allOptions.forEach((element) => expect(element.disabled).toBeTruthy()) }) }) describe('the group is readonly', () => { let option1: HTMLInputElement let option2: HTMLInputElement let option3: HTMLInputElement let allOptions: HTMLInputElement[] beforeEach(() => { render() option1 = screen.getByDisplayValue('option1') option2 = screen.getByDisplayValue('option2') option3 = screen.getByDisplayValue('option3') allOptions = [option1, option2, option3] }) it('all the options are disabled', () => { allOptions.forEach((element) => expect(element.disabled).toBeTruthy()) }) }) describe('the group has error', () => { let option1: HTMLInputElement let option2: HTMLInputElement let option3: HTMLInputElement let allOptions: HTMLInputElement[] beforeEach(() => { render() option1 = screen.getByDisplayValue('option1') option2 = screen.getByDisplayValue('option2') option3 = screen.getByDisplayValue('option3') allOptions = [option1, option2, option3] }) it('all the options have `aria-invalid="true"`', () => { allOptions.forEach((element) => expect(element.getAttribute('aria-invalid')).toBeTruthy(), ) }) }) describe('option1 is disabled', () => { let option1: HTMLInputElement let option2: HTMLInputElement beforeEach(() => { render() option1 = screen.getByDisplayValue('option1') option2 = screen.getByDisplayValue('option2') }) it('only option1 is disabled', () => { expect(option1.disabled).toBeTruthy() expect(option2.disabled).toBeFalsy() }) }) }) const TestComponent = ({ selected, parentOnChange = () => { return }, childOnChange, parentDisabled = false, readonly = false, invalid = false, firstOptionDisabled = false, }: { selected: string[] parentOnChange?: (selected: string[]) => void childOnChange?: (payload: { value: string; selected: boolean }) => void parentDisabled?: boolean readonly?: boolean invalid?: boolean firstOptionDisabled?: boolean }) => { return ( Option 1 Option 2 Option 3 ) }