import React, { useState } from 'react' import { type Selection } from '@react-types/shared' import { render, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { FilterMultiSelect, type FilterMultiSelectProps } from './FilterMultiSelect' import { type ItemType } from './types' import { getSelectedOptionLabels } from './utils' const user = userEvent.setup() const mockItems = [ { label: 'Front-End', value: 'id-fe', count: '1245' }, { label: 'Back-End', value: 'id-be', count: '4', isDisabled: true }, { label: 'SRE', value: 'id-sre', count: '4', isDisabled: true }, { label: 'Dev-ops', value: 'id-devops' }, { label: 'Others', value: 'id-others' }, ] satisfies ItemType[] const FilterMultiSelectWrapper = ({ selectedKeys: propsSelectedKeys, ...props }: Partial): JSX.Element => { const [selectedKeys, setSelectedKeys] = useState( propsSelectedKeys ?? new Set(['id-fe']), ) const handleSelectionChange = (keys: Selection): void => setSelectedKeys(keys) return ( ( )} {...props} > {(): JSX.Element => ( <> {({ allItems, hasNoItems }): JSX.Element | JSX.Element[] => { if (hasNoItems) { return No results found. } return allItems.map((item) => ) }} )} ) } describe('', () => { it('opens the popover using the trigger button', async () => { const { getByRole } = render() const triggerButton = getByRole('button', { name: 'Engineer : Front-End' }) await user.click(triggerButton) await waitFor(() => { expect(getByRole('listbox')).toBeVisible() }) }) it('selects an unselected option on click', async () => { const { getByRole } = render() const devOpsOption = getByRole('option', { name: 'Dev-ops', selected: false, }) await user.click(devOpsOption) await waitFor(() => { expect(devOpsOption).toHaveAttribute('aria-selected', 'true') }) }) it('deselects a selected option on click', async () => { const { getByRole } = render() const devOpsOption = getByRole('option', { name: 'Front-End', selected: true, }) await user.click(devOpsOption) await waitFor(() => { expect(devOpsOption).toHaveAttribute('aria-selected', 'false') }) }) it('filters out options which do not match the search term', async () => { const { getByRole, getAllByRole } = render() expect(getAllByRole('option')).toHaveLength(5) await user.type(getByRole('searchbox'), 'end') await waitFor(() => { expect(getAllByRole('option')).toHaveLength(2) }) }) describe('Clear button', () => { it('deselects all options when unfiltered', async () => { const { getByRole, queryAllByRole } = render( , ) expect(queryAllByRole('option', { selected: true })).toHaveLength(2) await user.click(getByRole('button', { name: 'Clear selections' })) await waitFor(() => { expect(queryAllByRole('option', { selected: true })).toHaveLength(0) }) }) it('deselects only selected filtered options', async () => { const { getByRole, queryAllByRole } = render( , ) expect(queryAllByRole('option')).toHaveLength(5) expect(queryAllByRole('option', { selected: true })).toHaveLength(2) const searchbox = getByRole('searchbox') await user.type(searchbox, 'dev') await waitFor(() => { expect(queryAllByRole('option', { selected: true })).toHaveLength(1) }) await user.click(getByRole('button', { name: 'Clear selections' })) await user.clear(searchbox) await waitFor(() => { expect(queryAllByRole('option', { selected: true })).toHaveLength(1) }) }) }) describe('Select all button', () => { const getDisabledOptions = (options: HTMLElement[]): HTMLElement[] => options.filter((option) => option.hasAttribute('aria-disabled')) it('selects all non-disabled options when unfiltered', async () => { const { getByRole, queryAllByRole } = render( , ) const allOptions = queryAllByRole('option') expect(allOptions).toHaveLength(5) expect(getDisabledOptions(allOptions)).toHaveLength(2) await user.click(getByRole('button', { name: 'Select all' })) await waitFor(() => { expect(queryAllByRole('option', { selected: true })).toHaveLength(3) }) }) it('selects only non-disabled filtered options', async () => { const { getByRole, queryAllByRole } = render( , ) expect(queryAllByRole('option')).toHaveLength(5) const searchbox = getByRole('searchbox') await user.type(searchbox, 'end') await waitFor(() => { const filteredOptions = queryAllByRole('option') expect(filteredOptions).toHaveLength(2) expect(getDisabledOptions(filteredOptions)).toHaveLength(1) }) await user.click(getByRole('button', { name: 'Select all' })) await user.clear(searchbox) await waitFor(() => { expect(queryAllByRole('option', { selected: true })).toHaveLength(1) }) }) }) })