Skip to content

Commit f26a0f3

Browse files
committed
Revert "remove index_management/client integration tests that are being really flaky"
This reverts commit 655f23b.
1 parent 9b07ddc commit f26a0f3

File tree

13 files changed

+1917
-0
lines changed

13 files changed

+1917
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export const TEMPLATE_NAME = 'my_template';
8+
9+
export const INDEX_PATTERNS = ['my_index_pattern'];
10+
11+
export const SETTINGS = {
12+
number_of_shards: 1,
13+
index: {
14+
lifecycle: {
15+
name: 'my_policy',
16+
},
17+
},
18+
};
19+
20+
export const ALIASES = {
21+
alias: {
22+
filter: {
23+
term: { user: 'my_user' },
24+
},
25+
},
26+
};
27+
28+
export const MAPPINGS = {
29+
properties: {},
30+
};
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { ReactWrapper } from 'enzyme';
8+
import { act } from 'react-dom/test-utils';
9+
import {
10+
registerTestBed,
11+
TestBed,
12+
TestBedConfig,
13+
findTestSubject,
14+
nextTick,
15+
} from '../../../../../test_utils';
16+
import { IndexManagementHome } from '../../../public/application/sections/home'; // eslint-disable-line @kbn/eslint/no-restricted-paths
17+
import { BASE_PATH } from '../../../common/constants';
18+
import { indexManagementStore } from '../../../public/application/store'; // eslint-disable-line @kbn/eslint/no-restricted-paths
19+
import { Template } from '../../../common/types';
20+
import { WithAppDependencies, services } from './setup_environment';
21+
22+
const testBedConfig: TestBedConfig = {
23+
store: () => indexManagementStore(services as any),
24+
memoryRouter: {
25+
initialEntries: [`${BASE_PATH}indices`],
26+
componentRoutePath: `${BASE_PATH}:section(indices|templates)`,
27+
},
28+
doMountAsync: true,
29+
};
30+
31+
const initTestBed = registerTestBed(WithAppDependencies(IndexManagementHome), testBedConfig);
32+
33+
export interface IdxMgmtHomeTestBed extends TestBed<IdxMgmtTestSubjects> {
34+
findAction: (action: 'edit' | 'clone' | 'delete') => ReactWrapper;
35+
actions: {
36+
selectHomeTab: (tab: 'indicesTab' | 'templatesTab') => void;
37+
selectDetailsTab: (tab: 'summary' | 'settings' | 'mappings' | 'aliases') => void;
38+
clickReloadButton: () => void;
39+
clickTemplateAction: (name: Template['name'], action: 'edit' | 'clone' | 'delete') => void;
40+
clickTemplateAt: (index: number) => void;
41+
clickCloseDetailsButton: () => void;
42+
clickActionMenu: (name: Template['name']) => void;
43+
};
44+
}
45+
46+
export const setup = async (): Promise<IdxMgmtHomeTestBed> => {
47+
const testBed = await initTestBed();
48+
49+
/**
50+
* Additional helpers
51+
*/
52+
const findAction = (action: 'edit' | 'clone' | 'delete') => {
53+
const actions = ['edit', 'clone', 'delete'];
54+
const { component } = testBed;
55+
56+
return component.find('.euiContextMenuItem').at(actions.indexOf(action));
57+
};
58+
59+
/**
60+
* User Actions
61+
*/
62+
63+
const selectHomeTab = (tab: 'indicesTab' | 'templatesTab') => {
64+
testBed.find(tab).simulate('click');
65+
};
66+
67+
const selectDetailsTab = (tab: 'summary' | 'settings' | 'mappings' | 'aliases') => {
68+
const tabs = ['summary', 'settings', 'mappings', 'aliases'];
69+
70+
testBed
71+
.find('templateDetails.tab')
72+
.at(tabs.indexOf(tab))
73+
.simulate('click');
74+
};
75+
76+
const clickReloadButton = () => {
77+
const { find } = testBed;
78+
find('reloadButton').simulate('click');
79+
};
80+
81+
const clickActionMenu = async (templateName: Template['name']) => {
82+
const { component } = testBed;
83+
84+
// When a table has > 2 actions, EUI displays an overflow menu with an id "<template_name>-actions"
85+
// The template name may contain a period (.) so we use bracket syntax for selector
86+
component.find(`div[id="${templateName}-actions"] button`).simulate('click');
87+
};
88+
89+
const clickTemplateAction = (
90+
templateName: Template['name'],
91+
action: 'edit' | 'clone' | 'delete'
92+
) => {
93+
const actions = ['edit', 'clone', 'delete'];
94+
const { component } = testBed;
95+
96+
clickActionMenu(templateName);
97+
98+
component
99+
.find('.euiContextMenuItem')
100+
.at(actions.indexOf(action))
101+
.simulate('click');
102+
};
103+
104+
const clickTemplateAt = async (index: number) => {
105+
const { component, table, router } = testBed;
106+
const { rows } = table.getMetaData('templateTable');
107+
const templateLink = findTestSubject(rows[index].reactWrapper, 'templateDetailsLink');
108+
109+
await act(async () => {
110+
const { href } = templateLink.props();
111+
router.navigateTo(href!);
112+
await nextTick();
113+
component.update();
114+
});
115+
};
116+
117+
const clickCloseDetailsButton = () => {
118+
const { find } = testBed;
119+
120+
find('closeDetailsButton').simulate('click');
121+
};
122+
123+
return {
124+
...testBed,
125+
findAction,
126+
actions: {
127+
selectHomeTab,
128+
selectDetailsTab,
129+
clickReloadButton,
130+
clickTemplateAction,
131+
clickTemplateAt,
132+
clickCloseDetailsButton,
133+
clickActionMenu,
134+
},
135+
};
136+
};
137+
138+
type IdxMgmtTestSubjects = TestSubjects;
139+
140+
export type TestSubjects =
141+
| 'aliasesTab'
142+
| 'appTitle'
143+
| 'cell'
144+
| 'closeDetailsButton'
145+
| 'createTemplateButton'
146+
| 'deleteSystemTemplateCallOut'
147+
| 'deleteTemplateButton'
148+
| 'deleteTemplatesConfirmation'
149+
| 'documentationLink'
150+
| 'emptyPrompt'
151+
| 'manageTemplateButton'
152+
| 'mappingsTab'
153+
| 'noAliasesCallout'
154+
| 'noMappingsCallout'
155+
| 'noSettingsCallout'
156+
| 'indicesList'
157+
| 'indicesTab'
158+
| 'reloadButton'
159+
| 'row'
160+
| 'sectionError'
161+
| 'sectionLoading'
162+
| 'settingsTab'
163+
| 'summaryTab'
164+
| 'summaryTitle'
165+
| 'systemTemplatesSwitch'
166+
| 'templateDetails'
167+
| 'templateDetails.manageTemplateButton'
168+
| 'templateDetails.sectionLoading'
169+
| 'templateDetails.tab'
170+
| 'templateDetails.title'
171+
| 'templateList'
172+
| 'templateTable'
173+
| 'templatesTab';
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import sinon, { SinonFakeServer } from 'sinon';
8+
import { API_BASE_PATH } from '../../../common/constants';
9+
10+
type HttpResponse = Record<string, any> | any[];
11+
12+
// Register helpers to mock HTTP Requests
13+
const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
14+
const setLoadTemplatesResponse = (response: HttpResponse = []) => {
15+
server.respondWith('GET', `${API_BASE_PATH}/templates`, [
16+
200,
17+
{ 'Content-Type': 'application/json' },
18+
JSON.stringify(response),
19+
]);
20+
};
21+
22+
const setLoadIndicesResponse = (response: HttpResponse = []) => {
23+
server.respondWith('GET', `${API_BASE_PATH}/indices`, [
24+
200,
25+
{ 'Content-Type': 'application/json' },
26+
JSON.stringify(response),
27+
]);
28+
};
29+
30+
const setDeleteTemplateResponse = (response: HttpResponse = []) => {
31+
server.respondWith('DELETE', `${API_BASE_PATH}/templates`, [
32+
200,
33+
{ 'Content-Type': 'application/json' },
34+
JSON.stringify(response),
35+
]);
36+
};
37+
38+
const setLoadTemplateResponse = (response?: HttpResponse, error?: any) => {
39+
const status = error ? error.status || 400 : 200;
40+
const body = error ? error.body : response;
41+
42+
server.respondWith('GET', `${API_BASE_PATH}/templates/:id`, [
43+
status,
44+
{ 'Content-Type': 'application/json' },
45+
JSON.stringify(body),
46+
]);
47+
};
48+
49+
const setCreateTemplateResponse = (response?: HttpResponse, error?: any) => {
50+
const status = error ? error.body.status || 400 : 200;
51+
const body = error ? JSON.stringify(error.body) : JSON.stringify(response);
52+
53+
server.respondWith('PUT', `${API_BASE_PATH}/templates`, [
54+
status,
55+
{ 'Content-Type': 'application/json' },
56+
body,
57+
]);
58+
};
59+
60+
const setUpdateTemplateResponse = (response?: HttpResponse, error?: any) => {
61+
const status = error ? error.status || 400 : 200;
62+
const body = error ? JSON.stringify(error.body) : JSON.stringify(response);
63+
64+
server.respondWith('PUT', `${API_BASE_PATH}/templates/:name`, [
65+
status,
66+
{ 'Content-Type': 'application/json' },
67+
body,
68+
]);
69+
};
70+
71+
return {
72+
setLoadTemplatesResponse,
73+
setLoadIndicesResponse,
74+
setDeleteTemplateResponse,
75+
setLoadTemplateResponse,
76+
setCreateTemplateResponse,
77+
setUpdateTemplateResponse,
78+
};
79+
};
80+
81+
export const init = () => {
82+
const server = sinon.fakeServer.create();
83+
server.respondImmediately = true;
84+
85+
// Define default response for unhandled requests.
86+
// We make requests to APIs which don't impact the component under test, e.g. UI metric telemetry,
87+
// and we can mock them all with a 200 instead of mocking each one individually.
88+
server.respondWith([200, {}, 'DefaultSinonMockServerResponse']);
89+
90+
const httpRequestsMockHelpers = registerHttpRequestMockHelpers(server);
91+
92+
return {
93+
server,
94+
httpRequestsMockHelpers,
95+
};
96+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { setup as homeSetup } from './home.helpers';
8+
import { setup as templateCreateSetup } from './template_create.helpers';
9+
import { setup as templateCloneSetup } from './template_clone.helpers';
10+
import { setup as templateEditSetup } from './template_edit.helpers';
11+
12+
export { nextTick, getRandomString, findTestSubject, TestBed } from '../../../../../test_utils';
13+
14+
export { setupEnvironment } from './setup_environment';
15+
16+
export const pageHelpers = {
17+
home: { setup: homeSetup },
18+
templateCreate: { setup: templateCreateSetup },
19+
templateClone: { setup: templateCloneSetup },
20+
templateEdit: { setup: templateEditSetup },
21+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
/* eslint-disable @kbn/eslint/no-restricted-paths */
7+
import React from 'react';
8+
import axios from 'axios';
9+
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
10+
11+
import {
12+
notificationServiceMock,
13+
docLinksServiceMock,
14+
} from '../../../../../../src/core/public/mocks';
15+
import { AppContextProvider } from '../../../public/application/app_context';
16+
import { httpService } from '../../../public/application/services/http';
17+
import { breadcrumbService } from '../../../public/application/services/breadcrumbs';
18+
import { documentationService } from '../../../public/application/services/documentation';
19+
import { notificationService } from '../../../public/application/services/notification';
20+
import { ExtensionsService } from '../../../public/services';
21+
import { UiMetricService } from '../../../public/application/services/ui_metric';
22+
import { setUiMetricService } from '../../../public/application/services/api';
23+
import { setExtensionsService } from '../../../public/application/store/selectors';
24+
import { init as initHttpRequests } from './http_requests';
25+
26+
const mockHttpClient = axios.create({ adapter: axiosXhrAdapter });
27+
28+
export const services = {
29+
extensionsService: new ExtensionsService(),
30+
uiMetricService: new UiMetricService('index_management'),
31+
};
32+
services.uiMetricService.setup({ reportUiStats() {} } as any);
33+
setExtensionsService(services.extensionsService);
34+
setUiMetricService(services.uiMetricService);
35+
const appDependencies = { services, core: {}, plugins: {} } as any;
36+
37+
export const setupEnvironment = () => {
38+
// Mock initialization of services
39+
// @ts-ignore
40+
httpService.setup(mockHttpClient);
41+
breadcrumbService.setup(() => undefined);
42+
documentationService.setup(docLinksServiceMock.createStartContract());
43+
notificationService.setup(notificationServiceMock.createSetupContract());
44+
45+
const { server, httpRequestsMockHelpers } = initHttpRequests();
46+
47+
return {
48+
server,
49+
httpRequestsMockHelpers,
50+
};
51+
};
52+
53+
export const WithAppDependencies = (Comp: any) => (props: any) => (
54+
<AppContextProvider value={appDependencies}>
55+
<Comp {...props} />
56+
</AppContextProvider>
57+
);

0 commit comments

Comments
 (0)