@rebilly/instruments 1.0.2-beta.8 → 2.1.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 (211) hide show
  1. package/.babelrc +13 -4
  2. package/.eslintrc.js +3 -0
  3. package/.prettierrc.js +11 -0
  4. package/README.md +15 -314
  5. package/dist/events/base-event.js +6 -9
  6. package/dist/events/events.spec.js +4 -4
  7. package/dist/events/index.js +2 -1
  8. package/dist/functions/destroy.js +12 -14
  9. package/dist/functions/destroy.spec.js +3 -3
  10. package/dist/functions/mount/fetch-data.js +183 -0
  11. package/dist/functions/mount/fetch-data.spec.js +189 -0
  12. package/dist/functions/mount/index.js +158 -251
  13. package/dist/functions/mount/mount.spec.js +24 -121
  14. package/dist/functions/mount/setup-element.js +40 -0
  15. package/dist/functions/mount/setup-framepay.js +46 -0
  16. package/dist/functions/mount/setup-i18n.js +33 -0
  17. package/dist/functions/mount/setup-options.js +96 -0
  18. package/dist/functions/mount/setup-options.spec.js +66 -0
  19. package/dist/functions/mount/setup-storefront.js +34 -0
  20. package/dist/functions/mount/setup-styles.js +43 -0
  21. package/dist/functions/on.js +13 -4
  22. package/dist/functions/on.spec.js +19 -5
  23. package/dist/functions/purchase.js +139 -22
  24. package/dist/functions/purchase.spec.js +23 -19
  25. package/dist/functions/setup.js +85 -0
  26. package/dist/functions/setup.spec.js +87 -0
  27. package/dist/functions/show.js +31 -14
  28. package/dist/functions/show.spec.js +47 -18
  29. package/dist/functions/update.js +53 -27
  30. package/dist/functions/update.spec.js +40 -21
  31. package/dist/i18n/en.json +4 -1
  32. package/dist/i18n/es.json +4 -1
  33. package/dist/index.js +67 -56
  34. package/dist/index.spec.js +7 -27
  35. package/dist/loader/index.js +4 -3
  36. package/dist/storefront/index.js +33 -0
  37. package/dist/storefront/invoices.js +27 -0
  38. package/dist/storefront/models/base-model.js +18 -0
  39. package/dist/storefront/models/invoice-model.js +14 -0
  40. package/dist/storefront/models/plan-model.js +4 -35
  41. package/dist/storefront/models/product-model.js +4 -23
  42. package/dist/storefront/models/summary-model.js +12 -25
  43. package/dist/storefront/models/transaction-model.js +31 -0
  44. package/dist/storefront/payment-instruments.js +47 -0
  45. package/dist/storefront/payment-instruments.spec.js +55 -0
  46. package/dist/storefront/plans.js +15 -24
  47. package/dist/storefront/plans.spec.js +17 -44
  48. package/dist/storefront/products.js +16 -20
  49. package/dist/storefront/products.spec.js +25 -49
  50. package/dist/storefront/purchase.js +28 -16
  51. package/dist/storefront/purchase.spec.js +4 -22
  52. package/dist/storefront/ready-to-pay.js +26 -22
  53. package/dist/storefront/ready-to-pay.spec.js +25 -54
  54. package/dist/storefront/storefront.spec.js +1 -1
  55. package/dist/storefront/summary.js +27 -24
  56. package/dist/storefront/summary.spec.js +44 -86
  57. package/dist/storefront/transactions.js +27 -0
  58. package/dist/style/base/theme.js +3 -3
  59. package/dist/style/components/methods.js +43 -42
  60. package/dist/style/utils/color-values.js +1 -3
  61. package/dist/style/views/confirmation.js +0 -4
  62. package/dist/style/views/method-selector.js +1 -1
  63. package/dist/style/views/modal.js +3 -1
  64. package/dist/style/views/summary.js +5 -1
  65. package/dist/utils/format-currency.js +4 -2
  66. package/dist/utils/has-valid-css-selector.js +1 -1
  67. package/dist/utils/process-property-as-dom-element.js +0 -2
  68. package/dist/views/__snapshots__/summary.spec.js.snap +103 -113
  69. package/dist/views/common/iframe/base-iframe.js +10 -2
  70. package/dist/views/common/iframe/modal-iframe.js +44 -3
  71. package/dist/views/confirmation.js +44 -20
  72. package/dist/views/method-selector/express-methods/apple-pay.js +92 -0
  73. package/dist/views/method-selector/express-methods/google-pay.js +31 -0
  74. package/dist/views/method-selector/express-methods/paypal.js +19 -0
  75. package/dist/views/method-selector/generate-digital-wallet.js +68 -0
  76. package/dist/views/method-selector/generate-digital-wallet.spec.js +135 -0
  77. package/dist/views/method-selector/get-payment-methods.js +28 -8
  78. package/dist/views/method-selector/get-payment-methods.spec.js +25 -26
  79. package/dist/views/method-selector/index.js +55 -86
  80. package/dist/views/method-selector/method-selector.spec.js +80 -69
  81. package/dist/views/method-selector/mount-express-methods.js +38 -62
  82. package/dist/views/method-selector/mount-methods.js +18 -18
  83. package/dist/views/modal.js +21 -15
  84. package/dist/views/result.js +13 -16
  85. package/dist/views/summary.js +170 -114
  86. package/dist/views/summary.spec.js +72 -76
  87. package/package.json +5 -4
  88. package/src/events/base-event.js +15 -17
  89. package/src/events/events.spec.js +6 -4
  90. package/src/events/index.js +6 -3
  91. package/src/functions/destroy.js +12 -13
  92. package/src/functions/destroy.spec.js +30 -31
  93. package/src/functions/mount/fetch-data.js +148 -0
  94. package/src/functions/mount/fetch-data.spec.js +238 -0
  95. package/src/functions/mount/index.js +129 -244
  96. package/src/functions/mount/mount.spec.js +35 -139
  97. package/src/functions/mount/setup-element.js +26 -0
  98. package/src/functions/mount/setup-framepay.js +41 -0
  99. package/src/functions/mount/setup-i18n.js +19 -0
  100. package/src/functions/mount/setup-options.js +100 -0
  101. package/src/functions/mount/setup-options.spec.js +60 -0
  102. package/src/functions/mount/setup-storefront.js +24 -0
  103. package/src/functions/mount/setup-styles.js +30 -0
  104. package/src/functions/on.js +13 -8
  105. package/src/functions/on.spec.js +30 -17
  106. package/src/functions/purchase.js +101 -19
  107. package/src/functions/purchase.spec.js +18 -18
  108. package/src/functions/setup.js +48 -0
  109. package/src/functions/setup.spec.js +98 -0
  110. package/src/functions/show.js +20 -10
  111. package/src/functions/show.spec.js +43 -22
  112. package/src/functions/update.js +50 -27
  113. package/src/functions/update.spec.js +57 -22
  114. package/src/i18n/en.json +4 -1
  115. package/src/i18n/es.json +4 -1
  116. package/src/i18n/i18n.spec.js +6 -4
  117. package/src/i18n/index.js +14 -11
  118. package/src/index.js +41 -52
  119. package/src/index.spec.js +8 -37
  120. package/src/loader/index.js +51 -47
  121. package/src/loader/loader.spec.js +26 -19
  122. package/src/storefront/index.js +37 -7
  123. package/src/storefront/invoices.js +11 -0
  124. package/src/storefront/models/base-model.js +10 -0
  125. package/src/storefront/models/invoice-model.js +3 -0
  126. package/src/storefront/models/plan-model.js +3 -35
  127. package/src/storefront/models/product-model.js +3 -23
  128. package/src/storefront/models/ready-to-pay-model.js +3 -3
  129. package/src/storefront/models/summary-model.js +15 -29
  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 +16 -23
  134. package/src/storefront/plans.spec.js +25 -54
  135. package/src/storefront/products.js +18 -22
  136. package/src/storefront/products.spec.js +23 -54
  137. package/src/storefront/purchase.js +14 -14
  138. package/src/storefront/purchase.spec.js +17 -29
  139. package/src/storefront/ready-to-pay.js +26 -23
  140. package/src/storefront/ready-to-pay.spec.js +41 -71
  141. package/src/storefront/storefront.spec.js +1 -1
  142. package/src/storefront/summary.js +26 -22
  143. package/src/storefront/summary.spec.js +60 -109
  144. package/src/storefront/transactions.js +11 -0
  145. package/src/style/base/theme.js +10 -8
  146. package/src/style/base/theme.spec.js +4 -2
  147. package/src/style/browserslist.js +1 -3
  148. package/src/style/components/button.js +3 -1
  149. package/src/style/components/forms/checkbox.js +3 -1
  150. package/src/style/components/index.js +1 -1
  151. package/src/style/components/loader.js +3 -1
  152. package/src/style/components/methods.js +43 -42
  153. package/src/style/helpers/index.js +1 -1
  154. package/src/style/index.js +2 -1
  155. package/src/style/utils/color-values.js +4 -4
  156. package/src/style/vendor/framepay.js +1 -1
  157. package/src/style/vendor/postmate.js +1 -1
  158. package/src/style/views/confirmation.js +0 -4
  159. package/src/style/views/index.js +1 -1
  160. package/src/style/views/method-selector.js +1 -1
  161. package/src/style/views/modal.js +4 -2
  162. package/src/style/views/summary.js +5 -1
  163. package/src/utils/add-dom-element.js +12 -13
  164. package/src/utils/format-currency.js +6 -2
  165. package/src/utils/has-valid-css-selector.js +2 -2
  166. package/src/utils/is-dom-element.js +1 -1
  167. package/src/utils/process-property-as-dom-element.js +27 -24
  168. package/src/utils/sleep.js +1 -1
  169. package/src/views/__snapshots__/summary.spec.js.snap +103 -113
  170. package/src/views/common/iframe/base-iframe.js +12 -4
  171. package/src/views/common/iframe/event-listeners.js +6 -6
  172. package/src/views/common/iframe/index.js +1 -1
  173. package/src/views/common/iframe/method-iframe.js +3 -6
  174. package/src/views/common/iframe/modal-iframe.js +42 -6
  175. package/src/views/common/iframe/view-iframe.js +3 -5
  176. package/src/views/common/render-utilities.js +3 -3
  177. package/src/views/confirmation.js +34 -25
  178. package/src/views/method-selector/express-methods/apple-pay.js +78 -0
  179. package/src/views/method-selector/express-methods/google-pay.js +24 -0
  180. package/src/views/method-selector/express-methods/paypal.js +7 -0
  181. package/src/views/method-selector/generate-digital-wallet.js +51 -0
  182. package/src/views/method-selector/generate-digital-wallet.spec.js +135 -0
  183. package/src/views/method-selector/get-method-data.js +7 -4
  184. package/src/views/method-selector/get-payment-methods.js +38 -29
  185. package/src/views/method-selector/get-payment-methods.spec.js +26 -33
  186. package/src/views/method-selector/index.js +70 -99
  187. package/src/views/method-selector/method-selector.spec.js +88 -78
  188. package/src/views/method-selector/mount-express-methods.js +36 -60
  189. package/src/views/method-selector/mount-methods.js +32 -21
  190. package/src/views/modal.js +37 -23
  191. package/src/views/result.js +12 -15
  192. package/src/views/summary.js +169 -101
  193. package/src/views/summary.spec.js +99 -74
  194. package/tests/async-utilities.js +22 -0
  195. package/tests/mocks/rebilly-instruments-mock.js +89 -77
  196. package/tests/mocks/storefront-api-mock.js +8 -0
  197. package/tests/mocks/storefront-mock.js +17 -0
  198. package/dist/events/purchase-completed.js +0 -24
  199. package/dist/functions/initialize.js +0 -82
  200. package/dist/functions/initialize.spec.js +0 -34
  201. package/dist/functions/mount/fetch-summary-data.js +0 -31
  202. package/dist/functions/mount/fetch-summary-data.spec.js +0 -45
  203. package/dist/views/method-selector/process-digital-wallet-options.js +0 -35
  204. package/dist/views/method-selector/process-digital-wallet-options.spec.js +0 -80
  205. package/src/events/purchase-completed.js +0 -11
  206. package/src/functions/initialize.js +0 -74
  207. package/src/functions/initialize.spec.js +0 -38
  208. package/src/functions/mount/fetch-summary-data.js +0 -26
  209. package/src/functions/mount/fetch-summary-data.spec.js +0 -46
  210. package/src/views/method-selector/process-digital-wallet-options.js +0 -16
  211. package/src/views/method-selector/process-digital-wallet-options.spec.js +0 -94
