Open jake-miles opened 2 years ago
Spent some time on this thinking it was only react-virtualized's 'AutoSizer' that was causing issues. However, it seems like the auto height higher order component throws in some issues too. Using these spies, I was able to render items in the dropdown:
const height = 100 // set to whatever you need
const width = 100 // set to whatever you need
jest.spyOn(HTMLElement.prototype, 'offsetWidth', 'get').mockReturnValue(
width
)
jest.spyOn(
HTMLElement.prototype,
'clientHeight',
'get'
).mockImplementation(() => height)
For reference,
https://github.com/kenshoo/react-multi-select/blob/master/src/components/with_responsive_height.js#L52 and (AutoSizer) https://github.com/kenshoo/react-multi-select/blob/master/src/components/list/items_list.js#L69
Expected Behavior
When a test written with jest and testing-library/react renders a MultiSelect component with a non-empty list of items, the items are rendered in the MultiSelect component, i.e. appear in the result of testing-library's
screen.debug
and are queryable using testing-library dom element queries.Actual Behavior
The rendered component does not include the items in the rendered DOM, although it does include the number selected (e.g. "1 selected") in the selection list component, implying that the component's state is up-to-date, and something about the test environment or MultiSelect configuration is preventing the items themselves from rendering.
Steps to Reproduce the Problem
Test:
import MultiSelect from '@kenshooui/react-multi-select'; import { render, screen } from '@testing-library/react';
describe("testing multiselect rendering", () => { it.only("renders something in the id list", async () => {
const items = [{ id: 'xyz1', label: 'xyz1' }]; let selected = items;
const setSelected = ids => selected = ids;
await render(<MultiSelect name="selected_items" items={items} selectedItems={selected} onChange={setSelected} />);
// would normally use getBy or findBy - using queryBy to more easily demo the issue const numSelected = screen.queryByText("1 selected"); expect(numSelected).not.toBeNull(); // => assertion passes
const item = screen.queryByText("xyz1"); expect(item).not.toBeNull(); => // assertion fails }); });
The first assertion passes and the second one fails, i.e. "1 selected" is in the rendered DOM, implying that the component's state is up to date, but the item's label "xyz1" is not, meaning that the selected item itself isn't rendering.
Likewise, the result of
screen.debug()
shows:which is the element in the target list on the right that reports the number of selected items in it, and includes the list component rendered, but no items within it:
Likewise, the source list on the left renders its top-level grid component, but no items:
When I inspect the DOM in a browser, those list components contains other elements rendering the list items.
Is this a missing configuration option? Perhaps something rendering itself differently based on device that isn't rendering in the test environment's dom?
My end goal is to write tests confirming that actions taken outside of this component in the surrounding page are updating this component's state correctly (i.e. my end goal is not to test MutiSelect itself, but that the set of currently-selected items is being propagated to it correctly, because other components in the page can also change the selection).
Thanks for any help with this.
Specifications