@rebilly/instruments 1.0.2-beta.9 → 3.0.0-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 (255) 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 +187 -0
  11. package/dist/functions/mount/fetch-data.spec.js +189 -0
  12. package/dist/functions/mount/index.js +164 -251
  13. package/dist/functions/mount/mount.spec.js +25 -124
  14. package/dist/functions/mount/setup-element.js +40 -0
  15. package/dist/functions/mount/setup-framepay-theme.js +95 -0
  16. package/dist/functions/mount/setup-framepay.js +46 -0
  17. package/dist/functions/mount/setup-i18n.js +33 -0
  18. package/dist/functions/mount/setup-options.js +99 -0
  19. package/dist/functions/mount/setup-options.spec.js +66 -0
  20. package/dist/functions/mount/setup-storefront.js +34 -0
  21. package/dist/functions/mount/setup-styles.js +43 -0
  22. package/dist/functions/on.js +13 -4
  23. package/dist/functions/on.spec.js +19 -5
  24. package/dist/functions/purchase.js +139 -22
  25. package/dist/functions/purchase.spec.js +23 -19
  26. package/dist/functions/setup.js +85 -0
  27. package/dist/functions/setup.spec.js +87 -0
  28. package/dist/functions/show.js +31 -14
  29. package/dist/functions/show.spec.js +47 -18
  30. package/dist/functions/update.js +53 -27
  31. package/dist/functions/update.spec.js +40 -21
  32. package/dist/i18n/en.json +5 -2
  33. package/dist/i18n/es.json +4 -1
  34. package/dist/index.js +67 -56
  35. package/dist/index.spec.js +7 -27
  36. package/dist/loader/index.js +4 -3
  37. package/dist/storefront/index.js +33 -0
  38. package/dist/storefront/invoices.js +27 -0
  39. package/dist/storefront/models/base-model.js +18 -0
  40. package/dist/storefront/models/invoice-model.js +14 -0
  41. package/dist/storefront/models/plan-model.js +4 -35
  42. package/dist/storefront/models/product-model.js +4 -23
  43. package/dist/storefront/models/summary-model.js +12 -25
  44. package/dist/storefront/models/transaction-model.js +31 -0
  45. package/dist/storefront/payment-instruments.js +47 -0
  46. package/dist/storefront/payment-instruments.spec.js +55 -0
  47. package/dist/storefront/plans.js +15 -24
  48. package/dist/storefront/plans.spec.js +17 -44
  49. package/dist/storefront/products.js +16 -20
  50. package/dist/storefront/products.spec.js +25 -49
  51. package/dist/storefront/purchase.js +28 -16
  52. package/dist/storefront/purchase.spec.js +4 -22
  53. package/dist/storefront/ready-to-pay.js +26 -22
  54. package/dist/storefront/ready-to-pay.spec.js +25 -54
  55. package/dist/storefront/storefront.spec.js +1 -1
  56. package/dist/storefront/summary.js +27 -24
  57. package/dist/storefront/summary.spec.js +44 -86
  58. package/dist/storefront/transactions.js +27 -0
  59. package/dist/style/base/__snapshots__/theme.spec.js.snap +188 -45
  60. package/dist/style/base/default-theme.js +699 -0
  61. package/dist/style/base/index.js +48 -16
  62. package/dist/style/base/theme.js +15 -48
  63. package/dist/style/base/theme.spec.js +4 -15
  64. package/dist/style/components/address.js +3 -3
  65. package/dist/style/components/button.js +32 -22
  66. package/dist/style/components/divider.js +9 -9
  67. package/dist/style/components/forms/checkbox.js +12 -9
  68. package/dist/style/components/forms/field.js +18 -6
  69. package/dist/style/components/forms/form.js +2 -2
  70. package/dist/style/components/forms/input.js +54 -13
  71. package/dist/style/components/forms/label.js +44 -18
  72. package/dist/style/components/forms/select.js +54 -22
  73. package/dist/style/components/forms/validation.js +53 -6
  74. package/dist/style/components/icons.js +4 -4
  75. package/dist/style/components/loader.js +5 -3
  76. package/dist/style/components/methods.js +52 -48
  77. package/dist/style/components/overlay.js +5 -5
  78. package/dist/style/helpers/index.js +46 -46
  79. package/dist/style/index.js +3 -1
  80. package/dist/style/payment-instruments/payment-card.js +4 -4
  81. package/dist/style/utils/border.js +47 -0
  82. package/dist/style/utils/color-values.js +37 -3
  83. package/dist/style/utils/remove-empty-null.js +20 -0
  84. package/dist/style/vendor/framepay.js +11 -8
  85. package/dist/style/vendor/postmate.js +2 -2
  86. package/dist/style/views/confirmation.js +13 -13
  87. package/dist/style/views/method-selector.js +3 -3
  88. package/dist/style/views/modal.js +8 -6
  89. package/dist/style/views/result.js +4 -4
  90. package/dist/style/views/summary.js +26 -22
  91. package/dist/utils/format-currency.js +4 -2
  92. package/dist/utils/has-valid-css-selector.js +1 -1
  93. package/dist/utils/process-property-as-dom-element.js +0 -2
  94. package/dist/views/__snapshots__/summary.spec.js.snap +72 -118
  95. package/dist/views/common/iframe/base-iframe.js +10 -2
  96. package/dist/views/common/iframe/modal-iframe.js +50 -4
  97. package/dist/views/confirmation.js +44 -20
  98. package/dist/views/method-selector/express-methods/apple-pay.js +92 -0
  99. package/dist/views/method-selector/express-methods/google-pay.js +31 -0
  100. package/dist/views/method-selector/express-methods/paypal.js +19 -0
  101. package/dist/views/method-selector/generate-digital-wallet.js +68 -0
  102. package/dist/views/method-selector/generate-digital-wallet.spec.js +135 -0
  103. package/dist/views/method-selector/get-payment-methods.js +27 -7
  104. package/dist/views/method-selector/get-payment-methods.spec.js +25 -26
  105. package/dist/views/method-selector/index.js +55 -86
  106. package/dist/views/method-selector/method-selector.spec.js +80 -69
  107. package/dist/views/method-selector/mount-express-methods.js +38 -62
  108. package/dist/views/method-selector/mount-methods.js +18 -18
  109. package/dist/views/modal.js +18 -12
  110. package/dist/views/result.js +13 -16
  111. package/dist/views/summary.js +176 -114
  112. package/dist/views/summary.spec.js +72 -76
  113. package/package.json +7 -4
  114. package/src/events/base-event.js +15 -17
  115. package/src/events/events.spec.js +6 -4
  116. package/src/events/index.js +6 -3
  117. package/src/functions/destroy.js +12 -13
  118. package/src/functions/destroy.spec.js +30 -31
  119. package/src/functions/mount/fetch-data.js +152 -0
  120. package/src/functions/mount/fetch-data.spec.js +238 -0
  121. package/src/functions/mount/index.js +131 -244
  122. package/src/functions/mount/mount.spec.js +35 -141
  123. package/src/functions/mount/setup-element.js +26 -0
  124. package/src/functions/mount/setup-framepay-theme.js +82 -0
  125. package/src/functions/mount/setup-framepay.js +41 -0
  126. package/src/functions/mount/setup-i18n.js +19 -0
  127. package/src/functions/mount/setup-options.js +103 -0
  128. package/src/functions/mount/setup-options.spec.js +60 -0
  129. package/src/functions/mount/setup-storefront.js +24 -0
  130. package/src/functions/mount/setup-styles.js +30 -0
  131. package/src/functions/on.js +13 -8
  132. package/src/functions/on.spec.js +30 -17
  133. package/src/functions/purchase.js +101 -19
  134. package/src/functions/purchase.spec.js +18 -18
  135. package/src/functions/setup.js +48 -0
  136. package/src/functions/setup.spec.js +98 -0
  137. package/src/functions/show.js +20 -10
  138. package/src/functions/show.spec.js +43 -22
  139. package/src/functions/update.js +50 -27
  140. package/src/functions/update.spec.js +57 -22
  141. package/src/i18n/en.json +5 -2
  142. package/src/i18n/es.json +4 -1
  143. package/src/i18n/i18n.spec.js +6 -4
  144. package/src/i18n/index.js +14 -11
  145. package/src/index.js +41 -52
  146. package/src/index.spec.js +8 -37
  147. package/src/loader/index.js +51 -47
  148. package/src/loader/loader.spec.js +26 -19
  149. package/src/storefront/index.js +37 -7
  150. package/src/storefront/invoices.js +11 -0
  151. package/src/storefront/models/base-model.js +10 -0
  152. package/src/storefront/models/invoice-model.js +3 -0
  153. package/src/storefront/models/plan-model.js +3 -35
  154. package/src/storefront/models/product-model.js +3 -23
  155. package/src/storefront/models/ready-to-pay-model.js +3 -3
  156. package/src/storefront/models/summary-model.js +15 -29
  157. package/src/storefront/models/transaction-model.js +19 -0
  158. package/src/storefront/payment-instruments.js +30 -0
  159. package/src/storefront/payment-instruments.spec.js +69 -0
  160. package/src/storefront/plans.js +16 -23
  161. package/src/storefront/plans.spec.js +25 -54
  162. package/src/storefront/products.js +18 -22
  163. package/src/storefront/products.spec.js +23 -54
  164. package/src/storefront/purchase.js +14 -14
  165. package/src/storefront/purchase.spec.js +17 -29
  166. package/src/storefront/ready-to-pay.js +26 -23
  167. package/src/storefront/ready-to-pay.spec.js +41 -71
  168. package/src/storefront/storefront.spec.js +1 -1
  169. package/src/storefront/summary.js +26 -22
  170. package/src/storefront/summary.spec.js +60 -109
  171. package/src/storefront/transactions.js +11 -0
  172. package/src/style/base/__snapshots__/theme.spec.js.snap +188 -45
  173. package/src/style/base/default-theme.js +674 -0
  174. package/src/style/base/index.js +48 -16
  175. package/src/style/base/theme.js +20 -48
  176. package/src/style/base/theme.spec.js +5 -15
  177. package/src/style/browserslist.js +1 -3
  178. package/src/style/components/address.js +3 -3
  179. package/src/style/components/button.js +32 -22
  180. package/src/style/components/divider.js +9 -9
  181. package/src/style/components/forms/checkbox.js +11 -9
  182. package/src/style/components/forms/field.js +18 -6
  183. package/src/style/components/forms/form.js +2 -2
  184. package/src/style/components/forms/input.js +54 -13
  185. package/src/style/components/forms/label.js +44 -18
  186. package/src/style/components/forms/select.js +54 -22
  187. package/src/style/components/forms/validation.js +53 -6
  188. package/src/style/components/icons.js +4 -4
  189. package/src/style/components/index.js +1 -1
  190. package/src/style/components/loader.js +4 -3
  191. package/src/style/components/methods.js +52 -48
  192. package/src/style/components/overlay.js +5 -5
  193. package/src/style/helpers/index.js +46 -46
  194. package/src/style/index.js +4 -2
  195. package/src/style/payment-instruments/payment-card.js +4 -4
  196. package/src/style/utils/border.js +34 -0
  197. package/src/style/utils/color-values.js +30 -4
  198. package/src/style/utils/remove-empty-null.js +10 -0
  199. package/src/style/vendor/framepay.js +12 -9
  200. package/src/style/vendor/postmate.js +3 -3
  201. package/src/style/views/confirmation.js +13 -13
  202. package/src/style/views/index.js +1 -1
  203. package/src/style/views/method-selector.js +3 -3
  204. package/src/style/views/modal.js +9 -7
  205. package/src/style/views/result.js +4 -4
  206. package/src/style/views/summary.js +26 -22
  207. package/src/utils/add-dom-element.js +12 -13
  208. package/src/utils/format-currency.js +6 -2
  209. package/src/utils/has-valid-css-selector.js +2 -2
  210. package/src/utils/is-dom-element.js +1 -1
  211. package/src/utils/process-property-as-dom-element.js +27 -24
  212. package/src/utils/sleep.js +1 -1
  213. package/src/views/__snapshots__/summary.spec.js.snap +72 -118
  214. package/src/views/common/iframe/base-iframe.js +12 -4
  215. package/src/views/common/iframe/event-listeners.js +6 -6
  216. package/src/views/common/iframe/index.js +1 -1
  217. package/src/views/common/iframe/method-iframe.js +3 -6
  218. package/src/views/common/iframe/modal-iframe.js +48 -6
  219. package/src/views/common/iframe/view-iframe.js +3 -5
  220. package/src/views/common/render-utilities.js +3 -3
  221. package/src/views/confirmation.js +34 -25
  222. package/src/views/method-selector/express-methods/apple-pay.js +78 -0
  223. package/src/views/method-selector/express-methods/google-pay.js +24 -0
  224. package/src/views/method-selector/express-methods/paypal.js +7 -0
  225. package/src/views/method-selector/generate-digital-wallet.js +51 -0
  226. package/src/views/method-selector/generate-digital-wallet.spec.js +135 -0
  227. package/src/views/method-selector/get-method-data.js +7 -4
  228. package/src/views/method-selector/get-payment-methods.js +38 -31
  229. package/src/views/method-selector/get-payment-methods.spec.js +26 -33
  230. package/src/views/method-selector/index.js +70 -99
  231. package/src/views/method-selector/method-selector.spec.js +88 -78
  232. package/src/views/method-selector/mount-express-methods.js +36 -60
  233. package/src/views/method-selector/mount-methods.js +32 -21
  234. package/src/views/modal.js +36 -22
  235. package/src/views/result.js +12 -15
  236. package/src/views/summary.js +175 -101
  237. package/src/views/summary.spec.js +99 -74
  238. package/tests/async-utilities.js +22 -0
  239. package/tests/mocks/rebilly-instruments-mock.js +89 -77
  240. package/tests/mocks/storefront-api-mock.js +8 -0
  241. package/tests/mocks/storefront-mock.js +17 -0
  242. package/dist/events/purchase-completed.js +0 -24
  243. package/dist/functions/initialize.js +0 -82
  244. package/dist/functions/initialize.spec.js +0 -34
  245. package/dist/functions/mount/fetch-summary-data.js +0 -31
  246. package/dist/functions/mount/fetch-summary-data.spec.js +0 -45
  247. package/dist/views/method-selector/process-digital-wallet-options.js +0 -35
  248. package/dist/views/method-selector/process-digital-wallet-options.spec.js +0 -80
  249. package/src/events/purchase-completed.js +0 -11
  250. package/src/functions/initialize.js +0 -74
  251. package/src/functions/initialize.spec.js +0 -38
  252. package/src/functions/mount/fetch-summary-data.js +0 -26
  253. package/src/functions/mount/fetch-summary-data.spec.js +0 -46
  254. package/src/views/method-selector/process-digital-wallet-options.js +0 -16
  255. package/src/views/method-selector/process-digital-wallet-options.spec.js +0 -94
