mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Remote clusters] Refactor tests (#82517)
This commit is contained in:
parent
051ed13858
commit
ea0736e74a
8 changed files with 142 additions and 80 deletions
|
@ -3,10 +3,10 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { registerTestBed } from '../../../../../test_utils';
|
||||
|
||||
/* eslint-disable @kbn/eslint/no-restricted-paths */
|
||||
import { RemoteClusterAdd } from '../../../public/application/sections/remote_cluster_add';
|
||||
import { createRemoteClustersStore } from '../../../public/application/store';
|
||||
import { registerRouter } from '../../../public/application/services/routing';
|
||||
|
@ -24,8 +24,12 @@ export const setup = (props) => {
|
|||
const testBed = initTestBed(props);
|
||||
|
||||
// User actions
|
||||
const clickSaveForm = () => {
|
||||
testBed.find('remoteClusterFormSaveButton').simulate('click');
|
||||
const clickSaveForm = async () => {
|
||||
await act(async () => {
|
||||
testBed.find('remoteClusterFormSaveButton').simulate('click');
|
||||
});
|
||||
|
||||
testBed.component.update();
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { nextTick, setupEnvironment } from '../helpers';
|
||||
import { setupEnvironment } from '../helpers';
|
||||
import { NON_ALPHA_NUMERIC_CHARS, ACCENTED_CHARS } from './special_characters';
|
||||
import { setup } from './remote_clusters_add.helpers';
|
||||
|
||||
|
@ -15,6 +16,7 @@ describe('Create Remote cluster', () => {
|
|||
let actions;
|
||||
let form;
|
||||
let server;
|
||||
let component;
|
||||
|
||||
beforeAll(() => {
|
||||
({ server } = setupEnvironment());
|
||||
|
@ -24,8 +26,11 @@ describe('Create Remote cluster', () => {
|
|||
server.restore();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
({ form, exists, find, actions } = setup());
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
({ form, exists, find, actions, component } = setup());
|
||||
});
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('should have the title of the page set correctly', () => {
|
||||
|
@ -45,7 +50,11 @@ describe('Create Remote cluster', () => {
|
|||
false
|
||||
);
|
||||
|
||||
form.toggleEuiSwitch('remoteClusterFormSkipUnavailableFormToggle');
|
||||
act(() => {
|
||||
form.toggleEuiSwitch('remoteClusterFormSkipUnavailableFormToggle');
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
expect(find('remoteClusterFormSkipUnavailableFormToggle').props()['aria-checked']).toBe(true);
|
||||
});
|
||||
|
@ -56,16 +65,20 @@ describe('Create Remote cluster', () => {
|
|||
// By default it should be set to "false"
|
||||
expect(find('remoteClusterFormConnectionModeToggle').props()['aria-checked']).toBe(false);
|
||||
|
||||
form.toggleEuiSwitch('remoteClusterFormConnectionModeToggle');
|
||||
act(() => {
|
||||
form.toggleEuiSwitch('remoteClusterFormConnectionModeToggle');
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
expect(find('remoteClusterFormConnectionModeToggle').props()['aria-checked']).toBe(true);
|
||||
});
|
||||
|
||||
test('should display errors and disable the save button when clicking "save" without filling the form', () => {
|
||||
test('should display errors and disable the save button when clicking "save" without filling the form', async () => {
|
||||
expect(exists('remoteClusterFormGlobalError')).toBe(false);
|
||||
expect(find('remoteClusterFormSaveButton').props().disabled).toBe(false);
|
||||
|
||||
actions.clickSaveForm();
|
||||
await actions.clickSaveForm();
|
||||
|
||||
expect(exists('remoteClusterFormGlobalError')).toBe(true);
|
||||
expect(form.getErrorsMessages()).toEqual([
|
||||
|
@ -83,19 +96,22 @@ describe('Create Remote cluster', () => {
|
|||
let form;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ component, form, actions } = setup());
|
||||
await act(async () => {
|
||||
({ component, form, actions } = setup());
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('should not allow spaces', () => {
|
||||
test('should not allow spaces', async () => {
|
||||
form.setInputValue('remoteClusterFormNameInput', 'with space');
|
||||
actions.clickSaveForm();
|
||||
|
||||
await actions.clickSaveForm();
|
||||
|
||||
expect(form.getErrorsMessages()).toContain('Spaces are not allowed in the name.');
|
||||
});
|
||||
|
||||
test('should only allow alpha-numeric characters, "-" (dash) and "_" (underscore)', () => {
|
||||
test('should only allow alpha-numeric characters, "-" (dash) and "_" (underscore)', async () => {
|
||||
const expectInvalidChar = (char) => {
|
||||
if (char === '-' || char === '_') {
|
||||
return;
|
||||
|
@ -103,6 +119,7 @@ describe('Create Remote cluster', () => {
|
|||
|
||||
try {
|
||||
form.setInputValue('remoteClusterFormNameInput', `with${char}`);
|
||||
|
||||
expect(form.getErrorsMessages()).toContain(
|
||||
`Remove the character ${char} from the name.`
|
||||
);
|
||||
|
@ -111,7 +128,7 @@ describe('Create Remote cluster', () => {
|
|||
}
|
||||
};
|
||||
|
||||
actions.clickSaveForm(); // display form errors
|
||||
await actions.clickSaveForm(); // display form errors
|
||||
|
||||
[...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS].forEach(expectInvalidChar);
|
||||
});
|
||||
|
@ -120,13 +137,20 @@ describe('Create Remote cluster', () => {
|
|||
describe('seeds', () => {
|
||||
let actions;
|
||||
let form;
|
||||
let component;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ form, actions } = setup());
|
||||
await act(async () => {
|
||||
({ form, actions, component } = setup());
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
form.setInputValue('remoteClusterFormNameInput', 'remote_cluster_test');
|
||||
});
|
||||
|
||||
test('should only allow alpha-numeric characters and "-" (dash) in the node "host" part', () => {
|
||||
actions.clickSaveForm(); // display form errors
|
||||
test('should only allow alpha-numeric characters and "-" (dash) in the node "host" part', async () => {
|
||||
await actions.clickSaveForm(); // display form errors
|
||||
|
||||
const notInArray = (array) => (value) => array.indexOf(value) < 0;
|
||||
|
||||
|
@ -142,8 +166,8 @@ describe('Create Remote cluster', () => {
|
|||
.forEach(expectInvalidChar);
|
||||
});
|
||||
|
||||
test('should require a numeric "port" to be set', () => {
|
||||
actions.clickSaveForm();
|
||||
test('should require a numeric "port" to be set', async () => {
|
||||
await actions.clickSaveForm();
|
||||
|
||||
form.setComboBoxValue('remoteClusterFormSeedsInput', '192.168.1.1');
|
||||
expect(form.getErrorsMessages()).toContain('A port is required.');
|
||||
|
@ -156,16 +180,25 @@ describe('Create Remote cluster', () => {
|
|||
describe('proxy address', () => {
|
||||
let actions;
|
||||
let form;
|
||||
let component;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ form, actions } = setup());
|
||||
await act(async () => {
|
||||
({ form, actions, component } = setup());
|
||||
});
|
||||
|
||||
// Enable "proxy" mode
|
||||
form.toggleEuiSwitch('remoteClusterFormConnectionModeToggle');
|
||||
component.update();
|
||||
|
||||
act(() => {
|
||||
// Enable "proxy" mode
|
||||
form.toggleEuiSwitch('remoteClusterFormConnectionModeToggle');
|
||||
});
|
||||
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('should only allow alpha-numeric characters and "-" (dash) in the proxy address "host" part', () => {
|
||||
actions.clickSaveForm(); // display form errors
|
||||
test('should only allow alpha-numeric characters and "-" (dash) in the proxy address "host" part', async () => {
|
||||
await actions.clickSaveForm(); // display form errors
|
||||
|
||||
const notInArray = (array) => (value) => array.indexOf(value) < 0;
|
||||
|
||||
|
@ -181,8 +214,8 @@ describe('Create Remote cluster', () => {
|
|||
.forEach(expectInvalidChar);
|
||||
});
|
||||
|
||||
test('should require a numeric "port" to be set', () => {
|
||||
actions.clickSaveForm();
|
||||
test('should require a numeric "port" to be set', async () => {
|
||||
await actions.clickSaveForm();
|
||||
|
||||
form.setInputValue('remoteClusterFormProxyAddressInput', '192.168.1.1');
|
||||
expect(form.getErrorsMessages()).toContain('A port is required.');
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { registerTestBed } from '../../../../../test_utils';
|
||||
|
||||
/* eslint-disable @kbn/eslint/no-restricted-paths */
|
||||
import { RemoteClusterEdit } from '../../../public/application/sections/remote_cluster_edit';
|
||||
import { createRemoteClustersStore } from '../../../public/application/store';
|
||||
import { registerRouter } from '../../../public/application/services/routing';
|
||||
|
|
|
@ -16,28 +16,23 @@ import {
|
|||
} from './remote_clusters_edit.helpers';
|
||||
|
||||
describe('Edit Remote cluster', () => {
|
||||
let server;
|
||||
let httpRequestsMockHelpers;
|
||||
let component;
|
||||
let find;
|
||||
let exists;
|
||||
let waitFor;
|
||||
|
||||
beforeAll(() => {
|
||||
({ server, httpRequestsMockHelpers } = setupEnvironment());
|
||||
});
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
|
||||
afterAll(() => {
|
||||
server.restore();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
httpRequestsMockHelpers.setLoadRemoteClustersResponse([REMOTE_CLUSTER_EDIT]);
|
||||
httpRequestsMockHelpers.setLoadRemoteClustersResponse([REMOTE_CLUSTER_EDIT]);
|
||||
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
({ component, find, exists, waitFor } = setup());
|
||||
await waitFor('remoteClusterForm');
|
||||
({ component, find, exists } = setup());
|
||||
});
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('should have the title of the page set correctly', () => {
|
||||
|
@ -59,9 +54,10 @@ describe('Edit Remote cluster', () => {
|
|||
|
||||
await act(async () => {
|
||||
addRemoteClusterTestBed = setupRemoteClustersAdd();
|
||||
addRemoteClusterTestBed.waitFor('remoteClusterAddPage');
|
||||
});
|
||||
|
||||
addRemoteClusterTestBed.component.update();
|
||||
|
||||
const formEdit = component.find(RemoteClusterForm);
|
||||
const formAdd = addRemoteClusterTestBed.component.find(RemoteClusterForm);
|
||||
|
||||
|
|
|
@ -3,20 +3,17 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import axios from 'axios';
|
||||
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
||||
|
||||
import {
|
||||
notificationServiceMock,
|
||||
fatalErrorsServiceMock,
|
||||
docLinksServiceMock,
|
||||
injectedMetadataServiceMock,
|
||||
} from '../../../../../../src/core/public/mocks';
|
||||
|
||||
import { usageCollectionPluginMock } from '../../../../../../src/plugins/usage_collection/public/mocks';
|
||||
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { HttpService } from '../../../../../../src/core/public/http';
|
||||
|
||||
/* eslint-disable @kbn/eslint/no-restricted-paths */
|
||||
import { init as initBreadcrumb } from '../../../public/application/services/breadcrumb';
|
||||
import { init as initHttp } from '../../../public/application/services/http';
|
||||
import { init as initNotification } from '../../../public/application/services/notification';
|
||||
|
@ -25,10 +22,10 @@ import { init as initDocumentation } from '../../../public/application/services/
|
|||
import { init as initHttpRequests } from './http_requests';
|
||||
|
||||
export const setupEnvironment = () => {
|
||||
const httpServiceSetupMock = new HttpService().setup({
|
||||
injectedMetadata: injectedMetadataServiceMock.createSetupContract(),
|
||||
fatalErrors: fatalErrorsServiceMock.createSetupContract(),
|
||||
});
|
||||
// axios has a similar interface to HttpSetup, but we
|
||||
// flatten out the response.
|
||||
const mockHttpClient = axios.create({ adapter: axiosXhrAdapter });
|
||||
mockHttpClient.interceptors.response.use(({ data }) => data);
|
||||
|
||||
initBreadcrumb(() => {});
|
||||
initDocumentation(docLinksServiceMock.createStartContract());
|
||||
|
@ -37,7 +34,7 @@ export const setupEnvironment = () => {
|
|||
notificationServiceMock.createSetupContract().toasts,
|
||||
fatalErrorsServiceMock.createSetupContract()
|
||||
);
|
||||
initHttp(httpServiceSetupMock);
|
||||
initHttp(mockHttpClient);
|
||||
|
||||
const { server, httpRequestsMockHelpers } = initHttpRequests();
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { registerTestBed, findTestSubject } from '../../../../../test_utils';
|
||||
|
||||
/* eslint-disable @kbn/eslint/no-restricted-paths */
|
||||
import { RemoteClusterList } from '../../../public/application/sections/remote_cluster_list';
|
||||
import { createRemoteClustersStore } from '../../../public/application/store';
|
||||
import { registerRouter } from '../../../public/application/services/routing';
|
||||
|
@ -29,15 +29,26 @@ export const setup = (props) => {
|
|||
const { rows } = testBed.table.getMetaData(EUI_TABLE);
|
||||
const row = rows[index];
|
||||
const checkBox = row.reactWrapper.find('input').hostNodes();
|
||||
checkBox.simulate('change', { target: { checked: true } });
|
||||
|
||||
act(() => {
|
||||
checkBox.simulate('change', { target: { checked: true } });
|
||||
});
|
||||
|
||||
testBed.component.update();
|
||||
};
|
||||
|
||||
const clickBulkDeleteButton = () => {
|
||||
testBed.find('remoteClusterBulkDeleteButton').simulate('click');
|
||||
const { find, component } = testBed;
|
||||
act(() => {
|
||||
find('remoteClusterBulkDeleteButton').simulate('click');
|
||||
});
|
||||
|
||||
component.update();
|
||||
};
|
||||
|
||||
const clickRowActionButtonAt = (index = 0, action = 'delete') => {
|
||||
const { rows } = testBed.table.getMetaData(EUI_TABLE);
|
||||
const { table, component } = testBed;
|
||||
const { rows } = table.getMetaData(EUI_TABLE);
|
||||
const indexLastColumn = rows[index].columns.length - 1;
|
||||
const tableCellActions = rows[index].columns[indexLastColumn].reactWrapper;
|
||||
|
||||
|
@ -45,32 +56,54 @@ export const setup = (props) => {
|
|||
if (action === 'delete') {
|
||||
button = findTestSubject(tableCellActions, 'remoteClusterTableRowRemoveButton');
|
||||
} else if (action === 'edit') {
|
||||
findTestSubject(tableCellActions, 'remoteClusterTableRowEditButton');
|
||||
button = findTestSubject(tableCellActions, 'remoteClusterTableRowEditButton');
|
||||
}
|
||||
|
||||
if (!button) {
|
||||
throw new Error(`Button for action "${action}" not found.`);
|
||||
}
|
||||
|
||||
button.simulate('click');
|
||||
act(() => {
|
||||
button.simulate('click');
|
||||
});
|
||||
|
||||
component.update();
|
||||
};
|
||||
|
||||
const clickConfirmModalDeleteRemoteCluster = () => {
|
||||
const modal = testBed.find('remoteClustersDeleteConfirmModal');
|
||||
findTestSubject(modal, 'confirmModalConfirmButton').simulate('click');
|
||||
const { find, component } = testBed;
|
||||
const modal = find('remoteClustersDeleteConfirmModal');
|
||||
|
||||
act(() => {
|
||||
findTestSubject(modal, 'confirmModalConfirmButton').simulate('click');
|
||||
});
|
||||
|
||||
component.update();
|
||||
};
|
||||
|
||||
const clickRemoteClusterAt = (index = 0) => {
|
||||
const { rows } = testBed.table.getMetaData(EUI_TABLE);
|
||||
const { table, component } = testBed;
|
||||
const { rows } = table.getMetaData(EUI_TABLE);
|
||||
const remoteClusterLink = findTestSubject(
|
||||
rows[index].reactWrapper,
|
||||
'remoteClustersTableListClusterLink'
|
||||
);
|
||||
remoteClusterLink.simulate('click');
|
||||
|
||||
act(() => {
|
||||
remoteClusterLink.simulate('click');
|
||||
});
|
||||
|
||||
component.update();
|
||||
};
|
||||
|
||||
const clickPaginationNextButton = () => {
|
||||
testBed.find('remoteClusterListTable.pagination-button-next').simulate('click');
|
||||
const { find, component } = testBed;
|
||||
|
||||
act(() => {
|
||||
find('remoteClusterListTable.pagination-button-next').simulate('click');
|
||||
});
|
||||
|
||||
component.update();
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -10,25 +10,23 @@ import { getRemoteClusterMock } from '../../../fixtures/remote_cluster';
|
|||
|
||||
import { PROXY_MODE } from '../../../common/constants';
|
||||
|
||||
import { setupEnvironment, nextTick, getRandomString, findTestSubject } from '../helpers';
|
||||
import { setupEnvironment, getRandomString, findTestSubject } from '../helpers';
|
||||
|
||||
import { setup } from './remote_clusters_list.helpers';
|
||||
|
||||
describe('<RemoteClusterList />', () => {
|
||||
let server;
|
||||
let httpRequestsMockHelpers;
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
|
||||
beforeAll(() => {
|
||||
({ server, httpRequestsMockHelpers } = setupEnvironment());
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
server.restore();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
httpRequestsMockHelpers.setLoadRemoteClustersResponse([]);
|
||||
});
|
||||
httpRequestsMockHelpers.setLoadRemoteClustersResponse([]);
|
||||
|
||||
describe('on component mount', () => {
|
||||
let exists;
|
||||
|
@ -47,9 +45,10 @@ describe('<RemoteClusterList />', () => {
|
|||
let component;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ exists, component } = setup());
|
||||
await act(async () => {
|
||||
({ exists, component } = setup());
|
||||
});
|
||||
|
||||
await nextTick(100); // We need to wait next tick for the mock server response to kick in
|
||||
component.update();
|
||||
});
|
||||
|
||||
|
@ -66,7 +65,7 @@ describe('<RemoteClusterList />', () => {
|
|||
let find;
|
||||
let table;
|
||||
let actions;
|
||||
let waitFor;
|
||||
let component;
|
||||
let form;
|
||||
|
||||
const remoteClusters = [
|
||||
|
@ -87,9 +86,10 @@ describe('<RemoteClusterList />', () => {
|
|||
httpRequestsMockHelpers.setLoadRemoteClustersResponse(remoteClusters);
|
||||
|
||||
await act(async () => {
|
||||
({ find, table, actions, waitFor, form } = setup());
|
||||
await waitFor('remoteClusterListTable');
|
||||
({ find, table, actions, form, component } = setup());
|
||||
});
|
||||
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('pagination works', () => {
|
||||
|
@ -117,7 +117,6 @@ describe('<RemoteClusterList />', () => {
|
|||
let actions;
|
||||
let tableCellsValues;
|
||||
let rows;
|
||||
let waitFor;
|
||||
|
||||
// For deterministic tests, we need to make sure that remoteCluster1 comes before remoteCluster2
|
||||
// in the table list that is rendered. As the table orders alphabetically by index name
|
||||
|
@ -151,11 +150,11 @@ describe('<RemoteClusterList />', () => {
|
|||
httpRequestsMockHelpers.setLoadRemoteClustersResponse(remoteClusters);
|
||||
|
||||
await act(async () => {
|
||||
({ component, find, exists, table, actions, waitFor } = setup());
|
||||
|
||||
await waitFor('remoteClusterListTable');
|
||||
({ component, find, exists, table, actions } = setup());
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
// Read the remote clusters list table
|
||||
({ rows, tableCellsValues } = table.getMetaData('remoteClusterListTable'));
|
||||
});
|
||||
|
@ -282,10 +281,11 @@ describe('<RemoteClusterList />', () => {
|
|||
actions.clickConfirmModalDeleteRemoteCluster();
|
||||
|
||||
await act(async () => {
|
||||
await nextTick(600); // there is a 500ms timeout in the api action
|
||||
component.update();
|
||||
jest.advanceTimersByTime(600); // there is a 500ms timeout in the api action
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
({ rows } = table.getMetaData('remoteClusterListTable'));
|
||||
|
||||
expect(rows.length).toBe(2);
|
||||
|
|
|
@ -122,7 +122,7 @@ In order to prevent flakiness in component integration tests, please consider th
|
|||
|
||||
- Be **synchronous** as much as possible.
|
||||
|
||||
Hooks are delicate when it comes to state updates. Sometimes calling `act()` synchronously works, sometimes it doesn't. The reasoning behind this isn't clear yet. The best approach is to try synchrounsly first and if it fails, because of an `act()` error, then use the async version.
|
||||
Hooks are delicate when it comes to state updates. Sometimes calling `act()` synchronously works, sometimes it doesn't. The reasoning behind this isn't clear yet. The best approach is to try synchronously first and if it fails, because of an `act()` error, then use the async version.
|
||||
|
||||
```js
|
||||
// First try this
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue