[ML] Migrate SelectInterval/SelectSeverity unit tests from enzyme to react-testing-lib (#153321)

Migrates the following React component tests from `enzyme` to
`react-testing-lib`.

- `SelectInterval`
- `SelectSeverity`
This commit is contained in:
Walter Rafelsberger 2023-03-23 09:26:40 +01:00 committed by GitHub
parent ec3294f2b3
commit 83ec37fe23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 122 deletions

View file

@ -5,58 +5,43 @@
* 2.0.
*/
import React from 'react';
import { act } from 'react-dom/test-utils';
import { MemoryRouter } from 'react-router-dom';
import { mount } from 'enzyme';
import { EuiSelect } from '@elastic/eui';
import { UrlStateProvider } from '@kbn/ml-url-state';
import React, { useState } from 'react';
import { render, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SelectInterval } from './select_interval';
describe('SelectInterval', () => {
test('creates correct initial selected value', () => {
const wrapper = mount(
<MemoryRouter>
<UrlStateProvider>
<SelectInterval />
</UrlStateProvider>
</MemoryRouter>
);
const select = wrapper.find(EuiSelect);
// The following mock setup is necessary so that we can simulate
// both triggering the update callback and the internal state update
// to update the dropdown to the new state.
const mockUpdateCallback = jest.fn();
const mockUseState = jest.fn().mockImplementation(useState);
jest.mock('@kbn/ml-url-state', () => ({
usePageUrlState: () => {
const [interval, setInterval] = mockUseState({ display: 'Auto', val: 'auto' });
return [interval, mockUpdateCallback.mockImplementation((d) => setInterval(d))];
},
}));
const defaultSelectedValue = select.props().value;
expect(defaultSelectedValue).toBe('auto');
describe('SelectInterval', () => {
afterEach(() => {
jest.clearAllMocks();
});
test('currently selected value is updated correctly on click', (done) => {
const wrapper = mount(
<MemoryRouter>
<UrlStateProvider>
<SelectInterval />
</UrlStateProvider>
</MemoryRouter>
);
const select = wrapper.find(EuiSelect).first();
const defaultSelectedValue = select.props().value;
expect(defaultSelectedValue).toBe('auto');
it('updates the selected value correctly on click', () => {
// arrange
const { getByText, getByTestId } = render(<SelectInterval />);
const onChange = select.props().onChange;
// assert initial state
expect((getByText('Auto') as HTMLOptionElement).selected).toBeTruthy();
// update
act(() => {
if (onChange !== undefined) {
onChange({ target: { value: 'day' } } as React.ChangeEvent<HTMLSelectElement>);
}
userEvent.selectOptions(getByTestId('mlAnomalyIntervalControls'), getByText('1 hour'));
});
setImmediate(() => {
wrapper.update();
const updatedSelect = wrapper.find(EuiSelect).first();
const updatedSelectedValue = updatedSelect.props().value;
expect(updatedSelectedValue).toBe('day');
done();
});
// assert updated state
expect(mockUpdateCallback).toBeCalledWith({ display: '1 hour', val: 'hour' });
expect((getByText('1 hour') as HTMLOptionElement).selected).toBeTruthy();
});
});

View file

@ -87,6 +87,7 @@ export const SelectIntervalUI: FC<SelectIntervalUIProps> = ({ interval, onChange
return (
<EuiSelect
data-test-subj="mlAnomalyIntervalControls"
prepend={i18n.translate('xpack.ml.explorer.intervalLabel', {
defaultMessage: 'Interval',
})}
@ -101,7 +102,6 @@ export const SelectIntervalUI: FC<SelectIntervalUIProps> = ({ interval, onChange
</EuiToolTip>
}
compressed
id="selectInterval"
options={OPTIONS}
value={interval.val}
onChange={handleOnChange}

View file

@ -4,96 +4,67 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useState } from 'react';
import { render, act, fireEvent, waitFor } from '@testing-library/react';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { MemoryRouter } from 'react-router-dom';
import { mount } from 'enzyme';
import { SelectSeverity, SEVERITY_OPTIONS } from './select_severity';
import { EuiSuperSelect } from '@elastic/eui';
import { UrlStateProvider } from '@kbn/ml-url-state';
import { SelectSeverity } from './select_severity';
// The following mock setup is necessary so that we can simulate
// both triggering the update callback and the internal state update
// to update the dropdown to the new state.
const mockSeverityOptions = SEVERITY_OPTIONS;
const mockUpdateCallback = jest.fn();
const mockUseState = jest.fn().mockImplementation(useState);
jest.mock('@kbn/ml-url-state', () => ({
usePageUrlState: () => {
const [severity, setSeverity] = mockUseState(mockSeverityOptions[0]);
return [severity, mockUpdateCallback.mockImplementation((d) => setSeverity(d))];
},
}));
describe('SelectSeverity', () => {
test('creates correct severity options and initial selected value', () => {
const wrapper = mount(
<MemoryRouter>
<UrlStateProvider>
<SelectSeverity />
</UrlStateProvider>
</MemoryRouter>
);
const select = wrapper.find(EuiSuperSelect);
const options = select.props().options;
const defaultSelectedValue = select.props().valueOfSelected;
expect(defaultSelectedValue).toBe('warning');
expect(options.length).toEqual(4);
// excpect options Array to equal Array containing Object that contains the property
expect(options).toEqual(
expect.arrayContaining([
expect.objectContaining({
value: 'warning',
}),
])
);
expect(options).toEqual(
expect.arrayContaining([
expect.objectContaining({
value: 'minor',
}),
])
);
expect(options).toEqual(
expect.arrayContaining([
expect.objectContaining({
value: 'major',
}),
])
);
expect(options).toEqual(
expect.arrayContaining([
expect.objectContaining({
value: 'critical',
}),
])
);
afterEach(() => {
jest.clearAllMocks();
});
test('state for currently selected value is updated correctly on click', (done) => {
const wrapper = mount(
<MemoryRouter>
<UrlStateProvider>
<SelectSeverity />
</UrlStateProvider>
</MemoryRouter>
it('updates the severity option correctly on click', async () => {
// arrange
const { getByText, getAllByText, queryByText, getByTestId } = render(
<IntlProvider locale="en">
<SelectSeverity />
</IntlProvider>
);
const select = wrapper.find(EuiSuperSelect).first();
const defaultSelectedValue = select.props().valueOfSelected;
expect(defaultSelectedValue).toBe('warning');
const onChange = select.props().onChange;
// assert initial state
expect(getAllByText('warning')).toHaveLength(2);
expect(queryByText('minor')).not.toBeInTheDocument();
expect(queryByText('major')).not.toBeInTheDocument();
expect(queryByText('critical')).not.toBeInTheDocument();
// open popover
act(() => {
if (onChange !== undefined) {
onChange('critical');
}
fireEvent.click(getByTestId('mlAnomalySeverityThresholdControls'));
});
setImmediate(() => {
wrapper.update();
const updatedSelect = wrapper.find(EuiSuperSelect).first();
const updatedSelectedValue = updatedSelect.props().valueOfSelected;
expect(updatedSelectedValue).toBe('critical');
done();
// assert open popover
expect(getAllByText('warning')).toHaveLength(3);
expect(getAllByText('minor')).toHaveLength(1);
expect(getAllByText('major')).toHaveLength(1);
expect(getAllByText('critical')).toHaveLength(1);
// click item in popver
act(() => {
fireEvent.click(getByText('major'));
});
// assert updated state
expect(mockUpdateCallback).toBeCalledWith(SEVERITY_OPTIONS[2]);
await waitFor(() => {
expect(queryByText('warning')).not.toBeInTheDocument();
expect(queryByText('minor')).not.toBeInTheDocument();
expect(getAllByText('major')).toHaveLength(2);
expect(queryByText('critical')).not.toBeInTheDocument();
});
});
});

View file

@ -150,7 +150,6 @@ export const SelectSeverityUI: FC<
prepend={i18n.translate('xpack.ml.explorer.severityThresholdLabel', {
defaultMessage: 'Severity',
})}
id="severityThreshold"
data-test-subj={'mlAnomalySeverityThresholdControls'}
className={classNames}
hasDividers