diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js
index c8badc92ab11c..f420e83adc031 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js
@@ -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 {
diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js
index 05a4a2e330325..545e3dd0ba969 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js
@@ -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.');
diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js
index b5402f3b017f0..331ef24d1d8a1 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js
@@ -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';
diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js
index b0e0832cb0831..d3dee936c68dc 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js
@@ -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);
diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js
index c912a4ddabc9d..de5c1e5290540 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js
@@ -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();
diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.helpers.js
index ce9638d95bd28..5f34728def3d3 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.helpers.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.helpers.js
@@ -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 {
diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.test.js
index 3c393cd70009a..765da32260eb7 100644
--- a/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.test.js
+++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/list/remote_clusters_list.test.js
@@ -10,26 +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';
-// FLAKY: https://github.com/elastic/kibana/issues/58681
-describe.skip('', () => {
- let server;
- let httpRequestsMockHelpers;
+describe('', () => {
+ 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;
@@ -48,9 +45,10 @@ describe.skip('', () => {
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();
});
@@ -67,7 +65,7 @@ describe.skip('', () => {
let find;
let table;
let actions;
- let waitFor;
+ let component;
let form;
const remoteClusters = [
@@ -88,9 +86,10 @@ describe.skip('', () => {
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', () => {
@@ -118,7 +117,6 @@ describe.skip('', () => {
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
@@ -152,11 +150,11 @@ describe.skip('', () => {
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'));
});
@@ -283,10 +281,11 @@ describe.skip('', () => {
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);
diff --git a/x-pack/test_utils/README.md b/x-pack/test_utils/README.md
index 04c920c4ae834..a6ca1a5d86866 100644
--- a/x-pack/test_utils/README.md
+++ b/x-pack/test_utils/README.md
@@ -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