From 85e53260405ea284029704e041c8d6354219672a Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Tue, 14 Mar 2023 17:24:04 +0000 Subject: [PATCH] Chore: Adjust unit tests so they work with react 18 (#64698) tweak unit tests so they work with react 18 --- .../ColorPicker/ColorPickerInput.test.tsx | 3 +- .../RelativeTimeRangePicker.test.tsx | 13 +- .../src/components/Dropdown/ButtonSelect.tsx | 2 +- .../Forms/Legacy/Input/Input.test.tsx | 6 +- .../components/Toggletip/Toggletip.test.tsx | 32 +-- .../core/components/Layers/LayerName.test.tsx | 22 +- .../ReadonlyFolderPicker.test.tsx | 12 +- .../alerting/unified/AlertGroups.test.tsx | 17 +- .../unified/PanelAlertTabContent.test.tsx | 24 +- .../SharePublicDashboard.test.tsx | 35 +-- .../ValueMappingsEditorModal.test.tsx | 247 ++++++++++-------- public/app/features/explore/Logs.test.tsx | 16 +- .../RichHistory/RichHistoryCard.test.tsx | 53 ++-- .../explore/SupplementaryResultError.test.tsx | 5 +- .../components/common/CopyIcon.test.tsx | 5 +- .../features/logs/components/LogRows.test.tsx | 6 +- .../playlist/PlaylistEditPage.test.tsx | 3 +- .../components/QueryEditorRowHeader.test.tsx | 23 +- .../components/DefaultSubscription.test.tsx | 5 +- .../ResourcePicker/AdvancedMulti.test.tsx | 3 +- .../MetricsQueryEditor.test.tsx | 56 ++-- .../components/QueryHeader.test.tsx | 18 +- .../SQLBuilderEditor/SQLGroupBy.test.tsx | 13 +- .../components/LokiQueryEditorByApp.test.tsx | 28 +- .../components/LabelBrowserModal.test.tsx | 9 +- .../LokiQueryBuilderOptions.test.tsx | 10 +- .../components/PromQueryEditorByApp.test.tsx | 31 ++- .../components/PromQueryField.test.tsx | 41 ++- .../PromQueryBuilderOptions.test.tsx | 31 +-- .../components/PromQueryCodeEditor.test.tsx | 12 +- .../PromQueryEditorSelector.test.tsx | 36 +-- .../alertGroups/AlertGroupsPanel.test.tsx | 18 +- .../components/FlameGraphHeader.test.tsx | 2 +- 33 files changed, 440 insertions(+), 397 deletions(-) diff --git a/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx index eeab0e71112..86f2b00a5e2 100644 --- a/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx @@ -24,7 +24,8 @@ describe('ColorPickerInput', () => { const mockOnChange = jest.fn(); render(); await userEvent.type(screen.getByRole('textbox'), 'some text'); - screen.getByRole('textbox').blur(); + // blur the input + await userEvent.click(document.body); await waitFor(() => expect(mockOnChange).not.toHaveBeenCalled()); expect(screen.getByRole('textbox')).toHaveValue(''); }); diff --git a/packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.test.tsx b/packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.test.tsx index 635d906a6f0..374dba3886e 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.test.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.test.tsx @@ -1,4 +1,5 @@ -import { render, fireEvent, RenderResult } from '@testing-library/react'; +import { render, RenderResult } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React, { useState } from 'react'; import { RelativeTimeRange } from '@grafana/data'; @@ -20,10 +21,10 @@ describe('RelativeTimePicker', () => { expect(getByText('now-15m to now')).toBeInTheDocument(); }); - it('should open the picker when clicking the button', () => { + it('should open the picker when clicking the button', async () => { const { getByText } = setup({ from: 900, to: 0 }); - fireEvent.click(getByText('now-15m to now')); + await userEvent.click(getByText('now-15m to now')); expect(getByText('Specify time range')).toBeInTheDocument(); expect(getByText('Example time ranges')).toBeInTheDocument(); @@ -35,11 +36,11 @@ describe('RelativeTimePicker', () => { expect(queryByText('Example time ranges')).toBeNull(); }); - it('should not be able to apply range via quick options', () => { + it('should not be able to apply range via quick options', async () => { const { getByText, queryByText } = setup({ from: 900, to: 0 }); - fireEvent.click(getByText('now-15m to now')); // open the picker - fireEvent.click(getByText('Last 30 minutes')); // select the quick range, should close picker. + await userEvent.click(getByText('now-15m to now')); // open the picker + await userEvent.click(getByText('Last 30 minutes')); // select the quick range, should close picker. expect(queryByText('Specify time range')).toBeNull(); expect(queryByText('Example time ranges')).toBeNull(); diff --git a/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx b/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx index 4341e4251b3..131b00e920e 100644 --- a/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx +++ b/packages/grafana-ui/src/components/Dropdown/ButtonSelect.tsx @@ -54,7 +54,7 @@ const ButtonSelectComponent = (props: Props) => { {...buttonProps} {...restProps} > - {value?.label || value?.value} + {value?.label || (value?.value != null ? String(value?.value) : null)} {state.isOpen && (
diff --git a/packages/grafana-ui/src/components/Forms/Legacy/Input/Input.test.tsx b/packages/grafana-ui/src/components/Forms/Legacy/Input/Input.test.tsx index 8ed2731ba21..acf7cd850a5 100644 --- a/packages/grafana-ui/src/components/Forms/Legacy/Input/Input.test.tsx +++ b/packages/grafana-ui/src/components/Forms/Legacy/Input/Input.test.tsx @@ -29,7 +29,8 @@ describe('Input', () => { render(); const inputEl = screen.getByPlaceholderText(PLACEHOLDER_TEXT); await userEvent.type(inputEl, 'abcde'); - inputEl.blur(); + // blur the field + await userEvent.click(document.body); await screen.findByText(TEST_ERROR_MESSAGE); }); @@ -37,7 +38,8 @@ describe('Input', () => { render(); const inputEl = screen.getByPlaceholderText(PLACEHOLDER_TEXT); await userEvent.type(inputEl, 'Hi'); - inputEl.blur(); + // blur the field + await userEvent.click(document.body); const errorMessage = screen.queryByText(TEST_ERROR_MESSAGE); expect(errorMessage).not.toBeInTheDocument(); }); diff --git a/packages/grafana-ui/src/components/Toggletip/Toggletip.test.tsx b/packages/grafana-ui/src/components/Toggletip/Toggletip.test.tsx index bc54d8579bb..8e40d7a600a 100644 --- a/packages/grafana-ui/src/components/Toggletip/Toggletip.test.tsx +++ b/packages/grafana-ui/src/components/Toggletip/Toggletip.test.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; @@ -17,9 +17,9 @@ describe('Toggletip', () => { ); expect(screen.getByText('Click me!')).toBeInTheDocument(); const button = screen.getByTestId('myButton'); - button.click(); + await userEvent.click(button); - await waitFor(() => expect(screen.getByTestId('toggletip-content')).toBeInTheDocument()); + expect(screen.getByTestId('toggletip-content')).toBeInTheDocument(); }); it('should close toogletip after click on close button', async () => { @@ -32,17 +32,15 @@ describe('Toggletip', () => { ); const button = screen.getByTestId('myButton'); - button.click(); + await userEvent.click(button); - await waitFor(() => expect(screen.getByTestId('toggletip-content')).toBeInTheDocument()); + expect(screen.getByTestId('toggletip-content')).toBeInTheDocument(); const closeButton = screen.getByTestId('toggletip-header-close'); expect(closeButton).toBeInTheDocument(); - closeButton.click(); + await userEvent.click(closeButton); - await waitFor(() => { - expect(closeSpy).toHaveBeenCalledTimes(1); - }); + expect(closeSpy).toHaveBeenCalledTimes(1); }); it('should close toogletip after press ESC', async () => { @@ -55,17 +53,13 @@ describe('Toggletip', () => { ); const button = screen.getByTestId('myButton'); - button.click(); + await userEvent.click(button); - await waitFor(() => expect(screen.getByTestId('toggletip-content')).toBeInTheDocument()); + expect(screen.getByTestId('toggletip-content')).toBeInTheDocument(); - fireEvent.keyDown(global.document, { - code: 'Escape', - key: 'Escape', - keyCode: 27, - }); + await userEvent.keyboard('{escape}'); - await waitFor(() => expect(closeSpy).toHaveBeenCalledTimes(1)); + expect(closeSpy).toHaveBeenCalledTimes(1); }); it('should display the toogletip after press ENTER', async () => { @@ -83,8 +77,8 @@ describe('Toggletip', () => { // open toggletip with enter const button = screen.getByTestId('myButton'); button.focus(); - userEvent.keyboard('{enter}'); + await userEvent.keyboard('{enter}'); - await waitFor(() => expect(screen.getByTestId('toggletip-content')).toBeInTheDocument()); + expect(screen.getByTestId('toggletip-content')).toBeInTheDocument(); }); }); diff --git a/public/app/core/components/Layers/LayerName.test.tsx b/public/app/core/components/Layers/LayerName.test.tsx index f1fc690f37d..904f1102b64 100644 --- a/public/app/core/components/Layers/LayerName.test.tsx +++ b/public/app/core/components/Layers/LayerName.test.tsx @@ -1,16 +1,19 @@ -import { fireEvent, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { LayerNameProps, LayerName } from './LayerName'; describe('LayerName', () => { - it('Can edit title', () => { + it('Can edit title', async () => { const scenario = renderScenario({}); - screen.getByTestId('layer-name-div').click(); + await userEvent.click(screen.getByTestId('layer-name-div')); const input = screen.getByTestId('layer-name-input'); - fireEvent.change(input, { target: { value: 'new name' } }); - fireEvent.blur(input); + await userEvent.clear(input); + await userEvent.type(input, 'new name'); + // blur the element + await userEvent.click(document.body); expect(jest.mocked(scenario.props.onChange).mock.calls[0][0]).toBe('new name'); }); @@ -18,9 +21,9 @@ describe('LayerName', () => { it('Show error when empty name is specified', async () => { renderScenario({}); - screen.getByTestId('layer-name-div').click(); + await userEvent.click(screen.getByTestId('layer-name-div')); const input = screen.getByTestId('layer-name-input'); - fireEvent.change(input, { target: { value: '' } }); + await userEvent.clear(input); const alert = await screen.findByRole('alert'); expect(alert.textContent).toBe('An empty layer name is not allowed'); @@ -29,9 +32,10 @@ describe('LayerName', () => { it('Show error when other layer with same name exists', async () => { renderScenario({}); - screen.getByTestId('layer-name-div').click(); + await userEvent.click(screen.getByTestId('layer-name-div')); const input = screen.getByTestId('layer-name-input'); - fireEvent.change(input, { target: { value: 'Layer 2' } }); + await userEvent.clear(input); + await userEvent.type(input, 'Layer 2'); const alert = await screen.findByRole('alert'); expect(alert.textContent).toBe('Layer name already exists'); diff --git a/public/app/core/components/Select/ReadonlyFolderPicker/ReadonlyFolderPicker.test.tsx b/public/app/core/components/Select/ReadonlyFolderPicker/ReadonlyFolderPicker.test.tsx index ac78be8ca21..55b268e19f9 100644 --- a/public/app/core/components/Select/ReadonlyFolderPicker/ReadonlyFolderPicker.test.tsx +++ b/public/app/core/components/Select/ReadonlyFolderPicker/ReadonlyFolderPicker.test.tsx @@ -1,4 +1,4 @@ -import { render, waitFor, within } from '@testing-library/react'; +import { render, screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { byTestId } from 'testing-library-selector'; @@ -34,7 +34,7 @@ async function getTestContext( Object.assign(props, propOverrides); render(); - await waitFor(() => expect(getFoldersAsOptionsSpy).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(screen.queryByText(/Loading/)).not.toBeInTheDocument()); return { getFoldersAsOptionsSpy, getFolderAsOptionSpy, selectors }; } @@ -93,14 +93,14 @@ describe('ReadonlyFolderPicker', () => { it('then the first folder in all folders should be selected', async () => { const { selectors } = await getTestContext({}, FOLDERS); - expect(within(selectors.container.get()).getByText('General')).toBeInTheDocument(); + expect(await within(selectors.container.get()).findByText('General')).toBeInTheDocument(); }); describe('and initialFolderId is passed in props and it matches an existing folder', () => { it('then the folder with an id equal to initialFolderId should be selected', async () => { const { selectors } = await getTestContext({ initialFolderId: 1 }, FOLDERS); - expect(within(selectors.container.get()).getByText('Test')).toBeInTheDocument(); + expect(await within(selectors.container.get()).findByText('Test')).toBeInTheDocument(); }); }); @@ -116,7 +116,7 @@ describe('ReadonlyFolderPicker', () => { folderById ); - expect(within(selectors.container.get()).getByText('Outside api search')).toBeInTheDocument(); + expect(await within(selectors.container.get()).findByText('Outside api search')).toBeInTheDocument(); expect(getFolderAsOptionSpy).toHaveBeenCalledTimes(1); expect(getFolderAsOptionSpy).toHaveBeenCalledWith(50000); }); @@ -130,7 +130,7 @@ describe('ReadonlyFolderPicker', () => { undefined ); - expect(within(selectors.container.get()).getByText('General')).toBeInTheDocument(); + expect(await within(selectors.container.get()).findByText('General')).toBeInTheDocument(); expect(getFolderAsOptionSpy).toHaveBeenCalledTimes(1); expect(getFolderAsOptionSpy).toHaveBeenCalledWith(50000); }); diff --git a/public/app/features/alerting/unified/AlertGroups.test.tsx b/public/app/features/alerting/unified/AlertGroups.test.tsx index e71d29fa39e..f0ce4a2ddd5 100644 --- a/public/app/features/alerting/unified/AlertGroups.test.tsx +++ b/public/app/features/alerting/unified/AlertGroups.test.tsx @@ -73,7 +73,7 @@ describe('AlertGroups', () => { await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled()); - const groups = ui.group.getAll(); + const groups = await ui.group.findAll(); expect(groups).toHaveLength(2); expect(groups[0]).toHaveTextContent('No grouping'); @@ -105,7 +105,7 @@ describe('AlertGroups', () => { renderAmNotifications(); await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled()); - let groups = ui.group.getAll(); + let groups = await ui.group.findAll(); const groupByInput = ui.groupByInput.get(); const groupByWrapper = ui.groupByContainer.get(); @@ -118,7 +118,7 @@ describe('AlertGroups', () => { await waitFor(() => expect(groupByWrapper).toHaveTextContent('appName')); - groups = ui.group.getAll(); + groups = await ui.group.findAll(); await waitFor(() => expect(ui.clearButton.get()).toBeInTheDocument()); expect(groups).toHaveLength(3); @@ -132,7 +132,7 @@ describe('AlertGroups', () => { await userEvent.type(groupByInput, 'env{enter}'); await waitFor(() => expect(groupByWrapper).toHaveTextContent('env')); - groups = ui.group.getAll(); + groups = await ui.group.findAll(); expect(groups).toHaveLength(2); expect(groups[0]).toHaveTextContent('env=production'); @@ -144,7 +144,7 @@ describe('AlertGroups', () => { await userEvent.type(groupByInput, 'uniqueLabel{enter}'); await waitFor(() => expect(groupByWrapper).toHaveTextContent('uniqueLabel')); - groups = ui.group.getAll(); + groups = await ui.group.findAll(); expect(groups).toHaveLength(2); expect(groups[0]).toHaveTextContent('No grouping'); expect(groups[1]).toHaveTextContent('uniqueLabel=true'); @@ -159,9 +159,8 @@ describe('AlertGroups', () => { return Promise.resolve(groups); }); renderAmNotifications(); - await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled()); - const groups = ui.group.getAll(); - - expect(groups).toHaveLength(1); + await waitFor(() => { + expect(ui.group.getAll()).toHaveLength(1); + }); }); }); diff --git a/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx b/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx index 37f226adbaa..7745083f61a 100644 --- a/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx +++ b/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx @@ -1,4 +1,4 @@ -import { render, act, waitFor } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import React from 'react'; import { TestProvider } from 'test/helpers/TestProvider'; import { byTestId } from 'testing-library-selector'; @@ -68,13 +68,11 @@ const renderAlertTabContent = ( panel: PanelModel, initialStore?: ReturnType ) => { - return act(async () => { - render( - - - - ); - }); + render( + + + + ); }; const rules = [ @@ -196,7 +194,7 @@ describe('PanelAlertTabContent', () => { }); it('Will take into account panel maxDataPoints', async () => { - await renderAlertTabContent( + renderAlertTabContent( dashboard, new PanelModel({ ...panel, @@ -225,7 +223,7 @@ describe('PanelAlertTabContent', () => { }); it('Will work with default datasource', async () => { - await renderAlertTabContent( + renderAlertTabContent( dashboard, new PanelModel({ ...panel, @@ -257,7 +255,7 @@ describe('PanelAlertTabContent', () => { it('Will take into account datasource minInterval', async () => { (getDatasourceSrv() as unknown as MockDataSourceSrv).datasources[dataSources.prometheus.uid].interval = '7m'; - await renderAlertTabContent( + renderAlertTabContent( dashboard, new PanelModel({ ...panel, @@ -288,7 +286,7 @@ describe('PanelAlertTabContent', () => { mocks.api.fetchRules.mockResolvedValue(rules); mocks.api.fetchRulerRules.mockResolvedValue(rulerRules); - await renderAlertTabContent(dashboard, panel); + renderAlertTabContent(dashboard, panel); const rows = await ui.row.findAll(); expect(rows).toHaveLength(1); @@ -331,7 +329,7 @@ describe('PanelAlertTabContent', () => { const panelToRuleValuesSpy = jest.spyOn(ruleFormUtils, 'panelToRuleFormValues'); const store = configureStore(); - await renderAlertTabContent(dashboard, panel, store); + renderAlertTabContent(dashboard, panel, store); store.dispatch( toKeyedAction( diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx index 5c4428e3490..98ddac59cbb 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx @@ -1,4 +1,5 @@ -import { fireEvent, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -198,11 +199,11 @@ describe('SharePublic - New config setup', () => { it('when checkboxes are filled, then create button is enabled', async () => { await renderSharePublicDashboard(); - fireEvent.click(screen.getByTestId(selectors.WillBePublicCheckbox)); - fireEvent.click(screen.getByTestId(selectors.LimitedDSCheckbox)); - fireEvent.click(screen.getByTestId(selectors.CostIncreaseCheckbox)); + await userEvent.click(screen.getByTestId(selectors.WillBePublicCheckbox)); + await userEvent.click(screen.getByTestId(selectors.LimitedDSCheckbox)); + await userEvent.click(screen.getByTestId(selectors.CostIncreaseCheckbox)); - await waitFor(() => expect(screen.getByTestId(selectors.CreateButton)).toBeEnabled()); + expect(screen.getByTestId(selectors.CreateButton)).toBeEnabled(); }); alertTests(); }); @@ -214,14 +215,16 @@ describe('SharePublic - Already persisted', () => { it('when modal is opened, then delete button is enabled', async () => { await renderSharePublicDashboard(); - await waitForElementToBeRemoved(screen.getAllByTestId('Spinner')); - expect(screen.getByTestId(selectors.DeleteButton)).toBeEnabled(); + await waitFor(() => { + expect(screen.getByTestId(selectors.DeleteButton)).toBeEnabled(); + }); }); it('when fetch is done, then inputs are checked and delete button is enabled', async () => { await renderSharePublicDashboard(); - await waitForElementToBeRemoved(screen.getAllByTestId('Spinner')); - expect(screen.getByTestId(selectors.EnableTimeRangeSwitch)).toBeEnabled(); + await waitFor(() => { + expect(screen.getByTestId(selectors.EnableTimeRangeSwitch)).toBeEnabled(); + }); expect(screen.getByTestId(selectors.EnableTimeRangeSwitch)).toBeChecked(); expect(screen.getByTestId(selectors.EnableAnnotationsSwitch)).toBeEnabled(); @@ -236,7 +239,7 @@ describe('SharePublic - Already persisted', () => { jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false); await renderSharePublicDashboard(); - expect(screen.getByTestId(selectors.EnableTimeRangeSwitch)).toBeDisabled(); + expect(await screen.findByTestId(selectors.EnableTimeRangeSwitch)).toBeDisabled(); expect(screen.getByTestId(selectors.EnableTimeRangeSwitch)).toBeChecked(); expect(screen.getByTestId(selectors.EnableAnnotationsSwitch)).toBeDisabled(); @@ -261,11 +264,12 @@ describe('SharePublic - Already persisted', () => { ); await renderSharePublicDashboard(); - await waitForElementToBeRemoved(screen.getAllByTestId('Spinner')); - const enableTimeRangeSwitch = screen.getByTestId(selectors.EnableTimeRangeSwitch); - expect(enableTimeRangeSwitch).toBeEnabled(); - expect(enableTimeRangeSwitch).not.toBeChecked(); + const enableTimeRangeSwitch = await screen.findByTestId(selectors.EnableTimeRangeSwitch); + await waitFor(() => { + expect(enableTimeRangeSwitch).toBeEnabled(); + expect(enableTimeRangeSwitch).not.toBeChecked(); + }); }); it('when pubdash is enabled, then link url is available', async () => { await renderSharePublicDashboard(); @@ -288,9 +292,8 @@ describe('SharePublic - Already persisted', () => { ); await renderSharePublicDashboard(); - await waitForElementToBeRemoved(screen.getAllByTestId('Spinner')); - expect(screen.queryByTestId(selectors.CopyUrlInput)).toBeInTheDocument(); + expect(await screen.findByTestId(selectors.CopyUrlInput)).toBeInTheDocument(); expect(screen.queryByTestId(selectors.CopyUrlButton)).not.toBeChecked(); expect(screen.getByTestId(selectors.PauseSwitch)).toBeChecked(); diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx index f2a7c224aa0..18bc74608cd 100644 --- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx +++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx @@ -1,4 +1,5 @@ -import { fireEvent, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { selectOptionInTest } from 'test/helpers/selectOptionInTest'; @@ -44,139 +45,155 @@ const setup = (spy?: jest.Mock, propOverrides?: Partial) => { render(); }; -describe('Render', () => { +describe('ValueMappingsEditorModal', () => { it('should render component', () => { setup(); }); -}); -describe('On remove mapping', () => { - it('Should remove mapping at index 0', () => { - const onChangeSpy = jest.fn(); - setup(onChangeSpy); + describe('On remove mapping', () => { + it('Should remove mapping at index 0', async () => { + const onChangeSpy = jest.fn(); + setup(onChangeSpy); - screen.getAllByTestId('remove-value-mapping')[0].click(); - screen.getByText('Update').click(); + await userEvent.click(screen.getAllByTestId('remove-value-mapping')[0]); + await userEvent.click(screen.getByText('Update')); - expect(onChangeSpy).toBeCalledWith([ - { - type: MappingType.RangeToText, - options: { - from: 21, - to: 30, - result: { - text: 'Meh', - index: 0, + expect(onChangeSpy).toBeCalledWith([ + { + type: MappingType.RangeToText, + options: { + from: 21, + to: 30, + result: { + text: 'Meh', + index: 0, + }, }, }, - }, - ]); + ]); + }); }); -}); -describe('When adding and updating value mapp', () => { - it('should be 3', async () => { - const onChangeSpy = jest.fn(); - setup(onChangeSpy); - - fireEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping'))); - const selectComponent = await screen.findByLabelText(selectors.components.ValuePicker.select('Add a new mapping')); - - await selectOptionInTest(selectComponent, 'Value'); - - const input = (await screen.findAllByPlaceholderText('Exact value to match'))[1]; - - fireEvent.change(input, { target: { value: 'New' } }); - fireEvent.change(screen.getAllByPlaceholderText('Optional display text')[2], { target: { value: 'display' } }); - fireEvent.click(screen.getByText('Update')); - - expect(onChangeSpy).toBeCalledWith([ - { - type: MappingType.ValueToText, - options: { - '20': { - text: 'Ok', - index: 0, - }, - New: { - text: 'display', - index: 2, + describe('When adding and updating value mapp', () => { + it('should be 3', async () => { + const onChangeSpy = jest.fn(); + setup(onChangeSpy); + + await userEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping'))); + const selectComponent = await screen.findByLabelText( + selectors.components.ValuePicker.select('Add a new mapping') + ); + + await selectOptionInTest(selectComponent, 'Value'); + + const input = (await screen.findAllByPlaceholderText('Exact value to match'))[1]; + + await userEvent.clear(input); + await userEvent.type(input, 'New'); + await userEvent.clear(screen.getAllByPlaceholderText('Optional display text')[2]); + await userEvent.type(screen.getAllByPlaceholderText('Optional display text')[2], 'display'); + await userEvent.click(screen.getByText('Update')); + + expect(onChangeSpy).toBeCalledWith([ + { + type: MappingType.ValueToText, + options: { + '20': { + text: 'Ok', + index: 0, + }, + New: { + text: 'display', + index: 2, + }, }, }, - }, - { - type: MappingType.RangeToText, - options: { - from: 21, - to: 30, - result: { - text: 'Meh', - index: 1, + { + type: MappingType.RangeToText, + options: { + from: 21, + to: 30, + result: { + text: 'Meh', + index: 1, + }, }, }, - }, - ]); + ]); + }); }); -}); - -describe('When adding and updating range map', () => { - it('should add new range map', async () => { - const onChangeSpy = jest.fn(); - setup(onChangeSpy, { value: [] }); - screen.getAllByTestId('remove-value-mapping')[0].click(); - - fireEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping'))); - const selectComponent = await screen.findByLabelText(selectors.components.ValuePicker.select('Add a new mapping')); - await selectOptionInTest(selectComponent, 'Range'); - - fireEvent.change(screen.getByPlaceholderText('Range start'), { target: { value: '10' } }); - fireEvent.change(screen.getByPlaceholderText('Range end'), { target: { value: '20' } }); - fireEvent.change(screen.getByPlaceholderText('Optional display text'), { target: { value: 'display' } }); - - fireEvent.click(screen.getByText('Update')); - - expect(onChangeSpy).toBeCalledWith([ - { - type: MappingType.RangeToText, - options: { - from: 10, - to: 20, - result: { - text: 'display', - index: 0, + + describe('When adding and updating range map', () => { + it('should add new range map', async () => { + const onChangeSpy = jest.fn(); + setup(onChangeSpy, { value: [] }); + await userEvent.click(screen.getAllByTestId('remove-value-mapping')[0]); + + await userEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping'))); + const selectComponent = await screen.findByLabelText( + selectors.components.ValuePicker.select('Add a new mapping') + ); + await selectOptionInTest(selectComponent, 'Range'); + + await userEvent.clear(screen.getByPlaceholderText('Range start')); + await userEvent.type(screen.getByPlaceholderText('Range start'), '10'); + + await userEvent.clear(screen.getByPlaceholderText('Range end')); + await userEvent.type(screen.getByPlaceholderText('Range end'), '20'); + + await userEvent.clear(screen.getByPlaceholderText('Optional display text')); + await userEvent.type(screen.getByPlaceholderText('Optional display text'), 'display'); + + await userEvent.click(screen.getByText('Update')); + + expect(onChangeSpy).toBeCalledWith([ + { + type: MappingType.RangeToText, + options: { + from: 10, + to: 20, + result: { + text: 'display', + index: 0, + }, }, }, - }, - ]); + ]); + }); }); -}); - -describe('When adding and updating regex map', () => { - it('should add new regex map', async () => { - const onChangeSpy = jest.fn(); - setup(onChangeSpy, { value: [] }); - screen.getAllByTestId('remove-value-mapping')[0].click(); - - fireEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping'))); - const selectComponent = await screen.findByLabelText(selectors.components.ValuePicker.select('Add a new mapping')); - await selectOptionInTest(selectComponent, 'Regex'); - - fireEvent.change(screen.getByPlaceholderText('Regular expression'), { target: { value: '(.*).example.com' } }); - fireEvent.change(screen.getByPlaceholderText('Optional display text'), { target: { value: '$1' } }); - - fireEvent.click(screen.getByText('Update')); - - expect(onChangeSpy).toBeCalledWith([ - { - type: MappingType.RegexToText, - options: { - pattern: '(.*).example.com', - result: { - text: '$1', - index: 0, + + describe('When adding and updating regex map', () => { + it('should add new regex map', async () => { + const onChangeSpy = jest.fn(); + setup(onChangeSpy, { value: [] }); + await userEvent.click(screen.getAllByTestId('remove-value-mapping')[0]); + + await userEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping'))); + const selectComponent = await screen.findByLabelText( + selectors.components.ValuePicker.select('Add a new mapping') + ); + await selectOptionInTest(selectComponent, 'Regex'); + + await userEvent.clear(screen.getByPlaceholderText('Regular expression')); + await userEvent.type(screen.getByPlaceholderText('Regular expression'), '(.*).example.com'); + + await userEvent.clear(screen.getByPlaceholderText('Optional display text')); + await userEvent.type(screen.getByPlaceholderText('Optional display text'), '$1'); + + await userEvent.click(screen.getByText('Update')); + + expect(onChangeSpy).toBeCalledWith([ + { + type: MappingType.RegexToText, + options: { + pattern: '(.*).example.com', + result: { + text: '$1', + index: 0, + }, }, }, - }, - ]); + ]); + }); }); }); diff --git a/public/app/features/explore/Logs.test.tsx b/public/app/features/explore/Logs.test.tsx index 11f7c553415..f7295da241d 100644 --- a/public/app/features/explore/Logs.test.tsx +++ b/public/app/features/explore/Logs.test.tsx @@ -1,4 +1,5 @@ -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { LoadingState, LogLevel, LogRowModel, MutableDataFrame, toUtc, EventBusSrv } from '@grafana/data'; @@ -44,14 +45,6 @@ describe('Logs', () => { ); }; - beforeEach(() => { - jest.useFakeTimers(); - }); - - afterEach(() => { - jest.useRealTimers(); - }); - it('should render logs', () => { setup(); const logsSection = screen.getByTestId('logRows'); @@ -189,11 +182,10 @@ describe('Logs', () => { expect(scanningStopped).toHaveBeenCalled(); }); - it('should flip the order', () => { + it('should flip the order', async () => { setup(); const oldestFirstSelection = screen.getByLabelText('Oldest first'); - fireEvent.click(oldestFirstSelection); - jest.advanceTimersByTime(1000); + await userEvent.click(oldestFirstSelection); const logsSection = screen.getByTestId('logRows'); let logRows = logsSection.querySelectorAll('tr'); expect(logRows.length).toBe(3); diff --git a/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx b/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx index 9b3011ff153..63cccb46522 100644 --- a/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx @@ -1,4 +1,5 @@ -import { render, screen, fireEvent, getByText, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen, getByText, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { DataSourceApi, DataSourceInstanceSettings, DataSourcePluginMeta } from '@grafana/data'; @@ -198,10 +199,8 @@ describe('RichHistoryCard', () => { }); const copyQueriesButton = await screen.findByRole('button', { name: 'Copy query to clipboard' }); expect(copyQueriesButton).toBeInTheDocument(); - fireEvent.click(copyQueriesButton); - await waitFor(() => { - expect(copyStringToClipboard).toHaveBeenCalledTimes(1); - }); + await userEvent.click(copyQueriesButton); + expect(copyStringToClipboard).toHaveBeenCalledTimes(1); expect(copyStringToClipboard).toHaveBeenCalledWith(JSON.stringify({ query: 'query1' })); }); @@ -219,10 +218,8 @@ describe('RichHistoryCard', () => { }); const copyQueriesButton = await screen.findByRole('button', { name: 'Copy query to clipboard' }); expect(copyQueriesButton).toBeInTheDocument(); - fireEvent.click(copyQueriesButton); - await waitFor(() => { - expect(copyStringToClipboard).toHaveBeenCalledTimes(1); - }); + await userEvent.click(copyQueriesButton); + expect(copyStringToClipboard).toHaveBeenCalledTimes(1); expect(copyStringToClipboard).toHaveBeenCalledWith(JSON.stringify({ query: 'query1' })); }); @@ -240,10 +237,8 @@ describe('RichHistoryCard', () => { }); const copyQueriesButton = await screen.findByRole('button', { name: 'Copy query to clipboard' }); expect(copyQueriesButton).toBeInTheDocument(); - fireEvent.click(copyQueriesButton); - await waitFor(() => { - expect(copyStringToClipboard).toHaveBeenCalledTimes(1); - }); + await userEvent.click(copyQueriesButton); + expect(copyStringToClipboard).toHaveBeenCalledTimes(1); expect(copyStringToClipboard).toHaveBeenCalledWith('query1'); }); @@ -264,10 +259,8 @@ describe('RichHistoryCard', () => { }); const copyQueriesButton = await screen.findByRole('button', { name: 'Copy query to clipboard' }); expect(copyQueriesButton).toBeInTheDocument(); - fireEvent.click(copyQueriesButton); - await waitFor(() => { - expect(copyStringToClipboard).toHaveBeenCalledTimes(1); - }); + await userEvent.click(copyQueriesButton); + expect(copyStringToClipboard).toHaveBeenCalledTimes(1); expect(copyStringToClipboard).toHaveBeenCalledWith(`query1\n${JSON.stringify({ query: 'query2' })}`); }); }); @@ -345,7 +338,7 @@ describe('RichHistoryCard', () => { }); const runQueryButton = await screen.findByRole('button', { name: /run query/i }); - fireEvent.click(runQueryButton); + await userEvent.click(runQueryButton); expect(setQueries).toHaveBeenCalledWith(expect.any(String), queries); expect(changeDatasource).not.toHaveBeenCalled(); @@ -373,7 +366,7 @@ describe('RichHistoryCard', () => { }); const runQueryButton = await screen.findByRole('button', { name: /run query/i }); - fireEvent.click(runQueryButton); + await userEvent.click(runQueryButton); await waitFor(() => { expect(setQueries).toHaveBeenCalledWith(expect.any(String), queries); @@ -406,15 +399,16 @@ describe('RichHistoryCard', () => { it('should open update comment form when edit comment button clicked', async () => { setup({ query: starredQueryWithComment }); const editComment = await screen.findByTitle('Edit comment'); - fireEvent.click(editComment); + await userEvent.click(editComment); const updateCommentForm = await screen.findByLabelText('Update comment form'); expect(updateCommentForm).toBeInTheDocument(); }); it('should close update comment form when escape key pressed', async () => { setup({ query: starredQueryWithComment }); const editComment = await screen.findByTitle('Edit comment'); - fireEvent.click(editComment); + await userEvent.click(editComment); const updateCommentForm = await screen.findByLabelText('Update comment form'); + await userEvent.click(updateCommentForm); fireEvent.keyDown(getByText(updateCommentForm, starredQueryWithComment.comment), { key: 'Escape', }); @@ -424,8 +418,9 @@ describe('RichHistoryCard', () => { it('should close update comment form when enter and shift keys pressed', async () => { setup({ query: starredQueryWithComment }); const editComment = await screen.findByTitle('Edit comment'); - fireEvent.click(editComment); + await userEvent.click(editComment); const updateCommentForm = await screen.findByLabelText('Update comment form'); + await userEvent.click(updateCommentForm); fireEvent.keyDown(getByText(updateCommentForm, starredQueryWithComment.comment), { key: 'Enter', shiftKey: true, @@ -436,8 +431,9 @@ describe('RichHistoryCard', () => { it('should close update comment form when enter and ctrl keys pressed', async () => { setup({ query: starredQueryWithComment }); const editComment = await screen.findByTitle('Edit comment'); - fireEvent.click(editComment); + await userEvent.click(editComment); const updateCommentForm = await screen.findByLabelText('Update comment form'); + await userEvent.click(updateCommentForm); fireEvent.keyDown(getByText(updateCommentForm, starredQueryWithComment.comment), { key: 'Enter', ctrlKey: true, @@ -448,8 +444,9 @@ describe('RichHistoryCard', () => { it('should not close update comment form when enter key pressed', async () => { setup({ query: starredQueryWithComment }); const editComment = await screen.findByTitle('Edit comment'); - fireEvent.click(editComment); + await userEvent.click(editComment); const updateCommentForm = await screen.findByLabelText('Update comment form'); + await userEvent.click(updateCommentForm); fireEvent.keyDown(getByText(updateCommentForm, starredQueryWithComment.comment), { key: 'Enter', shiftKey: false, @@ -464,14 +461,14 @@ describe('RichHistoryCard', () => { setup(); const starButton = await screen.findByTitle('Star query'); expect(starButton).toBeInTheDocument(); - fireEvent.click(starButton); + await userEvent.click(starButton); expect(starRichHistoryMock).toBeCalledWith(starredQueryWithComment.id, true); }); it('should have title "Unstar query", if not starred', async () => { setup({ query: starredQueryWithComment }); const unstarButton = await screen.findByTitle('Unstar query'); expect(unstarButton).toBeInTheDocument(); - fireEvent.click(unstarButton); + await userEvent.click(unstarButton); expect(starRichHistoryMock).toBeCalledWith(starredQueryWithComment.id, false); }); }); @@ -481,13 +478,13 @@ describe('RichHistoryCard', () => { setup(); const deleteButton = await screen.findByTitle('Delete query'); expect(deleteButton).toBeInTheDocument(); - fireEvent.click(deleteButton); + await userEvent.click(deleteButton); expect(deleteRichHistoryMock).toBeCalledWith(starredQueryWithComment.id); }); it('should display modal before deleting if starred', async () => { setup({ query: starredQueryWithComment }); const deleteButton = await screen.findByTitle('Delete query'); - fireEvent.click(deleteButton); + await userEvent.click(deleteButton); expect(deleteRichHistoryMock).not.toBeCalled(); expect(appEvents.publish).toHaveBeenCalledWith(new ShowConfirmModalEvent(expect.anything())); }); diff --git a/public/app/features/explore/SupplementaryResultError.test.tsx b/public/app/features/explore/SupplementaryResultError.test.tsx index c735d1b9818..2b5aa9a1df4 100644 --- a/public/app/features/explore/SupplementaryResultError.test.tsx +++ b/public/app/features/explore/SupplementaryResultError.test.tsx @@ -1,4 +1,5 @@ import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { SupplementaryResultError } from './SupplementaryResultError'; @@ -13,7 +14,7 @@ describe('SupplementaryResultError', () => { expect(screen.getByText(error.data.message)).toBeInTheDocument(); }); - it('shows long warning message', () => { + it('shows long warning message', async () => { // we make a long message const messagePart = 'One two three four five six seven eight nine ten.'; const message = messagePart.repeat(3); @@ -24,7 +25,7 @@ describe('SupplementaryResultError', () => { expect(screen.getByText(title)).toBeInTheDocument(); expect(screen.queryByText(message)).not.toBeInTheDocument(); const button = screen.getByText('Show details'); - button.click(); + await userEvent.click(button); expect(screen.getByText(message)).toBeInTheDocument(); }); }); diff --git a/public/app/features/explore/TraceView/components/common/CopyIcon.test.tsx b/public/app/features/explore/TraceView/components/common/CopyIcon.test.tsx index 9e00636459d..d4107a4a138 100644 --- a/public/app/features/explore/TraceView/components/common/CopyIcon.test.tsx +++ b/public/app/features/explore/TraceView/components/common/CopyIcon.test.tsx @@ -13,6 +13,7 @@ // limitations under the License. import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import CopyIcon from './CopyIcon'; @@ -43,11 +44,11 @@ describe('', () => { expect(() => render()).not.toThrow(); }); - it('copies when clicked', () => { + it('copies when clicked', async () => { render(); const button = screen.getByRole('button'); - button.click(); + await userEvent.click(button); expect(copySpy).toHaveBeenCalledWith(props.copyText); }); diff --git a/public/app/features/logs/components/LogRows.test.tsx b/public/app/features/logs/components/LogRows.test.tsx index 79a9f854fdc..ccb66f6b87f 100644 --- a/public/app/features/logs/components/LogRows.test.tsx +++ b/public/app/features/logs/components/LogRows.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; import { range } from 'lodash'; import React from 'react'; @@ -55,7 +55,9 @@ describe('LogRows', () => { expect(screen.queryAllByRole('row')).toHaveLength(2); expect(screen.queryAllByRole('row').at(0)).toHaveTextContent('log message 1'); - jest.runAllTimers(); + act(() => { + jest.runAllTimers(); + }); rerender( { it('then it should load playlist and header should be correct', async () => { await getTestContext(); - expect(screen.getByRole('heading', { name: /edit playlist/i })).toBeInTheDocument(); + expect(await screen.findByRole('heading', { name: /edit playlist/i })).toBeInTheDocument(); expect(screen.getByRole('textbox', { name: /playlist name/i })).toHaveValue('Test Playlist'); expect(screen.getByRole('textbox', { name: /playlist interval/i })).toHaveValue('5s'); expect(screen.getAllByRole('row')).toHaveLength(1); @@ -67,6 +67,7 @@ describe('PlaylistEditPage', () => { it('then correct api should be called', async () => { const { putMock } = await getTestContext(); + expect(await screen.findByRole('heading', { name: /edit playlist/i })).toBeInTheDocument(); expect(locationService.getLocation().pathname).toEqual('/'); await userEvent.clear(screen.getByRole('textbox', { name: /playlist name/i })); await userEvent.type(screen.getByRole('textbox', { name: /playlist name/i }), 'A Name'); diff --git a/public/app/features/query/components/QueryEditorRowHeader.test.tsx b/public/app/features/query/components/QueryEditorRowHeader.test.tsx index 4a876b4b4cc..668937d3cfa 100644 --- a/public/app/features/query/components/QueryEditorRowHeader.test.tsx +++ b/public/app/features/query/components/QueryEditorRowHeader.test.tsx @@ -1,4 +1,5 @@ -import { fireEvent, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { openMenu } from 'react-select-event'; @@ -30,13 +31,16 @@ jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => { }); describe('QueryEditorRowHeader', () => { - it('Can edit title', () => { + it('Can edit title', async () => { const scenario = renderScenario({}); - screen.getByTestId('query-name-div').click(); + await userEvent.click(screen.getByTestId('query-name-div')); const input = screen.getByTestId('query-name-input'); - fireEvent.change(input, { target: { value: 'new name' } }); - fireEvent.blur(input); + await userEvent.clear(input); + await userEvent.type(input, 'new name'); + + // blur the field + await userEvent.click(document.body); expect(jest.mocked(scenario.props.onChange).mock.calls[0][0].refId).toBe('new name'); }); @@ -44,9 +48,10 @@ describe('QueryEditorRowHeader', () => { it('Show error when other query with same name exists', async () => { renderScenario({}); - screen.getByTestId('query-name-div').click(); + await userEvent.click(screen.getByTestId('query-name-div')); const input = screen.getByTestId('query-name-input'); - fireEvent.change(input, { target: { value: 'B' } }); + await userEvent.clear(input); + await userEvent.type(input, 'B'); const alert = await screen.findByRole('alert'); expect(alert.textContent).toBe('Query name already exists'); @@ -55,9 +60,9 @@ describe('QueryEditorRowHeader', () => { it('Show error when empty name is specified', async () => { renderScenario({}); - screen.getByTestId('query-name-div').click(); + await userEvent.click(screen.getByTestId('query-name-div')); const input = screen.getByTestId('query-name-input'); - fireEvent.change(input, { target: { value: '' } }); + await userEvent.clear(input); const alert = await screen.findByRole('alert'); expect(alert.textContent).toBe('An empty query name is not allowed'); diff --git a/public/app/plugins/datasource/azuremonitor/components/DefaultSubscription.test.tsx b/public/app/plugins/datasource/azuremonitor/components/DefaultSubscription.test.tsx index 258f6e480f5..7fff646bb5d 100644 --- a/public/app/plugins/datasource/azuremonitor/components/DefaultSubscription.test.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/DefaultSubscription.test.tsx @@ -1,4 +1,5 @@ import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { createMockInstanceSetttings } from '../__mocks__/instanceSettings'; @@ -36,7 +37,7 @@ describe('DefaultSubscription', () => { expect(screen.getByTestId(selectors.components.configEditor.loadSubscriptions.button)).toBeDisabled(); }); - it('should enable load subscriptions if credentials are complete and set default subscription', () => { + it('should enable load subscriptions if credentials are complete and set default subscription', async () => { const props = { ...defaultProps, credentials: { ...defaultProps.credentials, clientSecret: 'client_secret' }, @@ -45,7 +46,7 @@ describe('DefaultSubscription', () => { const { rerender } = render(); expect(screen.getByTestId(selectors.components.configEditor.loadSubscriptions.button)).not.toBeDisabled(); - screen.getByTestId(selectors.components.configEditor.loadSubscriptions.button).click(); + await userEvent.click(screen.getByTestId(selectors.components.configEditor.loadSubscriptions.button)); rerender( { const renderAdvanced = jest.fn().mockReturnValue(
details!
); render(); const advancedSection = screen.getByText('Advanced'); - advancedSection.click(); + await userEvent.click(advancedSection); expect(await screen.findByText('details!')).toBeInTheDocument(); }); diff --git a/public/app/plugins/datasource/cloudwatch/components/MetricsQueryEditor/MetricsQueryEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/MetricsQueryEditor/MetricsQueryEditor.test.tsx index eeb1ed43e6e..ca3056303b9 100644 --- a/public/app/plugins/datasource/cloudwatch/components/MetricsQueryEditor/MetricsQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/MetricsQueryEditor/MetricsQueryEditor.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, act } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React from 'react'; import selectEvent from 'react-select-event'; @@ -89,7 +89,7 @@ describe('QueryEditor', () => { expect(await screen.findByText('Match exact')).toBeInTheDocument(); }); - it('shoud display wildcard option in dimension value dropdown', async () => { + it('should display wildcard option in dimension value dropdown', async () => { const props = setup(); if (props.query.queryMode !== 'Metrics') { fail(`expected props.query.queryMode to be 'Metrics', got '${props.query.queryMode}' instead`); @@ -112,44 +112,40 @@ describe('QueryEditor', () => { }); describe('when dynamic labels feature toggle is enabled', () => { - it('shoud render label field', async () => { - await act(async () => { - const props = setup(); - const originalValue = config.featureToggles.cloudWatchDynamicLabels; - config.featureToggles.cloudWatchDynamicLabels = true; + it('should render label field', async () => { + const props = setup(); + const originalValue = config.featureToggles.cloudWatchDynamicLabels; + config.featureToggles.cloudWatchDynamicLabels = true; - render( - - ); + render( + + ); - expect(screen.getByText('Label')).toBeInTheDocument(); - expect(screen.queryByText('Alias')).toBeNull(); - expect(screen.getByText("Period: ${PROP('Period')} InstanceId: ${PROP('Dim.InstanceId')}")); + expect(await screen.findByText('Label')).toBeInTheDocument(); + expect(screen.queryByText('Alias')).toBeNull(); + expect(screen.getByText("Period: ${PROP('Period')} InstanceId: ${PROP('Dim.InstanceId')}")); - config.featureToggles.cloudWatchDynamicLabels = originalValue; - }); + config.featureToggles.cloudWatchDynamicLabels = originalValue; }); }); describe('when dynamic labels feature toggle is disabled', () => { - it('shoud render alias field', async () => { - await act(async () => { - const props = setup(); - const originalValue = config.featureToggles.cloudWatchDynamicLabels; - config.featureToggles.cloudWatchDynamicLabels = false; + it('should render alias field', async () => { + const props = setup(); + const originalValue = config.featureToggles.cloudWatchDynamicLabels; + config.featureToggles.cloudWatchDynamicLabels = false; - const expected = 'Period: {{period}} InstanceId: {{InstanceId}}'; - render(); + const expected = 'Period: {{period}} InstanceId: {{InstanceId}}'; + render(); - expect(await screen.getByText('Alias')).toBeInTheDocument(); - expect(screen.queryByText('Label')).toBeNull(); - expect(screen.getByLabelText('Alias - optional')).toHaveValue(expected); + expect(await screen.findByText('Alias')).toBeInTheDocument(); + expect(screen.queryByText('Label')).toBeNull(); + expect(screen.getByLabelText('Alias - optional')).toHaveValue(expected); - config.featureToggles.cloudWatchDynamicLabels = originalValue; - }); + config.featureToggles.cloudWatchDynamicLabels = originalValue; }); }); }); diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryHeader.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryHeader.test.tsx index 9cc6fef9582..489757365b0 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryHeader.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryHeader.test.tsx @@ -1,4 +1,4 @@ -import { act, render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import selectEvent from 'react-select-event'; @@ -40,9 +40,7 @@ describe('QueryHeader', () => { /> ); await waitFor(() => expect(screen.queryByText('us-east-1')).toBeInTheDocument()); - await act(async () => { - await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); - }); + await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); expect(onChange).toHaveBeenCalledWith({ ...validMetricSearchBuilderQuery, region: 'us-east-2', @@ -65,9 +63,7 @@ describe('QueryHeader', () => { /> ); await waitFor(() => expect(screen.queryByText('us-east-1')).toBeInTheDocument()); - await act(async () => { - await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); - }); + await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); expect(onChange).toHaveBeenCalledWith({ ...validMetricSearchBuilderQuery, region: 'us-east-2', @@ -90,9 +86,7 @@ describe('QueryHeader', () => { /> ); await waitFor(() => expect(screen.queryByText('us-east-1')).toBeInTheDocument()); - await act(async () => { - await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); - }); + await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); expect(datasource.resources.isMonitoringAccount).not.toHaveBeenCalledWith('us-east-2'); }); @@ -111,9 +105,7 @@ describe('QueryHeader', () => { /> ); await waitFor(() => expect(screen.queryByText('us-east-1')).toBeInTheDocument()); - await act(async () => { - await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); - }); + await selectEvent.select(screen.getByLabelText(/Region/), 'us-east-2', { container: document.body }); expect(datasource.resources.isMonitoringAccount).not.toHaveBeenCalledWith(); }); }); diff --git a/public/app/plugins/datasource/cloudwatch/components/SQLBuilderEditor/SQLGroupBy.test.tsx b/public/app/plugins/datasource/cloudwatch/components/SQLBuilderEditor/SQLGroupBy.test.tsx index 6ca453eef3f..7ba7fa8d925 100644 --- a/public/app/plugins/datasource/cloudwatch/components/SQLBuilderEditor/SQLGroupBy.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/SQLBuilderEditor/SQLGroupBy.test.tsx @@ -1,4 +1,5 @@ import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import selectEvent from 'react-select-event'; @@ -66,12 +67,12 @@ describe('Cloudwatch SQLGroupBy', () => { const addButton = screen.getByRole('button', { name: 'Add' }); expect(addButton).toBeInTheDocument(); - addButton.click(); + await userEvent.click(addButton); - expect(await screen.findByText('Choose')).toBeInTheDocument(); + expect(screen.getByText('Choose')).toBeInTheDocument(); selectEvent.openMenu(screen.getByLabelText(/Group by/)); - expect(await screen.findByText('Template Variables')).toBeInTheDocument(); + expect(screen.getByText('Template Variables')).toBeInTheDocument(); }); it('should allow removing a dimension filter', async () => { @@ -84,10 +85,8 @@ describe('Cloudwatch SQLGroupBy', () => { const removeButton = screen.getByRole('button', { name: 'remove' }); expect(removeButton).toBeInTheDocument(); - removeButton.click(); + await userEvent.click(removeButton); - await waitFor(() => { - expect(screen.queryByText('InstanceId')).not.toBeInTheDocument(); - }); + expect(screen.queryByText('InstanceId')).not.toBeInTheDocument(); }); }); diff --git a/public/app/plugins/datasource/loki/components/LokiQueryEditorByApp.test.tsx b/public/app/plugins/datasource/loki/components/LokiQueryEditorByApp.test.tsx index c7530a2cddd..b531dd5906a 100644 --- a/public/app/plugins/datasource/loki/components/LokiQueryEditorByApp.test.tsx +++ b/public/app/plugins/datasource/loki/components/LokiQueryEditorByApp.test.tsx @@ -1,4 +1,4 @@ -import { render, RenderResult, waitFor } from '@testing-library/react'; +import { render, RenderResult, screen } from '@testing-library/react'; import { noop } from 'lodash'; import React from 'react'; @@ -35,30 +35,30 @@ function setup(app: CoreApp): RenderResult { } describe('LokiQueryEditorByApp', () => { - it('should render simplified query editor for cloud alerting', () => { - const { getByTestId, queryByTestId } = setup(CoreApp.CloudAlerting); + it('should render simplified query editor for cloud alerting', async () => { + setup(CoreApp.CloudAlerting); - expect(getByTestId(alertingTestIds.editor)).toBeInTheDocument(); - expect(queryByTestId(regularTestIds.editor)).toBeNull(); + expect(await screen.findByTestId(alertingTestIds.editor)).toBeInTheDocument(); + expect(screen.queryByTestId(regularTestIds.editor)).toBeNull(); }); it('should render regular query editor for unknown apps', async () => { - const { getByTestId, queryByTestId } = setup(CoreApp.Unknown); - expect(await waitFor(() => getByTestId(regularTestIds.editor))).toBeInTheDocument(); - expect(queryByTestId(alertingTestIds.editor)).toBeNull(); + setup(CoreApp.Unknown); + expect(await screen.findByTestId(regularTestIds.editor)).toBeInTheDocument(); + expect(screen.queryByTestId(alertingTestIds.editor)).toBeNull(); }); it('should render regular query editor for explore', async () => { - const { getByTestId, queryByTestId } = setup(CoreApp.Explore); + setup(CoreApp.Explore); - expect(await waitFor(() => getByTestId(regularTestIds.editor))).toBeInTheDocument(); - expect(queryByTestId(alertingTestIds.editor)).toBeNull(); + expect(await screen.findByTestId(regularTestIds.editor)).toBeInTheDocument(); + expect(screen.queryByTestId(alertingTestIds.editor)).toBeNull(); }); it('should render regular query editor for dashboard', async () => { - const { findByTestId, queryByTestId } = setup(CoreApp.Dashboard); + setup(CoreApp.Dashboard); - expect(await findByTestId(regularTestIds.editor)).toBeInTheDocument(); - expect(queryByTestId(alertingTestIds.editor)).toBeNull(); + expect(await screen.findByTestId(regularTestIds.editor)).toBeInTheDocument(); + expect(screen.queryByTestId(alertingTestIds.editor)).toBeNull(); }); }); diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LabelBrowserModal.test.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LabelBrowserModal.test.tsx index e36470b7d36..17db0881046 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LabelBrowserModal.test.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LabelBrowserModal.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { LokiDatasource } from '../../datasource'; @@ -33,14 +33,15 @@ describe('LabelBrowserModal', () => { it('renders the label browser modal when open', async () => { render(); - expect(await screen.findByText(/Loading/)).not.toBeInTheDocument(); - + await waitFor(() => { + expect(screen.queryByText(/Loading/)).not.toBeInTheDocument(); + }); expect(screen.getByRole('heading', { name: /label browser/i })).toBeInTheDocument(); }); it("doesn't render the label browser modal when closed", async () => { render(); - expect(screen.queryByRole('heading', { name: /label browser/i })).toBeNull(); + expect(screen.queryByRole('heading', { name: /label browser/i })).not.toBeInTheDocument(); }); }); diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx index ca098f1e3e1..3d59a9a020c 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; @@ -11,10 +11,10 @@ describe('LokiQueryBuilderOptions', () => { it('Can change query type', async () => { const { props } = setup(); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); expect(screen.getByLabelText('Range')).toBeChecked(); - screen.getByLabelText('Instant').click(); + await userEvent.click(screen.getByLabelText('Instant')); expect(props.onChange).toHaveBeenCalledWith({ ...props.query, @@ -25,11 +25,11 @@ describe('LokiQueryBuilderOptions', () => { it('Can change legend format', async () => { const { props } = setup(); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); const element = screen.getByLabelText('Legend'); await userEvent.type(element, 'asd'); - fireEvent.keyDown(element, { key: 'Enter', code: 'Enter', charCode: 13 }); + await userEvent.keyboard('{enter}'); expect(props.onChange).toHaveBeenCalledWith({ ...props.query, diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx index cd8a373b563..93cc8173792 100644 --- a/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx +++ b/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx @@ -1,4 +1,4 @@ -import { render, RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { noop } from 'lodash'; import React from 'react'; @@ -22,7 +22,7 @@ jest.mock('./monaco-query-field/MonacoQueryFieldLazy', () => { }; }); -function setup(app: CoreApp): RenderResult & { onRunQuery: jest.Mock } { +function setup(app: CoreApp): { onRunQuery: jest.Mock } { const dataSource = { createQuery: jest.fn((q) => q), getInitHints: () => [], @@ -37,7 +37,7 @@ function setup(app: CoreApp): RenderResult & { onRunQuery: jest.Mock } { } as unknown as PrometheusDatasource; const onRunQuery = jest.fn(); - const renderOutput = render( + render( { - it('should render simplified query editor for cloud alerting', () => { - const { getByTestId } = setup(CoreApp.CloudAlerting); + it('should render simplified query editor for cloud alerting', async () => { + setup(CoreApp.CloudAlerting); - expect(getByTestId(alertingTestIds.editor)).toBeInTheDocument(); + expect(await screen.findByTestId(alertingTestIds.editor)).toBeInTheDocument(); }); it('should render editor selector for unkown apps', () => { - const { getByTestId, queryByTestId } = setup(CoreApp.Unknown); + setup(CoreApp.Unknown); - expect(getByTestId('QueryEditorModeToggle')).toBeInTheDocument(); - expect(queryByTestId(alertingTestIds.editor)).toBeNull(); + expect(screen.getByTestId('QueryEditorModeToggle')).toBeInTheDocument(); + expect(screen.queryByTestId(alertingTestIds.editor)).toBeNull(); }); it('should render editor selector for explore', () => { - const { getByTestId, queryByTestId } = setup(CoreApp.Explore); + setup(CoreApp.Explore); - expect(getByTestId('QueryEditorModeToggle')).toBeInTheDocument(); - expect(queryByTestId(alertingTestIds.editor)).toBeNull(); + expect(screen.getByTestId('QueryEditorModeToggle')).toBeInTheDocument(); + expect(screen.queryByTestId(alertingTestIds.editor)).toBeNull(); }); it('should render editor selector for dashboard', () => { - const { getByTestId, queryByTestId } = setup(CoreApp.Dashboard); + setup(CoreApp.Dashboard); - expect(getByTestId('QueryEditorModeToggle')).toBeInTheDocument(); - expect(queryByTestId(alertingTestIds.editor)).toBeNull(); + expect(screen.getByTestId('QueryEditorModeToggle')).toBeInTheDocument(); + expect(screen.queryByTestId(alertingTestIds.editor)).toBeNull(); }); }); diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx index 6dc1d23111e..1f10acda38e 100644 --- a/public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx +++ b/public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx @@ -48,31 +48,40 @@ describe('PromQueryField', () => { window.getSelection = () => {}; }); - it('renders metrics chooser regularly if lookups are not disabled in the datasource settings', () => { + it('renders metrics chooser regularly if lookups are not disabled in the datasource settings', async () => { const queryField = render(); + // wait for component to render + await screen.findByRole('button'); + expect(queryField.getAllByRole('button')).toHaveLength(1); }); - it('renders a disabled metrics chooser if lookups are disabled in datasource settings', () => { + it('renders a disabled metrics chooser if lookups are disabled in datasource settings', async () => { const props = defaultProps; props.datasource.lookupsDisabled = true; const queryField = render(); + // wait for component to render + await screen.findByRole('button'); + const bcButton = queryField.getByRole('button'); expect(bcButton).toBeDisabled(); }); - it('renders an initial hint if no data and initial hint provided', () => { + it('renders an initial hint if no data and initial hint provided', async () => { const props = defaultProps; props.datasource.lookupsDisabled = true; props.datasource.getInitHints = () => [{ label: 'Initial hint', type: 'INFO' }]; render(); + // wait for component to render + await screen.findByRole('button'); + expect(screen.getByText('Initial hint')).toBeInTheDocument(); }); - it('renders query hint if data, query hint and initial hint provided', () => { + it('renders query hint if data, query hint and initial hint provided', async () => { const props = defaultProps; props.datasource.lookupsDisabled = true; props.datasource.getInitHints = () => [{ label: 'Initial hint', type: 'INFO' }]; @@ -89,6 +98,9 @@ describe('PromQueryField', () => { /> ); + // wait for component to render + await screen.findByRole('button'); + expect(screen.getByText('Query hint')).toBeInTheDocument(); expect(screen.queryByText('Initial hint')).not.toBeInTheDocument(); }); @@ -113,6 +125,9 @@ describe('PromQueryField', () => { /> ); + // wait for component to render + await screen.findByRole('button'); + const changedMetrics = ['baz', 'moo']; queryField.rerender( { // If we check the label browser right away it should be in loading state let labelBrowser = screen.getByRole('button'); expect(labelBrowser.textContent).toContain('Loading'); + + // wait for component to rerender + labelBrowser = await screen.findByRole('button'); + expect(labelBrowser.textContent).toContain('Metrics browser'); }); it('should not run query onBlur in explore', async () => { const onRunQuery = jest.fn(); const { container } = render(); + // wait for component to rerender + await screen.findByRole('button'); + const input = getByTestId(container, 'dummy-code-input'); expect(input).toBeInTheDocument(); await userEvent.type(input, 'metric'); - input.blur(); + + // blur element + await userEvent.click(document.body); expect(onRunQuery).not.toHaveBeenCalled(); }); @@ -144,10 +168,15 @@ describe('PromQueryField', () => { const onRunQuery = jest.fn(); const { container } = render(); + // wait for component to rerender + await screen.findByRole('button'); + const input = getByTestId(container, 'dummy-code-input'); expect(input).toBeInTheDocument(); await userEvent.type(input, 'metric'); - input.blur(); + + // blur element + await userEvent.click(document.body); expect(onRunQuery).toHaveBeenCalled(); }); }); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.test.tsx index a56bbcc1206..04aaf58b302 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.test.tsx @@ -1,4 +1,5 @@ import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { selectOptionInTest } from 'test/helpers/selectOptionInTest'; @@ -13,10 +14,10 @@ describe('PromQueryBuilderOptions', () => { it('Can change query type', async () => { const { props } = setup(); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); expect(screen.getByLabelText('Range')).toBeChecked(); - screen.getByLabelText('Instant').click(); + await userEvent.click(screen.getByLabelText('Instant')); expect(props.onChange).toHaveBeenCalledWith({ ...props.query, @@ -29,7 +30,7 @@ describe('PromQueryBuilderOptions', () => { it('Can set query type to "Both" on render for PanelEditor', async () => { setup({ instant: true, range: true }); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); expect(screen.getByLabelText('Both')).toBeChecked(); }); @@ -37,12 +38,12 @@ describe('PromQueryBuilderOptions', () => { it('Can set query type to "Both" on render for Explorer', async () => { setup({ instant: true, range: true }, CoreApp.Explore); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); expect(screen.getByLabelText('Both')).toBeChecked(); }); - it('Legend format default to Auto', async () => { + it('Legend format default to Auto', () => { setup(); expect(screen.getByText('Legend: Auto')).toBeInTheDocument(); }); @@ -50,12 +51,12 @@ describe('PromQueryBuilderOptions', () => { it('Can change legend format to verbose', async () => { const { props } = setup(); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); let legendModeSelect = screen.getByText('Auto').parentElement!; - legendModeSelect.click(); + await userEvent.click(legendModeSelect); - await selectOptionInTest(legendModeSelect as HTMLElement, 'Verbose'); + await selectOptionInTest(legendModeSelect, 'Verbose'); expect(props.onChange).toHaveBeenCalledWith({ ...props.query, @@ -66,12 +67,12 @@ describe('PromQueryBuilderOptions', () => { it('Can change legend format to custom', async () => { const { props } = setup(); - screen.getByTitle('Click to edit options').click(); + await userEvent.click(screen.getByTitle('Click to edit options')); let legendModeSelect = screen.getByText('Auto').parentElement!; - legendModeSelect.click(); + await userEvent.click(legendModeSelect); - await selectOptionInTest(legendModeSelect as HTMLElement, 'Custom'); + await selectOptionInTest(legendModeSelect, 'Custom'); expect(props.onChange).toHaveBeenCalledWith({ ...props.query, @@ -79,23 +80,23 @@ describe('PromQueryBuilderOptions', () => { }); }); - it('Handle defaults with undefined range', async () => { + it('Handle defaults with undefined range', () => { setup(getQueryWithDefaults({ refId: 'A', expr: '', range: undefined, instant: true }, CoreApp.Dashboard)); expect(screen.getByText('Type: Instant')).toBeInTheDocument(); }); - it('Should show "Exemplars: false" by default', async () => { + it('Should show "Exemplars: false" by default', () => { setup(); expect(screen.getByText('Exemplars: false')).toBeInTheDocument(); }); - it('Should show "Exemplars: false" when query has "Exemplars: false"', async () => { + it('Should show "Exemplars: false" when query has "Exemplars: false"', () => { setup({ exemplar: false }); expect(screen.getByText('Exemplars: false')).toBeInTheDocument(); }); - it('Should show "Exemplars: true" when query has "Exemplars: true"', async () => { + it('Should show "Exemplars: true" when query has "Exemplars: true"', () => { setup({ exemplar: true }); expect(screen.getByText('Exemplars: true')).toBeInTheDocument(); }); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.test.tsx index d42d6bb8881..90122c862c7 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.test.tsx @@ -45,13 +45,21 @@ describe('PromQueryCodeEditor', () => { const props = createProps(datasource); props.showExplain = true; render(); - expect(await screen.findByText(EXPLAIN_LABEL_FILTER_CONTENT)).toBeInTheDocument(); + + // wait for component to render + await screen.findByRole('button'); + + expect(screen.getByText(EXPLAIN_LABEL_FILTER_CONTENT)).toBeInTheDocument(); }); it('does not show explain section when showExplain is false', async () => { const { datasource } = createDatasource(); const props = createProps(datasource); render(); - expect(await screen.queryByText(EXPLAIN_LABEL_FILTER_CONTENT)).not.toBeInTheDocument(); + + // wait for component to render + await screen.findByRole('button'); + + expect(screen.queryByText(EXPLAIN_LABEL_FILTER_CONTENT)).not.toBeInTheDocument(); }); }); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx index 8dc1e640aa4..87beb07e386 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx @@ -99,41 +99,43 @@ describe('PromQueryEditorSelector', () => { it('shows code editor if expr and nothing else', async () => { // We opt for showing code editor for queries created before this feature was added render(); - expectCodeEditor(); + await expectCodeEditor(); }); it('shows code editor if no expr and nothing else since defaultEditor is code', async () => { renderWithDatasourceDefaultEditorMode(QueryEditorMode.Code); - expectCodeEditor(); + await expectCodeEditor(); }); it('shows builder if no expr and nothing else since defaultEditor is builder', async () => { renderWithDatasourceDefaultEditorMode(QueryEditorMode.Builder); - expectBuilder(); + await expectBuilder(); }); it('shows code editor when code mode is set', async () => { renderWithMode(QueryEditorMode.Code); - expectCodeEditor(); + await expectCodeEditor(); }); - it('shows builder when builder mode is set', () => { + it('shows builder when builder mode is set', async () => { renderWithMode(QueryEditorMode.Builder); - expectBuilder(); + await expectBuilder(); }); - it('shows Run Queries button in Dashboards', () => { + it('shows Run Queries button in Dashboards', async () => { renderWithProps({}, { app: CoreApp.Dashboard }); - expectRunQueriesButton(); + await expectRunQueriesButton(); }); - it('hides Run Queries button in Explore', () => { + it('hides Run Queries button in Explore', async () => { renderWithProps({}, { app: CoreApp.Explore }); + await expectCodeEditor(); expectNoRunQueriesButton(); }); - it('hides Run Queries button in Correlations Page', () => { + it('hides Run Queries button in Correlations Page', async () => { renderWithProps({}, { app: CoreApp.Correlations }); + await expectCodeEditor(); expectNoRunQueriesButton(); }); @@ -159,7 +161,7 @@ describe('PromQueryEditorSelector', () => { it('Can enable explain', async () => { renderWithMode(QueryEditorMode.Builder); expect(screen.queryByText(EXPLAIN_LABEL_FILTER_CONTENT)).not.toBeInTheDocument(); - screen.getByLabelText('Explain').click(); + await userEvent.click(screen.getByLabelText('Explain')); expect(await screen.findByText(EXPLAIN_LABEL_FILTER_CONTENT)).toBeInTheDocument(); }); @@ -228,16 +230,16 @@ function renderWithProps(overrides?: Partial, componentProps: Partial return { onChange, ...stuff }; } -function expectCodeEditor() { - expect(screen.getByText('MonacoQueryFieldWrapper')).toBeInTheDocument(); +async function expectCodeEditor() { + expect(await screen.findByText('MonacoQueryFieldWrapper')).toBeInTheDocument(); } -function expectBuilder() { - expect(screen.getByText('Metric')).toBeInTheDocument(); +async function expectBuilder() { + expect(await screen.findByText('Metric')).toBeInTheDocument(); } -function expectRunQueriesButton() { - expect(screen.getByRole('button', { name: /run queries/i })).toBeInTheDocument(); +async function expectRunQueriesButton() { + expect(await screen.findByRole('button', { name: /run queries/i })).toBeInTheDocument(); } function expectNoRunQueriesButton() { diff --git a/public/app/plugins/panel/alertGroups/AlertGroupsPanel.test.tsx b/public/app/plugins/panel/alertGroups/AlertGroupsPanel.test.tsx index df8b5bdf8fe..6849197c054 100644 --- a/public/app/plugins/panel/alertGroups/AlertGroupsPanel.test.tsx +++ b/public/app/plugins/panel/alertGroups/AlertGroupsPanel.test.tsx @@ -1,4 +1,4 @@ -import { render, waitFor } from '@testing-library/react'; +import { render } from '@testing-library/react'; import React from 'react'; import { Provider } from 'react-redux'; import { byTestId } from 'testing-library-selector'; @@ -116,10 +116,9 @@ describe('AlertGroupsPanel', () => { }); it('renders the panel with the groups', async () => { - await renderPanel(); + renderPanel(); - await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled()); - const groups = ui.group.getAll(); + const groups = await ui.group.findAll(); expect(groups).toHaveLength(2); @@ -131,19 +130,16 @@ describe('AlertGroupsPanel', () => { }); it('renders panel with groups expanded', async () => { - await renderPanel({ labels: '', alertmanager: 'Alertmanager', expandAll: true }); + renderPanel({ labels: '', alertmanager: 'Alertmanager', expandAll: true }); - await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled()); - const alerts = ui.alert.queryAll(); + const alerts = await ui.alert.findAll(); expect(alerts).toHaveLength(3); }); it('filters alerts by label filter', async () => { - await renderPanel({ labels: 'region=US-Central', alertmanager: 'Alertmanager', expandAll: true }); - - await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled()); - const alerts = ui.alert.queryAll(); + renderPanel({ labels: 'region=US-Central', alertmanager: 'Alertmanager', expandAll: true }); + const alerts = await ui.alert.findAll(); expect(alerts).toHaveLength(2); }); }); diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx index 78b6cefb309..b124a930a6f 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx @@ -33,7 +33,7 @@ describe('FlameGraphHeader', () => { render(); await userEvent.type(screen.getByPlaceholderText('Search..'), 'abc'); expect(screen.getByDisplayValue('abc')).toBeInTheDocument(); - screen.getByRole('button', { name: /Reset/i }).click(); + await userEvent.click(screen.getByRole('button', { name: /Reset/i })); expect(screen.queryByDisplayValue('abc')).not.toBeInTheDocument(); }); });