@rebilly/instruments 3.0.0-beta.0 → 3.1.2-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 (169) hide show
  1. package/dist/index.js +88 -107
  2. package/dist/index.min.js +88 -0
  3. package/package.json +17 -6
  4. package/rollup.config.js +84 -0
  5. package/src/functions/mount/fetch-data.js +13 -1
  6. package/src/functions/mount/index.js +6 -42
  7. package/src/functions/mount/setup-framepay-theme.js +2 -2
  8. package/src/functions/mount/setup-options.js +3 -0
  9. package/src/functions/mount/setup-user-flow.js +49 -0
  10. package/src/functions/purchase.js +1 -1
  11. package/src/functions/setup.js +1 -1
  12. package/src/functions/show.spec.js +1 -1
  13. package/src/i18n/en.json +3 -0
  14. package/src/i18n/index.js +1 -1
  15. package/src/index.js +1 -61
  16. package/src/instance.js +65 -0
  17. package/src/{index.spec.js → instance.spec.js} +2 -1
  18. package/src/loader/index.js +21 -1
  19. package/src/storefront/models/ready-to-pay-model.js +13 -2
  20. package/src/storefront/plans.js +8 -4
  21. package/src/storefront/plans.spec.js +8 -2
  22. package/src/storefront/products.js +8 -4
  23. package/src/storefront/products.spec.js +8 -2
  24. package/src/storefront/ready-to-pay.js +5 -4
  25. package/src/style/base/__snapshots__/theme.spec.js.snap +34 -2
  26. package/src/style/base/default-theme.js +106 -3
  27. package/src/style/components/button.js +17 -1
  28. package/src/style/components/forms/label.js +0 -5
  29. package/src/style/components/loader.js +2 -1
  30. package/src/style/payment-instruments/payment-card.js +2 -1
  31. package/src/style/utils/remove-empty-null.js +9 -9
  32. package/src/style/vendor/postmate.js +13 -0
  33. package/src/style/views/confirmation.js +2 -1
  34. package/src/views/common/iframe/base-iframe.js +2 -0
  35. package/src/views/common/iframe/event-listeners.js +10 -0
  36. package/src/views/common/iframe/method-iframe.js +3 -1
  37. package/src/views/confirmation.js +1 -0
  38. package/src/views/method-selector/express-methods/{google-pay.js → index.js} +3 -2
  39. package/src/views/method-selector/mount-express-methods.js +6 -18
  40. package/src/views/result.js +1 -0
  41. package/tests/mocks/rebilly-instruments-mock.js +2 -2
  42. package/dist/events/base-event.js +0 -66
  43. package/dist/events/events.spec.js +0 -18
  44. package/dist/events/index.js +0 -22
  45. package/dist/functions/destroy.js +0 -34
  46. package/dist/functions/destroy.spec.js +0 -69
  47. package/dist/functions/mount/fetch-data.js +0 -187
  48. package/dist/functions/mount/fetch-data.spec.js +0 -189
  49. package/dist/functions/mount/index.js +0 -218
  50. package/dist/functions/mount/mount.spec.js +0 -64
  51. package/dist/functions/mount/setup-element.js +0 -40
  52. package/dist/functions/mount/setup-framepay-theme.js +0 -95
  53. package/dist/functions/mount/setup-framepay.js +0 -46
  54. package/dist/functions/mount/setup-i18n.js +0 -33
  55. package/dist/functions/mount/setup-options.js +0 -99
  56. package/dist/functions/mount/setup-options.spec.js +0 -66
  57. package/dist/functions/mount/setup-storefront.js +0 -34
  58. package/dist/functions/mount/setup-styles.js +0 -43
  59. package/dist/functions/on.js +0 -40
  60. package/dist/functions/on.spec.js +0 -55
  61. package/dist/functions/purchase.js +0 -158
  62. package/dist/functions/purchase.spec.js +0 -74
  63. package/dist/functions/setup.js +0 -85
  64. package/dist/functions/setup.spec.js +0 -87
  65. package/dist/functions/show.js +0 -55
  66. package/dist/functions/show.spec.js +0 -61
  67. package/dist/functions/update.js +0 -74
  68. package/dist/functions/update.spec.js +0 -86
  69. package/dist/i18n/en.json +0 -22
  70. package/dist/i18n/es.json +0 -22
  71. package/dist/i18n/i18n.spec.js +0 -22
  72. package/dist/i18n/index.js +0 -72
  73. package/dist/index.spec.js +0 -35
  74. package/dist/loader/index.js +0 -94
  75. package/dist/loader/loader.spec.js +0 -69
  76. package/dist/storefront/index.js +0 -73
  77. package/dist/storefront/invoices.js +0 -27
  78. package/dist/storefront/models/base-model.js +0 -18
  79. package/dist/storefront/models/invoice-model.js +0 -14
  80. package/dist/storefront/models/plan-model.js +0 -14
  81. package/dist/storefront/models/product-model.js +0 -14
  82. package/dist/storefront/models/ready-to-pay-model.js +0 -46
  83. package/dist/storefront/models/summary-model.js +0 -79
  84. package/dist/storefront/models/transaction-model.js +0 -31
  85. package/dist/storefront/payment-instruments.js +0 -47
  86. package/dist/storefront/payment-instruments.spec.js +0 -55
  87. package/dist/storefront/plans.js +0 -37
  88. package/dist/storefront/plans.spec.js +0 -64
  89. package/dist/storefront/products.js +0 -40
  90. package/dist/storefront/products.spec.js +0 -65
  91. package/dist/storefront/purchase.js +0 -43
  92. package/dist/storefront/purchase.spec.js +0 -48
  93. package/dist/storefront/ready-to-pay.js +0 -58
  94. package/dist/storefront/ready-to-pay.spec.js +0 -69
  95. package/dist/storefront/storefront.spec.js +0 -15
  96. package/dist/storefront/summary.js +0 -55
  97. package/dist/storefront/summary.spec.js +0 -124
  98. package/dist/storefront/transactions.js +0 -27
  99. package/dist/style/base/__snapshots__/theme.spec.js.snap +0 -195
  100. package/dist/style/base/default-theme.js +0 -699
  101. package/dist/style/base/index.js +0 -104
  102. package/dist/style/base/theme.js +0 -41
  103. package/dist/style/base/theme.spec.js +0 -19
  104. package/dist/style/browserslist.js +0 -8
  105. package/dist/style/components/address.js +0 -64
  106. package/dist/style/components/button.js +0 -71
  107. package/dist/style/components/divider.js +0 -48
  108. package/dist/style/components/forms/checkbox.js +0 -86
  109. package/dist/style/components/forms/field.js +0 -65
  110. package/dist/style/components/forms/form.js +0 -28
  111. package/dist/style/components/forms/input.js +0 -86
  112. package/dist/style/components/forms/label.js +0 -69
  113. package/dist/style/components/forms/select.js +0 -95
  114. package/dist/style/components/forms/validation.js +0 -81
  115. package/dist/style/components/icons.js +0 -22
  116. package/dist/style/components/index.js +0 -57
  117. package/dist/style/components/loader.js +0 -50
  118. package/dist/style/components/methods.js +0 -108
  119. package/dist/style/components/overlay.js +0 -33
  120. package/dist/style/helpers/index.js +0 -59
  121. package/dist/style/index.js +0 -50
  122. package/dist/style/payment-instruments/content.js +0 -17
  123. package/dist/style/payment-instruments/index.js +0 -20
  124. package/dist/style/payment-instruments/payment-card.js +0 -35
  125. package/dist/style/utils/border.js +0 -47
  126. package/dist/style/utils/color-values.js +0 -58
  127. package/dist/style/utils/remove-empty-null.js +0 -20
  128. package/dist/style/vendor/framepay.js +0 -37
  129. package/dist/style/vendor/postmate.js +0 -17
  130. package/dist/style/views/confirmation.js +0 -85
  131. package/dist/style/views/index.js +0 -29
  132. package/dist/style/views/method-selector.js +0 -20
  133. package/dist/style/views/modal.js +0 -93
  134. package/dist/style/views/result.js +0 -61
  135. package/dist/style/views/summary.js +0 -127
  136. package/dist/utils/add-dom-element.js +0 -26
  137. package/dist/utils/format-currency.js +0 -15
  138. package/dist/utils/has-valid-css-selector.js +0 -11
  139. package/dist/utils/index.js +0 -55
  140. package/dist/utils/is-dom-element.js +0 -10
  141. package/dist/utils/process-property-as-dom-element.js +0 -38
  142. package/dist/utils/sleep.js +0 -10
  143. package/dist/views/__snapshots__/summary.spec.js.snap +0 -246
  144. package/dist/views/common/iframe/base-iframe.js +0 -59
  145. package/dist/views/common/iframe/event-listeners.js +0 -50
  146. package/dist/views/common/iframe/index.js +0 -19
  147. package/dist/views/common/iframe/method-iframe.js +0 -33
  148. package/dist/views/common/iframe/modal-iframe.js +0 -84
  149. package/dist/views/common/iframe/view-iframe.js +0 -31
  150. package/dist/views/common/render-utilities.js +0 -11
  151. package/dist/views/confirmation.js +0 -92
  152. package/dist/views/method-selector/__snapshots__/method-selector.spec.js.snap +0 -3
  153. package/dist/views/method-selector/express-methods/apple-pay.js +0 -92
  154. package/dist/views/method-selector/express-methods/google-pay.js +0 -31
  155. package/dist/views/method-selector/express-methods/paypal.js +0 -19
  156. package/dist/views/method-selector/generate-digital-wallet.js +0 -68
  157. package/dist/views/method-selector/generate-digital-wallet.spec.js +0 -135
  158. package/dist/views/method-selector/get-method-data.js +0 -25
  159. package/dist/views/method-selector/get-payment-methods.js +0 -66
  160. package/dist/views/method-selector/get-payment-methods.spec.js +0 -46
  161. package/dist/views/method-selector/index.js +0 -122
  162. package/dist/views/method-selector/method-selector.spec.js +0 -124
  163. package/dist/views/method-selector/mount-express-methods.js +0 -69
  164. package/dist/views/method-selector/mount-methods.js +0 -74
  165. package/dist/views/modal.js +0 -88
  166. package/dist/views/result.js +0 -40
  167. package/dist/views/summary.js +0 -215
  168. package/dist/views/summary.spec.js +0 -134
  169. package/src/views/method-selector/express-methods/paypal.js +0 -7
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@rebilly/instruments",
3
- "version": "3.0.0-beta.0",
3
+ "version": "3.1.2-beta.0",
4
4
  "author": "Rebilly",
