Skip to content

Commit

Permalink
Add handleAPIError helper
Browse files Browse the repository at this point in the history
- New and improved from ent-search - this one automatically sets flash messages for you so you don't have to pass in a callback!
  • Loading branch information
cee-chen committed Sep 11, 2020
1 parent 0e1f2eb commit 2b949c5
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

jest.mock('./', () => ({
FlashMessagesLogic: { actions: { setFlashMessages: jest.fn() } },
}));
import { FlashMessagesLogic } from './';

import { handleAPIError } from './handle_api_errors';

describe('handleAPIError', () => {
const mockHttpError = {
body: {
statusCode: 404,
error: 'Not Found',
message: 'Could not find X,Could not find Y,Something else bad happened',
attributes: {
errors: ['Could not find X', 'Could not find Y', 'Something else bad happened'],
},
},
} as any;

beforeEach(() => {
jest.clearAllMocks();
});

it('converts API errors into flash messages', () => {
handleAPIError(mockHttpError);

expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([
{ type: 'error', message: 'Could not find X' },
{ type: 'error', message: 'Could not find Y' },
{ type: 'error', message: 'Something else bad happened' },
]);
});

it('displays a generic error message and re-throws non-API errors', () => {
try {
handleAPIError(Error('whatever') as any);
} catch (e) {
expect(e.message).toEqual('whatever');
expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([
{ type: 'error', message: 'An unexpected error occurred' },
]);
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

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

import { FlashMessagesLogic, IFlashMessage } from './';

/**
* The API errors we are handling can come from one of two ways:
* - When our http calls recieve a response containing an error code, such as a 404 or 500
* - Our own JS while handling a successful response
*
* In the first case, if it is a purposeful error (like a 404) we will receive an
* `errors` property in the response's data, which will contain messages we can
* display to the user.
*/
interface IErrorResponse {
statusCode: number;
error: string;
message: string;
attributes: {
errors: string[];
};
}

/**
* Converts API/HTTP errors into user-facing Flash Messages
*/
export const handleAPIError = (error: HttpResponse<IErrorResponse>) => {
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: defaultErrorMessage }];

FlashMessagesLogic.actions.setFlashMessages(errorFlashMessages);

// If this was a programming error or a failed request (such as a CORS) error,
// we rethrow the error so it shows up in the developer console
if (!error?.body?.message) {
throw error;
}
};

0 comments on commit 2b949c5

Please sign in to comment.