@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.
- package/.babelrc +13 -4
- package/.eslintrc.js +3 -0
- package/.prettierrc.js +11 -0
- package/README.md +15 -314
- package/dist/events/base-event.js +6 -9
- package/dist/events/events.spec.js +4 -4
- package/dist/events/index.js +2 -1
- package/dist/functions/destroy.js +12 -14
- package/dist/functions/destroy.spec.js +3 -3
- package/dist/functions/mount/fetch-data.js +183 -0
- package/dist/functions/mount/fetch-data.spec.js +189 -0
- package/dist/functions/mount/index.js +158 -251
- package/dist/functions/mount/mount.spec.js +24 -121
- package/dist/functions/mount/setup-element.js +40 -0
- package/dist/functions/mount/setup-framepay.js +46 -0
- package/dist/functions/mount/setup-i18n.js +33 -0
- package/dist/functions/mount/setup-options.js +96 -0
- package/dist/functions/mount/setup-options.spec.js +66 -0
- package/dist/functions/mount/setup-storefront.js +34 -0
- package/dist/functions/mount/setup-styles.js +43 -0
- package/dist/functions/on.js +13 -4
- package/dist/functions/on.spec.js +19 -5
- package/dist/functions/purchase.js +139 -22
- package/dist/functions/purchase.spec.js +23 -19
- package/dist/functions/setup.js +85 -0
- package/dist/functions/setup.spec.js +87 -0
- package/dist/functions/show.js +31 -14
- package/dist/functions/show.spec.js +47 -18
- package/dist/functions/update.js +53 -27
- package/dist/functions/update.spec.js +40 -21
- package/dist/i18n/en.json +4 -1
- package/dist/i18n/es.json +4 -1
- package/dist/index.js +67 -56
- package/dist/index.spec.js +7 -27
- package/dist/loader/index.js +4 -3
- package/dist/storefront/index.js +33 -0
- package/dist/storefront/invoices.js +27 -0
- package/dist/storefront/models/base-model.js +18 -0
- package/dist/storefront/models/invoice-model.js +14 -0
- package/dist/storefront/models/plan-model.js +4 -35
- package/dist/storefront/models/product-model.js +4 -23
- package/dist/storefront/models/summary-model.js +12 -25
- package/dist/storefront/models/transaction-model.js +31 -0
- package/dist/storefront/payment-instruments.js +47 -0
- package/dist/storefront/payment-instruments.spec.js +55 -0
- package/dist/storefront/plans.js +15 -24
- package/dist/storefront/plans.spec.js +17 -44
- package/dist/storefront/products.js +16 -20
- package/dist/storefront/products.spec.js +25 -49
- package/dist/storefront/purchase.js +28 -16
- package/dist/storefront/purchase.spec.js +4 -22
- package/dist/storefront/ready-to-pay.js +26 -22
- package/dist/storefront/ready-to-pay.spec.js +25 -54
- package/dist/storefront/storefront.spec.js +1 -1
- package/dist/storefront/summary.js +27 -24
- package/dist/storefront/summary.spec.js +44 -86
- package/dist/storefront/transactions.js +27 -0
- package/dist/style/base/theme.js +3 -3
- package/dist/style/components/methods.js +43 -42
- package/dist/style/utils/color-values.js +1 -3
- package/dist/style/views/confirmation.js +0 -4
- package/dist/style/views/method-selector.js +1 -1
- package/dist/style/views/modal.js +3 -1
- package/dist/style/views/summary.js +5 -1
- package/dist/utils/format-currency.js +4 -2
- package/dist/utils/has-valid-css-selector.js +1 -1
- package/dist/utils/process-property-as-dom-element.js +0 -2
- package/dist/views/__snapshots__/summary.spec.js.snap +103 -113
- package/dist/views/common/iframe/base-iframe.js +10 -2
- package/dist/views/common/iframe/modal-iframe.js +44 -3
- package/dist/views/confirmation.js +44 -20
- package/dist/views/method-selector/express-methods/apple-pay.js +92 -0
- package/dist/views/method-selector/express-methods/google-pay.js +31 -0
- package/dist/views/method-selector/express-methods/paypal.js +19 -0
- package/dist/views/method-selector/generate-digital-wallet.js +68 -0
- package/dist/views/method-selector/generate-digital-wallet.spec.js +135 -0
- package/dist/views/method-selector/get-payment-methods.js +28 -8
- package/dist/views/method-selector/get-payment-methods.spec.js +25 -26
- package/dist/views/method-selector/index.js +55 -86
- package/dist/views/method-selector/method-selector.spec.js +80 -69
- package/dist/views/method-selector/mount-express-methods.js +38 -62
- package/dist/views/method-selector/mount-methods.js +18 -18
- package/dist/views/modal.js +21 -15
- package/dist/views/result.js +13 -16
- package/dist/views/summary.js +170 -114
- package/dist/views/summary.spec.js +72 -76
- package/package.json +5 -4
- package/src/events/base-event.js +15 -17
- package/src/events/events.spec.js +6 -4
- package/src/events/index.js +6 -3
- package/src/functions/destroy.js +12 -13
- package/src/functions/destroy.spec.js +30 -31
- package/src/functions/mount/fetch-data.js +148 -0
- package/src/functions/mount/fetch-data.spec.js +238 -0
- package/src/functions/mount/index.js +129 -244
- package/src/functions/mount/mount.spec.js +35 -139
- package/src/functions/mount/setup-element.js +26 -0
- package/src/functions/mount/setup-framepay.js +41 -0
- package/src/functions/mount/setup-i18n.js +19 -0
- package/src/functions/mount/setup-options.js +100 -0
- package/src/functions/mount/setup-options.spec.js +60 -0
- package/src/functions/mount/setup-storefront.js +24 -0
- package/src/functions/mount/setup-styles.js +30 -0
- package/src/functions/on.js +13 -8
- package/src/functions/on.spec.js +30 -17
- package/src/functions/purchase.js +101 -19
- package/src/functions/purchase.spec.js +18 -18
- package/src/functions/setup.js +48 -0
- package/src/functions/setup.spec.js +98 -0
- package/src/functions/show.js +20 -10
- package/src/functions/show.spec.js +43 -22
- package/src/functions/update.js +50 -27
- package/src/functions/update.spec.js +57 -22
- package/src/i18n/en.json +4 -1
- package/src/i18n/es.json +4 -1
- package/src/i18n/i18n.spec.js +6 -4
- package/src/i18n/index.js +14 -11
- package/src/index.js +41 -52
- package/src/index.spec.js +8 -37
- package/src/loader/index.js +51 -47
- package/src/loader/loader.spec.js +26 -19
- package/src/storefront/index.js +37 -7
- package/src/storefront/invoices.js +11 -0
- package/src/storefront/models/base-model.js +10 -0
- package/src/storefront/models/invoice-model.js +3 -0
- package/src/storefront/models/plan-model.js +3 -35
- package/src/storefront/models/product-model.js +3 -23
- package/src/storefront/models/ready-to-pay-model.js +3 -3
- package/src/storefront/models/summary-model.js +15 -29
- package/src/storefront/models/transaction-model.js +19 -0
- package/src/storefront/payment-instruments.js +30 -0
- package/src/storefront/payment-instruments.spec.js +69 -0
- package/src/storefront/plans.js +16 -23
- package/src/storefront/plans.spec.js +25 -54
- package/src/storefront/products.js +18 -22
- package/src/storefront/products.spec.js +23 -54
- package/src/storefront/purchase.js +14 -14
- package/src/storefront/purchase.spec.js +17 -29
- package/src/storefront/ready-to-pay.js +26 -23
- package/src/storefront/ready-to-pay.spec.js +41 -71
- package/src/storefront/storefront.spec.js +1 -1
- package/src/storefront/summary.js +26 -22
- package/src/storefront/summary.spec.js +60 -109
- package/src/storefront/transactions.js +11 -0
- package/src/style/base/theme.js +10 -8
- package/src/style/base/theme.spec.js +4 -2
- package/src/style/browserslist.js +1 -3
- package/src/style/components/button.js +3 -1
- package/src/style/components/forms/checkbox.js +3 -1
- package/src/style/components/index.js +1 -1
- package/src/style/components/loader.js +3 -1
- package/src/style/components/methods.js +43 -42
- package/src/style/helpers/index.js +1 -1
- package/src/style/index.js +2 -1
- package/src/style/utils/color-values.js +4 -4
- package/src/style/vendor/framepay.js +1 -1
- package/src/style/vendor/postmate.js +1 -1
- package/src/style/views/confirmation.js +0 -4
- package/src/style/views/index.js +1 -1
- package/src/style/views/method-selector.js +1 -1
- package/src/style/views/modal.js +4 -2
- package/src/style/views/summary.js +5 -1
- package/src/utils/add-dom-element.js +12 -13
- package/src/utils/format-currency.js +6 -2
- package/src/utils/has-valid-css-selector.js +2 -2
- package/src/utils/is-dom-element.js +1 -1
- package/src/utils/process-property-as-dom-element.js +27 -24
- package/src/utils/sleep.js +1 -1
- package/src/views/__snapshots__/summary.spec.js.snap +103 -113
- package/src/views/common/iframe/base-iframe.js +12 -4
- package/src/views/common/iframe/event-listeners.js +6 -6
- package/src/views/common/iframe/index.js +1 -1
- package/src/views/common/iframe/method-iframe.js +3 -6
- package/src/views/common/iframe/modal-iframe.js +42 -6
- package/src/views/common/iframe/view-iframe.js +3 -5
- package/src/views/common/render-utilities.js +3 -3
- package/src/views/confirmation.js +34 -25
- package/src/views/method-selector/express-methods/apple-pay.js +78 -0
- package/src/views/method-selector/express-methods/google-pay.js +24 -0
- package/src/views/method-selector/express-methods/paypal.js +7 -0
- package/src/views/method-selector/generate-digital-wallet.js +51 -0
- package/src/views/method-selector/generate-digital-wallet.spec.js +135 -0
- package/src/views/method-selector/get-method-data.js +7 -4
- package/src/views/method-selector/get-payment-methods.js +38 -29
- package/src/views/method-selector/get-payment-methods.spec.js +26 -33
- package/src/views/method-selector/index.js +70 -99
- package/src/views/method-selector/method-selector.spec.js +88 -78
- package/src/views/method-selector/mount-express-methods.js +36 -60
- package/src/views/method-selector/mount-methods.js +32 -21
- package/src/views/modal.js +37 -23
- package/src/views/result.js +12 -15
- package/src/views/summary.js +169 -101
- package/src/views/summary.spec.js +99 -74
- package/tests/async-utilities.js +22 -0
- package/tests/mocks/rebilly-instruments-mock.js +89 -77
- package/tests/mocks/storefront-api-mock.js +8 -0
- package/tests/mocks/storefront-mock.js +17 -0
- package/dist/events/purchase-completed.js +0 -24
- package/dist/functions/initialize.js +0 -82
- package/dist/functions/initialize.spec.js +0 -34
- package/dist/functions/mount/fetch-summary-data.js +0 -31
- package/dist/functions/mount/fetch-summary-data.spec.js +0 -45
- package/dist/views/method-selector/process-digital-wallet-options.js +0 -35
- package/dist/views/method-selector/process-digital-wallet-options.spec.js +0 -80
- package/src/events/purchase-completed.js +0 -11
- package/src/functions/initialize.js +0 -74
- package/src/functions/initialize.spec.js +0 -38
- package/src/functions/mount/fetch-summary-data.js +0 -26
- package/src/functions/mount/fetch-summary-data.spec.js +0 -46
- package/src/views/method-selector/process-digital-wallet-options.js +0 -16
- package/src/views/method-selector/process-digital-wallet-options.spec.js +0 -94
|
@@ -1,271 +1,156 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { mountSummary } from '../../views/summary';
|
|
3
|
+
import { mountMethodSelector } from '../../views/method-selector';
|
|
4
|
+
import { fetchData } from './fetch-data';
|
|
5
|
+
import { show } from '../show';
|
|
6
|
+
import { on } from '../on';
|
|
7
|
+
import setupElement from './setup-element';
|
|
8
|
+
import setupStorefront from './setup-storefront';
|
|
9
|
+
import setupOptions from './setup-options';
|
|
10
|
+
import setupFramepay from './setup-framepay';
|
|
11
|
+
import setupStyles from './setup-styles';
|
|
12
|
+
import setupI18n from './setup-i18n';
|
|
7
13
|
|
|
8
14
|
/**
|
|
9
15
|
* @typedef {object} Item
|
|
10
16
|
* @property {string} planId - The Rebilly id of the plan.
|
|
11
17
|
* @property {number} quantity - The number of the plans to be purchased.
|
|
12
18
|
* @property {string} thumbnail - The source img for the product. Recommend 100px by 100px.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* @
|
|
17
|
-
* @property {
|
|
18
|
-
*
|
|
19
|
-
* @
|
|
20
|
-
* @property {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
* @typedef {
|
|
25
|
-
* @
|
|
26
|
-
*
|
|
27
|
-
* @
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* @
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* @typedef {object} PaymentCard
|
|
38
|
-
* @param {boolean} popup - default: false. Show method as a button with a form popup
|
|
39
|
-
* <br>Otherwise the form will be mounted inline.
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
/**
|
|
19
|
+
*
|
|
20
|
+
* @typedef {object} GooglePayDisplayOptions
|
|
21
|
+
* @property {"back" | "white"} [buttonColor=black] - Color of google pay button
|
|
22
|
+
* @property {"short" | "long"} [buttonType=short] - The length of the button
|
|
23
|
+
* @property {string} [buttonHeight=44px] - The value and units of the button to match other payment buttons
|
|
24
|
+
*
|
|
25
|
+
* @typedef {object} ApplePayDisplayOptions
|
|
26
|
+
* @property {"back" | "white"} [buttonColor=black] - Color of apple pay button
|
|
27
|
+
* @property {"short" | "long"} [buttonType=short] - The length of the button
|
|
28
|
+
* @property {string} [buttonHeight=44px] - The value and units of the button to match other payment buttons
|
|
29
|
+
*
|
|
30
|
+
* @typedef {object} ApplePayMerchantOptions
|
|
31
|
+
* @property {string} merchantName - The name of the merchant store.
|
|
32
|
+
*
|
|
33
|
+
* @typedef {object} GooglePay
|
|
34
|
+
* @property {GooglePayDisplayOptions} displayOptions - display options for google pay instrument
|
|
35
|
+
*
|
|
36
|
+
* @typedef {object} ApplePay
|
|
37
|
+
* @property {ApplePayDisplayOptions} displayOptions - display options for apple pay instrument
|
|
38
|
+
* @property {ApplePayMerchantOptions} merchantOptions - merchant options for apple pay instrument
|
|
39
|
+
*
|
|
40
|
+
* @typedef {object} PaymentCard
|
|
41
|
+
* @property {boolean} [popup=true] - Show method as a button with a form popup. Otherwise the form will be mounted inline.
|
|
42
|
+
*
|
|
43
43
|
* @typedef {object} Address
|
|
44
|
-
* @
|
|
45
|
-
* @
|
|
46
|
-
* @
|
|
47
|
-
* @
|
|
48
|
-
* @
|
|
49
|
-
*
|
|
50
|
-
* <br>First name and last name are always required. Country is always required if the products require shipping.
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
/**
|
|
44
|
+
* @property {string} [name=default] - One of default, combined, or stacked.
|
|
45
|
+
* @property {string} [region=default] - One of default, split, or stacked.
|
|
46
|
+
* @property {Array.<"organization" | "phoneNumber">} show - Show extra fields listed.
|
|
47
|
+
* @property {Array.<"address" | "address2" | "email | "country" | "region" | "postalCode"">} hide - Hide the listed fields.
|
|
48
|
+
* @property {Array.<"organization" | "address" | "address2" | "email" | "phoneNumber" | "country" | "region" | "postalCode">} require - Require the listed fields.
|
|
49
|
+
*
|
|
54
50
|
* @typedef {object} PaymentInstruments
|
|
55
|
-
* @
|
|
56
|
-
*
|
|
57
|
-
* @
|
|
58
|
-
* @
|
|
59
|
-
* @
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* @
|
|
64
|
-
* @param {boolean} autoConfirmation - default: true. Will mount the confirmation screen after `instrument-ready`
|
|
65
|
-
* <br>event is triggered. Will need to trigger purchase manually if set to false.
|
|
66
|
-
* <br>Can use RebillyInstruments.show('confirmation', options) to mount defautl component
|
|
67
|
-
* @param {boolean} autoResult - default: true. Show results of transaction after `purchase-completed` event is triggered
|
|
68
|
-
* <br>Will need to handle purchase result manually if set to false.
|
|
69
|
-
* <br>Can use RebillyInstruments.show('result', options) to display default component
|
|
70
|
-
*/
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* @typedef {object} Options
|
|
74
|
-
* @property {Intent} intent - The information required for purchaseing or vaulting an instrument
|
|
75
|
-
* @property {PaymentInstruments} paymentInstruments - settings for various payment instruments
|
|
76
|
-
* @property {Features} features - flags to enable and disable different features
|
|
77
|
-
* @property {string} locale - default: auto. Language to render component text
|
|
51
|
+
* @property {boolean} [compactExpressInstruments=true] - Show express methods as inline pill buttons, or list of full width button.
|
|
52
|
+
* @property {PaymentCard} paymentCard - settings for payment card instruments
|
|
53
|
+
* @property {GooglePay} googlePay - settings for google pay instruments
|
|
54
|
+
* @property {ApplePay} applePay - settings for apple pay instruments
|
|
55
|
+
* @property {Address} address - customization for address components for all payment instruments.
|
|
56
|
+
*
|
|
57
|
+
* @typedef {object} Features
|
|
58
|
+
* @property {boolean} [autoConfirmation=true] - Will mount the confirmation screen after `instrument-ready` event is triggered.
|
|
59
|
+
* @property {boolean} [autoResult=true] - Show results of transaction after `purchase-completed` event is triggered
|
|
78
60
|
*/
|
|
79
61
|
|
|
80
62
|
/**
|
|
81
63
|
* Mount library with configurations.
|
|
82
|
-
* @param {
|
|
83
|
-
* @param {
|
|
84
|
-
* @param {
|
|
64
|
+
* @param {object} options - The options object
|
|
65
|
+
* @param {object} options.state - Global state
|
|
66
|
+
* @param {string | HTMLElement} options.form - The CSS class or HTML element were the form will be mounted.
|
|
67
|
+
* @param {string | HTMLElement} options.summary - The CSS class or HTML element were the summary will be mounted.
|
|
68
|
+
* @param {Item[]} options.items - Which plans the customer is purchasing.
|
|
69
|
+
* @param {string} options.invoiceId - The Rebilly id of the invoice used for purchasing.
|
|
70
|
+
* @param {string} options.customerJwt - The customer token to access the invoice.
|
|
71
|
+
* @param {string} [options.countryCode=USD] - The country code for the transaction
|
|
72
|
+
* @param {PaymentInstruments} options.paymentInstruments - settings for various payment instruments
|
|
73
|
+
* @param {Features} options.features - flags to enable and disable different features
|
|
74
|
+
* @param {string} options.locale - default: auto. Language to render component text
|
|
85
75
|
*/
|
|
86
|
-
export async function
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
options = {},
|
|
91
|
-
_dev = null,
|
|
92
|
-
} = {},
|
|
93
|
-
) {
|
|
94
|
-
this.form = form;
|
|
95
|
-
this.summary = summary;
|
|
96
|
-
this.mainStyle = null;
|
|
97
|
-
this._dev = _dev;
|
|
98
|
-
|
|
99
|
-
const framePayUrls = {
|
|
100
|
-
script: _dev ? _dev.framePayScriptLink || 'https://framepay.rebilly.com/rebilly.js' : 'https://framepay.rebilly.com/rebilly.js',
|
|
101
|
-
style: _dev ? _dev.framePayStyleLink || 'https://framepay.rebilly.com/rebilly.css' : 'https://framepay.rebilly.com/rebilly.css'
|
|
102
|
-
};
|
|
103
|
-
const _computed = {
|
|
104
|
-
paymentMethodsUrl: _dev ? _dev.paymentMethodsUrl || 'https://forms.local.rebilly.dev:3000' : 'https://forms.secure-payments.app',
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const OPTIONS_DEFAULTS = {
|
|
108
|
-
intent: {
|
|
109
|
-
countryCode: 'US'
|
|
110
|
-
},
|
|
111
|
-
locale: 'auto',
|
|
112
|
-
paymentInstruments: {
|
|
113
|
-
address: {
|
|
114
|
-
name: 'default',
|
|
115
|
-
region: 'default',
|
|
116
|
-
hide: [],
|
|
117
|
-
show: [],
|
|
118
|
-
require: [],
|
|
119
|
-
},
|
|
120
|
-
compactExpressInstruments: true,
|
|
121
|
-
googlePay: {
|
|
122
|
-
displayOptions: {
|
|
123
|
-
buttonColor: 'black',
|
|
124
|
-
buttonType: 'short',
|
|
125
|
-
buttonHeight: '44px'
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
paymentCard: {
|
|
129
|
-
popup: false
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
features: {
|
|
133
|
-
autoConfirmation: true,
|
|
134
|
-
autoResult: true
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const combinedOptions = {...options, _computed};
|
|
139
|
-
if (_dev) {
|
|
140
|
-
combinedOptions._dev = _dev;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
this.options = merge(OPTIONS_DEFAULTS, combinedOptions);
|
|
144
|
-
this.form = processPropertyAsDOMElement({prop: this.form, propName: 'form'});
|
|
145
|
-
this.summary = processPropertyAsDOMElement({prop: this.summary, propName: 'summary', isRequired: false});
|
|
146
|
-
|
|
147
|
-
// Setup loader
|
|
148
|
-
this.loader.addDOMElement({el: this.form});
|
|
149
|
-
this.loader.addDOMElement({section: 'summary', el: this.summary});
|
|
150
|
-
|
|
151
|
-
// Adds base stylesheet
|
|
152
|
-
this.mainStyle = await mainStyle(this.configs?.theme || {});
|
|
153
|
-
addDOMElement(
|
|
154
|
-
{
|
|
155
|
-
element: 'style',
|
|
156
|
-
attributes: {type: 'text/css'},
|
|
157
|
-
content: this.mainStyle,
|
|
158
|
-
target: 'head'
|
|
159
|
-
}
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
// Adds configs CSS to override any styles
|
|
163
|
-
if (this.configs.css) {
|
|
164
|
-
addDOMElement(
|
|
165
|
-
{
|
|
166
|
-
element: 'style',
|
|
167
|
-
attributes: {type: 'text/css'},
|
|
168
|
-
content: this.configs.css,
|
|
169
|
-
target: 'head'
|
|
170
|
-
}
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Adds FramePay
|
|
175
|
-
if (!document.querySelectorAll('[framepay*="script"]').length) {
|
|
176
|
-
addDOMElement(
|
|
177
|
-
{
|
|
178
|
-
element: 'script',
|
|
179
|
-
attributes: {
|
|
180
|
-
'framepay': 'script',
|
|
181
|
-
src: framePayUrls.script
|
|
182
|
-
},
|
|
183
|
-
target: 'head'
|
|
184
|
-
}
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if(!document.querySelectorAll('[framepay*="stylesheet"]').length) {
|
|
189
|
-
addDOMElement(
|
|
190
|
-
{
|
|
191
|
-
element: 'link',
|
|
192
|
-
attributes: {
|
|
193
|
-
'framepay': 'stylesheet',
|
|
194
|
-
href: framePayUrls.style,
|
|
195
|
-
rel: 'stylesheet'
|
|
196
|
-
},
|
|
197
|
-
target: 'head'
|
|
198
|
-
}
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
|
|
76
|
+
export async function mount({
|
|
77
|
+
state,
|
|
78
|
+
...options
|
|
79
|
+
} = {}) {
|
|
202
80
|
try {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
81
|
+
state.data = {};
|
|
82
|
+
state.options = {};
|
|
83
|
+
// Setup DOM
|
|
84
|
+
state.form = setupElement({ element: 'form', options });
|
|
85
|
+
state.summary = setupElement({ element: 'summary', options });
|
|
86
|
+
|
|
87
|
+
// Setup loader
|
|
88
|
+
state.loader.addDOMElement({ el: state.form });
|
|
89
|
+
state.loader.addDOMElement({ section: 'summary', el: state.summary });
|
|
90
|
+
state.loader.startLoading({ section: 'summary', id: 'initSummary' });
|
|
91
|
+
state.loader.startLoading({ id: 'initForm' });
|
|
92
|
+
|
|
93
|
+
// Setup state
|
|
94
|
+
state.storefront = setupStorefront({ options });
|
|
95
|
+
state.options = setupOptions({ options });
|
|
96
|
+
state.mainStyle = await setupStyles({ options });
|
|
97
|
+
state.data = await fetchData({ state });
|
|
98
|
+
const i18n = setupI18n({ state });
|
|
99
|
+
setupFramepay({ state });
|
|
100
|
+
|
|
101
|
+
if (state.data.transaction && state.data.transaction?.type === 'setup') {
|
|
102
|
+
state.options.transactionType = 'setup';
|
|
211
103
|
}
|
|
212
104
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const {
|
|
217
|
-
readyToPay,
|
|
218
|
-
summary: summaryData,
|
|
219
|
-
plans,
|
|
220
|
-
products
|
|
221
|
-
} = await FetchSummaryData.call(this, { riskMetadata });
|
|
222
|
-
|
|
223
|
-
this.hasMounted = true;
|
|
224
|
-
|
|
225
|
-
if (this.form) {
|
|
226
|
-
this.formOptions = {
|
|
227
|
-
summary: summaryData,
|
|
228
|
-
mainStyle: this.mainStyle,
|
|
229
|
-
readyToPay,
|
|
230
|
-
plans,
|
|
231
|
-
products,
|
|
232
|
-
};
|
|
233
|
-
this._mountMethodSelector(this.formOptions);
|
|
105
|
+
// Mount content
|
|
106
|
+
if (state.form) {
|
|
107
|
+
mountMethodSelector({ state });
|
|
234
108
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
this.summaryOptions = {
|
|
238
|
-
summary: summaryData,
|
|
239
|
-
readyToPay,
|
|
240
|
-
plans,
|
|
241
|
-
products,
|
|
242
|
-
};
|
|
243
|
-
this._mountSummary(this.summaryOptions);
|
|
109
|
+
if (state.summary) {
|
|
110
|
+
mountSummary({ state });
|
|
244
111
|
}
|
|
245
|
-
|
|
112
|
+
i18n({state});
|
|
113
|
+
state.hasMounted = true;
|
|
114
|
+
} catch (error) {
|
|
246
115
|
throw error;
|
|
247
116
|
}
|
|
248
117
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
});
|
|
118
|
+
if (state.options.features.autoConfirmation) {
|
|
119
|
+
on({
|
|
120
|
+
eventName: 'instrument-ready',
|
|
121
|
+
callback: (payload) => {
|
|
122
|
+
show({
|
|
123
|
+
componentName: 'confirmation',
|
|
124
|
+
payload,
|
|
125
|
+
state
|
|
126
|
+
});
|
|
127
|
+
}
|
|
260
128
|
});
|
|
261
129
|
}
|
|
262
130
|
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
131
|
+
if (state.options.features.autoResult) {
|
|
132
|
+
if (state.options.transactionType === 'setup') {
|
|
133
|
+
on({
|
|
134
|
+
eventName: 'setup-completed',
|
|
135
|
+
callback: (payload) => {
|
|
136
|
+
show({
|
|
137
|
+
componentName: 'result',
|
|
138
|
+
payload,
|
|
139
|
+
state
|
|
140
|
+
});
|
|
141
|
+
}
|
|
268
142
|
});
|
|
269
|
-
}
|
|
143
|
+
} else {
|
|
144
|
+
on({
|
|
145
|
+
eventName: 'purchase-completed',
|
|
146
|
+
callback: (payload) => {
|
|
147
|
+
show({
|
|
148
|
+
componentName: 'result',
|
|
149
|
+
payload,
|
|
150
|
+
state
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
270
155
|
}
|
|
271
|
-
}
|
|
156
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { RenderMockRebillyInstruments } from 'tests/mocks/rebilly-instruments-mock';
|
|
2
|
+
import { RebillyInstrumentsInstance } from '@rebilly/instruments';
|
|
3
3
|
import { get, ok, post } from 'msw-when-then';
|
|
4
4
|
import { when } from 'tests/msw/server';
|
|
5
5
|
import { storefrontURL } from 'tests/mocks/storefront-api-mock';
|
|
@@ -8,171 +8,67 @@ import ProductModel from '@/storefront/models/product-model';
|
|
|
8
8
|
import SummaryModel from '@/storefront/models/summary-model';
|
|
9
9
|
|
|
10
10
|
describe('RebillyInstruments instance', () => {
|
|
11
|
-
it(
|
|
12
|
-
document.body.innerHTML =
|
|
13
|
-
`
|
|
14
|
-
<div class="form-selector"></div>
|
|
15
|
-
<div class="summary-selector"></div>
|
|
16
|
-
`;
|
|
17
|
-
|
|
18
|
-
const rebillyInstruments = MockRebillyInstruments();
|
|
19
|
-
expect(async () => {
|
|
20
|
-
await rebillyInstruments.mount({})
|
|
21
|
-
}).rejects.toEqual(new Error('Could not find DOM element with CSS class or id ".rebilly-instruments" to mount form'));
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should throw error when providing the wrong type for the form property', () => {
|
|
25
|
-
document.body.innerHTML =
|
|
26
|
-
`
|
|
27
|
-
<div class="form-selector"></div>
|
|
28
|
-
<div class="summary-selector"></div>
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
const options = {
|
|
32
|
-
form: []
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const rebillyInstruments = MockRebillyInstruments();
|
|
36
|
-
expect(async () => {
|
|
37
|
-
await rebillyInstruments.mount(options)
|
|
38
|
-
}).rejects.toEqual(new Error('Please provide a valid CSS class, id or DOM element for "form" property'));
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should inject HTML to the merchant\'s website', async () => {
|
|
42
|
-
const testPlan = new PlanModel({name: 'Test Plan', id: 'test-plan-id-1'});
|
|
43
|
-
const testProduct = new ProductModel({description: 'My Awesome Product', id: 'test-product-1'});
|
|
44
|
-
const testSummary = new SummaryModel(
|
|
45
|
-
{
|
|
46
|
-
currency: 'USD',
|
|
47
|
-
lineItems: [
|
|
48
|
-
{
|
|
49
|
-
description: 'test-plan-id-1',
|
|
50
|
-
planId: 'test-plan-id-1',
|
|
51
|
-
productId: 'test-product-1',
|
|
52
|
-
quantity: 1,
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
}
|
|
56
|
-
);
|
|
11
|
+
it("should inject HTML to the merchant's website", async () => {
|
|
57
12
|
const framePayScriptUrl = 'https://framepay.rebilly.com/rebilly.js';
|
|
58
13
|
const framePayStyleUrl = 'https://dev.framepay.rebilly.com/rebilly.css';
|
|
59
14
|
|
|
60
|
-
when(post(`${storefrontURL}/ready-to-pay`)).thenReturn((() => {
|
|
61
|
-
return ok(
|
|
62
|
-
[{
|
|
63
|
-
method: 'payment-card',
|
|
64
|
-
feature: {
|
|
65
|
-
name: 'Google Pay',
|
|
66
|
-
merchantName: 'google-pay-merchant-name',
|
|
67
|
-
merchantOrigin: 'google-pay-merchant-origin'
|
|
68
|
-
},
|
|
69
|
-
brands: ['Visa', 'MasterCard', 'American Express', 'Discover'],
|
|
70
|
-
filters: []
|
|
71
|
-
}]
|
|
72
|
-
);
|
|
73
|
-
})());
|
|
74
|
-
|
|
75
|
-
when(post(`${storefrontURL}/preview-purchase`)).thenReturn((() => {
|
|
76
|
-
return ok(testSummary);
|
|
77
|
-
})());
|
|
78
|
-
|
|
79
|
-
when(get(`${storefrontURL}/plans`)).thenReturn((() => {
|
|
80
|
-
return ok([testPlan]);
|
|
81
|
-
})());
|
|
82
|
-
|
|
83
|
-
when(get(`${storefrontURL}/products`)).thenReturn((() => {
|
|
84
|
-
return ok([testProduct]);
|
|
85
|
-
})());
|
|
86
|
-
|
|
87
|
-
document.body.innerHTML =
|
|
88
|
-
`
|
|
89
|
-
<div class="form-selector"></div>
|
|
90
|
-
<div class="summary-selector"></div>
|
|
91
|
-
`;
|
|
92
|
-
|
|
93
15
|
const options = {
|
|
94
16
|
form: '.form-selector',
|
|
95
17
|
summary: '.summary-selector',
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
intent: {
|
|
102
|
-
items: [
|
|
103
|
-
{
|
|
104
|
-
planId: 'test-plan-id-1',
|
|
105
|
-
quantity: 1
|
|
106
|
-
}
|
|
107
|
-
]
|
|
18
|
+
locale: 'auto',
|
|
19
|
+
items: [
|
|
20
|
+
{
|
|
21
|
+
planId: 'test-plan-id-1',
|
|
22
|
+
quantity: 1
|
|
108
23
|
}
|
|
109
|
-
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const framepayMock = createFramepayMock();
|
|
113
|
-
global.Rebilly = framepayMock;
|
|
114
|
-
|
|
115
|
-
const rebillyInstruments = MockRebillyInstruments({
|
|
24
|
+
],
|
|
116
25
|
theme: {
|
|
117
26
|
color: {
|
|
118
27
|
background: '#000'
|
|
119
28
|
}
|
|
120
29
|
},
|
|
121
30
|
css: `
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
31
|
+
.rebilly-instruments-summary-line-item-synopsis-title {
|
|
32
|
+
color: rgb(0, 68, 212);
|
|
33
|
+
}
|
|
34
|
+
`,
|
|
35
|
+
_dev: {
|
|
36
|
+
framePayStyleLink: framePayStyleUrl
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
await RenderMockRebillyInstruments(options);
|
|
128
41
|
|
|
129
42
|
// Mounts form and summary
|
|
130
43
|
const summarySelector = document.querySelector('.summary-selector');
|
|
131
|
-
expect(summarySelector.innerHTML).toMatch(
|
|
44
|
+
expect(summarySelector.innerHTML).toMatch('My Product');
|
|
132
45
|
|
|
133
46
|
// Theme config overrides initial styles
|
|
134
|
-
const SUMMARY_CONTAINER = summarySelector.querySelector(
|
|
135
|
-
|
|
47
|
+
const SUMMARY_CONTAINER = summarySelector.querySelector(
|
|
48
|
+
'.rebilly-instruments-content'
|
|
49
|
+
);
|
|
50
|
+
expect(getComputedStyle(SUMMARY_CONTAINER).background).toEqual(
|
|
51
|
+
'rgb(0, 0, 0)'
|
|
52
|
+
);
|
|
136
53
|
|
|
137
54
|
// CSS config property overrides initial styles
|
|
138
|
-
const LINE_ITEM_TITLE = document.querySelector(
|
|
55
|
+
const LINE_ITEM_TITLE = document.querySelector(
|
|
56
|
+
'.rebilly-instruments-summary-line-item-synopsis-title'
|
|
57
|
+
);
|
|
139
58
|
expect(getComputedStyle(LINE_ITEM_TITLE).color).toEqual('rgb(0, 68, 212)');
|
|
140
59
|
|
|
141
60
|
// Mounts default FramePay script
|
|
142
61
|
const SCRIPTS = [...document.querySelectorAll('head script')];
|
|
143
|
-
const FRAMEPAY_SCRIPT = SCRIPTS.find(
|
|
62
|
+
const FRAMEPAY_SCRIPT = SCRIPTS.find(
|
|
63
|
+
(script) => script.src === framePayScriptUrl
|
|
64
|
+
);
|
|
144
65
|
expect(FRAMEPAY_SCRIPT.src).toEqual(framePayScriptUrl);
|
|
145
66
|
|
|
146
67
|
// Mounts _dev FramePay style
|
|
147
68
|
const STYLE_LINKS = [...document.querySelectorAll('head link')];
|
|
148
|
-
const FRAMEPAY_STYLE = STYLE_LINKS.find(
|
|
69
|
+
const FRAMEPAY_STYLE = STYLE_LINKS.find(
|
|
70
|
+
(script) => script.href === framePayStyleUrl
|
|
71
|
+
);
|
|
149
72
|
expect(FRAMEPAY_STYLE.href).toEqual(framePayStyleUrl);
|
|
150
|
-
|
|
151
|
-
// objectContaining allows matching a subset (this could be done with sinon + mocha too)
|
|
152
|
-
expect(framepayMock.initialize).toHaveBeenCalledWith(expect.objectContaining({
|
|
153
|
-
digitalWallet: {
|
|
154
|
-
googlePayDisplayOptions: {
|
|
155
|
-
buttonColor: 'black',
|
|
156
|
-
buttonHeight: '44px',
|
|
157
|
-
buttonType: 'short',
|
|
158
|
-
},
|
|
159
|
-
merchantConfig: {
|
|
160
|
-
merchantName: 'google-pay-merchant-name',
|
|
161
|
-
merchantOrigin: 'google-pay-merchant-origin',
|
|
162
|
-
},
|
|
163
|
-
transactionData: {
|
|
164
|
-
amount: 0,
|
|
165
|
-
countryCode: 'US',
|
|
166
|
-
currency: 'USD',
|
|
167
|
-
label: 'test-website-id',
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
organizationId: 'test-organization-id',
|
|
171
|
-
publishableKey: 'test-api-key',
|
|
172
|
-
}));
|
|
173
|
-
|
|
174
|
-
//Simulate that framepay is ready
|
|
175
|
-
framepayMock.simulateEvent('ready');
|
|
176
73
|
});
|
|
177
74
|
});
|
|
178
|
-
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { processPropertyAsDOMElement } from '../../utils';
|
|
2
|
+
|
|
3
|
+
export default ({element = '', options = {}}) => {
|
|
4
|
+
if (element !== 'form' && element !== 'summary') {
|
|
5
|
+
throw new Error('element must be "form" or "summary"');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const getProp = () => {
|
|
9
|
+
if (options[element]) {
|
|
10
|
+
return options[element]
|
|
11
|
+
}
|
|
12
|
+
switch(element) {
|
|
13
|
+
case 'summary':
|
|
14
|
+
return '.rebilly-instruments-summary'
|
|
15
|
+
case 'form':
|
|
16
|
+
default:
|
|
17
|
+
return '.rebilly-instruments'
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return processPropertyAsDOMElement({
|
|
22
|
+
prop: getProp(),
|
|
23
|
+
propName: element,
|
|
24
|
+
isRequired: ['form'].includes(element)
|
|
25
|
+
});
|
|
26
|
+
}
|