5
5
  "main": "dist/index.js",
6
+ "unpkg": "dist/index.min.js",
6
7
  "license": "MIT",
7
8
  "scripts": {
8
- "build": "yarn babel src --out-dir dist --copy-files",
9
- "dev": "yarn babel src --watch --out-dir dist",
9
+ "build": "yarn rollup -c --environment NODE_ENV:production",
10
+ "dev": "yarn rollup -c --watch --environment NODE_ENV:development",
10
11
  "test": "yarn jest",
11
12
  "test:watch": "yarn jest --watchAll"
12
13
  },
@@ -22,16 +23,26 @@
22
23
  "lodash.kebabcase": "^4.1.1",
23
24
  "lodash.merge": "^4.6.2",
24
25
  "popostmate": "^1.6.4",
25
- "postcss": "^8.3.6",
26
- "postcss-custom-properties": "^12.0.0",
26
+ "postcss": "^8.4.5",
27
+ "postcss-css-variables": "^0.18.0",
27
28
  "rebilly-js-sdk": "^44.4.0",
28
29
  "values.js": "^2.0.0"
29
30
  },
30
31
  "devDependencies": {
32
+ "@rollup/plugin-babel": "^5.1.0",
33
+ "@rollup/plugin-commonjs": "^14.0.0",
34
+ "@rollup/plugin-json": "^4.1.0",
35
+ "@rollup/plugin-node-resolve": "^8.4.0",
36
+ "@rollup/plugin-replace": "^3.0.0",
31
37
  "babel-plugin-module-resolver": "^4.1.0",
32
38
  "component-emitter": "^1.3.0",
33
39
  "jest": "^27.0.6",
34
40
  "msw": "^0.23.0",
35
- "msw-when-then": "^1.4.0"
41
+ "msw-when-then": "^1.4.0",
42
+ "rollup": "^2.35.1",
43
+ "rollup-plugin-ignore": "^1.0.10",
44
+ "rollup-plugin-polyfill-node": "^0.8.0",
45
+ "rollup-plugin-terser": "^7.0.2",
46
+ "rollup-plugin-version-injector": "^1.3.3"
36
47
  }
