import React, { useState } from 'react'; import { act, cleanup, fireEvent } from '@testing-library/react'; import { render } from '../../../utils/theme-render-wrapper'; import { MenuContent } from '../dropdown-menu'; import { areEqualDropdownMenuItems, processDropdownMenuItemsRecursive } from '../helpers'; import type { DropdownMenuItem, MenuContentProps } from '../types'; import { mockInfinityScroll, mockListItems } from '../__mocks__/menuItems'; import noop from 'lodash/noop'; beforeEach(() => jest.useFakeTimers()); afterEach(() => { jest.runAllTimers(); jest.useRealTimers(); cleanup(); }); const handleDelete = jest.fn(); const clickableItemName = mockListItems[1].name; const disabledItemName = mockListItems[4].name; const hiddenListItems = mockListItems.map(item => ({ ...item, hidden: true })); hiddenListItems[0].options = mockListItems; const inputText = 'hello world'; const Wrapper = (props: Partial) => { const { multiple } = props; const [listItems, setListItems] = useState(mockListItems); const handleMenuClick: NonNullable = (name, value) => () => { const itemToSelect = { name, value }; const newItems = processDropdownMenuItemsRecursive(listItems, item => { const areEqual = areEqualDropdownMenuItems(item, itemToSelect); if (multiple ? areEqual : areEqual || item.selected) { return { ...item, selected: !item.selected }; } return item; }); setListItems(newItems); }; return ( ); }; describe('', () => { describe('when ListItems uses MuiList (default)', () => { it(`should render empty menus without and with loader`, () => { const { baseElement } = render( <> ); expect(baseElement).toBeTruthy(); }); it(`should render empty menu with InsertBeforeList and InsertAfterList`, () => { const { baseElement } = render( null} InsertAfterList={() => null} listItems={[]} /> ); expect(baseElement).toBeTruthy(); }); it(`should render hidden items with groups and search`, () => { const { queryByTestId } = render( ); const inputEl = queryByTestId('searchField'); expect(inputEl).toBeTruthy(); if (inputEl) { fireEvent.change(inputEl, { target: { value: inputText } }); } }); it(`should render with modifyMenuItem`, () => { const { baseElement } = render( props.selected ? { actionIcons: [], showSelectedIcon: true } : {} } /> ); expect(baseElement).toBeTruthy(); }); it(`should render with menuListHeader and menuListFooter`, () => { const menuListHeader = 'Menu List Header'; const menuListFooter = 'Menu List Footer'; const { queryByText } = render( ); expect(queryByText(menuListHeader)).toBeTruthy(); expect(queryByText(menuListFooter)).toBeTruthy(); }); it(`should render multiple variant`, () => { const { queryByText, container } = render(); queryByText(clickableItemName)?.click(); const checkboxEl = container.querySelector('input:checked'); expect(checkboxEl).toBeTruthy(); }); it(`should render single variant and click on items`, () => { const { queryByText, queryByTestId } = render(); // ignore click on disabled item queryByText(disabledItemName)?.click(); let checkedIconEl = queryByTestId('singleCheckedIcon'); expect(checkedIconEl).toBeFalsy(); // handle click on clickable item queryByText(clickableItemName)?.click(); checkedIconEl = queryByTestId('singleCheckedIcon'); expect(checkedIconEl).toBeTruthy(); }); it(`should render sortable menu items`, () => { const { queryByTestId } = render(); const sortIconElm = queryByTestId('sortIcon_0'); expect(sortIconElm).toBeTruthy(); }); it(`should render deletable menu items`, () => { const { queryByTestId } = render(); const deleteIconElm = queryByTestId('deleteIcon_0'); deleteIconElm?.click(); expect(handleDelete).toHaveBeenCalled(); }); it(`should render with debounced search`, () => { const { queryByTestId } = render( ); const inputEl = queryByTestId('searchField'); expect(inputEl).toBeTruthy(); if (inputEl) { fireEvent.change(inputEl, { target: { value: inputText } }); fireEvent.keyDown(inputEl, { code: 'Space' }); } }); it(`should render with search highlight and clear icon`, () => { const clearSelectItemsHandler = jest.fn(); const { queryByTestId } = render( ); const inputEl = queryByTestId('searchField'); expect(inputEl).toBeTruthy(); if (inputEl) { fireEvent.change(inputEl, { target: { value: inputText } }); } act(() => { jest.runAllTimers(); // because of `searchDebounceTime` }); queryByTestId('searchClear')?.click(); expect(clearSelectItemsHandler).toHaveBeenCalled(); }); it(`should render with bottomButtonText`, () => { const bottomButtonText = 'Bottom Button Text'; const bottomButtonClickHandler = jest.fn(); const { queryByText } = render( ); const bottomButtonEl = queryByText(bottomButtonText); bottomButtonEl?.click(); expect(bottomButtonClickHandler).toHaveBeenCalled(); }); }); describe('when ListItems uses VariableSizeList', () => { it(`should render empty menus without and with loader`, () => { const { baseElement } = render( <> ); expect(baseElement).toBeTruthy(); }); it(`should render empty menu with InsertBeforeList and InsertAfterList`, () => { const { baseElement } = render( null} InsertAfterList={() => null} listItems={[]} variableSizeList /> ); expect(baseElement).toBeTruthy(); }); it(`should render empty menu with groups and search`, () => { const { queryByTestId } = render( ); const inputEl = queryByTestId('searchField'); expect(inputEl).toBeTruthy(); if (inputEl) { fireEvent.change(inputEl, { target: { value: inputText } }); } }); it(`should render hidden items with groups and search`, () => { const { queryByTestId } = render( ); const inputEl = queryByTestId('searchField'); expect(inputEl).toBeTruthy(); if (inputEl) { fireEvent.change(inputEl, { target: { value: inputText } }); } }); it(`should render single variant and click on items`, () => { const { queryByText, queryByTestId } = render( ); // ignore click on disabled item queryByText(disabledItemName)?.click(); let checkedIconEl = queryByTestId('singleCheckedIcon'); expect(checkedIconEl).toBeFalsy(); // handle click on clickable item const menuItemEl = queryByText(clickableItemName); if (menuItemEl) { fireEvent.mouseUp(menuItemEl); menuItemEl?.click(); } checkedIconEl = queryByTestId('singleCheckedIcon'); expect(checkedIconEl).toBeTruthy(); }); it(`should render sortable menu items`, () => { const { queryByTestId } = render(); const sortIconElm = queryByTestId('sortIcon_0'); expect(sortIconElm).toBeTruthy(); }); it(`should render with search and click on clear icon`, () => { const handleTextChange = jest.fn(); const { queryByTestId } = render( ); const inputEl = queryByTestId('searchField'); expect(inputEl).toBeTruthy(); if (inputEl) { fireEvent.change(inputEl, { target: { value: inputText } }); } act(() => { jest.runAllTimers(); // because of `searchDebounceTime` }); queryByTestId('searchClear')?.click(); expect(handleTextChange).toHaveBeenCalled(); }); }); describe('when ListItems uses InfinityScroll', () => { it(`should render infinityScroll`, () => { const { baseElement } = render( ); expect(baseElement).toBeTruthy(); }); it(`should render infinityScroll with variableSizeList`, () => { const { baseElement } = render( ); expect(baseElement).toBeTruthy(); }); }); });