Skip to content

Commit da077bb

Browse files
committed
Merge branch 'dh-accept_error_handler_for_api_entity_service' into 'develop'
Accept error handler for ApiEntityService See merge request amalgama/packages/npm/api-entity-service!15
2 parents cab2603 + bfb478e commit da077bb

File tree

6 files changed

+67
-16
lines changed

6 files changed

+67
-16
lines changed

src/errorHandlers/NullErrorHandler.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default class NullErrorHandler {
2+
// eslint-disable-next-line class-methods-use-this
3+
handleError( error: unknown ) {
4+
throw error;
5+
}
6+
}

src/service/ApiEntityService.ts

+21-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import { IEntityCreator, IResponseParser, ParsedResponse } from '../types';
1+
import {
2+
IEntityCreator, IErrorHandler, IResponseParser, ParsedResponse
3+
} from '../types';
24
import {
35
IApi, Attributes, Params, HTTPMethod, InitParameters,
46
RequestWithBodyConfig, RequestParameters,
57
MakeRequestParameters, EntityID, EntityResponse, SingleEntityResponse, MultiEntityResponse
68
} from './ApiEntityService.types';
9+
import NullErrorHandler from '../errorHandlers/NullErrorHandler';
710
import {
811
addParamsToURL, headersForRequest, serializeRequestDataForContentType,
912
requestHasBody
@@ -15,15 +18,17 @@ export default class ApiEntityService<T> {
1518
readonly parser: IResponseParser;
1619
readonly creator: IEntityCreator;
1720
readonly paths: { [ key: string ]: string };
21+
readonly errorHandler: IErrorHandler;
1822

1923
constructor( {
20-
api, basePath, parser, creator, paths = {}
24+
api, basePath, parser, creator, paths = {}, errorHandler = new NullErrorHandler()
2125
}: InitParameters ) {
2226
this.api = api;
2327
this.basePath = basePath;
2428
this.parser = parser;
2529
this.creator = creator;
2630
this.paths = paths;
31+
this.errorHandler = errorHandler;
2732
}
2833

2934
create(
@@ -89,15 +94,20 @@ export default class ApiEntityService<T> {
8994
params,
9095
config
9196
}: RequestParameters ): Promise<EntityResponse<T> | null> {
92-
const response = await this
93-
.makeRequest( {
94-
method, url, attributes, params, includesFiles: config.includesFiles || false
95-
} );
96-
97-
const { data } = response;
98-
const parsedResponse = this.parseResponse( data );
99-
100-
return this.createEntities( parsedResponse );
97+
try {
98+
const response = await this
99+
.makeRequest( {
100+
method, url, attributes, params, includesFiles: config.includesFiles || false
101+
} );
102+
103+
const { data } = response;
104+
const parsedResponse = this.parseResponse( data );
105+
106+
return this.createEntities( parsedResponse );
107+
} catch ( error ) {
108+
this.errorHandler.handleError( error );
109+
return null;
110+
}
101111
}
102112

103113
private makeRequest = ( {

src/service/ApiEntityService.types.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IEntityCreator, IResponseParser } from '../types';
1+
import { IEntityCreator, IErrorHandler, IResponseParser } from '../types';
22

33
export type Attributes = {
44
[ key: string ]: unknown
@@ -64,7 +64,8 @@ export interface InitParameters {
6464
basePath: string,
6565
parser: IResponseParser,
6666
creator: IEntityCreator,
67-
paths: { [ key: string ]: string }
67+
paths: { [ key: string ]: string },
68+
errorHandler: IErrorHandler
6869
}
6970

7071
export type RequestWithBodyConfig = {

src/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ export interface IResponseParser {
2323
export interface IEntityCreator {
2424
create<T>( parsedResponse: ParsedResponse ): ( null | T | T[] )
2525
}
26+
27+
export interface IErrorHandler {
28+
handleError( error: unknown ): unknown
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import NullErrorHandler from '../../src/errorHandlers/NullErrorHandler';
2+
3+
describe( 'NullErrorHandler', () => {
4+
describe( '@handleError', () => {
5+
it( 'throws the given error', () => {
6+
const errorHandler = new NullErrorHandler();
7+
const error = new Error( 'Something went wrong' );
8+
9+
expect( () => errorHandler.handleError( error ) ).toThrow( 'Something went wrong' );
10+
} );
11+
} );
12+
} );

tests/service/ApiEntityService.test.js

+21-3
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,24 @@ const creatorMock = {
9292

9393
const basePath = '1/users';
9494

95+
const errorHandlerMock = {
96+
handleError: jest.fn()
97+
};
98+
9599
describe( 'ApiEntityService', () => {
96100
const createService = ( {
97101
api = apiMock,
98102
parser = parserMock,
99103
creator = creatorMock,
100-
paths = {}
104+
paths = {},
105+
errorHandler = errorHandlerMock
101106
} = {} ) => new ApiEntityService( {
102107
api,
103108
basePath,
104109
parser,
105110
creator,
106-
paths
111+
paths,
112+
errorHandler
107113
} );
108114

109115
beforeEach( () => jest.clearAllMocks() );
@@ -129,7 +135,7 @@ describe( 'ApiEntityService', () => {
129135

130136
const hasResponse = !!response.data;
131137

132-
beforeEach( () => apiMock[ expectedApiMethod ].mockResolvedValueOnce( response ) );
138+
beforeEach( () => apiMock[ expectedApiMethod ].mockResolvedValue( response ) );
133139

134140
if ( attributes ) {
135141
it( 'calls the correct api method with the correct path, attributes and config', () => {
@@ -188,6 +194,18 @@ describe( 'ApiEntityService', () => {
188194
} );
189195
} );
190196

197+
describe( 'when the api throws an error', () => {
198+
it( 'calls the error handlers handleError method with the error', async () => {
199+
const error = new Error( 'Invalid entity' );
200+
apiMock[ expectedApiMethod ].mockRejectedValue( error );
201+
const service = createService();
202+
203+
await callService( service );
204+
205+
expect( errorHandlerMock.handleError ).toHaveBeenCalledWith( error );
206+
} );
207+
} );
208+
191209
if ( hasResponse ) {
192210
it( 'calls the parser with the received response', async () => {
193211
const service = createService();

0 commit comments

Comments
 (0)