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