@rebilly/instruments 2.0.0-beta → 3.0.1-beta.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.
Files changed (197) hide show
  1. package/dist/events/index.js +2 -1
  2. package/dist/functions/mount/fetch-data.js +187 -0
  3. package/dist/functions/mount/fetch-data.spec.js +189 -0
  4. package/dist/functions/mount/index.js +132 -164
  5. package/dist/functions/mount/mount.spec.js +2 -4
  6. package/dist/functions/mount/setup-element.js +40 -0
  7. package/dist/functions/mount/setup-framepay-theme.js +95 -0
  8. package/dist/functions/mount/setup-framepay.js +5 -1
  9. package/dist/functions/mount/setup-i18n.js +33 -0
  10. package/dist/functions/mount/setup-options.js +68 -47
  11. package/dist/functions/mount/setup-options.spec.js +66 -0
  12. package/dist/functions/mount/setup-storefront.js +6 -4
  13. package/dist/functions/mount/setup-styles.js +4 -2
  14. package/dist/functions/purchase.js +129 -24
  15. package/dist/functions/purchase.spec.js +13 -10
  16. package/dist/functions/setup.js +85 -0
  17. package/dist/functions/setup.spec.js +87 -0
  18. package/dist/functions/show.js +8 -4
  19. package/dist/functions/show.spec.js +9 -5
  20. package/dist/functions/update.js +39 -24
  21. package/dist/functions/update.spec.js +0 -4
  22. package/dist/i18n/en.json +5 -2
  23. package/dist/i18n/es.json +4 -1
  24. package/dist/index.js +17 -3
  25. package/dist/index.spec.js +3 -16
  26. package/dist/loader/index.js +4 -3
  27. package/dist/storefront/index.js +33 -0
  28. package/dist/storefront/invoices.js +27 -0
  29. package/dist/storefront/models/base-model.js +18 -0
  30. package/dist/storefront/models/invoice-model.js +14 -0
  31. package/dist/storefront/models/plan-model.js +4 -35
  32. package/dist/storefront/models/product-model.js +4 -23
  33. package/dist/storefront/models/summary-model.js +12 -25
  34. package/dist/storefront/models/transaction-model.js +31 -0
  35. package/dist/storefront/payment-instruments.js +47 -0
  36. package/dist/storefront/payment-instruments.spec.js +55 -0
  37. package/dist/storefront/plans.js +10 -18
  38. package/dist/storefront/plans.spec.js +3 -13
  39. package/dist/storefront/products.js +10 -13
  40. package/dist/storefront/products.spec.js +12 -19
  41. package/dist/storefront/purchase.js +23 -12
  42. package/dist/storefront/purchase.spec.js +1 -20
  43. package/dist/storefront/ready-to-pay.js +18 -15
  44. package/dist/storefront/ready-to-pay.spec.js +2 -12
  45. package/dist/storefront/summary.js +21 -17
  46. package/dist/storefront/summary.spec.js +4 -15
  47. package/dist/storefront/transactions.js +27 -0
  48. package/dist/style/base/__snapshots__/theme.spec.js.snap +188 -45
  49. package/dist/style/base/default-theme.js +699 -0
  50. package/dist/style/base/index.js +48 -16
  51. package/dist/style/base/theme.js +16 -48
  52. package/dist/style/base/theme.spec.js +4 -15
  53. package/dist/style/components/address.js +3 -3
  54. package/dist/style/components/button.js +32 -22
  55. package/dist/style/components/divider.js +9 -9
  56. package/dist/style/components/forms/checkbox.js +12 -9
  57. package/dist/style/components/forms/field.js +18 -6
  58. package/dist/style/components/forms/form.js +2 -2
  59. package/dist/style/components/forms/input.js +54 -13
  60. package/dist/style/components/forms/label.js +39 -18
  61. package/dist/style/components/forms/select.js +54 -22
  62. package/dist/style/components/forms/validation.js +53 -6
  63. package/dist/style/components/icons.js +4 -4
  64. package/dist/style/components/loader.js +5 -3
  65. package/dist/style/components/methods.js +18 -15
  66. package/dist/style/components/overlay.js +5 -5
  67. package/dist/style/helpers/index.js +46 -46
  68. package/dist/style/index.js +3 -1
  69. package/dist/style/payment-instruments/payment-card.js +4 -4
  70. package/dist/style/utils/border.js +47 -0
  71. package/dist/style/utils/color-values.js +39 -3
  72. package/dist/style/utils/remove-empty-null.js +20 -0
  73. package/dist/style/vendor/framepay.js +11 -8
  74. package/dist/style/vendor/postmate.js +2 -2
  75. package/dist/style/views/confirmation.js +13 -13
  76. package/dist/style/views/method-selector.js +2 -2
  77. package/dist/style/views/modal.js +6 -6
  78. package/dist/style/views/result.js +4 -4
  79. package/dist/style/views/summary.js +26 -22
  80. package/dist/views/__snapshots__/summary.spec.js.snap +77 -119
  81. package/dist/views/common/iframe/base-iframe.js +2 -0
  82. package/dist/views/common/iframe/modal-iframe.js +50 -4
  83. package/dist/views/confirmation.js +19 -8
  84. package/dist/views/method-selector/generate-digital-wallet.js +12 -3
  85. package/dist/views/method-selector/generate-digital-wallet.spec.js +11 -0
  86. package/dist/views/method-selector/get-payment-methods.js +13 -2
  87. package/dist/views/method-selector/get-payment-methods.spec.js +21 -19
  88. package/dist/views/method-selector/index.js +23 -34
  89. package/dist/views/method-selector/method-selector.spec.js +50 -55
  90. package/dist/views/method-selector/mount-methods.js +5 -8
  91. package/dist/views/modal.js +8 -2
  92. package/dist/views/result.js +3 -4
  93. package/dist/views/summary.js +156 -97
  94. package/dist/views/summary.spec.js +53 -58
  95. package/package.json +4 -2
  96. package/src/events/index.js +2 -1
  97. package/src/functions/mount/fetch-data.js +152 -0
  98. package/src/functions/mount/fetch-data.spec.js +238 -0
  99. package/src/functions/mount/index.js +101 -158
  100. package/src/functions/mount/mount.spec.js +3 -5
  101. package/src/functions/mount/setup-element.js +26 -0
  102. package/src/functions/mount/setup-framepay-theme.js +82 -0
  103. package/src/functions/mount/setup-framepay.js +5 -1
  104. package/src/functions/mount/setup-i18n.js +19 -0
  105. package/src/functions/mount/setup-options.js +78 -48
  106. package/src/functions/mount/setup-options.spec.js +60 -0
  107. package/src/functions/mount/setup-storefront.js +6 -4
  108. package/src/functions/mount/setup-styles.js +4 -2
  109. package/src/functions/on.spec.js +1 -1
  110. package/src/functions/purchase.js +99 -23
  111. package/src/functions/purchase.spec.js +10 -10
  112. package/src/functions/setup.js +48 -0
  113. package/src/functions/setup.spec.js +98 -0
  114. package/src/functions/show.js +2 -4
  115. package/src/functions/show.spec.js +3 -4
  116. package/src/functions/update.js +40 -25
  117. package/src/functions/update.spec.js +0 -4
  118. package/src/i18n/en.json +5 -2
  119. package/src/i18n/es.json +4 -1
  120. package/src/index.js +9 -3
  121. package/src/index.spec.js +3 -21
  122. package/src/loader/index.js +3 -3
  123. package/src/storefront/index.js +28 -0
  124. package/src/storefront/invoices.js +11 -0
  125. package/src/storefront/models/base-model.js +10 -0
  126. package/src/storefront/models/invoice-model.js +3 -0
  127. package/src/storefront/models/plan-model.js +3 -35
  128. package/src/storefront/models/product-model.js +3 -23
  129. package/src/storefront/models/summary-model.js +12 -19
  130. package/src/storefront/models/transaction-model.js +19 -0
  131. package/src/storefront/payment-instruments.js +30 -0
  132. package/src/storefront/payment-instruments.spec.js +69 -0
  133. package/src/storefront/plans.js +6 -17
  134. package/src/storefront/plans.spec.js +4 -11
  135. package/src/storefront/products.js +8 -16
  136. package/src/storefront/products.spec.js +16 -22
  137. package/src/storefront/purchase.js +14 -16
  138. package/src/storefront/purchase.spec.js +2 -14
  139. package/src/storefront/ready-to-pay.js +13 -16
  140. package/src/storefront/ready-to-pay.spec.js +3 -10
  141. package/src/storefront/summary.js +19 -17
  142. package/src/storefront/summary.spec.js +5 -12
  143. package/src/storefront/transactions.js +11 -0
  144. package/src/style/base/__snapshots__/theme.spec.js.snap +188 -45
  145. package/src/style/base/default-theme.js +674 -0
  146. package/src/style/base/index.js +48 -16
  147. package/src/style/base/theme.js +17 -47
  148. package/src/style/base/theme.spec.js +4 -16
  149. package/src/style/components/address.js +3 -3
  150. package/src/style/components/button.js +32 -24
  151. package/src/style/components/divider.js +9 -9
  152. package/src/style/components/forms/checkbox.js +11 -11
  153. package/src/style/components/forms/field.js +18 -6
  154. package/src/style/components/forms/form.js +2 -2
  155. package/src/style/components/forms/input.js +54 -13
  156. package/src/style/components/forms/label.js +39 -18
  157. package/src/style/components/forms/select.js +54 -22
  158. package/src/style/components/forms/validation.js +53 -6
  159. package/src/style/components/icons.js +4 -4
  160. package/src/style/components/loader.js +4 -5
  161. package/src/style/components/methods.js +18 -15
  162. package/src/style/components/overlay.js +5 -5
  163. package/src/style/helpers/index.js +46 -46
  164. package/src/style/index.js +2 -1
  165. package/src/style/payment-instruments/payment-card.js +4 -4
  166. package/src/style/utils/border.js +34 -0
  167. package/src/style/utils/color-values.js +27 -1
  168. package/src/style/utils/remove-empty-null.js +10 -0
  169. package/src/style/vendor/framepay.js +11 -8
  170. package/src/style/vendor/postmate.js +2 -2
  171. package/src/style/views/confirmation.js +13 -13
  172. package/src/style/views/method-selector.js +2 -2
  173. package/src/style/views/modal.js +6 -6
  174. package/src/style/views/result.js +4 -4
  175. package/src/style/views/summary.js +26 -22
  176. package/src/views/__snapshots__/summary.spec.js.snap +77 -119
  177. package/src/views/common/iframe/base-iframe.js +2 -0
  178. package/src/views/common/iframe/modal-iframe.js +45 -3
  179. package/src/views/confirmation.js +15 -5
  180. package/src/views/method-selector/generate-digital-wallet.js +10 -3
  181. package/src/views/method-selector/generate-digital-wallet.spec.js +10 -0
  182. package/src/views/method-selector/get-payment-methods.js +7 -2
  183. package/src/views/method-selector/get-payment-methods.spec.js +26 -23
  184. package/src/views/method-selector/index.js +21 -28
  185. package/src/views/method-selector/method-selector.spec.js +49 -64
  186. package/src/views/method-selector/mount-methods.js +5 -8
  187. package/src/views/modal.js +6 -2
  188. package/src/views/result.js +4 -3
  189. package/src/views/summary.js +161 -117
  190. package/src/views/summary.spec.js +60 -75
  191. package/tests/mocks/rebilly-instruments-mock.js +37 -7
  192. package/tests/mocks/storefront-api-mock.js +8 -0
  193. package/tests/mocks/storefront-mock.js +17 -0
  194. package/dist/functions/mount/fetch-summary-data.js +0 -46
  195. package/dist/functions/mount/fetch-summary-data.spec.js +0 -43
  196. package/src/functions/mount/fetch-summary-data.js +0 -29
  197. package/src/functions/mount/fetch-summary-data.spec.js +0 -40