37
48
  }
@@ -0,0 +1,84 @@
1
+ import babel from '@rollup/plugin-babel';
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import commonjs from '@rollup/plugin-commonjs';
4
+ import json from '@rollup/plugin-json';
5
+ import replace from '@rollup/plugin-replace';
6
+ import nodePolyfills from 'rollup-plugin-polyfill-node';
7
+ import ignore from 'rollup-plugin-ignore';
8
+ import versionInjector from 'rollup-plugin-version-injector';
9
+ import { builtinModules } from 'module'
10
+ import { terser } from 'rollup-plugin-terser';
11
+
12
+ const isDevMode = (process.env.NODE_ENV === 'development');
13
+
14
+ const buildOptions = () => {
15
+ const options = [
16
+ // Locates a module in the project's node_modules
17
+ resolve({
18
+ extensions: [ '.mjs', '.js', '.jsx', '.json' ],
19
+ preferBuiltins: true,
20
+ mainFields: ['browser', 'jsnext:main', 'module', 'main']
21
+ }),
22
+ // Converts CommonJS to ES6 modules
23
+ commonjs(),
24
+ // Fix commonjs issues with virtual node
25
+ // https://github.com/proteriax/rollup-plugin-ignore/issues/3
26
+ // https://github.com/rollup/plugins/issues/248
27
+ // https://github.com/rollup/rollup-plugin-commonjs/issues/315
28
+ ignore(builtinModules, { commonjsBugFix: true }),
29
+ // Replace values at bundle time
30
+ replace({
31
+ preventAssignment: true,
32
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
33
+ }),
34
+ // Allows the use of named imports in addition to the default import on node modules
35
+ nodePolyfills(),
36
+ // Babel transpiling
37
+ babel({
38
+ exclude: 'node_modules/**',
39
+ babelHelpers: 'runtime',
40
+ skipPreflightCheck: true
41
+ }),
42
+ // Converts .json files to ES6 modules
43
+ json(),
44
+ ]
45
+ if (!isDevMode) {
46
+ options.push(
47
+ // Inject version from package.json (RebillyInstruments.version)
48
+ versionInjector(),
49
+ // Minify and reduce bundle file sizes
50
+ terser())
51
+ }
52
+ return options;
53
+ }
54
+
55
+ const buildOutput = () => {
56
+ const output = [
57
+ {
58
+ file: 'dist/index.js',
59
+ format: 'es',
60
+ sourcemap: isDevMode ? 'inline' : false,
61
+ },
62
+ ]
63
+ if (!isDevMode) {
64
+ output.push(
65
+ {
66
+ file: 'dist/index.min.js',
67
+ format: 'iife',
68
+ name: 'RebillyInstruments',
69
+ exports: 'default'
70
+ },
71
+ )
72
+ }
73
+ return output;
74
+ }
75
+
76
+ export default {
77
+ input: 'src/index.js',
78
+ output: [
79
+ ...buildOutput(),
80
+ ],
81
+ plugins: [
82
+ ...buildOptions(),
83
+ ],
84
+ };
@@ -83,7 +83,19 @@ export class DataInstance {
83
83
  }