@@ -1,98 +1,176 @@
1
1
  import { collectData } from '@rebilly/risk-data-collector';
2
2
  import { formatCurrency } from '../utils';
3
- import { FetchSummaryData } from '../functions/mount/fetch-summary-data';
4
-
5
- export const baseSummaryHTML = `
6
- <div class="rebilly-instruments-content">
7
- <div class="rebilly-instruments-summary-line-items"></div>
8
- <div class="rebilly-instruments-summary-breakdown"></div>
9
- </div>
10
- `;
11
-
12
- export function MountSummary({summary, plans, products} = {}) {
13
- this.summary.innerHTML += baseSummaryHTML;
14
- const itemsContainer = document.querySelector('.rebilly-instruments-summary-line-items');
15
- const summaryBreakdown = document.querySelector('.rebilly-instruments-summary-breakdown')
16
- const {intent: {items: optionItems}} = this.options;
17
- const hasThumbnails = optionItems.some(optionItem => optionItem.thumbnail);
3
+ import { fetchData } from '../functions/mount/fetch-data';
18
4
 
5
+ export function lineItemHTML({state, lineItem}) {
6
+ const {products} = state.data;
19
7
  const {
20
- lineItems,
21
- currency,
22
- discountsAmount,
23
- shippingAmount,
24
- subtotalAmount,
25
- taxAmount,
26
- total
27
- } = summary;
28
-
29
- lineItems.forEach(lineItem => {
30
- const {thumbnail} = optionItems.find(optionItem => optionItem.planId === lineItem.planId);
31
- const {name} = plans.find(plan => plan.id === lineItem.planId);
32
- const {description} = products.find(product => product.id === lineItem.productId);
33
-
34
- itemsContainer.innerHTML += `
35
- <div class="rebilly-instruments-summary-line-item">
36
- ${hasThumbnails ? `
37
- <figure class="rebilly-instruments-summary-line-item-figure">
38
- ${thumbnail ? `<img src="${thumbnail}" alt="${name}">` : ''}
39
- </figure>
40
- ` : ''}
41
- <div class="rebilly-instruments-summary-line-item-synopsis">
42
- <p class="rebilly-instruments-summary-line-item-synopsis-title">${name}</p>
43
- ${description ? `
44
- <p class="rebilly-instruments-summary-line-item-synopsis-description">${description}</p>
45
- ` : ''}
46
- </div>
47
- <div class="rebilly-instruments-summary-line-item-price-breakdown">
48
- <p class="rebilly-instruments-summary-line-item-price-breakdown-quantity">${lineItem.quantity}</p>
49
- <svg class="rebilly-instruments-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
50
- <path d="M12 10.5858l2.8284-2.8284c.3906-.3906 1.0237-.3906 1.4142 0 .3906.3905.3906 1.0236 0 1.4142L13.4142 12l2.8284 2.8284c.3906.3906.3906 1.0237 0 1.4142-.3905.3906-1.0236.3906-1.4142 0L12 13.4142l-2.8284 2.8284c-.3906.3906-1.0237.3906-1.4142 0-.3906-.3905-.3906-1.0236 0-1.4142L10.5858 12 7.7574 9.1716c-.3906-.3906-.3906-1.0237 0-1.4142.3905-.3906 1.0236-.3906 1.4142 0L12 10.5858z" fill-rule="nonzero"/>
51
- </svg>
52
- <p class="rebilly-instruments-summary-line-item-price-breakdown-unit-price">${formatCurrency(lineItem.unitPrice, currency)}</p>
53
- </div>
8
+ currency = null,
9
+ } = state.data?.amountAndCurrency;
10
+
11
+ const {
12
+ items: optionItems = []
13
+ } = state.options;
14
+ const hasThumbnails = optionItems?.some((optionItem) => optionItem.thumbnail);
15
+ const { thumbnail = null } = optionItems.find(
16
+ (optionItem) => optionItem.planId === lineItem.planId
17
+ ) || {};
18
+
19
+ const { name } = products.find(
20
+ (product) => product.id === lineItem.productId
21
+ );
22
+
23
+ return `
24
+ <div class="rebilly-instruments-summary-line-item">
25
+ ${
26
+ hasThumbnails
27
+ ? `
28
+ <figure class="rebilly-instruments-summary-line-item-figure">
29
+ ${thumbnail ? `<img src="${thumbnail}" alt="${name}">` : ''}
30
+ </figure>
31
+ `
32
+ : ''
33
+ }
34
+ <div class="rebilly-instruments-summary-line-item-synopsis">
35
+ <p class="rebilly-instruments-summary-line-item-synopsis-title">${name}</p>
36
+ ${
37
+ lineItem.description
38
+ ? `
39
+ <p class="rebilly-instruments-summary-line-item-synopsis-description">${lineItem.description}</p>
40
+ `
41
+ : ''
42
+ }
43
+ </div>
44
+ <div class="rebilly-instruments-summary-line-item-price-breakdown">
45
+ <p class="rebilly-instruments-summary-line-item-price-breakdown-quantity">${
46
+ lineItem.quantity
47
+ }</p>
48
+ <svg class="rebilly-instruments-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
49
+ <path d="M12 10.5858l2.8284-2.8284c.3906-.3906 1.0237-.3906 1.4142 0 .3906.3905.3906 1.0236 0 1.4142L13.4142 12l2.8284 2.8284c.3906.3906.3906 1.0237 0 1.4142-.3905.3906-1.0236.3906-1.4142 0L12 13.4142l-2.8284 2.8284c-.3906.3906-1.0237.3906-1.4142 0-.3906-.3905-.3906-1.0236 0-1.4142L10.5858 12 7.7574 9.1716c-.3906-.3906-.3906-1.0237 0-1.4142.3905-.3906 1.0236-.3906 1.4142 0L12 10.5858z" fill-rule="nonzero"/>
50
+ </svg>
51
+ <p class="rebilly-instruments-summary-line-item-price-breakdown-unit-price">${formatCurrency(
52
+ lineItem.unitPrice,
53
+ currency
54
+ )}</p>
54
55
  </div>
55
- `;
56
- });
57
- summaryBreakdown.innerHTML = `
58
- <table>
59
- <colgroup>
60
- <col>
61
- <col>
62
- </colgroup>
63
- <tr class="rebilly-instruments-summary-breakdown-sub-total">
64
- <td data-rebilly-i18n="summary.subTotal">Sub Total</td>
65
- <td>${formatCurrency(subtotalAmount, currency)}</td>
66
- </tr>
67
- <tr class="rebilly-instruments-summary-breakdown-discounts">
68
- <td data-rebilly-i18n="summary.discounts">Discounts</td>
69
- <td>${formatCurrency(discountsAmount, currency)}</td>
70
- </tr>
71
- <tr class="rebilly-instruments-summary-breakdown-taxes">
72
- <td data-rebilly-i18n="summary.taxes">Taxes</td>
73
- <td>${formatCurrency(taxAmount, currency)}</td>
74
- </tr>
75
- <tr class="rebilly-instruments-summary-breakdown-taxes">
76
- <td data-rebilly-i18n="summary.shipping">Shipping</td>
77
- <td>${formatCurrency(shippingAmount, currency)}</td>
78
- </tr>
79
- </table>
80
- <div class="rebilly-instruments-summary-breakdown-total">
81
- <p data-rebilly-i18n="summary.total">Total</p>
82
- <p class="rebilly-instruments-summary-breakdown-total-amount">
83
- <span class="rebilly-instruments-summary-breakdown-total-amount-currency">${currency}</span>${formatCurrency(total, currency)}
84
- </p>
85
56
  </div>
86
57
  `;
58
+ }
59
+
60
+ export function summaryBreakdownHTML({state, element}) {
61
+ const {
62
+ amount = null,
63
+ currency = null,
64
+ discountsAmount = null,
65
+ shippingAmount = null,
66
+ subtotalAmount = null,
67
+ taxAmount = null,
68
+ } = {
69
+ ...state.data.amountAndCurrency,
70
+ ...state.data.summaryItems
71
+ };
72
+
73
+ let table = null;
74
+ [
75
+ {
76
+ label: 'Sub Total',
77
+ class: 'sub-total',
78
+ i18n: 'summary.subTotal',
79
+ value: subtotalAmount,
80
+ show: true,
81
+ },
82
+ {
83
+ label: 'Discounts',
84
+ class: 'discounts',
85
+ i18n: 'summary.discounts',
86
+ value: discountsAmount,
87
+ show: discountsAmount > 0
88
+ },
89
+ {
90
+ label: 'Taxes',
91
+ class: 'taxes',
92
+ i18n: 'summary.taxes',
93
+ value: taxAmount,
94
+ show: true,
95
+ },
96
+ {
97
+ label: 'Shipping',
98
+ class: 'shipping',
99
+ i18n: 'summary.shipping',
100
+ value: shippingAmount,
101
+ show: state.data.isShippingRequired,
102
+ },
103
+ ].filter(({value}) => value !== null)
104
+ .forEach(item => {
105
+ if (!table) {
106
+ table = document.createElement('table');
107
+ table.insertAdjacentHTML('beforeend', `
108
+ <colgroup>
109
+ <col>
110
+ <col>
111
+ </colgroup>
112
+ `);
113
+ }
114
+
115
+ if (item.show) {
116
+ const row = document.createElement('tr');
117
+ row.setAttribute('class', `rebilly-instruments-summary-breakdown-${item.class}`)
118
+ row.insertAdjacentHTML('beforeend', `
119
+ <td data-rebilly-i18n="${item.i18n}">${item.label}</td>
120
+ <td>${formatCurrency(item.value, currency)}</td>
121
+ `);
122
+ table.appendChild(row);
123
+ }
124
+ });
125
+ if (table) {
126
+ element.appendChild(table);
127
+ }
128
+
129
+ const totalElement = document.createElement('div');
130
+ totalElement.setAttribute('class', 'rebilly-instruments-summary-breakdown-total');
131
+ totalElement.insertAdjacentHTML('beforeend', `
132
+ <p data-rebilly-i18n="summary.total">Total</p>
133
+ <p class="rebilly-instruments-summary-breakdown-total-amount">
134
+ <span class="rebilly-instruments-summary-breakdown-total-amount-currency">
135
+ ${currency}
136
+ </span>
137
+ ${formatCurrency(amount, currency)}
138
+ <p>
139
+ `);
140
+ element.appendChild(totalElement);
141
+
142
+ return element;
143
+ }
144
+
145
+ export async function mountSummary({ state }) {
146
+ const contentContainer = document.createElement('div');
147
+ contentContainer.setAttribute('class', 'rebilly-instruments-content');
148
+
149
+ const lineItems = state.data.summaryLineItems;
150
+ if (lineItems) {
151
+ const lineItemsElement = document.createElement('div');
152
+ lineItemsElement.setAttribute('class', 'rebilly-instruments-summary-line-items');
153
+
154
+ lineItems.forEach((lineItem) => {
155
+ lineItemsElement.insertAdjacentHTML('beforeend', lineItemHTML({ state, lineItem }));
156
+ });
157
+ contentContainer.appendChild(lineItemsElement);
158
+ }
87
159
 
88
- this.translate.translateItems();
160
+ const summaryBreakdownElement = document.createElement('div');
161
+ summaryBreakdownElement.setAttribute('class', 'rebilly-instruments-summary-breakdown');
162
+ contentContainer.appendChild(summaryBreakdownHTML({ state, element: summaryBreakdownElement}));
163
+
164
+ state.summary.appendChild(contentContainer);
165
+ state.summary.style.minHeight = '';
89
166
 
90
- this.loader.stopLoading({section: 'summary', id: 'initSummary'});
91
- };
167
+ state.translate.translateItems();
168
+ state.loader.stopLoading({ section: 'summary', id: 'initSummary' });
169
+ }
92
170
 
93
- export async function UpdateSummary(instrument = null) {
94
- this.loader.startLoading({section: 'summary', id: 'initSummary'});
95
- const {riskMetadata} = await collectData();
171
+ export async function updateSummary({ state, instrument = null }) {
172
+ state.loader.startLoading({ section: 'summary', id: 'initSummary' });
173
+ const { riskMetadata } = await collectData();
96
174
 
97
175
  let summaryPayload;
98
176
 
@@ -102,25 +180,21 @@ export async function UpdateSummary(instrument = null) {
102
180
  };
103
181
  }
104
182
 
105
- const {
106
- readyToPay,
107
- summary: summaryData,
108
- plans,
109
- products
110
- } = await FetchSummaryData.call(this, {
183
+ state.data = await fetchData({
111
184
  riskMetadata,
112
- summaryPayload
185
+ summaryPayload,
186
+ state
113
187
  });
114
188
 
115
- this.summaryOptions = {
116
- summary: summaryData,
117
- readyToPay,
118
- plans,
119
- products,
120
- };
189
+ if (state.data.transaction && state.data.transaction?.type === 'setup') {
190
+ state.options.transactionType = 'setup';
191
+ }
121
192
 
122
- const itemsContainer = this.summary.querySelector('.rebilly-instruments-content');
193
+ const itemsContainer = state.summary.querySelector(
194
+ '.rebilly-instruments-content'
195
+ );
123
196
  itemsContainer?.remove();
124
197
 
125
- MountSummary.call(this, this.summaryOptions)
126
- }
198
+ mountSummary({ state });
199
+ }
200
+
@@ -3,7 +3,8 @@ import PlanModel from '@/storefront/models/plan-model';
3
3
  import ProductModel from '@/storefront/models/product-model';
4
4
  import { Loader } from '../loader';
5
5
  import { Translate } from '../i18n';
6
- import { MountSummary } from './summary';
6
+ import { mountSummary } from './summary';
7
+ import { DataInstance } from '../functions/mount/fetch-data';
7
8
 
8
9
  describe('Summary component', () => {
9
10
  let summaryElement;
@@ -11,110 +12,134 @@ describe('Summary component', () => {
11
12
  document.body.innerHTML = '';
12
13
  summaryElement = document.createElement('div');
13
14
  document.body.append(summaryElement);
14
- })
15
+ });
15
16
 
16
17
  class TestMountSummaryInstance {
17
18
  constructor({
18
- configs = {},
19
19
  options = {},
20
20
  summary = summaryElement,
21
21
  loader = new Loader(),
22
22
  translate = new Translate(),
23
+ data = {},
23
24
  } = {}) {
24
- this.configs = configs;
25
25
  this.options = options;
26
26
  this.summary = summary;
27
27
  this.loader = loader;
28
28
  this.translate = translate;
29
- }
30
-
31
- mountSummary(summaryProductsPlans, ...args) {
32
- this.loader.DOM.summary = this.summary;
33
- return MountSummary.apply(this, args.concat(summaryProductsPlans));
29
+ this.data = new DataInstance({
30
+ state: {options},
31
+ previewPurchase: new SummaryModel({
32
+ currency: 'USD',
33
+ lineItems: [
34
+ {
35
+ type: 'debit',
36
+ description: 'My Awesome Product',
37
+ unitPrice: 30,
38
+ quantity: 1,
39
+ price: 30,
40
+ productId: 'test-product-1',
41
+ planId: 'my-awesome-product'
42
+ },
43
+ {
44
+ type: 'debit',
45
+ description: 'Awesome T-Shirt',
46
+ unitPrice: 20,
47
+ quantity: 2,
48
+ price: 40,
49
+ productId: 'test-product-2',
50
+ planId: 'awesome-t-shirt'
51
+ }
52
+ ],
53
+ subtotalAmount: 70,
54
+ taxAmount: 0,
55
+ shippingAmount: 0,
56
+ discountsAmount: 0,
57
+ total: 70
58
+ }),
59
+ plans: [
60
+ new PlanModel({
61
+ name: 'My Awesome Product',
62
+ id: 'my-awesome-product',
63
+ productId: 'test-product-1'
64
+ }),
65
+ new PlanModel({
66
+ name: 'My Awesome T-Shirt',
67
+ id: 'awesome-t-shirt',
68
+ productId: 'test-product-2'
69
+ })
70
+ ],
71
+ products: [
72
+ new ProductModel({
73
+ name: 'My Awesome Product',
74
+ id: 'test-product-1'
75
+ }),
76
+ new ProductModel({
77
+ name: 'My Awesome T-Shirt',
78
+ id: 'test-product-2'
79
+ })
80
+ ],
81
+ ...data
82
+ });
34
83
  }
35
84
  }
36
85
 
37
86
  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
- }
87
+ websiteId: 'test-website-id',
88
+ countryCode: 'US',
89
+ items: [
90
+ {
91
+ planId: 'my-awesome-product',
92
+ quantity: 1,
93
+ thumbnail: ''
94
+ },
95
+ {
96
+ planId: 'awesome-t-shirt',
97
+ quantity: 2,
98
+ thumbnail: ''
99
+ }
100
+ ]
53
101
  };
54
102
 
55
- const summaryData = new SummaryModel({
56
- currency: "USD",
57
- lineItems: [{
58
- type: "debit",
59
- description: "My Awesome Product",
60
- unitPrice: 30,
61
- quantity: 1,
62
- price: 30,
63
- productId: "test-product-1",
64
- planId: "my-awesome-product"
65
- }, {
66
- type: "debit",
67
- description: "Awesome T-Shirt",
68
- unitPrice: 20,
69
- quantity: 2,
70
- price: 40,
71
- productId: "test-product-2",
72
- planId: "awesome-t-shirt"
73
- }],
74
- subtotalAmount: 70,
75
- taxAmount: 0,
76
- shippingAmount: 0,
77
- discountsAmount: 0,
78
- total: 70
79
- });
80
-
81
- const planData = [
82
- new PlanModel({name: 'My Awesome Product', id: 'my-awesome-product', productId: 'test-product-1'}),
83
- new PlanModel({name: 'My Awesome T-Shirt', id: 'awesome-t-shirt', productId: 'test-product-2'})
84
- ];
85
-
86
- const productData = [
87
- new ProductModel({description: 'My Awesome Product', id: 'test-product-1'}),
88
- new ProductModel({description: 'My Awesome T-Shirt', id: 'test-product-2'})
89
- ];
103
+ it('should render the summary correctly', () => {
104
+ const mountSummaryInstance = new TestMountSummaryInstance({
105
+ options
106
+ });
90
107
 
91
- const configs = {
92
- websiteId: 'test-website-id'
93
- };
108
+ //TODO: improve design to avoid this manual change
109
+ mountSummaryInstance.loader.DOM.summary = mountSummaryInstance.summary;
94
110
 
95
- it('should render the summary correctly', () => {
96
- const mountSummaryInstance = new TestMountSummaryInstance({configs, options});
97
- mountSummaryInstance.mountSummary({summary: summaryData, plans: planData, products: productData});
111
+ mountSummary({ state: mountSummaryInstance });
98
112
 
99
113
  // Number of line items
100
- const itemsContainer = document.querySelector('.rebilly-instruments-summary-line-items');
114
+ const itemsContainer = document.querySelector(
115
+ '.rebilly-instruments-summary-line-items'
116
+ );
101
117
  expect(itemsContainer).toMatchSnapshot();
102
118
 
103
119
  // Breakdown
104
- const summaryBreakdown = document.querySelector('.rebilly-instruments-summary-breakdown');
120
+ const summaryBreakdown = document.querySelector(
121
+ '.rebilly-instruments-summary-breakdown'
122
+ );
105
123
  expect(summaryBreakdown).toMatchSnapshot();
106
124
  });
107
125
 
108
126
  it('should not render the plan description if its falsy', () => {
109
- const mountSummaryInstance = new TestMountSummaryInstance({configs, options});
110
-
127
+ const mountSummaryInstance = new TestMountSummaryInstance({
128
+ options
129
+ });
130
+
111
131
  // Making one product description falsy
112
- productData[0].description = null;
113
- mountSummaryInstance.mountSummary({summary: summaryData, plans: planData, products: productData});
132
+ mountSummaryInstance.data.previewPurchase.lineItems[0].description = null;
133
+
134
+ //TODO: improve design to avoid this manual change
135
+ mountSummaryInstance.loader.DOM.summary = mountSummaryInstance.summary;
136
+
137
+ mountSummary({ state: mountSummaryInstance });
114
138
 
115
139
  // Check that only one description is render
116
- const itemsSynopsysDescription = document.querySelectorAll('.rebilly-instruments-summary-line-item-synopsis-description');
140
+ const itemsSynopsysDescription = document.querySelectorAll(
141
+ '.rebilly-instruments-summary-line-item-synopsis-description'
142
+ );
117
143
  expect(itemsSynopsysDescription.length).toEqual(1);
118
-
119
144
  });
120
- })
145
+ });
@@ -0,0 +1,22 @@
1
+ import { sleep } from '@/utils'
2
+
3
+ export async function avoidUnhandledPromises() {
4
+ // We need this sleep to avoid unhandled promises.
5
+ // This hack will be removed if we refactor the current design.
6
+ await sleep(100)
7
+ }
8
+
9
+ /**
10
+ * @param {Promise} promise
11
+ */
12
+ export async function expectConfigurationError(promise) {
13
+ const NoConfigOrOptionsError =
14
+ 'Could not use Rebilly Instruments mount options to fetch Rebilly data'
15
+ let error = null
16
+ try {
17
+ await promise
18
+ } catch (e) {
19
+ error = e
20
+ }
21
+ expect(error.message).toBe(NoConfigOrOptionsError)
22
+ }