package/src/index.spec.js CHANGED
@@ -4,14 +4,6 @@ import { avoidUnhandledPromises } from 'tests/async-utilities';
4
4
  describe('RebillyInstruments instance', () => {
5
5
  let rebillyInstruments;
6
6
 
7
- function setupInstance(
8
- options = {
9
- test: 'value'
10
- }
11
- ) {
12
- rebillyInstruments.mount(options);
13
- }
14
-
15
7
  beforeEach(() => {
16
8
  rebillyInstruments = RebillyInstruments;
17
9
  });
@@ -30,24 +22,14 @@ describe('RebillyInstruments instance', () => {
30
22
 
31
23
  const options = {
32
24
  form: '.form-selector',
33
- test: 'value'
25
+ summary: '.summary-selector',
26
+ items: []
34
27
  };
35
28
 
36
- setupInstance(options);
29
+ await rebillyInstruments.mount(options);
37
30
 
38
31
  expect(rebillyInstruments.mount).toHaveBeenCalledTimes(1);
39
32
  expect(rebillyInstruments.mount).toHaveBeenCalledWith(options);
40
33
  await avoidUnhandledPromises();
41
34
  });
42
-
43
- it('should be able to trigger a purchase', () => {
44
- jest.spyOn(rebillyInstruments, 'purchase');
45
-
46
- const instrument = {};
47
-
48
- setupInstance();
49
- rebillyInstruments.purchase(instrument);
50
-
51
- expect(rebillyInstruments.purchase).toHaveBeenCalledTimes(1);
52
- });
53
35
  });