84
84
 
85
85
  get isShippingRequired() {
86
- return this.products.some(product => product.requiresShipping);
86
+ return (this.products || []).some(product => product.requiresShipping);
87
+ }
88
+
89
+ toPostmatesModel() {
90
+ return {
91
+ ...this,
92
+ amountAndCurrency: this.amountAndCurrency,
93
+ isPayment: this.isPayment,
94
+ isPurchase: this.isPurchase,
95
+ summaryItems: this.summaryItems,
96
+ summaryLineItems: this.summaryLineItems,
97
+ isShippingRequired: this.isShippingRequired
98
+ }
87
99
  }
88
100
  }
89
101
 
@@ -2,8 +2,6 @@
2
2
  import { mountSummary } from '../../views/summary';
3
3
  import { mountMethodSelector } from '../../views/method-selector';
4
4
  import { fetchData } from './fetch-data';
5
- import { show } from '../show';
6
- import { on } from '../on';
7
5
  import setupElement from './setup-element';
8
6
  import setupStorefront from './setup-storefront';
9
7
  import setupOptions from './setup-options';
@@ -11,6 +9,7 @@ import setupFramepay from './setup-framepay';
11
9
  import setupStyles from './setup-styles';
12
10
  import setupI18n from './setup-i18n';
13
11
  import setupFramepayTheme from './setup-framepay-theme';
12
+ import setupUserFlow from './setup-user-flow';
14
13
 
