Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enterprise Search] Fix bug in Add Schema modal #104024

Merged
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 @@ -5,6 +5,8 @@
* 2.0.
*/

import { i18n } from '@kbn/i18n';

import { HttpResponse } from 'src/core/public';

import { FlashMessagesLogic } from './flash_messages_logic';
Expand All @@ -31,12 +33,17 @@ interface Options {
isQueued?: boolean;
}

export const defaultErrorMessage = i18n.translate(
'xpack.enterpriseSearch.shared.flashMessages.defaultErrorMessage',
{
defaultMessage: 'An unexpected error occurred',
}
);

/**
* Converts API/HTTP errors into user-facing Flash Messages
*/
export const flashAPIErrors = (error: HttpResponse<ErrorResponse>, { isQueued }: Options = {}) => {
const defaultErrorMessage = 'An unexpected error occurred';

const errorFlashMessages: IFlashMessage[] = Array.isArray(error?.body?.attributes?.errors)
? error.body!.attributes.errors.map((message) => ({ type: 'error', message }))
: [{ type: 'error', message: error?.body?.message || defaultErrorMessage }];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const spyScrollTo = jest.fn();
Object.defineProperty(global.window, 'scrollTo', { value: spyScrollTo });

import { ADD, UPDATE } from '../../../../../shared/constants/operations';
import { defaultErrorMessage } from '../../../../../shared/flash_messages/handle_api_errors';
import { SchemaType } from '../../../../../shared/schema/types';
import { AppLogic } from '../../../../app_logic';

Expand Down Expand Up @@ -390,13 +391,25 @@ describe('SchemaLogic', () => {
expect(onSchemaSetSuccessSpy).toHaveBeenCalledWith(serverResponse);
});

it('handles error', async () => {
it('handles error with message', async () => {
const onSchemaSetFormErrorsSpy = jest.spyOn(SchemaLogic.actions, 'onSchemaSetFormErrors');
// We expect body.message to be a string[] when it is present
http.post.mockReturnValue(Promise.reject({ body: { message: ['this is an error'] } }));
SchemaLogic.actions.setServerField(schema, ADD);
await nextTick();

expect(onSchemaSetFormErrorsSpy).toHaveBeenCalledWith(['this is an error']);
expect(spyScrollTo).toHaveBeenCalledWith(0, 0);
});

it('handles error with no message', async () => {
const onSchemaSetFormErrorsSpy = jest.spyOn(SchemaLogic.actions, 'onSchemaSetFormErrors');
http.post.mockReturnValue(Promise.reject({ message: 'this is an error' }));
http.post.mockReturnValue(Promise.reject());
SchemaLogic.actions.setServerField(schema, ADD);
await nextTick();

expect(onSchemaSetFormErrorsSpy).toHaveBeenCalledWith('this is an error');
expect(onSchemaSetFormErrorsSpy).toHaveBeenCalledWith([defaultErrorMessage]);
expect(spyScrollTo).toHaveBeenCalledWith(0, 0);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
setErrorMessage,
clearFlashMessages,
} from '../../../../../shared/flash_messages';
import { defaultErrorMessage } from '../../../../../shared/flash_messages/handle_api_errors';
import { HttpLogic } from '../../../../../shared/http';
import {
IndexJob,
Expand Down Expand Up @@ -349,7 +350,9 @@ export const SchemaLogic = kea<MakeLogicType<SchemaValues, SchemaActions>>({
} catch (e) {
window.scrollTo(0, 0);
if (isAdding) {
actions.onSchemaSetFormErrors(e?.message);
// We expect body.message to be a string[] for actions.onSchemaSetFormErrors
const message: string[] = e?.body?.message || [defaultErrorMessage];
actions.onSchemaSetFormErrors(message);
} else {
flashAPIErrors(e);
}
Comment on lines 352 to 358
Copy link
Contributor

@cee-chen cee-chen Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just add the e?.body?.message check into the conditional and let invalid error formats fall back to flashAPIErrors, instead having to manually fall back to defaultErrorMessage?

Suggested change
if (isAdding) {
actions.onSchemaSetFormErrors(e?.message);
// We expect body.message to be a string[] for actions.onSchemaSetFormErrors
const message: string[] = e?.body?.message || [defaultErrorMessage];
actions.onSchemaSetFormErrors(message);
} else {
flashAPIErrors(e);
}
const errorMessage: string[] = e?.body?.message;
if (isAdding && errorMessage) {
actions.onSchemaSetFormErrors(errorMessage);
} else {
flashAPIErrors(e);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be a slight functional difference, in that when the message is missing, it would appear as a Flash Message error. actions.onSchemaSetFormErrors sets addFormFieldErrors which is used inside a SchemaAddFieldModal. I think we'd still want the default error message to appear in the SchemaAddFieldModal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion either way. I guess I'm leaning slightly towards showing the error in the modal, closer to the user action that lead to the error. But I see the point in showing it as a flash message: if the error is unexpected, it's probably not caused by user action.

I will merge the PR as-is because the code fixes the original bug and is already tested.

Expand Down