@@ -15,17 +15,15 @@ export class Loader {
15
15
  }
16
16
 
17
17
  addDOMElement({ section = 'form', el = null } = {}) {
18
- const minHeight = '200px';
19
-
20
18
  if (isDOMElement(el)) {
21
19
  el.style.position = 'relative';
22
- el.style.minHeight = minHeight;
23
20
 
24
21
  this.DOM[section] = el;
25
22
  }
26
23
  }
27
24
 
28
25
  startLoading({ section = 'form', id = '' } = {}) {
26
+ const minHeight = '200px';
29
27
  this[section].push(id);
30
28
 
31
29
  if (this.DOM?.[section]) {
@@ -36,6 +34,7 @@ export class Loader {
36
34
  .querySelector('.rebilly-instruments-loader')
37
35
  .classList.add('is-active');
38
36
  }
37
+ this.DOM[section].style.minHeight = minHeight;
39
38
  }
40
39
  }
41
40
 
@@ -53,6 +52,7 @@ export class Loader {
53
52
  this.DOM[section]
54
53
  .querySelector('.rebilly-instruments-loader')
55
54
  .classList.remove('is-active');
55
+ this.DOM[section].style.minHeight = '';
56
56
  }
57
57
  }
58
58
 
@@ -1,5 +1,33 @@
1
1
  import { RebillyStorefrontAPI } from 'rebilly-js-sdk';