@@ -2,16 +2,18 @@
2
2
  import { collectData } from '@rebilly/risk-data-collector';
3
3
  import { getPaymentMethods } from './get-payment-methods';
4
4
  import { mountExpressMethods } from './mount-express-methods';
5
- import { processDigitalWalletOptions } from './process-digital-wallet-options';
5
+ import { generateDigitalWallet } from './generate-digital-wallet';
6
6
  import { MountMethods } from './mount-methods';
7
- import { FetchSummaryData } from '../../functions/mount/fetch-summary-data';
8
- import Events from '../../events';
7
+ import { fetchData } from '../../functions/mount/fetch-data';
9
8
 
10
9
  export const baseMethodSelectorHTML = (compactExpressInstruments) => `
11
10
  <div class="rebilly-instruments-content">
12
- <div class="rebilly-instruments-method-selector">
13
- <div class="rebilly-instruments-express-methods ${compactExpressInstruments ? 'is-compact' : ''}">
11
+ <div class="rebilly-instruments-method-selector ${compactExpressInstruments ? 'has-express-compact' : ''}">
12
+ <div class="rebilly-instruments-express-methods ${
13
+ compactExpressInstruments ? 'is-compact' : ''
14
+ }">
14
15
  <span data-rebilly-i18n="form.expressCheckout" class="rebilly-instruments-express-methods-label">Express checkout</span>
16
+ <div class="rebilly-instruments-express-methods-container"></div>
15
17
  </div>
16
18
  <div class="rebilly-instruments-divider">
17
19
  <span class="rebilly-instruments-divider-label" data-rebilly-i18n="form.or">Or</span>
@@ -21,112 +23,81 @@ export const baseMethodSelectorHTML = (compactExpressInstruments) => `
21
23
  </div>
