From 90334f33f1cb3bb9b1cb637e7faef93be6bee746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Myl=C3=A8ne?= <187286904+mleroy-pass@users.noreply.github.com> Date: Tue, 31 Dec 2024 10:37:18 +0100 Subject: [PATCH] (PC-33528)[PRO] feat: add test to the new component --- .../ui-kit/MultiSelect/MultiSelect.spec.tsx | 29 ---- .../MultiSelect/MultiSelect.stories.tsx | 11 ++ pro/src/ui-kit/MultiSelect/MultiSelect.tsx | 10 +- pro/src/ui-kit/MultiSelect/TODO.md | 1 + .../__specs__/MultiSelect.spec.tsx | 132 ++++++++++++++++++ .../__specs__/MultiSelectPanel.spec.tsx | 99 +++++++++++++ 6 files changed, 246 insertions(+), 36 deletions(-) delete mode 100644 pro/src/ui-kit/MultiSelect/MultiSelect.spec.tsx create mode 100644 pro/src/ui-kit/MultiSelect/__specs__/MultiSelect.spec.tsx create mode 100644 pro/src/ui-kit/MultiSelect/__specs__/MultiSelectPanel.spec.tsx diff --git a/pro/src/ui-kit/MultiSelect/MultiSelect.spec.tsx b/pro/src/ui-kit/MultiSelect/MultiSelect.spec.tsx deleted file mode 100644 index ffc4c57bf9c..00000000000 --- a/pro/src/ui-kit/MultiSelect/MultiSelect.spec.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { screen } from '@testing-library/react' -import { axe } from 'vitest-axe' - -import { - renderWithProviders, - RenderWithProvidersOptions, -} from 'commons/utils/renderWithProviders' - -import { MultiSelect } from './MultiSelect' - -const renderMultiSelect = (options?: RenderWithProvidersOptions) => { - return renderWithProviders(, { ...options }) -} - -describe('', () => { - it('should render correctly', async () => { - renderMultiSelect() - - expect( - await screen.findByRole('heading', { name: /MultiSelect/ }) - ).toBeInTheDocument() - }) - - it('should not have accessibility violations', async () => { - const { container } = renderMultiSelect() - - expect(await axe(container)).toHaveNoViolations() - }) -}) diff --git a/pro/src/ui-kit/MultiSelect/MultiSelect.stories.tsx b/pro/src/ui-kit/MultiSelect/MultiSelect.stories.tsx index 0040eefe920..2dcd9948586 100644 --- a/pro/src/ui-kit/MultiSelect/MultiSelect.stories.tsx +++ b/pro/src/ui-kit/MultiSelect/MultiSelect.stories.tsx @@ -57,3 +57,14 @@ export const WithSearchInput: StoryObj = { label: 'Selectionner des départements', }, } + +export const WithSelectAllOption: StoryObj = { + args: { + ...defaultProps, + hasSelectAllOptions: true, + searchExample: 'Ex : 44 - Nantes', + searchLabel: 'Rechercher des départements', + legend: 'Départements', + label: 'Selectionner des départements', + }, +} diff --git a/pro/src/ui-kit/MultiSelect/MultiSelect.tsx b/pro/src/ui-kit/MultiSelect/MultiSelect.tsx index 331178b987b..a6ee2e80ef9 100644 --- a/pro/src/ui-kit/MultiSelect/MultiSelect.tsx +++ b/pro/src/ui-kit/MultiSelect/MultiSelect.tsx @@ -124,7 +124,7 @@ export const MultiSelect = ({ )} item.id)} removeOption={handleRemoveItem} fieldName="tags" @@ -137,8 +137,7 @@ export const MultiSelect = ({ ) } -{ - /* +/* Label du bouton Rechercher des ... @@ -169,10 +168,8 @@ export const MultiSelect = ({ Pervenche */ -} -{ - /* +/* {departments.map(department => ( @@ -188,4 +185,3 @@ export const MultiSelect = ({ ))} */ -} diff --git a/pro/src/ui-kit/MultiSelect/TODO.md b/pro/src/ui-kit/MultiSelect/TODO.md index 42d132cd1ab..007015a3f7d 100644 --- a/pro/src/ui-kit/MultiSelect/TODO.md +++ b/pro/src/ui-kit/MultiSelect/TODO.md @@ -7,6 +7,7 @@ Fonctionnel Design - [] corriger la zone de clic sur BaseCheckbox +- [] Passer les selected tag en violet - [] corriger le curseur de BaseCheckbox - [] ajuster la hauteur des checkbox - [] utiliser les fonts du design system diff --git a/pro/src/ui-kit/MultiSelect/__specs__/MultiSelect.spec.tsx b/pro/src/ui-kit/MultiSelect/__specs__/MultiSelect.spec.tsx new file mode 100644 index 00000000000..ad8159e816a --- /dev/null +++ b/pro/src/ui-kit/MultiSelect/__specs__/MultiSelect.spec.tsx @@ -0,0 +1,132 @@ +import { render, screen, fireEvent, waitFor } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event' +import { axe } from 'vitest-axe' + +import { MultiSelect, Option } from '../MultiSelect' + +describe('', () => { + const options: Option[] = [ + { id: '1', label: 'Option 1' }, + { id: '2', label: 'Option 2' }, + { id: '3', label: 'Option 3' }, + ] + + const defaultOptions: Option[] = [{ id: '1', label: 'Option 1' }] + + it('should render correctly', async () => { + render( + + ) + + expect(await screen.findByText('Select Options')).toBeInTheDocument() + }) + + it('should not have accessibility violations', async () => { + const { container } = render( + + ) + + expect(await axe(container)).toHaveNoViolations() + }) + + it('renders the MultiSelect component with the correct initial selected options', () => { + render( + + ) + // Check that the initial selected options are rendered in the SelectedValuesTags + expect(screen.getByText('Option 1')).toBeInTheDocument() + }) + + it('toggles the dropdown when the trigger is clicked', async () => { + render( + + ) + const toggleButton = screen.getByText('Select Options') + await userEvent.click(toggleButton) // Open the dropdown + expect(screen.getByText(/Tout sélectionner/i)).toBeInTheDocument() + + await userEvent.click(toggleButton) // Close the dropdown + expect(screen.queryByText(/Tout sélectionner/i)).not.toBeInTheDocument() + }) + + it('selects all options when "Select All" is clicked', async () => { + render( + + ) + + const toggleButton = screen.getByText('Select Options') + await userEvent.click(toggleButton) // Open the dropdown + + const selectAllCheckbox = screen.getByLabelText(/Tout sélectionner/i) + fireEvent.click(selectAllCheckbox) // Select all options + + // Verify that all options are selected + options.forEach((option) => { + expect(screen.getByLabelText(option.label)).toBeChecked() + }) + }) + + it('removes an option from the selected items when clicked in SelectedValuesTags', async () => { + render( + + ) + + // Initially, Option 1 is selected + const selectedTag = screen.getByText('Option 1') + await userEvent.click(selectedTag) // Remove Option 1 + expect(screen.queryByText('Option 1')).not.toBeInTheDocument() + }) + + it('closes the dropdown when clicked outside or when Escape key is pressed', async () => { + render( + + ) + + const toggleButton = screen.getByText('Select Options') + + fireEvent.click(toggleButton) // Open the dropdown + expect(screen.queryByText('Option 1')).toBeInTheDocument() + + // Simulate a click outside the dropdown + fireEvent.click(document.body) + await waitFor(() => + expect(screen.queryByText('Option 1')).not.toBeInTheDocument() + ) + + fireEvent.click(toggleButton) // Open the dropdown again + fireEvent.keyDown(toggleButton, { key: 'Escape' }) // Close with Escape key + await waitFor(() => + expect(screen.queryByText('Option 1')).not.toBeInTheDocument() + ) + }) +}) diff --git a/pro/src/ui-kit/MultiSelect/__specs__/MultiSelectPanel.spec.tsx b/pro/src/ui-kit/MultiSelect/__specs__/MultiSelectPanel.spec.tsx new file mode 100644 index 00000000000..02132f0c2f8 --- /dev/null +++ b/pro/src/ui-kit/MultiSelect/__specs__/MultiSelectPanel.spec.tsx @@ -0,0 +1,99 @@ +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { axe } from 'vitest-axe' + +import { Option } from '../MultiSelect' +import { MultiSelectPanel } from '../MultiSelectPanel' + +describe('', () => { + const options: (Option & { checked: boolean })[] = [ + { id: '1', label: 'Option 1', checked: false }, + { id: '2', label: 'Option 2', checked: false }, + { id: '3', label: 'Option 3', checked: false }, + ] + + const defaultOptions: Option[] = [{ id: '1', label: 'Option 1' }] + + const onOptionSelect = vi.fn() + + it('renders options with checkboxes', () => { + render( + + ) + + expect(screen.getByLabelText('Option 1')).toBeInTheDocument() + expect(screen.getByLabelText('Option 2')).toBeInTheDocument() + expect(screen.getByLabelText('Option 3')).toBeInTheDocument() + }) + + it('renders the search input if hasSearch is true', () => { + render( + + ) + + expect(screen.getByText(/Exemple: Nantes/i)).toBeInTheDocument() + }) + + it('not renders the search input if hasSearch is false', () => { + render( + + ) + + expect(screen.queryByText(/Exemple: Nantes/i)).not.toBeInTheDocument() + }) + + it('should not have accessibility violations', async () => { + const { container } = render( + + ) + + expect(await axe(container)).toHaveNoViolations() + }) + + it('selects and deselects individual options', async () => { + render( + + ) + + // Initially, only Option 1 is selected + const option2Checkbox = screen.getByLabelText(/Option 2/i) + await userEvent.click(option2Checkbox) // Select Option 2 + expect(onOptionSelect).toHaveBeenCalledWith(options[1]) + + await userEvent.click(option2Checkbox) // Deselect Option 2 + expect(onOptionSelect).toHaveBeenCalledWith(options[1]) + }) +})