2
2
 
3
+ export function validateStateForStorefront({state}) {
4
+ if (!state.storefront) {
5
+ throw new Error('Could not access rebilly-js-sdk instance');
6
+ }
7
+
8
+ if (!state.options) {
9
+ throw new Error(
10
+ 'Could not use Rebilly Instruments mount options to fetch Rebilly data'
11
+ );
12
+ }
13
+ }
14
+
15
+ export async function Endpoint({
16
+ state
17
+ } = {}, callback) {
18
+ try {
19
+ validateStateForStorefront({state});
20
+ return await callback();
21
+ } catch(error) {
22
+ // TODO: standard error handling for all endpoints
23
+ // console.error(error);
24
+ if(error.status === 422) {
25
+ error.details.forEach(e => console.error(e));
26
+ }
27
+ throw error;
28
+ }
29
+ }
30
+
3
31
  export class StorefrontInstance {
4
32
  constructor({
5
33
  publishableKey = null,
@@ -0,0 +1,11 @@
1
+ import InvoiceModel from './models/invoice-model';
2
+ import { Endpoint } from './index';
3
+
4
+ export async function fetchInvoice({ data = null, state = null }) {
5
+ return Endpoint({state}, async () => {
6
+ state.storefront.setSessionToken(state.options.customerJwt);
7
+ const {fields} = await state.storefront.invoices.get(data);
8
+
9
+ return new InvoiceModel(fields);
10
+ });
11
+ }
@@ -0,0 +1,10 @@
1
+ export default class BaseModel {
2
+ constructor({
3
+ ...fields
4
+ } = {}) {
5
+ Object.entries(fields)
6
+ .forEach(([key, value]) => {
7
+ this[key] = value;
8
+ })
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ import BaseModel from './base-model';
2
+
3
+ export default class InvoiceModel extends BaseModel {}
@@ -1,35 +1,3 @@
1
- export default class PlanModel {
2
- constructor({
3
- id = '',
4
- name = '',
5
- productId = '',
6
- productOptions = {},
7
- currency = '',
8
- currencySign = '',
9
- pricing = {},
10
- recurringInterval = {},
11
- trial = null,
12
- isTrialOnly = false,
13
- setup = null,
14
- customFields = {},
15
- createdTime = '',
16
- updatedTime = '',
17
- invoiceTimeShift = {}
18
- } = {}) {
19
- this.id = id;
20
- this.name = name;
21
- this.productId = productId;
22
- this.productOptions = productOptions;
23
- this.currency = currency;
24
- this.currencySign = currencySign;
25
- this.pricing = pricing;
26
- this.recurringInterval = recurringInterval;
27
- this.trial = trial;
28
- this.isTrialOnly = isTrialOnly;
29
- this.setup = setup;
30
- this.customFields = customFields;
31
- this.createdTime = createdTime;
32
- this.updatedTime = updatedTime;
33
- this.invoiceTimeShift = invoiceTimeShift;
34
- }
35
- }
1
+ import BaseModel from './base-model';
2
+
3
+ export default class PlanModel extends BaseModel {}
@@ -1,23 +1,3 @@
1
- export default class ProductModel {
2
- constructor({
3
- id = '',
4
- name = '',
5
- unitLabel = '',
6
- description = {},
7
- requiresShipping = false,
8
- options = [],
9
- customFields = {},
10
- createdTime = '',
11
- updatedTime = ''
12
- } = {}) {
13
- this.id = id;
14
- this.name = name;
15
- this.unitLabel = unitLabel;
16
- this.description = description;
17
- this.requiresShipping = requiresShipping;
18
- this.options = options;
19
- this.customFields = customFields;
20
- this.createdTime = createdTime;
21
- this.updatedTime = updatedTime;
22
- }
23
- }
1
+ import BaseModel from './base-model';
2
+
3
+ export default class ProductModel extends BaseModel {}
@@ -1,35 +1,28 @@
1
- export class SummaryLineItemModel {
1
+ import BaseModel from './base-model';
2
+
3
+ export class SummaryLineItemModel extends BaseModel {
2
4
  constructor({
3
- type = '',
4
- description = '',
5
5
  unitPrice = 0.0,
6
6
  quantity = 0,
7
7
  price = 0.0,
8
- planId = '',
9
- productId = ''
8
+ ...fields
10
9
  } = {}) {
11
- this.type = type;
12
- this.description = description;
10
+ super(fields);
13
11
  this.unitPrice = unitPrice;
14
12
  this.quantity = quantity;
15
13
  this.price = price;
16
- this.planId = planId;
17
- this.productId = productId;
18
14
  }
19
15
  }
20
16
 
21
- export class SummaryTaxModel {
22
- constructor({ amount = '', description = '' } = {}) {
23
- this.amount = amount;
24
- this.description = description;
25
- }
26
- }
17
+ export class SummaryTaxModel extends BaseModel {}
27
18
 
28
- export class SummaryDiscountModel {
29
- constructor({ couponId = '', amount = 0, description = '' } = {}) {
30
- this.couponId = couponId;
19
+ export class SummaryDiscountModel extends BaseModel {
20
+ constructor({
21
+ amount = 0,
22
+ ...fields
23
+ }) {
24
+ super(fields);
31
25
  this.amount = amount;
32
- this.description = description;
33
26
  }
34
27
  }
35
28
 
@@ -0,0 +1,19 @@
1
+ import BaseModel from './base-model';
2
+
3
+ export default class TransactionModel extends BaseModel {
4
+ constructor({
5
+ invoiceIds = [],
6
+ ...fields
7
+ }) {
8
+ super(fields);
9
+ this.invoiceIds = invoiceIds || [];
10
+ }
11
+
12
+ get invoiceId () {
13
+ return this.invoiceIds[0] || null;
14
+ }
15
+
16
+ get hasInvoice () {
17
+ return !!this.invoiceId;
18
+ }
19
+ }
@@ -0,0 +1,30 @@
1
+ import { Endpoint } from './index';
2
+
3
+ export async function setupPaymentInstrument({ data, state }) {
4
+ return Endpoint({state}, async () => {
5
+ // Create payment instrument
6
+ const { fields: instrument } = await state.storefront.paymentInstruments.create({data});
7
+
8
+ // Setup the payment instrument
9
+ state.storefront.setSessionToken(instrument.token);
10
+
11
+ const setupPayload = {
12
+ id: instrument.id,
13
+ data: {
14
+ websiteId: state.options.websiteId,
15
+ ...data
16
+ }
17
+ }
18
+
19
+ if(state.data.getAmountAndCurrency) {
20
+ setupPayload.data = {
21
+ ...setupPayload.data,
22
+ ...state.data.getAmountAndCurrency
23
+ }
24
+ }
25
+
26
+ const { fields: transaction } = await state.storefront.paymentInstruments.setup(setupPayload);
27
+
28
+ return {instrument, transaction};
29
+ });
30
+ }
@@ -0,0 +1,69 @@
1
+ import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
2
+ import { ok, post } from 'msw-when-then';
3
+ import { when } from 'tests/msw/server';
4
+ import { storefrontURL } from 'tests/mocks/storefront-api-mock';
5
+
6
+ describe('Storefront API Setup', () => {
7
+ it('can make purchase', async () => {
8
+ const instance = new StorefontTestingInstance();
9
+
10
+ const paymentInstrumentFields = {
11
+ id: 'payment-instrument-id'
12
+ };
13
+
14
+ const paymentInstrumentSetupFields = {
15
+ id: 'payment-instrument-id',
16
+ approvalUrl: null
17
+ };
18
+
19
+ const paymentInstrumentPayload = {
20
+ data: {
21
+ token: 'test-token'
22
+ }
23
+ };
24
+
25
+ const paymentInstrumentSetupPayload = {
26
+ id: paymentInstrumentFields.id,
27
+ data: {
28
+ websiteId: 'website-id',
29
+ currency: 'USD',
30
+ amount: 30
31
+ }
32
+ };
33
+
34
+ when(post(`${storefrontURL}/payment-instruments`)).thenReturn(ok(paymentInstrumentFields));
35
+ when(post(`${storefrontURL}/payment-instruments/*/setup`)).thenReturn(ok(paymentInstrumentSetupFields));
36
+
37
+
38
+ jest.spyOn(instance.storefront.paymentInstruments, 'create');
39
+ jest.spyOn(instance.storefront.paymentInstruments, 'setup');
40
+
41
+ const paymentInstrumentResponse = await instance.storefront.paymentInstruments.create(
42
+ paymentInstrumentPayload
43
+ );
44
+
45
+ const paymentInstrumentSetupResponse = await instance.storefront.paymentInstruments.setup(
46
+ paymentInstrumentSetupPayload
47
+ );
48
+
49
+ expect(instance.storefront.paymentInstruments.create).toBeCalledTimes(1);
50
+ expect(instance.storefront.paymentInstruments.create).toBeCalledWith(paymentInstrumentPayload);
51
+
52
+ expect(instance.storefront.paymentInstruments.setup).toBeCalledTimes(1);
53
+ expect(instance.storefront.paymentInstruments.setup).toBeCalledWith(paymentInstrumentSetupPayload);
54
+
55
+ expect(paymentInstrumentResponse.config).toBeInstanceOf(Object);
56
+ expect(paymentInstrumentResponse.fields).toBeInstanceOf(Object);
57
+ expect(paymentInstrumentResponse.response).toBeInstanceOf(Object);
58
+
59
+ expect(paymentInstrumentResponse.fields).toEqual(paymentInstrumentFields);
60
+ expect(paymentInstrumentResponse.fields).toMatchObject(paymentInstrumentFields);
61
+
62
+ expect(paymentInstrumentSetupResponse.config).toBeInstanceOf(Object);
63
+ expect(paymentInstrumentSetupResponse.fields).toBeInstanceOf(Object);
64
+ expect(paymentInstrumentSetupResponse.response).toBeInstanceOf(Object);
65
+
66
+ expect(paymentInstrumentSetupResponse.fields).toEqual(paymentInstrumentSetupFields);
67
+ expect(paymentInstrumentSetupResponse.fields).toMatchObject(paymentInstrumentSetupFields);
68
+ });
69
+ });
@@ -1,24 +1,15 @@
1
1
  import PlanModel from './models/plan-model';
2
+ import { Endpoint } from './index';
2
3
 
3
- export async function fetchPlans({ data = null, state = null }) {
4
- if (!state.storefront) {
5
- throw new Error('Could not access rebilly-js-sdk instance');
6
- }
7
-
8
- if (!state.options) {
9
- throw new Error(
10
- 'Could not use Rebilly Instruments mount options to fetch Rebilly data'
11
- );
12
- }
13
-
14
- try {
15
- const { lineItems } = data || {};
4
+ export async function fetchPlans({ state = {}, data = {} }) {
5
+ return Endpoint({state}, async () => {
6
+ const lineItems = data.lineItems || state.data.summaryLineItems;
16
7
 
17
8
  const filterByPlanId = {
18
9
  filter: ''
19
10
  };
20
11
 
21
- if (lineItems) {
12
+ if (lineItems.length) {
22
13
  filterByPlanId.filter = `id:${lineItems
23
14
  .map((item) => item.planId)
24
15
  .join(',')}`;
@@ -28,7 +19,5 @@ export async function fetchPlans({ data = null, state = null }) {
28
19
  filterByPlanId
29
20
  );
30
21
  return planItems.map(({ fields }) => new PlanModel(fields));
31
- } catch (error) {
32
- throw error;
33
- }
22
+ });
34
23
  }
@@ -1,4 +1,4 @@
1
- import { MockStorefront } from 'tests/mocks/storefront-mock';
1
+ import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
2
2
  import { ok, get } from 'msw-when-then';
3
3
  import { when } from 'tests/msw/server';
4
4
  import { storefrontURL } from 'tests/mocks/storefront-api-mock';
@@ -7,19 +7,12 @@ import PlanModel from './models/plan-model';
7
7
  import { expectConfigurationError } from 'tests/async-utilities';
8
8
 
9
9
  describe('Storefront API Plan', () => {
10
- class TestPlansInstance {
11
- constructor({ options = {} } = {}) {
12
- this.options = options;
13
- this.storefront = MockStorefront();
14
- }
15
- }
16
-
17
10
  it('can fetch plans', async () => {
18
11
  const testPlan = { name: 'Test Plan', id: 'test-plan-id-1' };
19
12
 
20
13
  when(get(`${storefrontURL}/plans`)).thenReturn(ok([testPlan]));
21
14
 
22
- const instance = new TestPlansInstance();
15
+ const instance = new StorefontTestingInstance();
23
16
 
24
17
  jest.spyOn(instance.storefront.plans, 'getAll');
25
18
 
@@ -35,7 +28,7 @@ describe('Storefront API Plan', () => {
35
28
  });
36
29
 
37
30
  it('can fetch plans with filter', async () => {
38
- const instance = new TestPlansInstance();
31
+ const instance = new StorefontTestingInstance();
39
32
 
40
33
  jest.spyOn(instance.storefront.plans, 'getAll');
41
34
 
@@ -59,7 +52,7 @@ describe('Storefront API Plan', () => {
59
52
  });
60
53
 
61
54
  it('should throw errors with no options', async () => {
62
- const noConfigOrOptionsInstance = new TestPlansInstance({
55
+ const noConfigOrOptionsInstance = new StorefontTestingInstance({
63
56
  options: null
64
57
  });
65
58
  await expectConfigurationError(
@@ -1,19 +1,13 @@
1
1
  import ProductModel from './models/product-model';
2
+ import { Endpoint } from './index';
2
3
 
3
- export async function fetchProducts({ data = null, state }) {
4
- if (!state.storefront) {
5
- throw new Error('Could not access rebilly-js-sdk instance');
6
- }
7
-
8
- if (!state.options) {
9
- throw new Error(
10
- 'Could not use Rebilly Instruments mount options to fetch Rebilly data'
11
- );
12
- }
13
-
14
- try {
15
- const plansData = data || [];
4
+ export async function fetchProducts({ state }) {
5
+ return Endpoint({state}, async () => {
6
+ if (state.data.plans === null) {
7
+ return null;
8
+ }
16
9
 
10
+ const plansData = state.data.plans || [];
17
11
  const filterByProductId = {
18
12
  filter: ''
19
13
  };
@@ -28,7 +22,5 @@ export async function fetchProducts({ data = null, state }) {
28
22
  filterByProductId
29
23
  );
30
24
  return productItems.map(({ fields }) => new ProductModel(fields));
31
- } catch (error) {
32
- throw error;
33
- }
25
+ });
34
26
  }
@@ -1,4 +1,4 @@
1
- import { MockStorefront } from 'tests/mocks/storefront-mock';
1
+ import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
2
2
  import { ok, get } from 'msw-when-then';
3
3
  import { when } from 'tests/msw/server';
4
4
  import { storefrontURL } from 'tests/mocks/storefront-api-mock';
@@ -7,19 +7,12 @@ import ProductModel from './models/product-model';
7
7
  import { expectConfigurationError } from 'tests/async-utilities';
8
8
 
9
9
  describe('Storefront API Plan', () => {
10
- class TestProductsInstance {
11
- constructor({ options = {} } = {}) {
12
- this.options = options;
13
- this.storefront = MockStorefront();
14
- }
15
- }
16
-
17
10
  it('can fetch products', async () => {
18
11
  const testProduct = { name: 'Test Product', id: 'test-product-id-1' };
19
12
 
20
13
  when(get(`${storefrontURL}/products`)).thenReturn(ok([testProduct]));
21
14
 
22
- const instance = new TestProductsInstance();
15
+ const instance = new StorefontTestingInstance();
23
16
 
24
17
  jest.spyOn(instance.storefront.products, 'getAll');
25
18
 
@@ -35,21 +28,22 @@ describe('Storefront API Plan', () => {
35
28
  });
36
29
 
37
30
  it('can fetch products with filter', async () => {
38
- const instance = new TestProductsInstance();
31
+ const instance = new StorefontTestingInstance({
32
+ data: {
33
+ plans: [
34
+ {
35
+ productId: 'test-product-1'
36
+ },
37
+ {
38
+ productId: 'test-product-2'
39
+ }
40
+ ]
41
+ }
42
+ });
39
43
 
40
44
  jest.spyOn(instance.storefront.products, 'getAll');
41
45
 
42
- await fetchProducts({
43
- state: instance,
44
- data: [
45
- {
46
- productId: 'test-product-1'
47
- },
48
- {
49
- productId: 'test-product-2'
50
- }
51
- ]
52
- });
46
+ await fetchProducts({ state: instance });
53
47
 
54
48
  expect(instance.storefront.products.getAll).toBeCalledWith({
55
49
  filter: 'id:test-product-1,test-product-2'
@@ -57,7 +51,7 @@ describe('Storefront API Plan', () => {
57
51
  });
58
52
 
59
53
  it('should throw errors with no options', async () => {
60
- const noConfigOrOptionsInstance = new TestProductsInstance({
54
+ const noConfigOrOptionsInstance = new StorefontTestingInstance({
61
55
  options: null
62
56
  });
63
57
  await expectConfigurationError(
@@ -1,21 +1,19 @@
1
- export async function postPurchase({ data, state }) {
2
- if (!state.storefront) {
3
- throw new Error('Could not access rebilly-js-sdk instance');
4
- }
5
-
6
- if (!state.options) {
7
- throw new Error(
8
- 'Could not use Rebilly Instruments mount options to fetch Rebilly data'
9
- );
10
- }
1
+ import { Endpoint } from './index';
11
2
 
12
- try {
3
+ export async function postPurchase({ data, state }) {
4
+ return Endpoint({state}, async () => {
13
5
  if (data._raw) {
14
6
  delete data._raw;
15
7
  }
16
- const resp = await state.storefront.purchase.purchase({ data });
17
- return resp;
18
- } catch (error) {
19
- throw error;
20
- }
8
+ return state.storefront.purchase.purchase({ data });
9
+ });
21
10
  }
11
+
12
+ export async function postPayment({ data, state }) {
13
+ return Endpoint({state}, async () => {
14
+ if (data._raw) {
15
+ delete data._raw;
16
+ }
17
+ return state.storefront.purchase.payment({ data });
18
+ });
19
+ }
@@ -1,23 +1,11 @@
1
- import { MockStorefront } from 'tests/mocks/storefront-mock';
1
+ import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
2
2
  import { ok, post } from 'msw-when-then';
3
3
  import { when } from 'tests/msw/server';
4
4
  import { storefrontURL } from 'tests/mocks/storefront-api-mock';
5
- import { postPurchase } from './purchase';
6
5
 
7
6
  describe('Storefront API Purchase', () => {
8
- class TestPurchaseInstance {
9
- constructor({ options = {} } = {}) {
10
- this.options = options;
11
- this.storefront = MockStorefront();
12
- }
13
-
14
- postPurchase(...args) {
15
- return postPurchase({ state: this, data: args });
16
- }
17
- }
18
-
19
7
  it('can make purchase', async () => {
20
- const instance = new TestPurchaseInstance();
8
+ const instance = StorefontTestingInstance();
21
9
  const payload = {
22
10
  websiteId: 'test-website-id',
23
11
  items: [
@@ -1,31 +1,30 @@
1
1
  import { collectData } from '@rebilly/risk-data-collector';
2
2
  import ReadyToPayModel from './models/ready-to-pay-model';
3
+ import { Endpoint } from './index';
3
4
 
4
5
  export async function fetchReadyToPay({ state, riskMetadata = null }) {
5
- if (!state.storefront) {
6
- throw new Error('Could not access rebilly-js-sdk instance');
7
- }
8
-
9
- if (!state.options) {
10
- throw new Error(
11
- 'Could not use Rebilly Instruments mount options to fetch Rebilly data'
12
- );
13
- }
14
-
15
- try {
6
+ return Endpoint({state}, async () => {
16
7
  if (!riskMetadata) {
17
8
  const { riskMetadata: data } = await collectData();
18
9
  riskMetadata = data;
19
10
  }
20
11
  const websiteId = state.options?.websiteId || null;
21
- const items = state.options?.items || [];
22
12
 
23
13
  const data = {
24
- items,
25
14
  websiteId,
26
15
  riskMetadata
27
16
  };
28
17
 
18
+ if (state.options?.items) {
19
+ data.items = state.options.items;
20
+ }
21
+
22
+ if (state.data?.amountAndCurrency) {
23
+ const money = state.data.amountAndCurrency;
24
+ data.amount = money.amount;
25
+ data.currency = money.currency;
26
+ }
27
+
29
28
  const { fields: readyToPayFields } =
30
29
  await state.storefront.purchase.readyToPay({ data });
31
30
 
@@ -36,7 +35,5 @@ export async function fetchReadyToPay({ state, riskMetadata = null }) {
36
35
  ...fields
37
36
  })
38
37
  );
39
- } catch (error) {
40
- throw error;
41
- }
38
+ });
42
39
  }