@symbo.ls/sdk 2.33.40 → 2.34.0

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.
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-useless-escape */
1
2
  /* eslint-disable no-undefined */
2
3
  import test from 'tape'
3
4
  import sinon from 'sinon'
@@ -15,8 +16,7 @@ test('updatePlanWithValidation should return response data', async t => {
15
16
  planId: 'testString',
16
17
  planData: {
17
18
  name: 'testName',
18
- key: 'testkey',
19
- price: 1.0
19
+ key: 'testkey'
20
20
  }
21
21
  }
22
22
  const planServiceStub = new PlanService()
@@ -42,9 +42,13 @@ function planIdEmptyOrNotAString () {
42
42
  name: 'planId is null',
43
43
  testValue: null
44
44
  },
45
- planIdNotAString: {
46
- name: 'planId is not a string',
45
+ planIdIsAnObject: {
46
+ name: 'planId is an object',
47
47
  testValue: {}
48
+ },
49
+ planIdIsANumber: {
50
+ name: 'planId is number',
51
+ testValue: 123
48
52
  }
49
53
  }
50
54
 
@@ -53,8 +57,7 @@ function planIdEmptyOrNotAString () {
53
57
  t.plan(1)
54
58
  const planData = {
55
59
  name: 'testName',
56
- key: 'testkey',
57
- price: 1.0
60
+ key: 'testkey'
58
61
  }
59
62
  const planId = badData[key].testValue
60
63
  const planServiceStub = new PlanService()
@@ -81,9 +84,17 @@ function planDataEmptyOrNotAnObject () {
81
84
  name: 'planData is undefined',
82
85
  testValue: undefined
83
86
  },
84
- planDataNotAnObject: {
85
- name: 'planData is not an object',
86
- testValue: 'Not An Object'
87
+ planDataIsNull: {
88
+ name: 'planData is null',
89
+ testValue: null
90
+ },
91
+ planDataIsAString: {
92
+ name: 'planData is a string',
93
+ testValue: 'test string'
94
+ },
95
+ planDataIsANumber: {
96
+ name: 'planData is a string',
97
+ testValue: 123
87
98
  }
88
99
  }
89
100
 
@@ -109,28 +120,134 @@ function planDataEmptyOrNotAnObject () {
109
120
  })
110
121
  }
111
122
 