22
24
  `;
23
25
 
24
- export function MountMethodSelector(
25
- {
26
- readyToPay,
27
- summary,
28
- plans,
29
- products,
30
- mainStyle
31
- } = {}) {
32
- const {EXPRESS_METHODS, METHODS} = getPaymentMethods.call(this, readyToPay);
33
-
34
- this.form.innerHTML += baseMethodSelectorHTML(this.options.paymentInstruments.compactExpressInstruments);
35
-
36
- const EXPRESS_METHODS_CONTAINER = document.querySelector('.rebilly-instruments-express-methods');
37
- const METHODS_DIVIDER = document.querySelector('.rebilly-instruments-divider');
38
- METHODS_DIVIDER.style.display = METHODS.length && EXPRESS_METHODS.length ? 'block' : 'none';
39
- const METHODS_CONTAINER = document.querySelector('.rebilly-instruments-methods');
40
-
41
- const digitalWallet = {
42
- transactionData: {
43
- amount: summary.total,
44
- currency: summary.currency,
45
- countryCode: this.options.intent.countryCode,
46
- label: this.configs.websiteId
47
- },
48
- ...processDigitalWalletOptions(this.options, EXPRESS_METHODS)
49
- }
50
-
51
- this.configs = {
52
- ...this.configs,
53
- digitalWallet
54
- };
55
-
56
- function initializeFramepay() {
57
- if (Rebilly.initialized) {
58
- mountExpressMethods.call(this, {
59
- EXPRESS_METHODS,
60
- EXPRESS_METHODS_CONTAINER,
61
- });
62
- } else {
63
- Rebilly.initialize({
64
- publishableKey: this.configs.publishableKey,
65
- organizationId: this.configs.organizationId,
66
- digitalWallet,
67
- });
68
-
69
- Rebilly.on('ready', () => {
70
- mountExpressMethods.call(this, {
71
- EXPRESS_METHODS,
72
- EXPRESS_METHODS_CONTAINER,
73
- })
74
- });
75
-
76
- Rebilly.on('token-ready', (data) => {
77
- Events.instrumentReady.dispatch(data);
78
- });
79
- }
80
- }
81
-
82
- if (METHODS.length) {
83
- MountMethods.call(this, {
26
+ export function mountMethodSelector({ state }) {
27
+ const { EXPRESS_METHODS, METHODS } = getPaymentMethods({ state });
28
+
29
+ state.form.innerHTML += baseMethodSelectorHTML(
30
+ state.options.paymentInstruments.compactExpressInstruments && EXPRESS_METHODS.length
31
+ );
32
+
33
+ const EXPRESS_METHODS_CONTAINER = document.querySelector(
34
+ '.rebilly-instruments-express-methods-container'
35
+ );
36
+ const METHODS_DIVIDER = document.querySelector(
37
+ '.rebilly-instruments-divider'
38
+ );
39
+ METHODS_DIVIDER.style.display =
40
+ METHODS.length && EXPRESS_METHODS.length ? 'block' : 'none';
41
+ const METHODS_CONTAINER = document.querySelector(
42
+ '.rebilly-instruments-methods'
43
+ );
44
+
45
+ state.options.digitalWallet = generateDigitalWallet({state, EXPRESS_METHODS});
46
+
47
+ if (METHODS.length) {
48
+ MountMethods({
49
+ state,
84
50
  METHODS_CONTAINER,
85
- METHODS,
86
- mainStyle,
87
- plans,
88
- products
51
+ METHODS
89
52
  });
90
53
  } else {
91
54
  METHODS_CONTAINER.style.display = 'none';
92
55
  }
93
56
 
94
- if (window.Rebilly && EXPRESS_METHODS.length) {
95
- initializeFramepay.call(this);
57
+ if (EXPRESS_METHODS.length) {
58
+ mountExpressMethods({
59
+ state,
60
+ EXPRESS_METHODS,
61
+ EXPRESS_METHODS_CONTAINER
62
+ });
96
63
  } else {
97
- EXPRESS_METHODS_CONTAINER.style.display = 'none';
64
+ EXPRESS_METHODS_CONTAINER.parentNode.style.display = 'none';
98
65
  }
99
66
 
100
- this.translate.translateItems();
67
+ if (!METHODS.length && !EXPRESS_METHODS.length) {
68
+ state.form.innerHTML = `
69
+ <p data-rebilly-i18n="form.error.noPaymentMethods">
70
+ No payment methods available for this transaction, please contact support.
71
+ <p>
72
+ `;
73
+ state.form.style.minHeight = 'auto';
74
+ }
75
+
76
+ state.translate.translateItems();
101
77
 
102
- this.loader.stopLoading({id: 'initForm'});
103
- };
78
+ state.loader.stopLoading({ id: 'initForm' });
79
+ }
104
80
 
105
- export async function UpdateMethodSelector({mainStyle} = {}) {
106
- this.loader.startLoading({id: 'initForm'});
107
- const {riskMetadata} = await collectData();
81
+ export async function updateMethodSelector({ state }) {
82
+ state.loader.startLoading({ id: 'initForm' });
83
+ const { riskMetadata } = await collectData();
108
84
 
109
- const {
110
- readyToPay,
111
- summary: summaryData,
112
- plans,
113
- products
114
- } = await FetchSummaryData.call(this, { riskMetadata });
85
+ state.data = await fetchData({ state, riskMetadata });
115
86
 
116
- this.formOptions = {
117
- summary: summaryData,
118
- readyToPay,
119
- plans,
120
- products,
121
- mainStyle,
122
- };
87
+ if (state.data.transaction && state.data.transaction?.type === 'setup') {
88
+ state.options.transactionType = 'setup';
89
+ }
123
90
 
124
- this.form.querySelectorAll(':not(.rebilly-instruments-confirmation)').forEach(element => {
125
- if (!element.classList.contains('rebilly-instruments-loader')
126
- && !element.classList.contains('rebilly-instruments-loader-spinner')) {
127
- element.remove();
128
- }
129
- });
91
+ state.form
92
+ .querySelectorAll(':not(.rebilly-instruments-confirmation)')
93
+ .forEach((element) => {
94
+ if (
95
+ !element.classList.contains('rebilly-instruments-loader') &&
96
+ !element.classList.contains('rebilly-instruments-loader-spinner')
97
+ ) {
98
+ element.remove();
99
+ }
100
+ });
130
101
 
131
- MountMethodSelector.call(this, this.formOptions);
132
- }
102
+ mountMethodSelector({ state });
103
+ }
@@ -2,109 +2,119 @@ import SummaryModel from '@/storefront/models/summary-model';
2
2
  import ReadyToPayModel from '@/storefront/models/ready-to-pay-model';
3
3
  import { Loader } from '../../loader';
4
4
  import { Translate } from '../../i18n';
5
- import { MountMethodSelector } from './index';
5
+ import { mountMethodSelector, updateMethodSelector } from './index';
6
+ import { avoidUnhandledPromises } from 'tests/async-utilities';
7
+ import { MockStorefront } from 'tests/mocks/storefront-mock';
8
+ import { DataInstance } from '../../functions/mount/fetch-data';
9
+ import setupOptions from '../../functions/mount/setup-options';
6
10
 
7
11
  describe('Summary component', () => {
8
12
  let formElement;
9
13
  beforeEach(() => {
10
14
  formElement = document.createElement('div');
11
15
  document.body.append(formElement);
12
- })
16
+ });
13
17
 
14
18
  class TestMountMethodSelectorInstance {
15
19
  constructor({
16
- configs = {},
17
20
  options = {},
18
21
  form = formElement,
19
22
  loader = new Loader(),
20
- translate = new Translate(),
21
- zoidComponents = {},
23
+ translate = new Translate()
22
24
  } = {}) {
23
- this.configs = configs;
24
- this.options = options;
25
+ this.options = setupOptions({options});
25
26
  this.form = form;
26
27
  this.loader = loader;
27
28
  this.translate = translate;
28
- this.zoidComponents = zoidComponents;
29
- }
30
-
31
- mountMethodSelector(readyToPayAndSummary, ...args) {
32
- this.loader.DOM.form = this.form;
33
- return MountMethodSelector.apply(this, args.concat(readyToPayAndSummary));
29
+ this.storefront = MockStorefront();
30
+ this.data = new DataInstance({
31
+ state: {options},
32
+ previewPurchase: new SummaryModel({
33
+ currency: 'USD',
34
+ lineItems: [
35
+ {
36
+ type: 'debit',
37
+ description: 'My Awesome Product',
38
+ unitPrice: 30,
39
+ quantity: 1,
40
+ price: 30,
41
+ productId: 'my-awesome-product',
42
+ planId: 'my-awesome-product'
43
+ },
44
+ {
45
+ type: 'debit',
46
+ description: 'Awesome T-Shirt',
47
+ unitPrice: 20,
48
+ quantity: 2,
49
+ price: 40,
50
+ productId: 'my-app',
51
+ planId: 'awesome-t-shirt'
52
+ }
53
+ ],
54
+ subtotalAmount: 70,
55
+ taxAmount: 0,
56
+ shippingAmount: 0,
57
+ discountsAmount: 0,
58
+ total: 70
59
+ }),
60
+ readyToPay: [
61
+ new ReadyToPayModel({
62
+ method: 'payment-card',
63
+ feature: {
64
+ name: 'Google Pay',
65
+ merchantName: 'google-pay-merchant-name',
66
+ merchantOrigin: 'google-pay-merchant-origin'
67
+ },
68
+ brands: ['Visa'],
69
+ filters: []
70
+ }),
71
+ ]
72
+ });
34
73
  }
35
74
  }
36
75
 
37
76
  const options = {
38
- intent: {
39
- countryCode: 'US',
40
- items: [
41
- {
42
- planId: 'my-awesome-product',
43
- quantity: 1,
44
- thumbnail: '',
45
- },
46
- {
47
- planId: 'awesome-t-shirt',
48
- quantity: 2,
49
- thumbnail: '',
50
- }
51
- ]
52
- },
53
- paymentInstruments: {
54
- compactExpressInstruments: true
55
- },
56
- };
57
-
58
- const summaryData = new SummaryModel({
59
- currency: "USD",
60
- lineItems: [{
61
- type: "debit",
62
- description: "My Awesome Product",
63
- unitPrice: 30,
64
- quantity: 1,
65
- price: 30,
66
- productId: "my-awesome-product",
67
- planId: "my-awesome-product"
68
- }, {
69
- type: "debit",
70
- description: "Awesome T-Shirt",
71
- unitPrice: 20,
72
- quantity: 2,
73
- price: 40,
74
- productId: "my-app",
75
- planId: "awesome-t-shirt"
76
- }],
77
- subtotalAmount: 70,
78
- taxAmount: 0,
79
- shippingAmount: 0,
80
- discountsAmount: 0,
81
- total: 70
82
- });
83
-
84
- const readyToPayData = [
85
- new ReadyToPayModel(
77
+ websiteId: 'test-website-id',
78
+ countryCode: 'US',
79
+ items: [
80
+ {
81
+ planId: 'my-awesome-product',
82
+ quantity: 1
83
+ },
86
84
  {
87
- method: 'payment-card',
88
- feature: {
89
- name: 'Google Pay',
90
- merchantName: 'google-pay-merchant-name',
91
- merchantOrigin: 'google-pay-merchant-origin'
92
- },
93
- brands: ['Visa'],
94
- filters: []
85
+ planId: 'awesome-t-shirt',
86
+ quantity: 2
95
87
  }
96
- )
97
- ];
98
-
99
- const configs = {
100
- websiteId: 'test-website-id'
88
+ ],
89
+ _computed: {
90
+ paymentMethodsUrl: ''
91
+ }
101
92
  };
102
93
 
103
- it('should inject the proper HTML for express methods', () => {
104
- const mountSummaryInstance = new TestMountMethodSelectorInstance({configs, options});
105
- mountSummaryInstance.mountMethodSelector({summary: summaryData, readyToPay: readyToPayData});
94
+ it('should inject the proper HTML for express methods', async () => {
95
+ const mountSummaryInstance = new TestMountMethodSelectorInstance({
96
+ options
97
+ });
98
+
99
+ mountSummaryInstance.loader.DOM.form = mountSummaryInstance.form;
100
+
101
+ mountMethodSelector({ state: mountSummaryInstance });
106
102
 
107
103
  const form = document.querySelector('.rebilly-instruments-form');
108
104
  expect(form).toMatchSnapshot();
105
+ await avoidUnhandledPromises();
106
+ });
107
+
108
+ it('should allow updating method selector', async () => {
109
+ const state = new TestMountMethodSelectorInstance({
110
+ options
111
+ });
112
+
113
+ state.loader.DOM.form = state.form;
114
+
115
+ await updateMethodSelector({
116
+ state,
117
+ mainStyle: 'any main style'
118
+ });
109
119
  });
110
- })
120
+ });
@@ -1,77 +1,53 @@
1
- /* eslint-disable no-undef */
2
- import { MethodIframe } from '../common/iframe';
1
+
2
+ import mountGooglePay from './express-methods/google-pay';
3
+ import mountApplePay from './express-methods/apple-pay';
4
+ import mountPaypal from './express-methods/paypal';
3
5
  import { getMethodData } from './get-method-data';
4
6
 
5
- async function mountGooglePay({
6
- methodId,
7
+ export function mountExpressMethods({
8
+ state,
9
+ EXPRESS_METHODS,
10
+ EXPRESS_METHODS_CONTAINER
7
11
  }) {
8
- const container = document.querySelector('.rebilly-instruments-express-methods');
9
-
10
- const {paymentMethodsUrl} = this.options._computed;
12
+ // A child div for each method must be created before mounting.
13
+ // Any DOM operation (innerHTML, append, etc) done on the parent div (EXPRESS_METHODS_CONTAINER) in between
14
+ // the two Postmate's instantiation (1 parent, 1 child) will cause the parent <-> child handshake to fail
15
+ EXPRESS_METHODS.forEach((expressMethod) => {
16
+ const { METHOD_ID } = getMethodData(expressMethod);
11
17
 
12
- const model = {
13
- configs: this.configs,
14
- options: this.options,
15
- };
16
- const iframe = await new MethodIframe({
17
- name: methodId,
18
- url: `${paymentMethodsUrl}/${methodId}`,
19
- container,
20
- model
21
- });
22
- iframe.bindEventListeners({
23
- loader: this.loader
18
+ EXPRESS_METHODS_CONTAINER.innerHTML += `
19
+ <div class="rebilly-instruments-${METHOD_ID}-method"></div>
20
+ `;
24
21
  });
25
- this.iframeComponents.push(iframe);
26
- }
27
-
28
- function mountApplePay({
29
- EXPRESS_METHODS_CONTAINER,
30
- METHOD_ID,
31
- METHOD_TYPE,
32
- }) {
33
- EXPRESS_METHODS_CONTAINER.innerHTML += `
34
- <div id="rebilly-instruments-${METHOD_ID}" data-rebilly-instruments-express-type="${METHOD_TYPE}"></div>
35
- `;
36
- Rebilly.applePay.mount(`#rebilly-instruments-${METHOD_ID}`);
37
22
 
