Chore: Adjust unit tests so they work with react 18 (#64698)

tweak unit tests so they work with react 18
This commit is contained in:
Ashley Harrison
2023-03-14 17:24:04 +00:00
committed by GitHub
parent c29b6c07dc
commit 85e5326040
33 changed files with 452 additions and 409 deletions

View File

@@ -24,7 +24,8 @@ describe('ColorPickerInput', () => {
const mockOnChange = jest.fn();
render(<ColorPickerInput onChange={mockOnChange} />);
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('');
});

View File

@@ -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();

View File

@@ -54,7 +54,7 @@ const ButtonSelectComponent = <T,>(props: Props<T>) => {
{...buttonProps}
{...restProps}
>
{value?.label || value?.value}
{value?.label || (value?.value != null ? String(value?.value) : null)}
</ToolbarButton>
{state.isOpen && (
<div className={styles.menuWrapper}>

View File

@@ -29,7 +29,8 @@ describe('Input', () => {
render(<Input validationEvents={testBlurValidation} placeholder={PLACEHOLDER_TEXT} />);
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(<Input validationEvents={testBlurValidation} placeholder={PLACEHOLDER_TEXT} />);
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();
});

View File

@@ -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', () => {
</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', () => {
</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();
});
});

View File

@@ -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');

View File

@@ -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(<ReadonlyFolderPicker {...props} />);
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);
});

View File

@@ -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);
});
});
});

View File

@@ -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<typeof configureStore>
) => {
return act(async () => {
render(
<TestProvider store={initialStore}>
<PanelAlertTabContent dashboard={dashboard} panel={panel} />
</TestProvider>
);
});
render(
<TestProvider store={initialStore}>
<PanelAlertTabContent dashboard={dashboard} panel={panel} />
</TestProvider>
);
};
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(

View File

@@ -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();

View File

@@ -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<Props>) => {
render(<ValueMappingsEditorModal {...props} />);
};
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,
},
},
},
{
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 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 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,
},
},
},
]);
});
});
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: [] });
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,
},
},
},
]);
});
});
});

View File

@@ -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);

View File

@@ -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()));
});

View File

@@ -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();
});
});

View File

@@ -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('<CopyIcon />', () => {
expect(() => render(<CopyIcon {...props} />)).not.toThrow();
});
it('copies when clicked', () => {
it('copies when clicked', async () => {
render(<CopyIcon {...props} />);
const button = screen.getByRole('button');
button.click();
await userEvent.click(button);
expect(copySpy).toHaveBeenCalledWith(props.copyText);
});

View File

@@ -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(
<LogRows
logRows={rows}

View File

@@ -56,7 +56,7 @@ describe('PlaylistEditPage', () => {
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');

View File

@@ -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');

View File

@@ -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(<DefaultSubscription {...props} />);
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(
<DefaultSubscription
{...props}

View File

@@ -1,4 +1,5 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import AdvancedMulti from './AdvancedMulti';
@@ -9,7 +10,7 @@ describe('AdvancedMulti', () => {
const renderAdvanced = jest.fn().mockReturnValue(<div>details!</div>);
render(<AdvancedMulti onChange={onChange} resources={[{}]} renderAdvanced={renderAdvanced} />);
const advancedSection = screen.getByText('Advanced');
advancedSection.click();
await userEvent.click(advancedSection);
expect(await screen.findByText('details!')).toBeInTheDocument();
});

View File

@@ -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(
<MetricsQueryEditor
{...props}
query={{ ...props.query, refId: 'A', alias: 'Period: {{period}} InstanceId: {{InstanceId}}' }}
/>
);
render(
<MetricsQueryEditor
{...props}
query={{ ...props.query, refId: 'A', alias: 'Period: {{period}} InstanceId: {{InstanceId}}' }}
/>
);
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(<MetricsQueryEditor {...props} query={{ ...props.query, refId: 'A', alias: expected }} />);
const expected = 'Period: {{period}} InstanceId: {{InstanceId}}';
render(<MetricsQueryEditor {...props} query={{ ...props.query, refId: 'A', alias: expected }} />);
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;
});
});
});

View File

@@ -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();
});
});

View File

@@ -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();
});
});

View File

@@ -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();
});
});

View File

@@ -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(<LabelBrowserModal {...props} />);
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(<LabelBrowserModal {...props} isOpen={false} />);
expect(screen.queryByRole('heading', { name: /label browser/i })).toBeNull();
expect(screen.queryByRole('heading', { name: /label browser/i })).not.toBeInTheDocument();
});
});

View File

@@ -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,

View File

@@ -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(
<PromQueryEditorByApp
app={app}
onChange={noop}
@@ -48,36 +48,35 @@ function setup(app: CoreApp): RenderResult & { onRunQuery: jest.Mock } {
);
return {
...renderOutput,
onRunQuery,
};
}
describe('PromQueryEditorByApp', () => {
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();
});
});

View File

@@ -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(<PromQueryField {...defaultProps} />);
// 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(<PromQueryField {...props} />);
// 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(<PromQueryField {...props} />);
// 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(
<PromQueryField
@@ -127,16 +142,25 @@ describe('PromQueryField', () => {
// 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(<PromQueryField {...defaultProps} app={CoreApp.Explore} onRunQuery={onRunQuery} />);
// 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(<PromQueryField {...defaultProps} app={CoreApp.Dashboard} onRunQuery={onRunQuery} />);
// 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();
});
});

View File

@@ -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();
});

View File

@@ -45,13 +45,21 @@ describe('PromQueryCodeEditor', () => {
const props = createProps(datasource);
props.showExplain = true;
render(<PromQueryCodeEditor {...props} query={{ expr: '', refId: 'refid', interval: '1s' }} />);
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(<PromQueryCodeEditor {...props} query={{ expr: '', refId: 'refid', interval: '1s' }} />);
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();
});
});

View File

@@ -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(<PromQueryEditorSelector {...defaultProps} />);
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<PromQuery>, 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() {

View File

@@ -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);
});
});

View File

@@ -33,7 +33,7 @@ describe('FlameGraphHeader', () => {
render(<FlameGraphHeaderWithProps />);
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();
});
});