diff --git a/superset-frontend/src/components/Select/Select.stories.tsx b/superset-frontend/src/components/Select/Select.stories.tsx index 33f1ce6d50..b258232672 100644 --- a/superset-frontend/src/components/Select/Select.stories.tsx +++ b/superset-frontend/src/components/Select/Select.stories.tsx @@ -79,6 +79,12 @@ const ARG_TYPES = { disable: true, }, }, + labelInValue: { + defaultValue: true, + table: { + disable: true, + }, + }, name: { table: { disable: true, @@ -171,7 +177,11 @@ export const AtEveryCorner = () => ( position: 'absolute', }} > - ))}

@@ -206,7 +216,7 @@ export const PageScroll = () => ( right: 30, }} > -

{ - const ariaLabel = 'test'; - render( - ); + expect(screen.getByText(headerText)).toBeInTheDocument(); +}); + +test('inverts the selection', async () => { + render(); + const option3 = OPTIONS[2].label; + const option8 = OPTIONS[7].label; + await open(); + userEvent.click(await findSelectOption(option3)); + userEvent.click(await findSelectOption(option8)); + await type('{esc}'); + await open(); + const sortedOptions = await findAllSelectOptions(); + expect(sortedOptions[0]).toHaveTextContent(option3); + expect(sortedOptions[1]).toHaveTextContent(option8); +}); + +test('searches for label or value', async () => { + const option = OPTIONS[11]; + render(, + ); + userEvent.click(screen.getByLabelText('close-circle')); + expect(onClear).toHaveBeenCalled(); + const values = await findAllSelectValues(); + expect(values.length).toBe(0); +}); + +test('does not add a new option if allowNewValue is false', async () => { + render(); + expect(getSelect()).toBeInTheDocument(); +}); + +test('static - opens the select without any data', async () => { + render(); + const optionText = 'Emma'; + await open(); + userEvent.click(await findSelectOption(optionText)); + expect(await findSelectValue()).toHaveTextContent(optionText); +}); + +test('static - multiple selections in multiple mode', async () => { + render(); + await open(); + const [firstOption, secondOption] = OPTIONS; + userEvent.click(await findSelectOption(firstOption.label)); + expect(await findSelectValue()).toHaveTextContent(firstOption.label); + expect(onChange).toHaveBeenCalledWith( + expect.objectContaining(firstOption), + firstOption, + ); + userEvent.click(await findSelectOption(secondOption.label)); + expect(onChange).toHaveBeenCalledWith( + expect.objectContaining(secondOption), + secondOption, + ); + expect(await findSelectValue()).toHaveTextContent(secondOption.label); +}); + +test('static - deselects an item in multiple mode', async () => { + render(); + await open(); + await type(NEW_OPTION); + expect(await findSelectOption(NEW_OPTION)).toBeInTheDocument(); +}); + +test('static - does not add a new option if the option already exists', async () => { + render(); + expect(await findSelectValue()).toHaveTextContent(OPTIONS[0].label); +}); + +test('static - sets a initial value in multiple mode', async () => { + render( + ); + const search = 'Oli'; + await type(search); + const options = await findAllSelectOptions(); + expect(options.length).toBe(2); + expect(options[0]).toHaveTextContent('Olivia'); + expect(options[1]).toHaveTextContent('Oliver'); +}); + +test('async - renders the select with default props', () => { + render( ({ data: [], totalCount: 0 })} + />, + ); + await open(); + expect(await screen.findByText(/no data/i)).toBeInTheDocument(); +}); + +test('async - displays the loading indicator when opening', async () => { + render(); + await type('John'); + expect(screen.getByText(LOADING)).toBeInTheDocument(); + await waitFor(() => + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(), + ); +}); + +test('async - makes a selection in single mode', async () => { + render(); + await open(); + const [firstOption, secondOption] = OPTIONS; + userEvent.click(await findSelectOption(firstOption.label)); + userEvent.click(await findSelectOption(secondOption.label)); + const values = await findAllSelectValues(); + expect(values[0]).toHaveTextContent(firstOption.label); + expect(values[1]).toHaveTextContent(secondOption.label); +}); + +test('async - changes the selected item in single mode', async () => { + const onChange = jest.fn(); + render( + ); + await open(); + const [firstOption, secondOption] = OPTIONS; + userEvent.click(await findSelectOption(firstOption.label)); + userEvent.click(await findSelectOption(secondOption.label)); + let values = await findAllSelectValues(); + expect(values.length).toBe(2); + expect(values[0]).toHaveTextContent(firstOption.label); + expect(values[1]).toHaveTextContent(secondOption.label); + userEvent.click(await findSelectOption(firstOption.label)); + values = await findAllSelectValues(); + expect(values.length).toBe(1); + expect(values[0]).toHaveTextContent(secondOption.label); +}); + +test('async - adds a new option if none is available and allowNewOptions is true', async () => { + render(); + const option = OPTIONS[0].label; + await open(); + await type(option); + await waitFor(() => { + const array = within( + getElementByClassName('.rc-virtual-list'), + ).getAllByText(option); + expect(array.length).toBe(1); + }); +}); + +test('async - sets a initial value in single mode', async () => { + render(, + ); + const values = await findAllSelectValues(); + expect(values[0]).toHaveTextContent(OPTIONS[0].label); + expect(values[1]).toHaveTextContent(OPTIONS[1].label); +}); + +test('async - searches for an item already loaded', async () => { + render(); + const search = 'Ashfaq'; + await open(); + await type(search); + await waitForElementToBeRemoved(screen.getByText(LOADING)); + const options = await findAllSelectOptions(); + expect(options.length).toBe(1); + expect(options[0]).toHaveTextContent(search); +}); + +test('async - does not fetches data when rendering', async () => { + const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 })); + render(); + await open(); + expect(loadOptions).toHaveBeenCalled(); +}); + +test('async - fetches data only after a search input is entered if fetchOnlyOnSearch is true', async () => { + const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 })); + render(); + await open(); + expect(screen.getByText(error)).toBeInTheDocument(); +}); + +test('async - does not fire a new request for the same search input', async () => { + const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 })); + render(