Skip to content

Commit

Permalink
fix(iows): throw a IOWS2DeprecationError on deprecation header (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ephigenia committed Dec 17, 2021
1 parent a04df08 commit 270c3a5
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 21 deletions.
6 changes: 4 additions & 2 deletions source/cli-stock.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,12 @@ Examples:
if (err instanceof errors.IOWS2ParseError) {
return { stock: 0, probability: 'PARSE_ERROR', createdAt: new Date() };
}
// when product could not be found return an empty availability
if (err.response && err.response.status === 404 && promises.length > 1) {
if (err instanceof errors.IOWS2NotFoundError) {
return { stock: 0, probability: 'NOT_FOUND', createdAt: new Date() };
}
if (err instanceof errors.IOWS2DeprecatedError) {
return { stock: 0, probability: 'DEPRECATED', createdAt: new Date() };
}
throw err;
})
.then((availability) => ({
Expand Down
49 changes: 34 additions & 15 deletions source/lib/iows2.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,21 +86,40 @@ class IOWS2 {
* @param {import('axios').AxiosRequestConfig} [options={}] additional
* options
* @return {Promise<Object>} response body data
* @throws {import('./errors').IOWS2ResponseError}
* @throws {import('./errors').IOWS2ParseError} in case the response
* body is not an object
* @throws {import('./errors').IOWS2NotFoundError} in case the response
* status code is 404
* @throws {import('./errors').IOWS2DeprecatedError} in case the response
* contains a "deprecation" header
* @throws {import('./errors').IOWS2ResponseError} in any other case
*/
async fetch(url, options = {}) {
// required headers, without them IOWS endpoint will return
// 409 (gone), 401 or even 404
return this.api.get(url, options)
.then(response => {
if (typeof response.data !== 'object') {
throw new errors.IOWS2ParseError('Unable to parse response');
let response;
try {
response = await this.api.get(url, options);
} catch (error) {
if (error.request) {
// 20211217 some of the country endpoints started to reply with a
// deprecation and warning header stating that the IOWS2 API is
// going to be deprecated.
const responseHeaders = error.request.res.headers;
if (responseHeaders.deprecation) {
throw new errors.IOWS2DeprecatedError(error);
}
return response.data;
})
.catch(err => {
throw new errors.IOWS2ResponseError(err);
});
if (error.request.res.statusCode === 404) {
throw new errors.IOWS2NotFoundError(error);
}
}
throw new errors.IOWS2ResponseError(error);
}

// double check if the response was successfully parsed and is an object
if (typeof response.data !== 'object') {
throw new errors.IOWS2ParseError('Unable to parse response', response.data);
}

return response.data;
}

/**
Expand Down Expand Up @@ -184,11 +203,11 @@ class IOWS2 {
const url = this.buildUrl(this.baseUrl, this.countryCode, this.languageCode, buCode, productId, productType);
return this.fetch(url)
.catch(err => {
if (err.response) {
if (err.request.res) {
err.message =
`Unable to receive product ${productId} availability for store ` +
`${buCode} status code: ${err.response.status} ${err.response.statusText} ` +
`using url: ${err.request.url}`;
`${buCode} status code: ${err.request.res.statusCode} ${err.request.res.statusText} ` +
`using url: ${err.request.path}`;
}
throw err;
})
Expand Down
19 changes: 17 additions & 2 deletions source/lib/iows2.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,26 @@ describe('IOWS2', () => {
});
it('throws an error when the response doesn’t contain valid json', () => {
const scope = nock(URL).get(/.+/).reply(200, '<html>');
return iows.fetch(URL, {})
.catch(err => {
expect(err).to.be.instanceOf(errors.IOWS2ParseError);
expect(err).to.have.property('message').to.match(/Unable to parse/i);
scope.isDone();
});
});

it('throws a IOWS2Deprecated error when the api returns a deprecation warning', () => {
const scope = nock(URL).get(/.+/)
.reply(404, 'Gone', {
'deprecation': 'version="1", date="Sat, 31 Dec 2022 23:59:59 GMT"',
'warning': 'IOWSStockAvailabilityService.GetStockAvailability.v1 API is now deprecated.',
'link': 'alternate="Customer Item Availability. Enquire via slack #rrm-cia"',
'x-global-transaction-id': 'a345495061bc8d13018340e5',
});
return iows.fetch(URL, {})
.then(() => {throw Error('Unexpected resolved promise')})
.catch(err => {
expect(err).to.be.instanceOf(Error);
expect(err.message).to.match(/Unable to parse/i);
expect(err).to.be.instanceof(errors.IOWS2DeprecatedError);
scope.isDone();
});
});
Expand Down
9 changes: 7 additions & 2 deletions source/lib/iows2Errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,21 @@ class IOWS2ParseError extends IOWS2Error{

class IOWS2ResponseError extends IOWS2Error {
/**
* @param {import('axios').AxiosError} error error message
* @param {import('axios').AxiosError} error Axios Error object
*/
constructor(error) {
super(error.message);
Object.assign(this, error);
}
}

class IOWS2DeprecatedError extends IOWS2ResponseError {}
class IOWS2NotFoundError extends IOWS2ResponseError {}

module.exports = {
IOWS2DeprecatedError,
IOWS2Error,
IOWS2NotFoundError,
IOWS2ParseError,
IOWS2ResponseError,
}
};

0 comments on commit 270c3a5

Please sign in to comment.