ti2-ventrata 1.0.3

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.test.js ADDED
@@ -0,0 +1,237 @@
1
+ /* globals describe, beforeAll, it, expect */
2
+ const R = require('ramda');
3
+ const moment = require('moment');
4
+ const faker = require('faker');
5
+
6
+ const Plugin = require('./index');
7
+ const fixtureUnits = require('./__fixtures__/units.js');
8
+
9
+ const app = new Plugin({
10
+ jwtKey: process.env.ti2_ventrata_jwtKey,
11
+ });
12
+
13
+ const rnd = (arr) => arr[Math.floor(Math.random() * arr.length)];
14
+
15
+ describe('search tests', () => {
16
+ let products;
17
+ let testProduct = {
18
+ productName: 'Pub Crawl Tour',
19
+ }
20
+ const token = {
21
+ apiKey: process.env.ti2_ventrata_apiKey,
22
+ endpoint: process.env.ti2_ventrata_endpoint,
23
+ octoEnv: process.env.ti2_ventrata_octoEnv,
24
+ acceptLanguage: process.env.ti2_ventrata_acceptLanguage,
25
+ };
26
+ const dateFormat = 'DD/MM/YYYY';
27
+ beforeAll(async () => {
28
+ // nada
29
+ });
30
+ describe('utilities', () => {
31
+ describe('pickUnit', () => {
32
+ it('adult', () => {
33
+ const result = Plugin.pickUnit(fixtureUnits, [{ age: 40 }]);
34
+ expect(result.length).toBe(1);
35
+ expect(result[0]).toContainObject([{ id: 'adult' }]);
36
+ });
37
+ it('child', () => {
38
+ const result = Plugin.pickUnit(fixtureUnits, [{ age: 10 }]);
39
+ expect(result.length).toBe(1);
40
+ expect(result[0]).toContainObject([{ id: 'child' }]);
41
+ });
42
+ it('senior', () => {
43
+ const result = Plugin.pickUnit(fixtureUnits, [{ age: 70 }]);
44
+ expect(result.length).toBe(1);
45
+ expect(result[0]).toContainObject([{ id: 'senior' }]);
46
+ });
47
+ it('family', () => {
48
+ const result = Plugin.pickUnit(fixtureUnits, [
49
+ { age: 70 }, { age: 32 }, { age: 32 }, { age: 14 },
50
+ ]);
51
+ expect(result.length).toBe(1);
52
+ expect(result[0]).toContainObject([{ id: 'family' }]);
53
+ });
54
+ it.todo('family + one');
55
+ });
56
+ });
57
+ describe('booking process', () => {
58
+ it('get for all products, a test product should exist', async () => {
59
+ const retVal = await app.searchProducts({
60
+ token,
61
+ });
62
+ expect(Array.isArray(retVal.products)).toBeTruthy();
63
+ // console.log(retVal.products.filter(({ productName }) => productName === testProduct.productName));
64
+ expect(retVal.products).toContainObject([{
65
+ productName: testProduct.productName,
66
+ }]);
67
+ testProduct = {
68
+ ...retVal.products.find(({ productName }) => productName === testProduct.productName),
69
+ };
70
+ expect(testProduct.productId).toBeTruthy();
71
+ });
72
+ it('should be able to get a single product', async () => {
73
+ const retVal = await app.searchProducts({
74
+ token,
75
+ payload: {
76
+ productId: testProduct.productId,
77
+ }
78
+ });
79
+ expect(Array.isArray(retVal.products)).toBeTruthy();
80
+ expect(retVal.products).toHaveLength(1);
81
+ });
82
+ let busProducts = [];
83
+ it('should be able to get a product by name', async () => {
84
+ const retVal = await app.searchProducts({
85
+ token,
86
+ payload: {
87
+ productName: '*bus*',
88
+ }
89
+ });
90
+ expect(Array.isArray(retVal.products)).toBeTruthy();
91
+ expect(retVal.products.length).toBeGreaterThan(0);
92
+ busProducts = retVal.products;
93
+ });
94
+ it('should be able to get quotes', async () => {
95
+ const retVal = await app.searchQuote({
96
+ token,
97
+ payload: {
98
+ startDate: moment().add(6, 'M').format(dateFormat),
99
+ endDate: moment().add(6, 'M').add(2, 'd').format(dateFormat),
100
+ dateFormat,
101
+ productIds: busProducts.map(({ productId }) => productId),
102
+ optionIds: busProducts.map(({ options }) =>
103
+ faker.random.arrayElement(options).optionId
104
+ ),
105
+ occupancies: [
106
+ [{ age: 30 }, { age: 40 }],
107
+ [{ age: 30 }, { age: 40 }],
108
+ ],
109
+ },
110
+ });
111
+ expect(retVal).toBeTruthy();
112
+ ({ quote } = retVal);
113
+ expect(quote.length).toBeGreaterThan(0);
114
+ expect(quote[0]).toContainObject([{
115
+ rateId: 'adult',
116
+ pricing: expect.toContainObject([{
117
+ currency: 'USD',
118
+ }]),
119
+ }]);
120
+ });
121
+ let availabilityKey;
122
+ it('should be able to get availability', async () => {
123
+ const retVal = await app.searchAvailability({
124
+ token,
125
+ payload: {
126
+ startDate: moment().add(6, 'M').format(dateFormat),
127
+ endDate: moment().add(6, 'M').add(2, 'd').format(dateFormat),
128
+ dateFormat,
129
+ productIds: [
130
+ '28ca088b-bc7b-4746-ab06-5971f1ed5a5e',
131
+ '5d981651-e204-4549-bfbe-691043dd2515'
132
+ ],
133
+ optionIds: ['DEFAULT', 'DEFAULT'],
134
+ occupancies: [
135
+ [{ age: 30 }, { age: 40 }],
136
+ [{ age: 30 }, { age: 40 }],
137
+ ],
138
+ },
139
+ });
140
+ expect(retVal).toBeTruthy();
141
+ ({ availability } = retVal);
142
+ expect(availability).toHaveLength(2);
143
+ expect(availability[0].length).toBeGreaterThan(0)
144
+ availabilityKey = R.path([0, 0, 'key'], availability);
145
+ expect(availabilityKey).toBeTruthy();
146
+ });
147
+ let booking;
148
+ const reference = faker.datatype.uuid();
149
+ it('should be able to create a booking', async () => {
150
+ const fullName = faker.name.findName().split(' ');
151
+ const retVal = await app.createBooking({
152
+ token,
153
+ payload: {
154
+ availabilityKey,
155
+ notes: faker.lorem.paragraph(),
156
+ holder: {
157
+ name: fullName[0],
158
+ surname: fullName[1],
159
+ phoneNumber: faker.phone.phoneNumber(),
160
+ emailAddress: `salvador+tests_${faker.lorem.slug()}@tourconnect.com`,
161
+ country: faker.address.countryCode(),
162
+ locales:  ['en-US', 'en', 'es'],
163
+ },
164
+ reference,
165
+ },
166
+ });
167
+ expect(retVal.booking).toBeTruthy();
168
+ ({ booking } = retVal);
169
+ expect(booking).toBeTruthy();
170
+ expect(R.path(['id'], booking)).toBeTruthy()
171
+ expect(R.path(['supplierId'], booking)).toBeTruthy()
172
+ expect(R.path(['cancellable'], booking)).toBeTruthy()
173
+ // console.log({ booking });
174
+ });
175
+ it('should be able to cancel the booking', async () => {
176
+ const retVal = await app.cancelBooking({
177
+ token,
178
+ payload: {
179
+ bookingId: booking.id,
180
+ reason: faker.lorem.paragraph(),
181
+ }
182
+ });
183
+ ({ cancellation } = retVal);
184
+ expect(cancellation).toBeTruthy();
185
+ expect(cancellation).toBeTruthy();
186
+ expect(R.path(['id'], cancellation)).toBeTruthy()
187
+ expect(R.path(['cancellable'], cancellation)).toBeFalsy()
188
+ });
189
+ let bookings = [];
190
+ it('it should be able to search bookings by id', async () => {
191
+ const retVal = await app.searchBooking({
192
+ token,
193
+ payload: {
194
+ bookingId: booking.id,
195
+ }
196
+ });
197
+ expect(Array.isArray(retVal.bookings)).toBeTruthy();
198
+ ({ bookings } = retVal);
199
+ expect(R.path([0, 'id'], bookings)).toBeTruthy()
200
+ });
201
+ it('it should be able to search bookings by reference', async () => {
202
+ const retVal = await app.searchBooking({
203
+ token,
204
+ payload: {
205
+ bookingId: reference,
206
+ }
207
+ });
208
+ expect(Array.isArray(retVal.bookings)).toBeTruthy();
209
+ ({ bookings } = retVal);
210
+ expect(R.path([0, 'id'], bookings)).toBeTruthy()
211
+ });
212
+ it('it should be able to search bookings by supplierId', async () => {
213
+ const retVal = await app.searchBooking({
214
+ token,
215
+ payload: {
216
+ bookingId: booking.supplierId,
217
+ }
218
+ });
219
+ expect(Array.isArray(retVal.bookings)).toBeTruthy();
220
+ ({ bookings } = retVal);
221
+ expect(R.path([0, 'id'], bookings)).toBeTruthy()
222
+ });
223
+ it('it should be able to search bookings by travelDate', async () => {
224
+ const retVal = await app.searchBooking({
225
+ token,
226
+ payload: {
227
+ travelDateStart: moment().add(6, 'M').format(dateFormat),
228
+ travelDateEnd: moment().add(6, 'M').add(2, 'd').format(dateFormat),
229
+ dateFormat,
230
+ }
231
+ });
232
+ expect(Array.isArray(retVal.bookings)).toBeTruthy();
233
+ ({ bookings } = retVal);
234
+ expect(R.path([0, 'id'], bookings)).toBeTruthy()
235
+ });
236
+ });
237
+ });
package/jest.setup.js ADDED
@@ -0,0 +1,38 @@
1
+ /* globals expect */
2
+ // should not require internals but is the only way to make it work on nested instances
3
+ const { equals } = require('expect/build/jasmineUtils');
4
+ const { diff: diffDefault } = require('jest-diff');
5
+
6
+ require('util').inspect.defaultOptions.depth = 8;
7
+
8
+ expect.extend({
9
+ toContainObject(receivedParam, argument) {
10
+ const received = (() => {
11
+ if (Array.isArray(receivedParam)) return receivedParam;
12
+ return [receivedParam];
13
+ })();
14
+ const pass = (() => {
15
+ if (Array.isArray(argument)) {
16
+ return equals(received,
17
+ expect.arrayContaining(argument.map(arg => expect.objectContaining(arg)))
18
+ );
19
+ }
20
+ return equals(received,
21
+ expect.arrayContaining([
22
+ expect.objectContaining(argument)
23
+ ])
24
+ );
25
+ })();
26
+ if (pass) {
27
+ return {
28
+ message: () => (`expected ${this.utils.printReceived(received)} not to contain object ${this.utils.printExpected(argument)}`),
29
+ pass: true
30
+ }
31
+ } else {
32
+ return {
33
+ message: () => (diffDefault(received, argument)),
34
+ pass: false
35
+ }
36
+ }
37
+ }
38
+ });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "ti2-ventrata",
3
+ "version": "1.0.3",
4
+ "description": "Ventrata's TI2 Plugin",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "jest"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/TourConnect/ti2-ventrata.git"
12
+ },
13
+ "author": "",
14
+ "license": "GPLV3",
15
+ "bugs": {
16
+ "url": "https://github.com/TourConnect/ti2-ventrata/issues"
17
+ },
18
+ "homepage": "https://github.com/TourConnect/ti2-ventrata#readme",
19
+ "jest": {
20
+ "testEnvironment": "node",
21
+ "coveragePathIgnorePatterns": [
22
+ "/node_modules/"
23
+ ],
24
+ "setupFilesAfterEnv": [
25
+ "./jest.setup.js"
26
+ ],
27
+ "testTimeout": 10000
28
+ },
29
+ "dependencies": {
30
+ "axios": "^0.24.0",
31
+ "bluebird": "^3.7.2",
32
+ "jsonwebtoken": "^8.5.1",
33
+ "moment": "^2.29.1",
34
+ "ramda": "^0.27.1"
35
+ },
36
+ "devDependencies": {
37
+ "eslint": "^8.4.1",
38
+ "eslint-config-airbnb": "^19.0.2",
39
+ "eslint-plugin-import": "^2.25.4",
40
+ "faker": "^5.5.3",
41
+ "jest": "^27.4.5",
42
+ "jest-cli": "^27.4.7",
43
+ "jest-diff": "^27.4.2"
44
+ }
45
+ }
@@ -0,0 +1,23 @@
1
+ // from https://stackoverflow.com/questions/1714786/query-string-encoding-of-a-javascript-object
2
+ module.exports = initialObj => {
3
+ const reducer = (obj, parentPrefix = null) => (prev, key) => {
4
+ const val = obj[key];
5
+ key = encodeURIComponent(key);
6
+ const prefix = parentPrefix ? `${parentPrefix}[${key}]` : key;
7
+
8
+ if (val == null || typeof val === 'function') {
9
+ prev.push(`${prefix}=`);
10
+ return prev;
11
+ }
12
+
13
+ if (['number', 'boolean', 'string'].includes(typeof val)) {
14
+ prev.push(`${prefix}=${encodeURIComponent(val)}`);
15
+ return prev;
16
+ }
17
+
18
+ prev.push(Object.keys(val).reduce(reducer(val, prefix), []).join('&'));
19
+ return prev;
20
+ };
21
+
22
+ return Object.keys(initialObj).reduce(reducer(initialObj), []).join('&');
23
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = (wildcard, str) => {
2
+ let w = wildcard.replace(/[.+^${}()|[\]\\]/g, '\\$&'); // regexp escape
3
+ const re = new RegExp(`^${w.replace(/\*/g,'.*').replace(/\?/g,'.')}$`,'i');
4
+ return re.test(str); // remove last 'i' above to have case sensitive
5
+ }