From 27631f28907435c38fe460c6cbbd2b663c83a7c1 Mon Sep 17 00:00:00 2001 From: Matt Gallo Date: Wed, 24 Jan 2024 19:14:38 -0500 Subject: [PATCH] test(Datagrid): increase filtering test coverage (v1) (#4143) * test(Datagrid): increase filtering test coverage * fix(FilterSummary): change boolean proptype to bool --------- Co-authored-by: elysia --- cspell.json | 1 + .../src/components/Datagrid/Datagrid.test.js | 387 +++++++++++++++++- .../Datagrid/Datagrid/DatagridContent.js | 2 - .../Datagrid/addons/Filtering/FilterFlyout.js | 19 +- .../Datagrid/addons/Filtering/FilterPanel.js | 25 +- .../addons/Filtering/hooks/useFilters.js | 13 +- .../hooks/useShouldDisableButtons.js | 4 +- .../Datagrid/addons/Filtering/utils.js | 8 +- .../Extensions/Filtering/Flyout.stories.js | 27 +- .../src/components/Datagrid/useFiltering.js | 3 +- .../Datagrid/utils/filterPropsForTesting.js | 169 ++++++++ .../components/FilterSummary/FilterSummary.js | 17 +- .../FilterSummary/FilterSummary.test.js | 59 +++ 13 files changed, 675 insertions(+), 59 deletions(-) create mode 100644 packages/ibm-products/src/components/Datagrid/utils/filterPropsForTesting.js create mode 100644 packages/ibm-products/src/components/FilterSummary/FilterSummary.test.js diff --git a/cspell.json b/cspell.json index d3ead1e7c7..db86e3107e 100644 --- a/cspell.json +++ b/cspell.json @@ -73,6 +73,7 @@ "coachmarks", "colindex", "columnheader", + "combobox", "composability", "csstools", "ctacol", diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid.test.js b/packages/ibm-products/src/components/Datagrid/Datagrid.test.js index eb44e14593..b653a12528 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid.test.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid.test.js @@ -14,7 +14,7 @@ import { makeData } from './utils/makeData'; import { carbon, pkg } from '../../settings'; import { expectWarn, mockHTMLElement } from '../../global/js/utils/test-helper'; -import { Datagrid } from '.'; +import { Datagrid, useFilterContext } from '.'; import { useDatagrid, @@ -52,12 +52,16 @@ import { } from '@carbon/icons-react'; import { getInlineEditColumns } from './utils/getInlineEditColumns'; +import { FilteringUsage } from './Extensions/Filtering/Panel.stories'; import { - FilteringUsage, - filterProps, -} from './Extensions/Filtering/Panel.stories'; + FilteringUsage as FlyoutUsage, + filterProps as flyoutProps, +} from './Extensions/Filtering/Flyout.stories'; -// import { DatagridActions, DatagridBatchActions, DatagridPagination, } from './Datagrid.stories'; +import { + generateDummyCheckboxes, + filterProps as testFilterProps, +} from './utils/filterPropsForTesting'; import namor from 'namor'; @@ -2436,18 +2440,361 @@ describe(componentName, () => { expect(tableElement).not.toHaveClass(`${blockClass}__table-grid-active`); }); + const sharedFilterGridProps = { + gridTitle: 'Data table title', + gridDescription: 'Additional information if needed', + useDenseHeader: false, + emptyStateTitle: 'No filters match', + emptyStateDescription: + 'Data was not found with the current filters applied. Change filters or clear filters to see other results.', + }; + it('should test basic interactions of filter panel', async () => { + const { keyboard, click } = userEvent; + const dropdownOnChange = jest.fn(); + render( + + ); + const toolbar = screen.getByLabelText('data table toolbar').parentElement; + const panelContainer = toolbar.nextElementSibling; + const toolbarButtons = within(toolbar).getAllByRole('button'); + const filterToggleButton = toolbarButtons[0]; + // Open filter panel + click(filterToggleButton); + expect(panelContainer).toHaveClass( + `${blockClass}__table-container--filter-open` + ); + const normalCheckbox = screen.getByRole('checkbox', { name: 'Normal' }); + click(normalCheckbox); + + const applyButton = screen.getByRole('button', { name: 'Apply' }); + click(applyButton); + + const panelCloseButton = screen.getByLabelText('Close filter panel'); + click(panelCloseButton); + expect(panelContainer).not.toHaveClass( + `${blockClass}__table-container--filter-open` + ); + // Reopen filter panel + click(filterToggleButton); + expect(panelContainer).toHaveClass( + `${blockClass}__table-container--filter-open` + ); + + // Add value to number input and apply to filter panel + const visitsInput = screen.getByPlaceholderText( + 'Type a number amount of visits' + ); + click(visitsInput); + keyboard('5'); + expect(visitsInput).toHaveFocus(); + click(applyButton); + + // Add value to radio button and apply to filter panel + const radio = screen.getByRole('radio', { name: 'Developer' }); + click(radio); + expect(radio.checked).toEqual(true); + + // Add value to dropdown and apply to filter panel + const statusAccordion = screen.getByRole('button', { name: 'Status' }); + click(statusAccordion); + const statusDropdown = screen.getByRole('button', { + name: 'Marital status', + }); + click(statusDropdown.firstElementChild); + const dropdownOption = screen.getByRole('option', { name: 'single' }); + click(dropdownOption); + expect(dropdownOnChange).toHaveBeenCalledTimes(1); + + // Add beginning date but no end date, confirm no changes are made since we need a beginning and end date + const dateInput = screen.getAllByPlaceholderText('mm/dd/yyyy'); + click(dateInput[0]); + keyboard('01/01/2024'); + expect(dateInput[0].value).toEqual('01/01/2024'); + // Apply radio button change + const designerRadio = screen.getByRole('radio', { name: 'Designer' }); + click(designerRadio); + expect(designerRadio.checked).toEqual(true); + // Apply valid date filter + const dateInputs = screen.getAllByPlaceholderText('mm/dd/yyyy'); + click(dateInputs[0]); + keyboard('01/01/2024'); + click(dateInputs[1]); + keyboard('01/02/2024'); + expect(dateInput[0].value).toEqual('01/01/2024'); + expect(dateInput[1].value).toEqual('01/02/2024'); + // Reset to "Any" radio filter + const anyRadio = screen.getByRole('radio', { name: 'Any' }); + click(anyRadio); + expect(anyRadio.checked).toEqual(true); + // Reset number input to empty string + click(visitsInput); + fireEvent.change(visitsInput, { target: { value: '' } }); + expect(visitsInput.value).toEqual(''); + // Apply single checkbox + click(normalCheckbox); + expect(normalCheckbox.checked).toEqual(true); + // Remove checkbox + click(normalCheckbox); + expect(normalCheckbox.checked).toEqual(false); + }); + + const FilterUsageError = () => { + useFilterContext(); + return
; + }; + + it('should simulate useFilterContext error', async () => { + expect(() => { + render(); + }).toThrow('useFilterContext was used outside of its Provider'); + }); + + it('should test basic interactions of filter flyout', async () => { + const { click } = userEvent; + const updatedFilterProps = { ...flyoutProps }; + // Removing certain properties to test default function parameters in FilterFlyout + delete updatedFilterProps.panelTitle; + delete updatedFilterProps.updateMethod; + delete updatedFilterProps.primaryActionLabel; + delete updatedFilterProps.secondaryActionLabel; + delete updatedFilterProps.flyoutIconDescription; + delete updatedFilterProps.onFlyoutOpen; + delete updatedFilterProps.onFlyoutClose; + const { container } = render( + + ); + const toolbar = screen.getByLabelText('data table toolbar').parentElement; + const flyoutTrigger = within(toolbar).getByRole('button', { + name: 'Open filters', + }); + + // Open filter flyout + click(flyoutTrigger); + expect(flyoutTrigger.nextElementSibling).toHaveClass( + `${blockClass}-filter-flyout--open` + ); + + const cancelButton = screen.getByRole('button', { name: 'Cancel' }); + // Toggle radio button + const radio = screen.getByRole('radio', { name: 'Developer' }); + click(radio); + click(cancelButton); + + click(container); + expect(flyoutTrigger.nextElementSibling).not.toHaveClass( + `${blockClass}-filter-flyout--open` + ); + }); + + it('should render initial filters in flyout', async () => { + render( + + ); + const filterTags = screen.getAllByTitle('Role: developer'); + expect(Array.from(filterTags).length).toEqual(1); + }); + + it('should render initial filters in panel', async () => { const { click } = userEvent; + const ref = React.createRef(); render( + ); + const filterTags = screen.getAllByTitle('Role: developer'); + expect(Array.from(filterTags).length).toEqual(2); // Only one visible tag, but the TagSet renders two tags (one visible and one hidden which is used for measure available space) + const clearButton = screen.getByRole('button', { name: /Clear filters/i }); + click(clearButton); + const tableElement = screen.getByRole('table'); + const innerContainer = tableElement.parentElement.parentElement; + // After filter summary is removed (via Clear filters button) inner should only have 1 child + expect(innerContainer.childElementCount).toEqual(1); + }); + + const findFilterTagAndRemove = async () => { + const { click } = userEvent; + const filterTagCloseButtons = screen.getAllByTitle('Clear filters'); + const visibleFilterTags = filterTagCloseButtons.filter((el) => + el.parentElement.parentElement.classList.contains( + `${pkg.prefix}--tag-set__displayed-tag` + ) + ); + click(visibleFilterTags[0]); + const checkAgainForCloseFilterButton = + screen.queryAllByTitle('Clear filters'); + expect(checkAgainForCloseFilterButton).toEqual([]); + }; + + it('should render initial filters in panel and test close button on filter tag', async () => { + render( + + ); + + await findFilterTagAndRemove(); + }); + + it('should test default `renderDateLabel` displays filter tag as expected', async () => { + const updatedFilterProps = Object.assign(testFilterProps(), { + renderDateLabel: null, + }); + const todayDate = new Date(); + render( + + ); + const filterTags = screen.getAllByTitle( + `Joined: 1/1/2022 - ${todayDate.toLocaleDateString()}` + ); + filterTags.forEach((filterTag) => { + expect(filterTag).toBeInTheDocument(); + }); + await findFilterTagAndRemove(); + }); + + it('should test removal of checkbox filter tag', async () => { + render( + + ); + await findFilterTagAndRemove(); + }); + it.skip('should test overflow checkbox list and removal of checkbox filter tag', async () => { + const { click } = userEvent; + const defaultCheckboxFilters = [ + { + id: 'normal', + labelText: 'Normal', + value: 'normal', + selected: true, + }, + { + id: 'minor-warning', + labelText: 'Minor warning', + value: 'minor-warning', + selected: false, + }, + { + id: 'critical', + labelText: 'Critical', + value: 'critical', + selected: false, + }, + ]; + render( + ); @@ -2460,6 +2807,22 @@ describe(componentName, () => { expect(panelContainer).toHaveClass( `${blockClass}__table-container--filter-open` ); + const checkboxTotal = [ + ...defaultCheckboxFilters, + ...generateDummyCheckboxes, + ].length; + const viewMoreButton = screen.getByRole('button', { + name: `View all (${checkboxTotal})`, + }); + expect(viewMoreButton).toBeInTheDocument(); + click(viewMoreButton); + const viewLessButton = screen.getByRole('button', { name: 'View less' }); + expect(viewLessButton).toBeInTheDocument(); + click(viewLessButton); + expect(viewMoreButton).toBeInTheDocument(); + const checkboxElement = screen.getByRole('checkbox', { name: 'Critical' }); + click(checkboxElement); + expect(checkboxElement.checked).toEqual(true); }); }); diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridContent.js b/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridContent.js index 9840117af9..12338d2225 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridContent.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridContent.js @@ -157,7 +157,6 @@ export const DatagridContent = ({ datagridState, title }) => { clearSingleFilter(id, setAllFilters, state) ); - /* istanbul ignore next */ const renderFilterSummary = () => state.filters.length > 0 && ( { > {filterProps?.variation === 'panel' && ( {}, onFlyoutClose = () => {}, onApply = () => {}, onCancel = () => {}, - secondaryActionLabel = 'Cancel', + secondaryActionLabel = defaults.secondaryActionLabel, setAllFilters, data = [], reactTableFiltersState = [], @@ -80,6 +87,8 @@ const FilterFlyout = ({ prevFiltersRef, }); + // Skip resize testing + /* istanbul ignore next */ const handleResize = (current) => { const filterFlyoutRefPosition = flyoutInnerRef?.current.getBoundingClientRect(); diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/FilterPanel.js b/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/FilterPanel.js index d3c2fc6b6a..e9e2696940 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/FilterPanel.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/FilterPanel.js @@ -38,10 +38,19 @@ const componentClass = `${blockClass}-filter-panel`; const MotionActionSet = motion(ActionSet); +const defaults = { + title: 'Filter', + closeIconDescription: 'Close filter panel', + primaryActionLabel: 'Apply', + secondaryActionLabel: 'Cancel', + searchLabelText: 'Filter search', + searchPlaceholder: 'Find filters', +}; + const FilterPanel = ({ - title = 'Filter', - closeIconDescription = 'Close filter panel', - updateMethod = BATCH, + title = defaults.title, + closeIconDescription = defaults.closeIconDescription, + updateMethod, filterSections, setAllFilters, onApply = () => {}, @@ -50,10 +59,10 @@ const FilterPanel = ({ onPanelClose = () => {}, showFilterSearch = false, filterPanelMinHeight = 600, - primaryActionLabel = 'Apply', - secondaryActionLabel = 'Cancel', - searchLabelText = 'Filter search', - searchPlaceholder = 'Find filters', + primaryActionLabel = defaults.primaryActionLabel, + secondaryActionLabel = defaults.secondaryActionLabel, + searchLabelText = defaults.searchLabelText, + searchPlaceholder = defaults.searchPlaceholder, reactTableFiltersState = [], isFetching = false, }) => { @@ -195,6 +204,7 @@ const FilterPanel = ({ actionSetRef.current?.getBoundingClientRect().height; const height = `calc(100vh - ${filterHeadingHeight}px - ${ + /* istanbul ignore next */ showFilterSearch ? filterSearchHeight : 0 }px - ${updateMethod === BATCH ? actionSetHeight : 0}px)`; @@ -232,6 +242,7 @@ const FilterPanel = ({ onClick={closePanel} /> {showFilterSearch && ( + /* istanbul ignore next */
{}, + onCancel, panelOpen, isFetching, }) => { diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/hooks/useShouldDisableButtons.js b/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/hooks/useShouldDisableButtons.js index 288c127196..4379c064e8 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/hooks/useShouldDisableButtons.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/hooks/useShouldDisableButtons.js @@ -1,5 +1,5 @@ /** - * Copyright IBM Corp. 2023, 2023 + * Copyright IBM Corp. 2023, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -17,7 +17,7 @@ import isEqual from 'lodash/isEqual'; * @returns {Array} returns a tuple of the state and setter function */ const useShouldDisableButtons = ({ - initialValue = true, // initially the buttons should be disabled + initialValue, // initially the buttons should be disabled filtersState, prevFiltersRef, }) => { diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/utils.js b/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/utils.js index fb179908f9..f7f995a6ce 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/utils.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid/addons/Filtering/utils.js @@ -1,5 +1,5 @@ /** - * Copyright IBM Corp. 2022, 2022 + * Copyright IBM Corp. 2022, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -28,8 +28,8 @@ const applyInitialFilters = (filterState, initialFilters) => { // This functions takes the filters passed in and makes an object to track it's state export const getInitialStateFromFilters = ( filters, - variation = FLYOUT, - initialFilters = [] + variation, + initialFilters ) => { const initialFilterState = {}; @@ -73,8 +73,6 @@ export const getInitialStateFromFilters = ( filters.forEach(({ filters: sections = [] }) => { sections.forEach(({ filter }) => setInitialState(filter)); }); - } else { - console.error('No variation passed into useInitialStateFromFilters'); } if (initialFilters.length > 0) { diff --git a/packages/ibm-products/src/components/Datagrid/Extensions/Filtering/Flyout.stories.js b/packages/ibm-products/src/components/Datagrid/Extensions/Filtering/Flyout.stories.js index a546660eda..f4865a3431 100644 --- a/packages/ibm-products/src/components/Datagrid/Extensions/Filtering/Flyout.stories.js +++ b/packages/ibm-products/src/components/Datagrid/Extensions/Filtering/Flyout.stories.js @@ -44,9 +44,10 @@ export default { }, }, }, + excludeStories: ['FilteringUsage', 'filterProps'], }; -const FilteringUsage = ({ defaultGridProps }) => { +export const FilteringUsage = ({ defaultGridProps }) => { const { gridDescription, gridTitle, @@ -300,6 +301,18 @@ export const FlyoutBatch = prepareStory(FilteringTemplateWrapper, { }, }); +export const filterProps = { + variation: 'flyout', + updateMethod: 'instant', + primaryActionLabel: 'Apply', + secondaryActionLabel: 'Cancel', + flyoutIconDescription: 'Open filters', + onFlyoutOpen: action('onFlyoutOpen'), + onFlyoutClose: action('onFlyoutClose'), + filters, + renderLabel: (key, value) => handleFilterTagLabelText(key, value), +}; + export const FlyoutInstant = prepareStory(FilteringTemplateWrapper, { storyName: 'Filter flyout with instant update', argTypes: { @@ -315,17 +328,7 @@ export const FlyoutInstant = prepareStory(FilteringTemplateWrapper, { emptyStateTitle: 'No filters match', emptyStateDescription: 'Data was not found with the current filters applied. Change filters or clear filters to see other results.', - filterProps: { - variation: 'flyout', - updateMethod: 'instant', - primaryActionLabel: 'Apply', - secondaryActionLabel: 'Cancel', - flyoutIconDescription: 'Open filters', - onFlyoutOpen: action('onFlyoutOpen'), - onFlyoutClose: action('onFlyoutClose'), - filters, - renderLabel: (key, value) => handleFilterTagLabelText(key, value), - }, + filterProps, }, }); diff --git a/packages/ibm-products/src/components/Datagrid/useFiltering.js b/packages/ibm-products/src/components/Datagrid/useFiltering.js index 16d30b3228..1c581692aa 100644 --- a/packages/ibm-products/src/components/Datagrid/useFiltering.js +++ b/packages/ibm-products/src/components/Datagrid/useFiltering.js @@ -1,5 +1,5 @@ /** - * Copyright IBM Corp. 2022, 2023 + * Copyright IBM Corp. 2022, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -15,6 +15,7 @@ const useFiltering = (hooks) => { pkg.checkReportFeatureEnabled('Datagrid.useFiltering'); }, []); + /* istanbul ignore next */ const filterTypes = useMemo( () => ({ date: (rows, id, [startDate, endDate]) => { diff --git a/packages/ibm-products/src/components/Datagrid/utils/filterPropsForTesting.js b/packages/ibm-products/src/components/Datagrid/utils/filterPropsForTesting.js new file mode 100644 index 0000000000..7864696bf9 --- /dev/null +++ b/packages/ibm-products/src/components/Datagrid/utils/filterPropsForTesting.js @@ -0,0 +1,169 @@ +/** + * Copyright IBM Corp. 2024, 2024 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { handleFilterTagLabelText } from './handleFilterTagLabelText'; + +export const generateDummyCheckboxes = Array(25) + .fill(null) + .map((_, index) => ({ + id: `${index}`, + labelText: `Dummy checkbox ${index + 1}`, + value: 'dummy-checkbox', + disabled: true, + })); + +export const filterProps = ({ + includeManyCheckboxes = false, + dropdownOnChange = () => {}, +} = {}) => { + const checkboxList = [ + { + id: 'normal', + labelText: 'Normal', + value: 'normal', + }, + { + id: 'minor-warning', + labelText: 'Minor warning', + value: 'minor-warning', + }, + { + id: 'critical', + labelText: 'Critical', + value: 'critical', + }, + ...(includeManyCheckboxes ? generateDummyCheckboxes : []), + ]; + return { + autoHideFilters: includeManyCheckboxes ? false : true, + variation: 'panel', + panelIconDescription: 'Open filters', + sections: [ + { + categoryTitle: 'Category title', + hasAccordion: true, + filters: [ + { + filterLabel: 'Joined', + filter: { + type: 'date', + column: 'joined', + props: { + DatePicker: { + datePickerType: 'range', + }, + DatePickerInput: { + start: { + id: 'date-picker-input-id-start', + placeholder: 'mm/dd/yyyy', + labelText: 'Joined start date', + }, + end: { + id: 'date-picker-input-id-end', + placeholder: 'mm/dd/yyyy', + labelText: 'Joined end date', + }, + }, + }, + }, + }, + { + filterLabel: 'Status', + filter: { + type: 'dropdown', + column: 'status', + props: { + Dropdown: { + id: 'marital-status-dropdown', + ['aria-label']: 'Marital status dropdown', + items: ['relationship', 'complicated', 'single'], + label: 'Marital status', + titleText: 'Marital status', + onChange: dropdownOnChange, + }, + }, + }, + }, + ], + }, + { + categoryTitle: 'Category title', + filters: [ + { + filterLabel: 'Role', + filter: { + type: 'radio', + column: 'role', + props: { + FormGroup: { + legendText: 'Role', + }, + RadioButtonGroup: { + orientation: 'vertical', + legend: 'Role legend', + name: 'role-radio-button-group', + }, + RadioButton: [ + { + id: 'developer', + labelText: 'Developer', + value: 'developer', + }, + { + id: 'designer', + labelText: 'Designer', + value: 'designer', + }, + { + id: 'researcher', + labelText: 'Researcher', + value: 'researcher', + }, + ], + }, + }, + }, + { + filterLabel: 'Visits', + filter: { + type: 'number', + column: 'visits', + props: { + NumberInput: { + min: 0, + id: 'visits-number-input', + invalidText: 'A valid value is required', + label: 'Visits', + placeholder: 'Type a number amount of visits', + }, + }, + }, + }, + { + filterLabel: 'Password strength', + filter: { + type: 'checkbox', + column: 'passwordStrength', + props: { + FormGroup: { + legendText: 'Password strength', + }, + Checkbox: checkboxList, + }, + }, + }, + ], + }, + ], + renderLabel: (key, value) => handleFilterTagLabelText(key, value), + renderDateLabel: (start, end) => { + const startDateObj = new Date(start); + const endDateObj = new Date(end); + return `${startDateObj.toLocaleDateString()} - ${endDateObj.toLocaleDateString()}`; + }, + }; +}; diff --git a/packages/ibm-products/src/components/FilterSummary/FilterSummary.js b/packages/ibm-products/src/components/FilterSummary/FilterSummary.js index b23e333859..95cb00b8c1 100644 --- a/packages/ibm-products/src/components/FilterSummary/FilterSummary.js +++ b/packages/ibm-products/src/components/FilterSummary/FilterSummary.js @@ -1,5 +1,5 @@ /** - * Copyright IBM Corp. 2022, 2023 + * Copyright IBM Corp. 2022, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -11,6 +11,7 @@ import cx from 'classnames'; import { TagSet } from '../TagSet'; import { pkg } from '../../settings'; import uuidv4 from '../../global/js/utils/uuidv4'; +import { getDevtoolsProps } from '../../global/js/utils/devtools'; const blockClass = `${pkg.prefix}--filter-summary`; @@ -19,11 +20,12 @@ let FilterSummary = React.forwardRef( { className = '', clearFiltersText = 'Clear filters', - clearFilters = () => {}, - filters = [], + clearFilters, + filters, renderLabel = null, overflowType = 'default', clearButtonInline = true, + ...rest }, ref ) => { @@ -32,16 +34,19 @@ let FilterSummary = React.forwardRef( ...rest, type: 'gray', label: renderLabel?.(key, value) ?? `${key}: ${value}`, + title: clearFiltersText, })); const filterSummaryClearButton = useRef(); const filterSummaryRef = useRef(); - const localRef = filterSummaryRef || ref; + const localRef = ref || filterSummaryRef; return (
{ + const [filters, setFilters] = useState([ + { key: 'name', value: 'Thor' }, + { key: 'location', value: 'Asgard' }, + // cspell: disable + { key: 'weapon', value: 'Mjölnir' }, + ]); + const clearFilters = () => setFilters([]); + return ( + + ); +}); + +const renderComponent = ({ ...rest } = {}) => + render(); + +describe(componentName, () => { + const { ResizeObserver } = window; + + beforeEach(() => { + window.ResizeObserver = jest.fn().mockImplementation(() => ({ + observe: jest.fn(), + unobserve: jest.fn(), + disconnect: jest.fn(), + })); + }); + + afterEach(() => { + window.ResizeObserver = ResizeObserver; + }); + + it('should render a filter summary component', () => { + renderComponent({ 'data-testid': dataTestId }); + screen.getByTestId(dataTestId); + }); +});