Skip to content
Merged
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 @@ -134,6 +151,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
setLoadTemplateResponse,
setCreateTemplateResponse,
setUpdateTemplateResponse,
setUpdateIndexSettingsResponse,
setSimulateTemplateResponse,
setLoadComponentTemplatesResponse,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,6 @@ export type TestSubjects =
| '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', () => {
Comment thread
sabarasaba marked this conversation as resolved.
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 @@ -212,4 +237,43 @@ describe('<IndexManagementHome />', () => {
expect(exists('unfreezeIndexMenuButton')).toBe(false);
});
});

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,17 @@
*/

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 +90,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 +144,7 @@ export class EditSettingsJson extends React.PureComponent {
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{this.errorMessage()}
<EuiSpacer />
<EuiLink
href={documentationService.getSettingsDocumentationLink()}
Expand All @@ -153,7 +163,6 @@ export class EditSettingsJson extends React.PureComponent {
this.aceDiv = aceDiv;
}}
/>
{this.errorMessage()}
<EuiSpacer />
</div>
);
Expand Down
17 changes: 10 additions & 7 deletions x-pack/plugins/index_management/public/application/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,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