From 5c44a20a7539fb7c69e31cf8393df71fedf5dccc Mon Sep 17 00:00:00 2001 From: Soumya Raju Date: Fri, 6 Dec 2024 21:39:27 +0530 Subject: [PATCH] Increase code coverage for multiselect component (#18146) * test: multiselect adding tests * test: multiselect adding tests * test: multiselect adding more tests * test: multiselect adding more tests * test: multiselect adding more tests * test: multiselect adding more tests --------- Co-authored-by: Gururaj J <89023023+Gururajj77@users.noreply.github.com> Co-authored-by: Nikhil Tomar <63502271+2nikhiltom@users.noreply.github.com> --- .../MultiSelect/__tests__/MultiSelect-test.js | 133 +++++++++++++++++- 1 file changed, 128 insertions(+), 5 deletions(-) diff --git a/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js b/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js index 8e16e2c4dc20..d335cc8fe3e7 100644 --- a/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js +++ b/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js @@ -5,15 +5,22 @@ * LICENSE file in the root directory of this source tree. */ -import { getByText, isElementVisible } from '@carbon/test-utils/dom'; -import { act, render, screen } from '@testing-library/react'; import React, { useState } from 'react'; -import MultiSelect from '../'; -import { generateItems, generateGenericItem } from '../../ListBox/test-helpers'; -import userEvent from '@testing-library/user-event'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from '@testing-library/react'; +import { generateGenericItem, generateItems } from '../../ListBox/test-helpers'; +import { getByText, isElementVisible } from '@carbon/test-utils/dom'; + import { AILabel } from '../../AILabel'; import Button from '../../Button'; import ButtonSet from '../../ButtonSet'; +import MultiSelect from '../'; +import userEvent from '@testing-library/user-event'; const prefix = 'cds'; const waitForPosition = () => act(async () => {}); @@ -802,4 +809,120 @@ describe('MultiSelect', () => { ); }); }); + + it('should prevent default behavior for ArrowDown, ArrowUp, Space, and Enter keys', async () => { + const items = generateItems(4, generateGenericItem); + const label = 'test-label'; + + render(); + + await waitForPosition(); + + const combobox = screen.getByRole('combobox'); + const keysToTest = ['ArrowDown', 'ArrowUp', ' ', 'Enter']; + + for (const key of keysToTest) { + const event = new KeyboardEvent('keydown', { + key, + bubbles: true, + cancelable: true, + }); + + const preventDefaultMock = jest.fn(); + Object.defineProperty(event, 'preventDefault', { + value: preventDefaultMock, + writable: true, + }); + + // Wrap the event dispatch in act(...) + await act(async () => { + combobox.dispatchEvent(event); + }); + + expect(preventDefaultMock).toHaveBeenCalled(); + } + }); + + it('should focus the element if mergedRef.current is defined', async () => { + const items = generateItems(4, generateGenericItem); + const label = 'test-label'; + const mergedRef = React.createRef(); // No TypeScript type annotation needed here + + render( + + ); + + // Wait for mergedRef to be defined (i.e., after component mounts) + await waitFor(() => expect(mergedRef.current).toBeDefined()); + + // Wrap the action of focusing inside `act()` + await act(async () => { + if (mergedRef.current) { + mergedRef.current.focus(); + } + }); + + // Verify that the element is focused + if (mergedRef.current) { + expect(mergedRef.current).toHaveFocus(); + } + }); + + it('should not throw an error when slug is not defined', () => { + render(); + + const combobox = screen.getByRole('combobox'); + expect(combobox).toBeInTheDocument(); + }); + it('should call preventDefault for select access keys when readonly is true', () => { + const mockPreventDefault = jest.fn(); + render( + + ); + const combobox = screen.getByRole('combobox'); + expect(combobox).toBeInTheDocument(); + combobox.addEventListener('keydown', (event) => { + if (event.key === 'Enter') { + event.preventDefault(); + mockPreventDefault(); + } + }); + fireEvent.keyDown(combobox, { key: 'Enter' }); + expect(mockPreventDefault).toHaveBeenCalled(); + }); + + it('should return a comma-separated string for an array of items', () => { + const mockItems = [{ value: 'item1' }, { value: 'item2' }]; + const mockItemToString = jest.fn((item) => item.value); + + const selectProps = { + stateReducer: jest.fn(), + isOpen: false, + itemToString: (filteredItems) => + Array.isArray(filteredItems) + ? filteredItems.map((item) => mockItemToString(item)).join(', ') + : '', + }; + const result = selectProps.itemToString(mockItems); + expect(result).toBe('item1, item2'); + expect(mockItemToString).toHaveBeenCalledTimes(2); + }); + + it('should return an empty string for non-array input', () => { + const mockItemToString = jest.fn(); + + const selectProps = { + stateReducer: jest.fn(), + isOpen: false, + itemToString: (filteredItems) => + Array.isArray(filteredItems) + ? filteredItems.map((item) => mockItemToString(item)).join(', ') + : '', + }; + + const result = selectProps.itemToString(null); + + expect(result).toBe(''); + expect(mockItemToString).not.toHaveBeenCalled(); + }); });