Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { API_BASE_PATH } from '../../../common/constants';

type HttpResponse = Record<string, any> | any[];

export interface ResponseError {
statusCode: number;
message: string | Error;
attributes?: Record<string, any>;
}

// Register helpers to mock HTTP Requests
const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
const setLoadTemplatesResponse = (response: HttpResponse = []) => {
Expand Down Expand Up @@ -101,6 +107,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
]);
};

const setUpdateIndexSettingsResponse = (response?: HttpResponse, error?: ResponseError) => {
const status = error ? error.statusCode || 400 : 200;
const body = error ?? response;

server.respondWith('PUT', `${API_BASE_PATH}/settings/:name`, [
status,
{ 'Content-Type': 'application/json' },
JSON.stringify(body),
]);
};

const setSimulateTemplateResponse = (response?: HttpResponse, error?: any) => {
const status = error ? error.status || 400 : 200;
const body = error ? JSON.stringify(error.body) : JSON.stringify(response);
Expand Down Expand Up @@ -145,6 +162,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
setLoadTemplateResponse,
setCreateTemplateResponse,
setUpdateTemplateResponse,
setUpdateIndexSettingsResponse,
setSimulateTemplateResponse,
setLoadComponentTemplatesResponse,
setLoadNodesPluginsResponse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,7 @@ export type TestSubjects =
| 'templatesTab'
| 'templateTable'
| 'title'
| 'unfreezeIndexMenuButton'
| 'updateEditIndexSettingsButton'
| 'updateIndexSettingsErrorCallout'
| 'viewButton';
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ import { setupEnvironment, nextTick } from '../helpers';
import { IndicesTestBed, setup } from './indices_tab.helpers';
import { createDataStreamPayload, createNonDataStreamIndex } from './data_streams_tab.helpers';

// Since the editor component being used for editing index settings is not a React
// component but an editor being instantiated on a div reference, we cannot mock
// the component and replace it with something else. In this particular case we're
// mocking the returned instance of the editor to always have the same values.
const mockGetAceEditorValue = jest.fn().mockReturnValue(`{}`);

jest.mock('../../../public/application/lib/ace.js', () => {
const createAceEditor = () => {
return {
getValue: mockGetAceEditorValue,
getSession: () => {
return {
on: () => null,
getValue: () => null,
};
},
destroy: () => null,
};
};

return {
createAceEditor,
};
});

/**
* The below import is required to avoid a console error warn from the "brace" package
* console.warn ../node_modules/brace/index.js:3999
Expand Down Expand Up @@ -195,4 +220,43 @@ describe('<IndexManagementHome />', () => {
expect(server.requests[requestsCount - 1].url).toBe(`${API_BASE_PATH}/indices/reload`);
});
});

describe('Edit index settings', () => {
const indexName = 'testIndex';

beforeEach(async () => {
httpRequestsMockHelpers.setLoadIndicesResponse([createNonDataStreamIndex(indexName)]);

testBed = await setup();
const { find, component } = testBed;
component.update();

find('indexTableIndexNameLink').at(0).simulate('click');
});

test('shows error callout when request fails', async () => {
const { actions, find, component, exists } = testBed;

mockGetAceEditorValue.mockReturnValue(`{
"index.routing.allocation.include._tier_preference": "non_existent_tier"
}`);

const error = {
statusCode: 400,
error: 'Bad Request',
message: 'invalid tier names found in ...',
};
httpRequestsMockHelpers.setUpdateIndexSettingsResponse(undefined, error);

await actions.selectIndexDetailsTab('edit_settings');

await act(async () => {
find('updateEditIndexSettingsButton').simulate('click');
});

component.update();

expect(exists('updateIndexSettingsErrorCallout')).toBe(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
*/

import React from 'react';

import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { documentationService } from '../../../../../services/documentation';

import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiCallOut,
EuiLink,
EuiSpacer,
EuiTextColor,
EuiTitle,
} from '@elastic/eui';
import { TAB_SETTINGS } from '../../../../../constants';
Expand Down Expand Up @@ -90,16 +91,25 @@ export class EditSettingsJson extends React.PureComponent {
};
errorMessage() {
const { error } = this.props;

if (!error) {
return null;
}

return (
<div>
<EuiSpacer />
<EuiIcon color="danger" type="alert" />
<EuiTextColor color="danger">{error}</EuiTextColor>
<>
<EuiSpacer />
</div>
<EuiCallOut
title={i18n.translate('xpack.idxMgmt.editSettingsJSON.saveJSONCalloutErrorTitle', {
defaultMessage: 'There was an error while trying to save your settings',
})}
color="danger"
iconType="alert"
data-test-subj="updateIndexSettingsErrorCallout"
>
<p>{error}</p>
</EuiCallOut>
</>
);
}
render() {
Expand Down Expand Up @@ -135,6 +145,7 @@ export class EditSettingsJson extends React.PureComponent {
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{this.errorMessage()}
<EuiSpacer />
<EuiLink
href={documentationService.getSettingsDocumentationLink()}
Expand All @@ -153,7 +164,6 @@ export class EditSettingsJson extends React.PureComponent {
this.aceDiv = aceDiv;
}}
/>
{this.errorMessage()}
<EuiSpacer />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,17 @@ export async function loadIndexSettings(indexName: string) {
}

export async function updateIndexSettings(indexName: string, body: object) {
const response = await httpService.httpClient.put(
`${API_BASE_PATH}/settings/${encodeURIComponent(indexName)}`,
{
body: JSON.stringify(body),
}
);
const response = await sendRequest({
path: `${API_BASE_PATH}/settings/${encodeURIComponent(indexName)}`,
method: 'put',
body: JSON.stringify(body),
});

// Only track successful requests.
uiMetricService.trackMetric(METRIC_TYPE.COUNT, UIM_UPDATE_SETTINGS);
if (!response.error) {
uiMetricService.trackMetric(METRIC_TYPE.COUNT, UIM_UPDATE_SETTINGS);
}

return response;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,9 @@ export const updateIndexSettings =
({ indexName, settings }) =>
async (dispatch) => {
if (Object.keys(settings).length !== 0) {
try {
const { error, message } = await request(indexName, settings);
const { error } = await request(indexName, settings);

if (error) {
return dispatch(updateIndexSettingsError({ error: message }));
}
} catch (error) {
if (error) {
return dispatch(updateIndexSettingsError({ error: error.message }));
}
}
Expand Down