ti2 1.0.58 → 1.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/controllers/__tests__/allotments.js +38 -8
- package/controllers/graphql-schemas/availability.js +1 -1
- package/index.js +19 -32
- package/lib/get-error-message.js +21 -0
- package/package.json +2 -1
- package/test/plugin.js +40 -2
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/* globals beforeAll describe it expect */
|
|
2
|
-
|
|
2
|
+
const axios = require('axios');
|
|
3
|
+
const MockAdapter = require('axios-mock-adapter');
|
|
3
4
|
const chance = require('chance').Chance();
|
|
5
|
+
|
|
6
|
+
|
|
4
7
|
const testUtils = require('../../test/utils');
|
|
5
8
|
|
|
6
9
|
const { env: { adminKey } } = process;
|
|
@@ -26,6 +29,7 @@ describe('allotment', () => {
|
|
|
26
29
|
let doApiGet;
|
|
27
30
|
let doApiPost;
|
|
28
31
|
let plugins;
|
|
32
|
+
let userToken;
|
|
29
33
|
beforeAll(async () => {
|
|
30
34
|
({
|
|
31
35
|
doApiDelete,
|
|
@@ -35,10 +39,8 @@ describe('allotment', () => {
|
|
|
35
39
|
} = await testUtils({
|
|
36
40
|
plugins: [appKey],
|
|
37
41
|
}));
|
|
38
|
-
});
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
it('drop any existing user integration', async () => {
|
|
43
|
+
// drop any existing user integrations
|
|
42
44
|
try {
|
|
43
45
|
await doApiDelete({
|
|
44
46
|
url: `/${appKey}/${userId}`,
|
|
@@ -48,16 +50,16 @@ describe('allotment', () => {
|
|
|
48
50
|
} catch (err) {
|
|
49
51
|
// console.debug(err);
|
|
50
52
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
|
|
54
|
+
// create the user
|
|
53
55
|
({ value: userToken } = await doApiPost({
|
|
54
56
|
url: '/user',
|
|
55
57
|
token: adminKey,
|
|
56
58
|
payload: { userId },
|
|
57
59
|
}));
|
|
58
60
|
expect(userToken).toBeTruthy();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
|
|
62
|
+
// create the App+User setup
|
|
61
63
|
const { userAppKeys } = await doApiGet({
|
|
62
64
|
url: `/user/${userId}/apps`,
|
|
63
65
|
token: userToken,
|
|
@@ -103,4 +105,32 @@ describe('allotment', () => {
|
|
|
103
105
|
expect(call.payload).toEqual(payload);
|
|
104
106
|
expect(call.token).toEqual(token);
|
|
105
107
|
});
|
|
108
|
+
it('should be able to receive an axios error', async () => {
|
|
109
|
+
let urlParamsError = new URLSearchParams({
|
|
110
|
+
...payload,
|
|
111
|
+
keyPath: 'errorAxios',
|
|
112
|
+
}).toString();
|
|
113
|
+
const returnValue = await doApiGet({
|
|
114
|
+
url: `/allotment/${appKey}/${newIntegration.tokenHint}/${userId}?${urlParamsError}`,
|
|
115
|
+
token: userToken,
|
|
116
|
+
expectStatusCode: 500,
|
|
117
|
+
});
|
|
118
|
+
expect(returnValue.allotments).toBeFalsy();
|
|
119
|
+
expect(returnValue.message).toBe('ECONNREFUSED');
|
|
120
|
+
});
|
|
121
|
+
it('should be able to receive an error from a regular response', async () => {
|
|
122
|
+
const mock = new MockAdapter(axios);
|
|
123
|
+
mock.onGet('http://www.example.com').reply(200, { error: 'something went wrong' });
|
|
124
|
+
let urlParamsError = new URLSearchParams({
|
|
125
|
+
...payload,
|
|
126
|
+
keyPath: 'errorGeneral',
|
|
127
|
+
}).toString();
|
|
128
|
+
const returnValue = await doApiGet({
|
|
129
|
+
url: `/allotment/${appKey}/${newIntegration.tokenHint}/${userId}?${urlParamsError}`,
|
|
130
|
+
token: userToken,
|
|
131
|
+
expectStatusCode: 500,
|
|
132
|
+
});
|
|
133
|
+
expect(returnValue.allotments).toBeFalsy();
|
|
134
|
+
expect(returnValue.message).toBe('something went wrong');
|
|
135
|
+
});
|
|
106
136
|
});
|
package/index.js
CHANGED
|
@@ -15,10 +15,6 @@ const EventEmitter = require('eventemitter2');
|
|
|
15
15
|
const axios = require('axios');
|
|
16
16
|
const curlirize = require('axios-curlirize');
|
|
17
17
|
|
|
18
|
-
if (process.env.debug) {
|
|
19
|
-
curlirize(axios);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
18
|
const cacheSettings = {
|
|
23
19
|
'*': [
|
|
24
20
|
'getAffiliateAgents',
|
|
@@ -44,6 +40,7 @@ const bookingsController = require('./controllers/bookings');
|
|
|
44
40
|
const allotmentController = require('./controllers/allotment');
|
|
45
41
|
const { Integration } = require('./models');
|
|
46
42
|
const cache = require('./cache');
|
|
43
|
+
const getErrorMessage = require('./lib/get-error-message.js');
|
|
47
44
|
|
|
48
45
|
// src : https://github.com/ramda/ramda/issues/3137#issuecomment-1016012904
|
|
49
46
|
const rebuild = fn => obj =>
|
|
@@ -221,43 +218,33 @@ module.exports = async ({
|
|
|
221
218
|
});
|
|
222
219
|
axiosPlugin.interceptors.response.use(response => {
|
|
223
220
|
ti2Events.emit(`${pluginName}.axios.response`, { ...axiosSafeResponse(response), userId });
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
err: errMsg,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
throw new Eror(errMsg);
|
|
221
|
+
const errMsg = getErrorMessage({ err: response, handlers: errorPathsAxiosAny, force: false });
|
|
222
|
+
if (errMsg) {
|
|
223
|
+
if (process.env.debug) console.error(`error in ${pluginName}`, errMsg);
|
|
224
|
+
if (ti2Events.events) {
|
|
225
|
+
ti2Events.events.emit(`${pluginName}.axios.error`, {
|
|
226
|
+
response: axiosSafeResponse(response),
|
|
227
|
+
err: errMsg,
|
|
228
|
+
});
|
|
236
229
|
}
|
|
230
|
+
throw new Error(errMsg);
|
|
237
231
|
}
|
|
238
232
|
return response;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const defaultErr = R.omit(['config'], err.toJSON()); // default error
|
|
243
|
-
if (errorPathsAxiosErrors.length > 0) {
|
|
244
|
-
const pathMatch = errorPathsAxiosErrors.find(errorPath => R.path(errorPath, err));
|
|
245
|
-
if (pathMatch) {
|
|
246
|
-
return R.path(pathMatch, err);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return defaultErr;
|
|
250
|
-
})();
|
|
251
|
-
if (console.env.debug) console.error(`error in ${pluginName}`, args[0], errMsg);
|
|
233
|
+
}, err => {
|
|
234
|
+
const errMsg = getErrorMessage({ err, handlers: errorPathsAxiosErrors });
|
|
235
|
+
if (process.env.debug) console.error(`error in ${pluginName}`, args[0], errMsg);
|
|
252
236
|
if (ti2Events.events) {
|
|
253
237
|
ti2Events.events.emit(`${pluginName}.axios.error`, {
|
|
254
238
|
request: args[0],
|
|
255
239
|
err: errMsg,
|
|
256
240
|
});
|
|
257
241
|
}
|
|
258
|
-
|
|
242
|
+
return Promise.reject(errMsg);
|
|
259
243
|
});
|
|
260
|
-
|
|
244
|
+
if (process.env.debug) {
|
|
245
|
+
curlirize(axiosPlugin);
|
|
246
|
+
}
|
|
247
|
+
req.axios = axiosPlugin;
|
|
261
248
|
next();
|
|
262
249
|
});
|
|
263
250
|
|
|
@@ -310,7 +297,7 @@ module.exports = async ({
|
|
|
310
297
|
return next(err);
|
|
311
298
|
}
|
|
312
299
|
if (process.env.CONSOLE_ERRORS || process.env.JEST_WORKER_ID) {
|
|
313
|
-
console.error(R.
|
|
300
|
+
console.error(R.pathOr(err, ['response', 'data'], err));
|
|
314
301
|
}
|
|
315
302
|
return res.status((() => {
|
|
316
303
|
if (!isNumber(err.status)) return 500;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const R = require('ramda');
|
|
2
|
+
|
|
3
|
+
const getErrorMessage = ({ err, handlers = [], force = true }) => {
|
|
4
|
+
for (const handler of handlers) {
|
|
5
|
+
let errorMessage;
|
|
6
|
+
if (Array.isArray(handler)) {
|
|
7
|
+
errorMessage = R.path(handler, err);
|
|
8
|
+
} else if (typeof handler === 'function') {
|
|
9
|
+
errorMessage = handler(err);
|
|
10
|
+
}
|
|
11
|
+
if (errorMessage) {
|
|
12
|
+
return errorMessage;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (force) return R.pathOr(
|
|
16
|
+
err,
|
|
17
|
+
['message'],
|
|
18
|
+
err
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
module.exports = getErrorMessage;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ti2",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.60",
|
|
4
4
|
"description": "Tourist Industry Exchange (TI2)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@salvador/minami": "^1.2.3",
|
|
55
|
+
"axios-mock-adapter": "^1.21.4",
|
|
55
56
|
"chance": "^1.1.8",
|
|
56
57
|
"eslint": "^8.7.0",
|
|
57
58
|
"eslint-config-airbnb-base": "^15.0.0",
|
package/test/plugin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* global jest, expect */
|
|
2
2
|
/* eslint class-methods-use-this: "off", max-len: "off" */
|
|
3
|
+
const R = require('ramda');
|
|
3
4
|
|
|
4
5
|
const jestPlugin = (() => {
|
|
5
6
|
if (typeof jest === 'undefined') {
|
|
@@ -53,7 +54,19 @@ class Plugin {
|
|
|
53
54
|
});
|
|
54
55
|
this.searchQuote = jestPlugin.fn(() => ({ quote: [{ id: chance.guid() }] }));
|
|
55
56
|
this.createBooking = jestPlugin.fn(() => {});
|
|
56
|
-
this.queryAllotment = jestPlugin.fn(() =>
|
|
57
|
+
this.queryAllotment = jestPlugin.fn(async (args) => {
|
|
58
|
+
const {
|
|
59
|
+
axios,
|
|
60
|
+
payload,
|
|
61
|
+
} = args;
|
|
62
|
+
if (payload.keyPath === 'errorAxios') {
|
|
63
|
+
await axios.get('http://localhost:1235/');
|
|
64
|
+
}
|
|
65
|
+
if (payload.keyPath === 'errorGeneral') {
|
|
66
|
+
await axios.get('http://www.example.com');
|
|
67
|
+
}
|
|
68
|
+
return { allotments: [] }
|
|
69
|
+
});
|
|
57
70
|
this.tokenTemplate = jestPlugin.fn(() => ({
|
|
58
71
|
apiKey: {
|
|
59
72
|
type: 'text',
|
|
@@ -61,6 +74,14 @@ class Plugin {
|
|
|
61
74
|
description: 'Api Key',
|
|
62
75
|
},
|
|
63
76
|
}));
|
|
77
|
+
this.errorPathsAxiosErrors = jestPlugin.fn(() => ([
|
|
78
|
+
['code'],
|
|
79
|
+
]));
|
|
80
|
+
this.errorPathsAxiosAny = jestPlugin.fn(() => ([
|
|
81
|
+
err => {
|
|
82
|
+
return R.path(['data', 'error'], err);
|
|
83
|
+
}
|
|
84
|
+
]));
|
|
64
85
|
|
|
65
86
|
/**
|
|
66
87
|
* Background and schedule Jos
|
|
@@ -458,6 +479,23 @@ class Plugin {
|
|
|
458
479
|
*/
|
|
459
480
|
createBooking() {}
|
|
460
481
|
|
|
482
|
+
/**
|
|
483
|
+
* Allotment Object
|
|
484
|
+
/**
|
|
485
|
+
* @typedef {Object} Allotment
|
|
486
|
+
* @property {string} name - The name of the allotment.
|
|
487
|
+
* @property {string} description - A description of the allotment.
|
|
488
|
+
* @property {string} appliesTo - Specifies what the allotment applies to.
|
|
489
|
+
* @property {string} splitCode - The code used to split the allotment.
|
|
490
|
+
* @property {string} unitType - The type of unit used for the allotment.
|
|
491
|
+
* @property {Date} date - The date associated with the allotment using the input format.
|
|
492
|
+
* @property {string} release - The release period of the allotment as specified in the day inventory.
|
|
493
|
+
* @property {number} max - The maximum quantity allowed for the allotment as specified in the day inventory.
|
|
494
|
+
* @property {number} booked - The booked quantity of the allotment as specified in the day inventory.
|
|
495
|
+
* @property {boolean} request - Indicates whether requests are allowed for the allotment, based on the day inventory.
|
|
496
|
+
* @property {string[]} keyPaths - An array of key paths generated by combining supplier code and product codes.
|
|
497
|
+
*/
|
|
498
|
+
|
|
461
499
|
/**
|
|
462
500
|
* Query Allotment
|
|
463
501
|
* @async
|
|
@@ -473,7 +511,7 @@ class Plugin {
|
|
|
473
511
|
* @param {string} args.payload.endDate - End date for the query of allotment objects
|
|
474
512
|
* @param {string} args.payload.keyPath - End date for the query of allotment objects
|
|
475
513
|
* @returns {object} retVal - the return object.
|
|
476
|
-
* @returns {
|
|
514
|
+
* @returns {Allotment[]} retVal.allotment - An array of allotment spec objects.
|
|
477
515
|
*/
|
|
478
516
|
queryAllotment() {}
|
|
479
517
|
}
|