38
- Rebilly.on('token-ready', (token) => {
39
- dispatch('instrument-ready', token);
40
- });
41
- }
42
23
 
43
- function mountPaypal() {
44
- console.log('PayPal - work in progress');
45
- this.loader.stopLoading({id: 'paypal-express'});
46
- }
47
-
48
- const browserIsSafari = () => window.ApplePaySession;
49
-
50
- export function mountExpressMethods({
51
- EXPRESS_METHODS,
52
- EXPRESS_METHODS_CONTAINER,
53
- }) {
54
24
  EXPRESS_METHODS.forEach((expressMethod) => {
55
- const {method, feature} = expressMethod;
56
- const methodData = getMethodData(expressMethod);
57
-
58
- if (method === 'paypal') {
59
- mountPaypal.call(this);
60
- };
25
+ const { method, feature } = expressMethod;
26
+ const { METHOD_ID, METHOD_TYPE } = getMethodData(expressMethod);
61
27
 
62
28
  if (feature?.name === 'Google Pay') {
63
- mountGooglePay.call(this, {
64
- methodId: methodData.METHOD_ID
29
+ mountGooglePay({
30
+ state,
31
+ METHOD_ID
65
32
  });
66
33
  }
67
34
 
68
- if (feature?.name === 'Apple Pay' && browserIsSafari()) {
69
- mountApplePay.call(this, {
70
- EXPRESS_METHODS_CONTAINER,
71
- ...methodData,
35
+ if (feature?.name === 'Apple Pay') {
36
+ mountApplePay({
37
+ state,
38
+ METHOD_ID,
39
+ METHOD_TYPE,
40
+ EXPRESS_METHODS,
41
+ EXPRESS_METHODS_CONTAINER
42
+ });
43
+ }
44
+
45
+ if (method === 'paypal') {
46
+ mountPaypal({
47
+ state,
48
+ METHOD_ID,
49
+ METHOD_TYPE,
72
50
  });
73
- } else {
74
- this.loader.stopLoading({id: 'payment-card-express'});
75
51
  }
76
52
  });
77
53
  }
@@ -1,30 +1,35 @@
1
1
  import camelCase from 'lodash.camelcase';
2
+ import { mountModal } from '../modal';
2
3
  import { MethodIframe } from '../common/iframe';
3
4
  import { getMethodData } from './get-method-data';
4
5
 
5
6
  export function MountMethods({
7
+ state,
6
8
  METHODS_CONTAINER,
7
- METHODS,
8
- mainStyle,
9
- plans,
10
- products
9
+ METHODS
11
10
  }) {
12
- METHODS.forEach(async method => {
13
- const { METHOD_ID: methodId, METHOD_TYPE: methodType } = getMethodData(method);
14
- const { paymentMethodsUrl } = this.options._computed || 'https://www.example.com';
11
+ METHODS.forEach(async (method) => {
12
+ const { METHOD_ID: methodId, METHOD_TYPE: methodType } =
13
+ getMethodData(method);
14
+ const { paymentMethodsUrl } =
15
+ state.options._computed || 'https://www.example.com';
15
16
 
16
17
  const selector = `rebilly-instruments-${methodId}`;
17
- const isiFrame = methodId === 'payment-card' && !this.options.paymentInstruments[methodType]?.popup;
18
+ const isiFrame =
19
+ methodId === 'payment-card' &&
20
+ !state.options.paymentInstruments[methodType]?.popup;
18
21
  const model = {
19
- configs: this.configs,
20
- options: this.options,
21
- mainStyle,
22
- method,
23
- plans,
24
- products,
22
+ options: state.options,
23
+ mainStyle: state.mainStyle,
24
+ plans: state.data.plans,
25
+ products: state.data.products,
26
+ method
25
27
  };
26
28
 
27
- METHODS_CONTAINER.insertAdjacentHTML('beforeend', `<div id="${selector}" data-rebilly-instruments-type="${methodId}"></div>`);
29
+ METHODS_CONTAINER.insertAdjacentHTML(
30
+ 'beforeend',
31
+ `<div id="${selector}" data-rebilly-instruments-type="${methodId}"></div>`
32
+ );
28
33
  const container = document.querySelector(`#${selector}`);
29
34
 
30
35
  if (isiFrame) {
@@ -35,22 +40,28 @@ export function MountMethods({
35
40
  model
36
41
  });
37
42
  iframe.bindEventListeners({
38
- loader: this.loader,
43
+ loader: state.loader,
39
44
  id: method.method
40
45
  });
41
- this.iframeComponents.push(iframe);
46
+ state.iframeComponents.push(iframe);
42
47
  } else {
43
- container.insertAdjacentHTML('beforeend', `<button class="${selector} rebilly-instruments-button" data-rebilly-i18n="paymentMethods.${method.method}">${camelCase(method.method)}</button>`);
48
+ container.insertAdjacentHTML(
49
+ 'beforeend',
50
+ `<button class="${selector} rebilly-instruments-button" data-rebilly-i18n="paymentMethods.${
51
+ method.method
52
+ }">${camelCase(method.method)}</button>`
53
+ );
44
54
  const paymentCardButton = document.querySelector(`.${selector}`);
45
55
  paymentCardButton.addEventListener('click', async () => {
46
- const iframe = await this._mountModal.call(this, {
56
+ const iframe = await mountModal({
57
+ state,
47
58
  name: methodId,
48
59
  url: `${paymentMethodsUrl}/${methodId}`,
49
60
  model
50
61
  });
51
- this.iframeComponents.push(iframe);
62
+ state.iframeComponents.push(iframe);
52
63
  });
53
- this.loader.stopLoading({id: method.method});
64
+ state.loader.stopLoading({ id: method.method });
54
65
  }
55
66
  });
56
67
  }