15
14
  /**
16
15
  * @typedef {object} Item
@@ -81,6 +80,7 @@ export async function mount({
81
80
  try {
82
81
  state.data = {};
83
82
  state.options = {};
83
+
84
84
  // Setup DOM
85
85
  state.form = setupElement({ element: 'form', options });
86
86
  state.summary = setupElement({ element: 'summary', options });
@@ -97,7 +97,8 @@ export async function mount({
97
97
  state.mainStyle = await setupStyles({ options });
98
98
  state.data = await fetchData({ state });
99
99
  state.options.themeFramepay = await setupFramepayTheme({ state, options });
100
- const i18n = setupI18n({ state });
100
+ state.i18n = setupI18n({ state });
101
+
101
102
  setupFramepay({ state });
102
103
 
103
104
  if (state.data.transaction && state.data.transaction?.type === 'setup') {
@@ -111,48 +112,11 @@ export async function mount({
111
112
  if (state.summary) {
112
113
  mountSummary({ state });
113
114
  }
114
- i18n({state});
115
+ state.i18n({state});
115
116
  state.hasMounted = true;
116
117
  } catch (error) {
117
118
  throw error;
118
119
  }
119
120
 
120
- if (state.options.features.autoConfirmation) {
121
- on({
122
- eventName: 'instrument-ready',
123
- callback: (payload) => {
124
- show({
125
- componentName: 'confirmation',
126
- payload,
127
- state
128
- });
129
- }
130
- });
131
- }
132
-
133
- if (state.options.features.autoResult) {
134
- if (state.options.transactionType === 'setup') {
135
- on({
136
- eventName: 'setup-completed',
137
- callback: (payload) => {
138
- show({
139
- componentName: 'result',
140
- payload,
141
- state
142
- });
143
- }
144
- });
145
- } else {
146
- on({
147
- eventName: 'purchase-completed',
148
- callback: (payload) => {
149
- show({
150
- componentName: 'result',
151
- payload,
152
- state
153
- });
154
- }
155
- });
156
- }
157
- }
121
+ setupUserFlow({state});
158
122
  }
@@ -1,10 +1,10 @@
1
1
  import css from 'css';
2
2
  import postcss from 'postcss';
3
- import postcssCustomProperties from 'postcss-custom-properties';
3
+ import cssvariables from 'postcss-css-variables';
4
4
  import camelCase from 'lodash.camelcase';
5
5
 
6
6
  const resolveCssVars = async (rawCss) => postcss([
7
- postcssCustomProperties({ preserve: false })
7
+ cssvariables({ preserve: false })
8
8
  ])
9
9
  .process(rawCss, { from: undefined })
10
10
  .then(output => output.css);
@@ -31,6 +31,9 @@ export const defaults = {
31
31
  },
32
32
  paymentCard: {
33
33
  popup: false
34
+ },
35
+ paypal: {
36
+ buttonHeight: 44,
34
37
  }
35
38
  },
36
39
  transactionType: 'purchase',
@@ -0,0 +1,49 @@
1
+ import { on } from '../on';
2
+ import { show } from '../show';
3
+ import { purchase } from '../purchase';
4
+ import { setup } from '../setup';
5
+
6
+ function showResult({state, payload}) {
7
+ show({
8
+ componentName: 'result',
9
+ payload,
10
+ state
11
+ });
12
+ }
13
+
14
+ export default ({state = {}}) => {
15
+ if (state.options.features.autoConfirmation) {
16
+ on({
17
+ eventName: 'instrument-ready',
18
+ callback: (payload) => {
19
+ // Alternate flow for paypal.
20
+ if (payload._raw?.method === 'paypal') {
21
+ if (!state.data.isShippingRequired) {
22
+ if (state.options.transactionType === 'setup') {
23
+ setup({state, payload});
24
+ } else {
25
+ purchase({state, payload});
26
+ }
27
+ state.loader.startLoading({state, id: 'express-purchase', message: 'form.loaderMessages.processingPayment' });
28
+ return;
29
+ }
30
+ }
31
+ show({
32
+ componentName: 'confirmation',
33
+ payload,
34
+ state
35
+ });
36
+ }
37
+ });
38
+ }
39
+
40
+ if (state.options.features.autoResult) {
41
+ on({
42
+ eventName: state.options.transactionType === 'setup' ?
43
+ 'setup-completed' : 'purchase-completed',
44
+ callback: (payload) => {
45
+ showResult({state, payload});
46
+ }
47
+ });
48
+ }
49
+ }
@@ -93,7 +93,7 @@ export async function purchase({ state, payload }) {
93
93
  fields = await makePurchase({ state, payload });
94
94
  }
95
95
 
96
- if (fields.transaction?.approvalUrl) {
96
+ if (fields.transaction?.approvalUrl && fields.transaction?.result === 'unknown') {
97
97
  handleApprovalUrl({state, fields});
98
98
  } else {
99
99
  Events.purchaseCompleted.dispatch(fields);
@@ -16,7 +16,7 @@ export async function setup({ state, payload }) {
16
16
 
17
17
  state.data = new DataInstance({state, instrument, transaction});
18
18
 
19
- if (transaction.approvalUrl) {
19
+ if (transaction.approvalUrl && transaction.result === 'unknown') {
20
20
  const { paymentMethodsUrl } = state.options._computed;
21
21
  mountModal({
22
22
  state,
@@ -1,7 +1,7 @@
1
1
  import * as result from '@/views/result';
2
2
  import * as confirmation from '@/views/confirmation';
3
3
  import { RenderMockRebillyInstruments } from 'tests/mocks/rebilly-instruments-mock';
4
- import { RebillyInstrumentsInstance } from '../index';
4
+ import { RebillyInstrumentsInstance } from '../instance';
5
5
 
6
6
  const iframeMock = { destroy: jest.fn() };
7
7
 
package/src/i18n/en.json CHANGED
@@ -13,6 +13,9 @@
13
13
  "popupOverlayText": "Click here to show popup window",
14
14
  "error": {
15
15
  "noPaymentMethods": "No payment methods available for this transaction, please contact support."
16
+ },
17
+ "loaderMessages": {
18
+ "processingPayment": "Processing payment instrument."
16
19
  }
17
20
  },
18
21
  "paymentMethods": {
package/src/i18n/index.js CHANGED
@@ -12,7 +12,7 @@ export class Translate {
12
12
  init(locale, messages) {
13
13
  this.items = document.querySelectorAll('[data-rebilly-i18n]');
14
14
  this.locale = this.getLocale(locale);
15
- this.languages = merge({ ...en, ...es }, messages);
15
+ this.languages = merge({}, { ...en, ...es }, messages);
16
16
  }
17
17
 
18
18
  translateItems() {
package/src/index.js CHANGED
@@ -1,63 +1,3 @@
1
- import { mount } from './functions/mount';
2
- import { purchase } from './functions/purchase';
3
- import { setup } from './functions/setup';
4
- import { on } from './functions/on';
5
- import { update } from './functions/update';
6
- import { destroy } from './functions/destroy';
7
- import { Loader } from './loader';
8
- import { Translate } from './i18n';
9
- import { show } from './functions/show';
10
-
11
- export class InstrumentsState {
12
- constructor() {
13
- this.options = null;
14
- this.data = {};
15
- this.mountingPoints = null;
16
- this.storefront = null;
17
- this.form = null;
18
- this.summary = null;
19
- this.loader = new Loader();
20
- this.translate = new Translate();
21
- this.iframeComponents = [];
22
- this.hasMounted = false;
23
- }
24
- }
25
-
26
- export class RebillyInstrumentsInstance {
27
- constructor() {
28
- this.state = new InstrumentsState();
29
- // TODO: mountConfirmation, mountResult have different contract shape when they look similar
30
- // TODO: review test coverage of UpdateSummary and UpdateMethodSelector as no tests were broken
31
- // when commenting them
32
- }
33
-
34
- async mount(options) {
35
- await mount({ state: this.state, ...options });
36
- }
37
-
38
- async destroy() {
39
- await destroy({ state: this.state });
40
- }
41
-
42
- async update(newOptions) {
43
- await update({state: this.state, newOptions});
44
- }
45
-
46
- async purchase(payload) {
47
- await purchase({ state: this.state, payload });
48
- }
49
-
50
- async setup(payload) {
51
- await setup({ state: this.state, payload });
52
- }
53
-
54
- async show(componentName, payload) {
55
- await show({ state: this.state, componentName, payload });
56
- }
57
-
58
- on(eventName, callback) {
59
- on({ state: this.state, eventName, callback });
60
- }
61
- }
1
+ import { RebillyInstrumentsInstance } from './instance';
62
2
 
63
3
  export default new RebillyInstrumentsInstance();
@@ -0,0 +1,65 @@
1
+ import { mount } from './functions/mount';
2
+ import { purchase } from './functions/purchase';
3
+ import { setup } from './functions/setup';
4
+ import { on } from './functions/on';
5
+ import { update } from './functions/update';
6
+ import { destroy } from './functions/destroy';
7
+ import { Loader } from './loader';
8
+ import { Translate } from './i18n';
9
+ import { show } from './functions/show';
10
+
11
+ export class InstrumentsState {
12
+ constructor() {
13
+ this.options = null;
14
+ this.data = {};
15
+ this.mountingPoints = null;
16
+ this.storefront = null;
17
+ this.form = null;
18
+ this.summary = null;
19
+ this.loader = new Loader();
20
+ this.translate = new Translate();
21
+ this.iframeComponents = [];
22
+ this.hasMounted = false;
23
+ }
24
+ }
25
+
26
+ export class RebillyInstrumentsInstance {
27
+ constructor() {
28
+ this.state = new InstrumentsState();
29
+ // TODO: mountConfirmation, mountResult have different contract shape when they look similar
30
+ // TODO: review test coverage of UpdateSummary and UpdateMethodSelector as no tests were broken
31
+ // when commenting them
32
+ }
33
+
34
+ async mount(options) {
35
+ await mount({ state: this.state, ...options });
36
+ }
37
+
38
+ async destroy() {
39
+ await destroy({ state: this.state });
40
+ }
41
+
42
+ async update(newOptions) {
43
+ await update({state: this.state, newOptions});
44
+ }
45
+
46
+ async purchase(payload) {
47
+ await purchase({ state: this.state, payload });
48
+ }
49
+
50
+ async setup(payload) {
51
+ await setup({ state: this.state, payload });
52
+ }
53
+
54
+ async show(componentName, payload) {
55
+ await show({ state: this.state, componentName, payload });
56
+ }
57
+
58
+ get version() {
59
+ return 'RebillyInstruments Ver.[VI]{version}[/VI]';
60
+ }
61
+
62
+ on(eventName, callback) {
63
+ on({ state: this.state, eventName, callback });
64
+ }
65
+ }
@@ -1,4 +1,5 @@
1
- import RebillyInstruments, { RebillyInstrumentsInstance } from './index';
1
+ import RebillyInstruments from './index';
2
+ import { RebillyInstrumentsInstance } from './instance';
2
3
  import { avoidUnhandledPromises } from 'tests/async-utilities';
3
4
 
4
5
  describe('RebillyInstruments instance', () => {
@@ -9,6 +9,7 @@ export class Loader {
9
9
  loading: `
10
10
  <div class="rebilly-instruments-loader is-active">
11
11
  <div class="rebilly-instruments-loader-spinner"></div>
12
+ <span class="rebilly-instuments-loader-message"><span>
12
13
  </div>
13
14
  `
14
15
  };
@@ -22,7 +23,7 @@ export class Loader {
22
23
  }
23
24
  }
24
25
 
25
- startLoading({ section = 'form', id = '' } = {}) {
26
+ startLoading({state, section = 'form', id = '', message = null } = {}) {
26
27
  const minHeight = '200px';
27
28
  this[section].push(id);
28
29
 
@@ -36,6 +37,17 @@ export class Loader {
36
37
  }
37
38
  this.DOM[section].style.minHeight = minHeight;
38
39
  }
40
+
41
+ if (message) {
42
+ const loaderMessage = this.DOM[section].querySelector('.rebilly-instuments-loader-message');
43
+ if (loaderMessage) {
44
+ loaderMessage.innerHTML = message;
45
+ loaderMessage.style.marginTop = '10px';
46
+ loaderMessage.setAttribute('data-message-id', id);
47
+ loaderMessage.setAttribute('data-rebilly-i18n', message);
48
+ state.i18n({state});
49
+ }
50
+ }
39
51
  }
40
52
 
41
53
  stopLoading({ section = 'form', id = '' } = {}) {
@@ -54,6 +66,14 @@ export class Loader {
54
66
  .classList.remove('is-active');
55
67
  this.DOM[section].style.minHeight = '';
56
68
  }
69
+
70
+ const loaderMessage = this.DOM[section].querySelector(`.rebilly-instuments-loader-message[data-message-id="${id}"]`);
71
+ if (loaderMessage) {
72
+ loaderMessage.innerHTML = null;
73
+ loaderMessage.style.marginTop = '0px';
74
+ loaderMessage.removeAttribute('data-message-id');
75
+ loaderMessage.removeAttribute('data-rebilly-i18n');
76
+ }
57
77
  }
58
78
 
59
79
  clearAll() {
@@ -1,18 +1,29 @@
1
1
  export class ReadyToPayFeatureModel {
2
2
  constructor({
3
3
  name = '',
4
+ expirationTime = '',
5
+
4
6
  // Google Pay fields
5
7
  merchantName = '',
6
8
  merchantOrigin = '',
9
+
10
+ // Paypal fields
11
+ paypalMerchantId = '',
12
+ billingAgreementToken = '',
13
+
7
14
  // Plaid fields
8
15
  linkToken = '',
9
- expirationTime = ''
10
16
  } = {}) {
11
17
  this.name = name;
18
+ this.expirationTime = expirationTime;
19
+
12
20
  this.merchantName = merchantName;
13
21
  this.merchantOrigin = merchantOrigin;
22
+
23
+ this.paypalMerchantId = paypalMerchantId;
24
+ this.billingAgreementToken = billingAgreementToken;
25
+
14
26
  this.linkToken = linkToken;
15
- this.expirationTime = expirationTime;
16
27
  }
17
28
  }
18
29
 
@@ -15,9 +15,13 @@ export async function fetchPlans({ state = {}, data = {} }) {
15
15
  .join(',')}`;
16
16
  }
17
17
 
18
- const { items: planItems } = await state.storefront.plans.getAll(
19
- filterByPlanId
20
- );
21
- return planItems.map(({ fields }) => new PlanModel(fields));
18
+ // Only fetch plans if we hae specific plans to fetch
19
+ if (filterByPlanId.filter.length) {
20
+ const { items: planItems } = await state.storefront.plans.getAll(
21
+ filterByPlanId
22
+ );
23
+ return planItems.map(({ fields }) => new PlanModel(fields));
24
+ }
25
+ return [];
22
26
  });
23
27
  }
@@ -16,11 +16,17 @@ describe('Storefront API Plan', () => {
16
16
 
17
17
  jest.spyOn(instance.storefront.plans, 'getAll');
18
18
 
19
- const response = await fetchPlans({ state: instance });
19
+ const response = await fetchPlans({ state: instance, data: {
20
+ lineItems: [
21
+ {
22
+ planId: 'test-plan-id'
23
+ }
24
+ ]
25
+ } });
20
26
 
21
27
  expect(instance.storefront.plans.getAll).toBeCalledTimes(1);
22
28
  expect(instance.storefront.plans.getAll).toBeCalledWith({
23
- filter: ''
29
+ filter: 'id:test-plan-id'
24
30
  });
25
31
  expect(response).toBeInstanceOf(Array);
26
32
  expect(response[0]).toBeInstanceOf(PlanModel);
@@ -18,9 +18,13 @@ export async function fetchProducts({ state }) {
18
18
  .join(',')}`;
19
19
  }
20
20
 
21
- const { items: productItems } = await state.storefront.products.getAll(
22
- filterByProductId
23
- );
24
- return productItems.map(({ fields }) => new ProductModel(fields));
21
+ // Only fetch products if we hae specific products to fetch
22
+ if (filterByProductId.filter.length) {
23
+ const { items: productItems } = await state.storefront.products.getAll(
24
+ filterByProductId
25
+ );
26
+ return productItems.map(({ fields }) => new ProductModel(fields));
27
+ }
28
+ return [];
25
29
  });
26
30
  }
@@ -12,7 +12,13 @@ describe('Storefront API Plan', () => {
12
12
 
13
13
  when(get(`${storefrontURL}/products`)).thenReturn(ok([testProduct]));
14
14
 
15
- const instance = new StorefontTestingInstance();
15
+ const instance = new StorefontTestingInstance({
16
+ data: {
17
+ plans: [{
18
+ productId: 'test-product-id'
19
+ }
20
+ ]}
21
+ });
16
22
 
17
23
  jest.spyOn(instance.storefront.products, 'getAll');
18
24
 
@@ -20,7 +26,7 @@ describe('Storefront API Plan', () => {
20
26
 
21
27
  expect(instance.storefront.products.getAll).toBeCalledTimes(1);
22
28
  expect(instance.storefront.products.getAll).toBeCalledWith({
23
- filter: ''
29
+ filter: 'id:test-product-id'
24
30
  });
25
31
  expect(response).toBeInstanceOf(Array);
26
32
  expect(response[0]).toBeInstanceOf(ProductModel);