ti2-ventrata 1.0.10 → 1.0.12

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/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const axios = require('axios');
2
+ const curlirize = require('axios-curlirize');
2
3
  const R = require('ramda');
3
4
  const Promise = require('bluebird');
4
5
  const assert = require('assert');
@@ -7,6 +8,9 @@ const jwt = require('jsonwebtoken');
7
8
  const wildcardMatch = require('./utils/wildcardMatch');
8
9
 
9
10
  const CONCURRENCY = 3; // is this ok ?
11
+ if (process.env.debug) {
12
+ curlirize(axios);
13
+ }
10
14
 
11
15
  const isNilOrEmpty = R.either(R.isNil, R.isEmpty);
12
16
  const isNilOrEmptyArray = el => {
@@ -54,12 +58,26 @@ const rateMap = {
54
58
  pricing: R.path(['pricingFrom']),
55
59
  };
56
60
 
61
+ const unitPricingMap = {
62
+ unitId: R.prop('unitId'),
63
+ original: R.prop('original'),
64
+ retail: R.prop('retail'),
65
+ net: R.prop('net'),
66
+ currencyPrecision: R.prop('currencyPrecision'),
67
+ };
68
+
57
69
  const availabilityMap = {
58
70
  dateTimeStart: root => R.path(['localDateTimeStart'], root) || R.path(['localDate'], root),
59
- dateTimeEnd: root => R.path(['localDateTimeEnd']) || R.path(['localDate'], root),
71
+ dateTimeEnd: root => R.path(['localDateTimeEnd'], root) || R.path(['localDate'], root),
60
72
  allDay: R.path(['allDay']),
61
73
  pricing: root => R.path(['pricing'], root) || R.path(['pricingFrom'], root),
62
- unitPricing: root => R.path(['unitPricing'], root) || R.path(['unitPricingFrom'], root),
74
+ unitPricing: root => {
75
+ let before = [];
76
+ if (R.path(['unitPricing'], root)) before = R.path(['unitPricing'], root);
77
+ else before = R.path(['unitPricingFrom'], root) || [];
78
+ return before.map(item => doMap(item, unitPricingMap));
79
+ },
80
+ vacancies: R.prop('vacancies'),
63
81
  offer: avail => (avail.offerCode ? doMap(avail, {
64
82
  offerId: R.path(['offerCode']),
65
83
  title: R.pathOr(undefined, ['offerTitle']),
@@ -109,7 +127,7 @@ const unitItemMap = {
109
127
  unitItemId: R.path(['uuid']),
110
128
  unitId: R.path(['unitId']),
111
129
  unitName: R.path(['unit', 'title']),
112
- supplierId: R.path(['supplierReference']),
130
+ supplierBookingId: R.path(['supplierReference']),
113
131
  status: e => capitalize(R.path(['status'], e)),
114
132
  contact: R.path(['contact']),
115
133
  pricing: R.path(['pricing']),
@@ -131,7 +149,7 @@ const bookingMap = {
131
149
  id: R.path(['id']),
132
150
  orderId: R.path(['orderReference']),
133
151
  bookingId: R.path(['supplierReference']),
134
- supplierId: R.path(['supplierReference']),
152
+ supplierBookingId: R.path(['supplierReference']),
135
153
  status: e => capitalize(R.path(['status'], e)),
136
154
  productId: R.path(['product', 'id']),
137
155
  productName: R.path(['product', 'title']),
@@ -171,11 +189,17 @@ const contactMap = {
171
189
  country: R.path(['country']),
172
190
  };
173
191
 
174
- const getHeaders = ({ apiKey, acceptLanguage, octoEnv }) => ({
192
+ const getHeaders = ({
193
+ apiKey,
194
+ acceptLanguage,
195
+ octoEnv,
196
+ referrer,
197
+ }) => ({
175
198
  Authorization: `Bearer ${apiKey}`,
176
199
  'Octo-Env': octoEnv,
177
200
  ...acceptLanguage ? { 'Accept-Language': acceptLanguage } : {},
178
201
  'Content-Type': 'application/json',
202
+ ...referrer ? { Referer: referrer } : {},
179
203
  });
180
204
 
181
205
  class Plugin {
@@ -454,48 +478,51 @@ class Plugin {
454
478
  },
455
479
  payload: {
456
480
  availabilityKey,
481
+ holder,
457
482
  notes,
458
483
  reference,
459
- holder,
484
+ referrer,
485
+ settlementMethod,
460
486
  },
461
487
  }) {
462
- try {
463
- assert(availabilityKey, 'an availability code is required !');
464
- assert(R.path(['name'], holder), 'a holder\' first name is required');
465
- assert(R.path(['surname'], holder), 'a holder\' surname is required');
466
- assert(R.path(['emailAddress'], holder), 'a holder\' email address is required');
467
- const headers = getHeaders({
468
- apiKey,
469
- endpoint,
470
- octoEnv,
471
- acceptLanguage,
472
- });
473
- let url = `${endpoint || this.endpoint}/bookings`;
474
- let data = await jwt.verify(availabilityKey, this.jwtKey);
475
- let booking = R.path(['data'], await axios({
476
- method: 'post',
477
- url,
478
- data: { ...data, notes },
479
- headers,
480
- }));
481
- url = `${endpoint || this.endpoint}/bookings/${booking.uuid}/confirm`;
482
- const contact = doMap(holder, contactMap);
483
- data = {
488
+ assert(availabilityKey, 'an availability code is required !');
489
+ assert(R.path(['name'], holder), 'a holder\' first name is required');
490
+ assert(R.path(['surname'], holder), 'a holder\' surname is required');
491
+ assert(R.path(['emailAddress'], holder), 'a holder\' email address is required');
492
+ const headers = getHeaders({
493
+ apiKey,
494
+ endpoint,
495
+ octoEnv,
496
+ acceptLanguage,
497
+ referrer,
498
+ });
499
+ let url = `${endpoint || this.endpoint}/bookings`;
500
+ let data = await jwt.verify(availabilityKey, this.jwtKey);
501
+ let booking = R.path(['data'], await axios({
502
+ method: 'post',
503
+ url,
504
+ data: {
505
+ settlementMethod,
506
+ ...data,
484
507
  notes,
485
- contact,
486
- resellerReference: reference,
487
- };
488
- booking = R.path(['data'], await axios({
489
- method: 'post',
490
- url,
491
- data,
492
- headers,
493
- }));
494
- return ({ booking: doMap(booking, bookingMap) });
495
- } catch (err) {
496
- console.log('createBooking-ventrata', err);
497
- throw Error(err);
498
- }
508
+ },
509
+ headers,
510
+ }));
511
+ url = `${endpoint || this.endpoint}/bookings/${booking.uuid}/confirm`;
512
+ const contact = doMap(holder, contactMap);
513
+ data = {
514
+ contact,
515
+ notes,
516
+ resellerReference: reference,
517
+ settlementMethod,
518
+ };
519
+ booking = R.path(['data'], await axios({
520
+ method: 'post',
521
+ url,
522
+ data,
523
+ headers,
524
+ }));
525
+ return ({ booking: doMap(booking, bookingMap) });
499
526
  }
500
527
 
501
528
  async cancelBooking({
@@ -538,7 +565,7 @@ class Plugin {
538
565
  payload: {
539
566
  bookingId,
540
567
  resellerReference,
541
- supplierId,
568
+ supplierBookingId,
542
569
  travelDateStart,
543
570
  travelDateEnd,
544
571
  dateFormat,
@@ -547,7 +574,7 @@ class Plugin {
547
574
  assert(
548
575
  !isNilOrEmpty(bookingId)
549
576
  || !isNilOrEmpty(resellerReference)
550
- || !isNilOrEmpty(supplierId)
577
+ || !isNilOrEmpty(supplierBookingId)
551
578
  || !(
552
579
  isNilOrEmpty(travelDateStart) && isNilOrEmpty(travelDateEnd) && isNilOrEmpty(dateFormat)
553
580
  ),
@@ -587,8 +614,8 @@ class Plugin {
587
614
  headers,
588
615
  }));
589
616
  }
590
- if (!isNilOrEmpty(supplierId)) {
591
- url = `${endpoint || this.endpoint}/bookings?supplierReference=${supplierId}`;
617
+ if (!isNilOrEmpty(supplierBookingId)) {
618
+ url = `${endpoint || this.endpoint}/bookings?supplierReference=${supplierBookingId}`;
592
619
  return R.path(['data'], await axios({
593
620
  method: 'get',
594
621
  url,
package/index.test.js CHANGED
@@ -175,6 +175,7 @@ describe('search tests', () => {
175
175
  payload: {
176
176
  availabilityKey,
177
177
  notes: faker.lorem.paragraph(),
178
+ settlementMethod: 'DEFERRED',
178
179
  holder: {
179
180
  name: fullName[0],
180
181
  surname: fullName[1],
@@ -190,7 +191,7 @@ describe('search tests', () => {
190
191
  ({ booking } = retVal);
191
192
  expect(booking).toBeTruthy();
192
193
  expect(R.path(['id'], booking)).toBeTruthy();
193
- expect(R.path(['supplierId'], booking)).toBeTruthy();
194
+ expect(R.path(['supplierBookingId'], booking)).toBeTruthy();
194
195
  expect(R.path(['cancellable'], booking)).toBeTruthy();
195
196
  // console.log({ booking });
196
197
  });
@@ -231,11 +232,11 @@ describe('search tests', () => {
231
232
  ({ bookings } = retVal);
232
233
  expect(R.path([0, 'id'], bookings)).toBeTruthy();
233
234
  });
234
- it('it should be able to search bookings by supplierId', async () => {
235
+ it('it should be able to search bookings by supplierBookingId', async () => {
235
236
  const retVal = await app.searchBooking({
236
237
  token,
237
238
  payload: {
238
- bookingId: booking.supplierId,
239
+ bookingId: booking.supplierBookingId,
239
240
  },
240
241
  });
241
242
  expect(Array.isArray(retVal.bookings)).toBeTruthy();
@@ -255,5 +256,32 @@ describe('search tests', () => {
255
256
  ({ bookings } = retVal);
256
257
  expect(R.path([0, 'id'], bookings)).toBeTruthy();
257
258
  });
259
+ it('should be able to create a booking for a referrer', async () => {
260
+ const fullName = faker.name.findName().split(' ');
261
+ const retVal = await app.createBooking({
262
+ token,
263
+ payload: {
264
+ availabilityKey,
265
+ notes: faker.lorem.paragraph(),
266
+ holder: {
267
+ name: fullName[0],
268
+ surname: fullName[1],
269
+ phoneNumber: faker.phone.phoneNumber(),
270
+ emailAddress: `salvador+tests_${faker.lorem.slug()}@tourconnect.com`,
271
+ country: faker.address.countryCode(),
272
+ locales: ['en-US', 'en', 'es'],
273
+ },
274
+ reference,
275
+ referrer: 'referrerforapitest',
276
+ settlementMethod: 'DEFERRED',
277
+ },
278
+ });
279
+ expect(retVal.booking).toBeTruthy();
280
+ ({ booking } = retVal);
281
+ expect(booking).toBeTruthy();
282
+ expect(R.path(['id'], booking)).toBeTruthy();
283
+ expect(R.path(['supplierBookingId'], booking)).toBeTruthy();
284
+ expect(R.path(['cancellable'], booking)).toBeTruthy();
285
+ });
258
286
  });
259
287
  });
@@ -0,0 +1,81 @@
1
+ const NodeEnvironment = require('jest-environment-node');
2
+ const chalk = require('chalk');
3
+
4
+ const { debug } = process.env;
5
+
6
+ class NodeEnvironmentFailFast extends NodeEnvironment {
7
+ constructor(config, context) {
8
+ super(config, context);
9
+ this.failedDescribeMap = {};
10
+ this.registeredEventHandler = [];
11
+ this.lastParent = undefined;
12
+ }
13
+
14
+ async setup() {
15
+ await super.setup();
16
+ this.global.testEnvironment = this;
17
+ }
18
+
19
+ registerTestEventHandler(registeredEventHandler) {
20
+ this.registeredEventHandler.push(registeredEventHandler);
21
+ }
22
+
23
+ async executeTestEventHandlers(event, state) {
24
+ for (const handler of this.registeredEventHandler) {
25
+ await handler(event, state);
26
+ }
27
+ }
28
+
29
+ async handleTestEvent(event, state) {
30
+ await this.executeTestEventHandlers(event, state);
31
+
32
+ switch (event.name) {
33
+ case 'hook_failure': {
34
+ const describeBlockName = event.hook.parent.name;
35
+ this.failedDescribeMap[describeBlockName] = true;
36
+ // hook errors are not displayed if tests are skipped, so display them manually
37
+ console.error(`ERROR: ${describeBlockName} > ${event.hook.type}\n\n`, event.error, '\n');
38
+ break;
39
+ }
40
+ case 'test_fn_success': {
41
+ if (debug) {
42
+ if (this.lastParent !== event.test.parent.name) {
43
+ console.log(`${event.test.parent.name}\n ${chalk.green('\u2713')} ${event.test.name}`);
44
+ } else {
45
+ console.log(` ${chalk.green('\u2713')} ${event.test.name}`);
46
+ }
47
+ this.lastParent = event.test.parent.name;
48
+ }
49
+ break;
50
+ }
51
+ case 'test_fn_failure': {
52
+ this.failedDescribeMap[event.test.parent.name] = true;
53
+ if (debug) {
54
+ if (this.lastParent !== event.test.parent.name) {
55
+ console.log(`${event.test.parent.name}\n ${chalk.red('\u2715')} ${event.test.name}`);
56
+ } else {
57
+ console.log(` ${chalk.red('\u2715')} ${event.test.name}`);
58
+ }
59
+ this.lastParent = event.test.parent.name;
60
+ console.error(event.error.message);
61
+ }
62
+ break;
63
+ }
64
+ case 'test_start': {
65
+ if (this.failedDescribeMap[event.test.parent.name]) {
66
+ event.test.mode = 'skip';
67
+ }
68
+ break;
69
+ }
70
+ }
71
+
72
+ if (super.handleTestEvent) {
73
+ super.handleTestEvent(event, state);
74
+ }
75
+ }
76
+
77
+ async teardown() {
78
+ await super.teardown();
79
+ }
80
+ }
81
+ module.exports = NodeEnvironmentFailFast;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ti2-ventrata",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "Ventrata's TI2 Plugin",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "homepage": "https://github.com/TourConnect/ti2-ventrata#readme",
19
19
  "jest": {
20
- "testEnvironment": "node",
20
+ "testEnvironment": "<rootDir>/jestEnvironment.js",
21
21
  "coveragePathIgnorePatterns": [
22
22
  "/node_modules/"
23
23
  ],
@@ -28,18 +28,22 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "axios": "^0.24.0",
31
+ "axios-curlirize": "^1.3.7",
31
32
  "bluebird": "^3.7.2",
32
33
  "jsonwebtoken": "^8.5.1",
33
34
  "moment": "^2.29.1",
34
35
  "ramda": "^0.27.1"
35
36
  },
36
37
  "devDependencies": {
38
+ "chalk": "^4.1.2",
37
39
  "eslint": "^8.4.1",
38
40
  "eslint-config-airbnb": "^19.0.2",
39
41
  "eslint-plugin-import": "^2.25.4",
40
42
  "faker": "^5.5.3",
41
43
  "jest": "^27.4.5",
42
44
  "jest-cli": "^27.4.7",
43
- "jest-diff": "^27.4.2"
45
+ "jest-diff": "^27.4.2",
46
+ "jest-environment-node": "27.4",
47
+ "jest-util": "27.4"
44
48
  }
45
49
  }