112
- function priceValidation () {
113
- const badPriceData = ['A string', -10, {}]
114
- for (let ii = 0; ii < badPriceData.length; ii++) {
115
- test(`Price validation should throw an error checking for: ${badPriceData[ii]}`, async t => {
123
+ test('Price validation should throw an error when price field is present', async t => {
124
+ t.plan(1)
125
+ const planId = 'testString'
126
+ const planData = {
127
+ name: 'testName',
128
+ description: 'test description',
129
+ price: 1.0
130
+ }
131
+ const planServiceStub = new PlanService()
132
+ try {
133
+ await planServiceStub.updatePlanWithValidation(planId, planData)
134
+ t.fail('Price validation successfully threw an error')
135
+ } catch (err) {
136
+ t.equal(
137
+ err.toString(),
138
+ 'Error: Field "price" is no longer supported. Use unified "pricingOptions" with "amount" instead.',
139
+ 'Price validation detected unsupported price field'
140
+ )
141
+ }
142
+ sandbox.restore()
143
+ t.end()
144
+ })
145
+
146
+ function pricingOptionsValidation () {
147
+ // Data test object
148
+ const planData = {
149
+ name: 'testName',
150
+ description: 'test description'
151
+ }
152
+
153
+ const badPricingOptions = {
154
+ stringValue: 'test string',
155
+ numberValue: 123,
156
+ falseBooleanValue: false,
157
+ trueBooleanValue: true,
158
+ emptyArray: []
159
+ }
160
+ Object.keys(badPricingOptions).forEach(field => {
161
+ test(`pricingOptions validation throws error for ${field}`, async t => {
116
162
  t.plan(1)
163
+ const planId = 'testString'
164
+ const { ...testData } = planData
165
+ testData.pricingOptions = badPricingOptions[field]
166
+ const planServiceStub = new PlanService()
167
+ try {
168
+ await planServiceStub.updatePlanWithValidation(planId, testData)
169
+ t.fail('updatePlanWithValidation failed - bad pricingOptions detected')
170
+ } catch (err) {
171
+ t.equal(
172
+ err.toString(),
173
+ 'Error: pricingOptions must be a non-empty array when provided',
174
+ `pricingOptions validation failed successfully on bad pricingOptions data: ${field}`
175
+ )
176
+ }
177
+ sandbox.restore()
178
+ t.end()
179
+ })
180
+ })
181
+ }
182
+
183
+ function keyTypeValidation () {
184
+ const badKeyData = [
185
+ { name: 'array value', key: [] },
186
+ { name: 'number value', key: 123 },
187
+ { name: 'null value', key: null },
188
+ { name: 'undefined value', key: undefined },
189
+ { name: 'false boolean value', key: false }
190
+ ]
191
+ for (let ii = 0; ii < badKeyData.length; ii++) {
192
+ test(`Key type validation should throw an error checking for: ${badKeyData[ii].name}`, async t => {
193
+ t.plan(1)
194
+ const planId = 'testString'
117
195
  const planData = {
118
196
  name: 'testName',
119
- key: 'test-key'
197
+ description: 'test description',
198
+ pricingOptions: []
120
199
  }
200
+ planData.pricingOptions.push(badKeyData[ii])
201
+ const responseStub = [sandbox.stub()]
202
+ const planServiceStub = new PlanService()
203
+ sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
204
+ try {
205
+ await planServiceStub.updatePlanWithValidation(planId, planData)
206
+ t.fail('Key type validation successfully threw an error')
207
+ } catch (err) {
208
+ t.ok(
209
+ err
210
+ .toString()
211
+ .includes(
212
+ "Error: Pricing option at index 0 is missing required field 'key'"
213
+ ),
214
+ `Key type validation detected bad data: ${badKeyData[ii].name}`
215
+ )
216
+ }
217
+ sandbox.restore()
218
+ t.end()
219
+ })
220
+ }
221
+ }
222
+
223
+ function keyFormatValidation () {
224
+ const badKeyData = [
225
+ { name: 'capital letters', key: 'CAPITALLETTERS' },
226
+ { name: 'special character', key: 'Special @ Character' },
227
+ { name: 'under score', key: 'under_score' },
228
+ { name: 'punctuation', key: 'syntax!' }
229
+ ]
230
+ for (let ii = 0; ii < badKeyData.length; ii++) {
231
+ test(`Key format validation should throw an error checking for: ${badKeyData[ii].name}`, async t => {
232
+ t.plan(1)
121
233
  const planId = 'testString'
122
- planData.price = badPriceData[ii]
234
+ const planData = {
235
+ name: 'testName',
236
+ description: 'test description',
237
+ pricingOptions: []
238
+ }
239
+ planData.pricingOptions.push(badKeyData[ii])
123
240
  const responseStub = [sandbox.stub()]
124
241
  const planServiceStub = new PlanService()
125
242
  sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
126
243
  try {
127
244
  await planServiceStub.updatePlanWithValidation(planId, planData)
128
- t.fail('Price validation successfully threw an error')
245
+ t.fail('Key type validation successfully threw an error')
129
246
  } catch (err) {
130
247
  t.equal(
131
248
  err.toString(),
132
- 'Error: Price must be a positive number',
133
- `Price validation detected bad price data: ${planData.price}`
249
+ `Error: Pricing option key '${badKeyData[ii].key}' must contain only lowercase letters, numbers, and hyphens`,
250
+ `Key format validation detected bad data: ${badKeyData[ii].name}`
134
251
  )
135
252
  }
136
253
  sandbox.restore()
@@ -139,33 +256,38 @@ function priceValidation () {
139
256
  }
140
257
  }
141
258
 
142
- function keyValidation () {
143
- const badKeyData = [
144
- 'CAPITALLETTERS',
145
- 'Special @ Character',
146
- 'under_score',
147
- 'syntax!'
259
+ function displayNameValidation () {
260
+ const badDisplayNameData = [
261
+ {
262
+ name: 'false boolean value',
263
+ displayName: false,
264
+ key: 'false-boolean-value'
265
+ },
266
+ { name: 'number value', displayName: 123, key: 'number-value' },
267
+ { name: 'undefined value', displayName: undefined, key: 'undefined-value' },
268
+ { name: 'null value', displayName: null, key: 'null-value' }
148
269
  ]
149
- for (let ii = 0; ii < badKeyData.length; ii++) {
150
- test(`Key validation should throw an error checking for: ${badKeyData[ii]}`, async t => {
270
+ for (let ii = 0; ii < badDisplayNameData.length; ii++) {
271
+ test(`displayName validation should throw an error checking for: ${badDisplayNameData[ii].name}`, async t => {
151
272
  t.plan(1)
152
273
  const planId = 'testString'
153
274
  const planData = {
154
275
  name: 'testName',
155
- price: 1.0
276
+ description: 'test description',
277
+ pricingOptions: []
156
278
  }
157
- planData.key = badKeyData[ii]
279
+ planData.pricingOptions.push(badDisplayNameData[ii])
158
280
  const responseStub = [sandbox.stub()]
159
281
  const planServiceStub = new PlanService()
160
282
  sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
161
283
  try {
162
284
  await planServiceStub.updatePlanWithValidation(planId, planData)
163
- t.fail('Key validation successfully threw an error')
285
+ t.fail('Key type validation successfully threw an error')
164
286
  } catch (err) {
165
287
  t.equal(
166
288
  err.toString(),
167
- 'Error: Plan key must contain only lowercase letters, numbers, and hyphens',
168
- `Key validation detected bad price data: ${planData.key}`
289
+ `Error: Pricing option \'${badDisplayNameData[ii].key}\' is missing required field \'displayName\'`,
290
+ `displayName validation detected bad data: ${badDisplayNameData[ii].name}`
169
291
  )
170
292
  }
171
293
  sandbox.restore()
@@ -174,47 +296,256 @@ function keyValidation () {
174
296
  }
175
297
  }
176
298
 
177
- test('getActivePlans should return active plans', async t => {
178
- t.plan(3)
179
- const numActivePlans = 2
180
- const plansStub = [
299
+ function amountValidation () {
300
+ const badAmountData = [
301
+ {
302
+ name: 'negative amount value',
303
+ displayName: 'test displayname',
304
+ key: 'negative-amount-value',
305
+ amount: -1
306
+ },
181
307
  {
182
- plan: 'plan1',
183
- active: true
308
+ name: 'letter value',
309
+ displayName: 'test displayname',
310
+ key: 'letter-value',
311
+ amount: 'abc123'
184
312
  },
185
313
  {
186
- plan: 'plan2',
187
- active: false
314
+ name: 'undefined value',
315
+ displayName: 'test displayname',
316
+ key: 'undefined-value',
317
+ amount: undefined
188
318
  },
189
319
  {
190
- plan: 'plan3',
191
- active: true
320
+ name: 'null value',
321
+ displayName: 'test displayname',
322
+ key: 'null-value',
323
+ amount: null
192
324
  }
193
325
  ]
194
- const planServiceStub = new PlanService()
195
- sandbox.stub(planServiceStub, 'getPlans').resolves(plansStub)
196
- const response = await planServiceStub.getActivePlans()
197
- t.equal(
198
- response.length,
199
- numActivePlans,
200
- 'Correct number of active plans returned'
201
- )
202
- t.equal(
203
- response[0].plan,
204
- plansStub[0].plan,
205
- 'First plan successfully returned'
206
- )
207
- t.equal(
208
- response[1].plan,
209
- plansStub[2].plan,
210
- 'Third plan successfully returned'
211
- )
212
- })
326
+ for (let ii = 0; ii < badAmountData.length; ii++) {
327
+ test(`amount validation should throw an error checking for: ${badAmountData[ii].name}`, async t => {
328
+ t.plan(1)
329
+ const planId = 'testString'
330
+ const planData = {
331
+ name: 'testName',
332
+ description: 'test description',
333
+ pricingOptions: []
334
+ }
335
+ planData.pricingOptions.push(badAmountData[ii])
336
+ const responseStub = [sandbox.stub()]
337
+ const planServiceStub = new PlanService()
338
+ sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
339
+ try {
340
+ await planServiceStub.updatePlanWithValidation(planId, planData)
341
+ t.fail('Key type validation successfully threw an error')
342
+ } catch (err) {
343
+ t.equal(
344
+ err.toString(),
345
+ `Error: Pricing option \'${badAmountData[ii].key}\' must have a non-negative numeric \'amount\'`,
346
+ `amount validation detected bad data: ${badAmountData[ii].name}`
347
+ )
348
+ }
349
+ sandbox.restore()
350
+ t.end()
351
+ })
352
+ }
353
+ }
354
+
355
+ function intervalValidation () {
356
+ const badAmountData = [
357
+ {
358
+ name: 'number value',
359
+ displayName: 'test displayname',
360
+ key: 'number-amount-value',
361
+ amount: 0,
362
+ interval: 123
363
+ },
364
+ {
365
+ name: 'unsupported string value',
366
+ displayName: 'test displayname',
367
+ key: 'letter-value',
368
+ amount: 0,
369
+ interval: 'abc123'
370
+ },
371
+ {
372
+ name: 'undefined value',
373
+ displayName: 'test displayname',
374
+ key: 'undefined-value',
375
+ amount: 0,
376
+ interval: undefined
377
+ }
378
+ ]
379
+ for (let ii = 0; ii < badAmountData.length; ii++) {
380
+ test(`interval validation should throw an error checking for: ${badAmountData[ii].name}`, async t => {
381
+ t.plan(1)
382
+ const planId = 'testString'
383
+ const planData = {
384
+ name: 'testName',
385
+ description: 'test description',
386
+ pricingOptions: []
387
+ }
388
+ planData.pricingOptions.push(badAmountData[ii])
389
+ const responseStub = [sandbox.stub()]
390
+ const planServiceStub = new PlanService()
391
+ sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
392
+ try {
393
+ await planServiceStub.updatePlanWithValidation(planId, planData)
394
+ t.fail('Key type validation successfully threw an error')
395
+ } catch (err) {
396
+ t.equal(
397
+ err.toString(),
398
+ `Error: Pricing option \'${badAmountData[ii].key}\' has invalid interval \'${badAmountData[ii].interval}\'. Allowed: month, year, week, day or null`,
399
+ `interval validation detected bad data: ${badAmountData[ii].name}`
400
+ )
401
+ }
402
+ sandbox.restore()
403
+ t.end()
404
+ })
405
+ }
406
+ }
407
+
408
+ function lookupKeyValidation () {
409
+ const badData = [
410
+ {
411
+ name: 'number value',
412
+ displayName: 'test displayname',
413
+ key: 'number-amount-value',
414
+ amount: 0,
415
+ interval: null,
416
+ lookupKey: 123
417
+ },
418
+ {
419
+ name: 'false boolean value',
420
+ displayName: 'test displayname',
421
+ key: 'letter-value',
422
+ amount: 0,
423
+ interval: null,
424
+ lookupKey: false
425
+ },
426
+ {
427
+ name: 'true boolean value',
428
+ displayName: 'test displayname',
429
+ key: 'letter-value',
430
+ amount: 0,
431
+ interval: null,
432
+ lookupKey: true
433
+ },
434
+ {
435
+ name: 'object value',
436
+ displayName: 'test displayname',
437
+ key: 'undefined-value',
438
+ amount: 0,
439
+ interval: null,
440
+ lookupKey: {}
441
+ },
442
+ {
443
+ name: 'undefined value',
444
+ displayName: 'test displayname',
445
+ key: 'undefined-value',
446
+ amount: 0,
447
+ interval: null,
448
+ lookupKey: undefined
449
+ },
450
+ {
451
+ name: 'null value',
452
+ displayName: 'test displayname',
453
+ key: 'undefined-value',
454
+ amount: 0,
455
+ interval: null,
456
+ lookupKey: null
457
+ }
458
+ ]
459
+ for (let ii = 0; ii < badData.length; ii++) {
460
+ test(`lookup key validation should throw an error checking for: ${badData[ii].name}`, async t => {
461
+ t.plan(1)
462
+ const planId = 'testString'
463
+ const planData = {
464
+ name: 'testName',
465
+ description: 'test description',
466
+ pricingOptions: []
467
+ }
468
+ planData.pricingOptions.push(badData[ii])
469
+ const responseStub = [sandbox.stub()]
470
+ const planServiceStub = new PlanService()
471
+ sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
472
+ try {
473
+ await planServiceStub.updatePlanWithValidation(planId, planData)
474
+ t.fail('Key type validation successfully threw an error')
475
+ } catch (err) {
476
+ t.equal(
477
+ err.toString(),
478
+ `Error: Pricing option \'${badData[ii].key}\' is missing required field \'lookupKey\'`,
479
+ `lookup key validation detected bad data: ${badData[ii].name}`
480
+ )
481
+ }
482
+ sandbox.restore()
483
+ t.end()
484
+ })
485
+ }
486
+ }
487
+
488
+ function topLevelKeyValidation () {
489
+ const planData = [
490
+ {
491
+ name: 'Uppercase letters',
492
+ description: 'test description',
493
+ key: 'ALLCAPS'
494
+ },
495
+ {
496
+ name: 'Underscore character',
497
+ description: 'test description',
498
+ key: '_'
499
+ },
500
+ {
501
+ name: 'Special characters',
502
+ description: 'test description',
503
+ key: '!@#$%'
504
+ },
505
+ {
506
+ name: 'Object type',
507
+ description: 'test description',
508
+ key: {}
509
+ },
510
+ {
511
+ name: 'Null value',
512
+ description: 'test description',
513
+ key: null
514
+ }
515
+ ]
516
+ for (let ii = 0; ii < planData.length; ii++) {
517
+ test(`top-level key validation should throw an error checking for: ${planData[ii].name}`, async t => {
518
+ t.plan(1)
519
+ const planId = 'testString'
520
+ const responseStub = [sandbox.stub()]
521
+ const planServiceStub = new PlanService()
522
+ sandbox.stub(planServiceStub, 'updatePlan').resolves(responseStub)
523
+ try {
524
+ await planServiceStub.updatePlanWithValidation(planId, planData[ii])
525
+ t.fail('Key type validation successfully threw an error')
526
+ } catch (err) {
527
+ t.equal(
528
+ err.toString(),
529
+ 'Error: Plan key must contain only lowercase letters, numbers, and hyphens',
530
+ `displayName validation detected bad data: ${planData[ii].name} with ${err}`
531
+ )
532
+ }
533
+ sandbox.restore()
534
+ t.end()
535
+ })
536
+ }
537
+ }
213
538
 
214
- keyValidation()
215
- priceValidation()
539
+ amountValidation()
540
+ displayNameValidation()
541
+ intervalValidation()
542
+ keyFormatValidation()
543
+ keyTypeValidation()
544
+ lookupKeyValidation()
216
545
  planIdEmptyOrNotAString()
217
546
  planDataEmptyOrNotAnObject()
547
+ pricingOptionsValidation()
548
+ topLevelKeyValidation()
218
549
  // #endregion
219
550
 
220
551
  // #region Cleanup