@rebilly/instruments 3.22.0-beta.0 → 3.23.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.
- package/dist/index.js +10 -17
- package/dist/index.min.js +49 -56
- package/package.json +3 -1
- package/src/functions/destroy.js +11 -9
- package/src/functions/mount/fetch-data.js +14 -16
- package/src/functions/mount/fetch-data.spec.js +140 -93
- package/src/functions/mount/index.js +9 -10
- package/src/functions/mount/mount.spec.js +5 -7
- package/src/functions/mount/setup-framepay-theme.js +2 -1
- package/src/functions/mount/setup-framepay.js +3 -1
- package/src/functions/mount/setup-i18n.js +4 -2
- package/src/functions/mount/setup-options.js +6 -4
- package/src/functions/on.spec.js +3 -2
- package/src/functions/purchase.js +16 -5
- package/src/functions/setup.js +3 -4
- package/src/functions/show.js +7 -6
- package/src/functions/show.spec.js +11 -7
- package/src/functions/update.js +3 -3
- package/src/functions/update.spec.js +4 -3
- package/src/instance.js +11 -31
- package/src/state/iframes.js +23 -0
- package/src/state/index.js +61 -0
- package/src/storefront/account-and-website.js +3 -2
- package/src/storefront/{fetch-plans-from-addons-bumpOffers.js → fetch-plans-from-addons-bumpOffer.js} +5 -4
- package/src/storefront/fetch-products-from-plans.js +5 -4
- package/src/storefront/index.js +3 -4
- package/src/storefront/invoices.js +6 -4
- package/src/storefront/payment-instruments.js +5 -4
- package/src/storefront/purchase.js +5 -4
- package/src/storefront/ready-to-pay.js +2 -2
- package/src/storefront/summary.js +8 -3
- package/src/storefront/transactions.js +3 -2
- package/src/style/base/index.js +243 -0
- package/src/views/common/iframe/base-iframe.js +0 -2
- package/src/views/common/iframe/events/update-addons-handler.js +8 -13
- package/src/views/common/iframe/events/update-coupons-handler.js +5 -11
- package/src/views/confirmation.js +16 -6
- package/src/views/method-selector/__snapshots__/method-selector.spec.js.snap +182 -1
- package/src/views/method-selector/generate-digital-wallet.js +2 -1
- package/src/views/method-selector/generate-digital-wallet.spec.js +32 -37
- package/src/views/method-selector/generate-framepay-config.js +1 -1
- package/src/views/method-selector/generate-framepay-config.spec.js +9 -12
- package/src/views/method-selector/get-payment-methods.js +3 -1
- package/src/views/method-selector/get-payment-methods.spec.js +25 -34
- package/src/views/method-selector/index.js +39 -20
- package/src/views/method-selector/method-selector.spec.js +9 -109
- package/src/views/method-selector/mount-bump-offer.js +99 -0
- package/src/views/method-selector/mount-express-methods.js +1 -2
- package/src/views/modal.js +3 -3
- package/src/views/result.js +7 -5
- package/src/views/summary.js +12 -16
- package/tests/mocks/rebilly-instruments-mock.js +17 -19
- package/tests/mocks/storefront-mock.js +10 -9
- package/tests/setup-jest.js +2 -0
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import {generateFramepayConfig} from './generate-framepay-config';
|
|
2
|
+
import state from '../../state';
|
|
2
3
|
|
|
3
4
|
describe('Generate FramePay Config', () => {
|
|
4
|
-
let state;
|
|
5
|
-
|
|
6
5
|
beforeEach(() => {
|
|
7
|
-
state = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
websiteId: 'test-website-id'
|
|
13
|
-
},
|
|
14
|
-
data: {
|
|
15
|
-
readyToPay: []
|
|
16
|
-
}
|
|
6
|
+
state.options = {
|
|
7
|
+
themeFramepay: {},
|
|
8
|
+
locale: 'en-CA',
|
|
9
|
+
organizationId: 'test-organization-id',
|
|
10
|
+
websiteId: 'test-website-id'
|
|
17
11
|
};
|
|
12
|
+
state.data = {
|
|
13
|
+
readyToPay: []
|
|
14
|
+
}
|
|
18
15
|
});
|
|
19
16
|
|
|
20
17
|
it('should generate default config', () => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import state from '../../state';
|
|
2
|
+
|
|
1
3
|
// TODO: Express methods should be filtered from RTP some how
|
|
2
4
|
export const SUPPORTED_EXPRESS_METHODS = [
|
|
3
5
|
'Google Pay',
|
|
@@ -21,7 +23,7 @@ const isExpressMethod = ({ method, feature }) => (
|
|
|
21
23
|
|
|
22
24
|
const isSupportedMethod = ({ method }) => SUPPORTED_METHODS.includes(method);
|
|
23
25
|
|
|
24
|
-
export function getPaymentMethods(
|
|
26
|
+
export function getPaymentMethods() {
|
|
25
27
|
const result = {
|
|
26
28
|
EXPRESS_METHODS: [],
|
|
27
29
|
METHODS: []
|
|
@@ -1,42 +1,33 @@
|
|
|
1
1
|
import { getPaymentMethods } from './get-payment-methods';
|
|
2
2
|
import ReadyToPayModel from '@/storefront/models/ready-to-pay-model';
|
|
3
|
-
|
|
4
|
-
class TestInstance {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.loader = {
|
|
7
|
-
startLoading: jest.fn(),
|
|
8
|
-
stopLoading: jest.fn()
|
|
9
|
-
};
|
|
10
|
-
this.data = {
|
|
11
|
-
readyToPay: [
|
|
12
|
-
new ReadyToPayModel({
|
|
13
|
-
method: 'payment-card',
|
|
14
|
-
feature: {
|
|
15
|
-
name: 'Google Pay',
|
|
16
|
-
merchantName: 'google-pay-merchant-name',
|
|
17
|
-
merchantOrigin: 'google-pay-merchant-origin'
|
|
18
|
-
},
|
|
19
|
-
brands: ['Visa'],
|
|
20
|
-
filters: []
|
|
21
|
-
}),
|
|
22
|
-
new ReadyToPayModel({
|
|
23
|
-
method: 'fake-method',
|
|
24
|
-
filters: []
|
|
25
|
-
}),
|
|
26
|
-
new ReadyToPayModel({
|
|
27
|
-
method: 'payment-card',
|
|
28
|
-
brands: ['Visa'],
|
|
29
|
-
filters: []
|
|
30
|
-
})
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
3
|
+
import state from 'src/state';
|
|
35
4
|
|
|
36
5
|
it('should only return the allowed methods', () => {
|
|
37
|
-
|
|
6
|
+
state.data = {
|
|
7
|
+
readyToPay: [
|
|
8
|
+
new ReadyToPayModel({
|
|
9
|
+
method: 'payment-card',
|
|
10
|
+
feature: {
|
|
11
|
+
name: 'Google Pay',
|
|
12
|
+
merchantName: 'google-pay-merchant-name',
|
|
13
|
+
merchantOrigin: 'google-pay-merchant-origin'
|
|
14
|
+
},
|
|
15
|
+
brands: ['Visa'],
|
|
16
|
+
filters: []
|
|
17
|
+
}),
|
|
18
|
+
new ReadyToPayModel({
|
|
19
|
+
method: 'fake-method',
|
|
20
|
+
filters: []
|
|
21
|
+
}),
|
|
22
|
+
new ReadyToPayModel({
|
|
23
|
+
method: 'payment-card',
|
|
24
|
+
brands: ['Visa'],
|
|
25
|
+
filters: []
|
|
26
|
+
})
|
|
27
|
+
]
|
|
28
|
+
}
|
|
38
29
|
|
|
39
|
-
const results = getPaymentMethods(
|
|
30
|
+
const results = getPaymentMethods();
|
|
40
31
|
expect(results.hasOwnProperty('EXPRESS_METHODS')).toEqual(true);
|
|
41
32
|
expect(results['EXPRESS_METHODS'].length).toEqual(1);
|
|
42
33
|
expect(results['METHODS'].length).toEqual(1);
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
/* eslint-disable no-undef */
|
|
2
2
|
import { collectData } from '@rebilly/risk-data-collector';
|
|
3
|
+
import state from '../../state';
|
|
4
|
+
import iframes from '../../state/iframes';
|
|
3
5
|
import { getPaymentMethods } from './get-payment-methods';
|
|
4
6
|
import { fetchData } from '../../functions/mount/fetch-data';
|
|
5
7
|
import { ViewIframe } from '../common/iframe';
|
|
6
8
|
import { purchase } from '../../functions/purchase';
|
|
7
9
|
import { setup } from '../../functions/setup';
|
|
8
10
|
import { mountExpressMethods } from './mount-express-methods';
|
|
11
|
+
import { mountBumpOffer } from './mount-bump-offer';
|
|
9
12
|
import { generateDigitalWallet } from './generate-digital-wallet';
|
|
10
13
|
import { updateSummary } from '../summary';
|
|
11
14
|
|
|
12
|
-
export const baseMethodSelectorHTML = (compactExpressInstruments) => `
|
|
15
|
+
export const baseMethodSelectorHTML = ({compactExpressInstruments, bumpOffer}) => `
|
|
13
16
|
<div class="rebilly-instruments-content">
|
|
14
17
|
<div id="rebilly-instruments-error"></div>
|
|
18
|
+
${bumpOffer.length ? '<div data-rebilly-instruments="bump-offer" class="rebilly-instruments-bump-offers"></div>' : ''}
|
|
15
19
|
<div data-rebilly-instruments="express-method" class="rebilly-instruments-method-selector ${compactExpressInstruments ? 'has-express-compact' : ''}">
|
|
16
20
|
<div class="rebilly-instruments-express-methods ${
|
|
17
21
|
compactExpressInstruments ? 'is-compact' : ''
|
|
@@ -23,31 +27,32 @@ export const baseMethodSelectorHTML = (compactExpressInstruments) => `
|
|
|
23
27
|
<span class="rebilly-instruments-divider-label" data-rebilly-i18n="form.or">Or</span>
|
|
24
28
|
</div>
|
|
25
29
|
</div>
|
|
26
|
-
<div class="rebilly-instruments-methods"></div>
|
|
30
|
+
<div data-rebilly-instruments="methods" class="rebilly-instruments-methods"></div>
|
|
27
31
|
</div>
|
|
28
32
|
`;
|
|
29
33
|
|
|
30
|
-
export async function mountMethodSelector(
|
|
31
|
-
const { EXPRESS_METHODS, METHODS } = getPaymentMethods(
|
|
34
|
+
export async function mountMethodSelector() {
|
|
35
|
+
const { EXPRESS_METHODS, METHODS } = getPaymentMethods();
|
|
32
36
|
|
|
33
37
|
const methodSelectorElement = state.form.querySelector('.rebilly-instruments-method-selector');
|
|
34
38
|
if (methodSelectorElement) {
|
|
35
39
|
methodSelectorElement.style.visibility = 'visible';
|
|
36
40
|
methodSelectorElement.style.height = 'auto';
|
|
37
41
|
} else {
|
|
38
|
-
state.form.innerHTML += baseMethodSelectorHTML(
|
|
39
|
-
state.options.paymentInstruments.compactExpressInstruments && EXPRESS_METHODS.length
|
|
40
|
-
|
|
42
|
+
state.form.innerHTML += baseMethodSelectorHTML({
|
|
43
|
+
compactExpressInstruments: state.options.paymentInstruments.compactExpressInstruments && EXPRESS_METHODS.length,
|
|
44
|
+
bumpOffer: state.options.bumpOffer
|
|
45
|
+
});
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
const
|
|
48
|
+
const BUMPOFFER_CONTAINER = document.querySelector('[data-rebilly-instruments="bump-offer"]');
|
|
49
|
+
const METHODS_CONTAINER = document.querySelector('[data-rebilly-instruments="methods"]');
|
|
44
50
|
const EXPRESS_METHODS_CONTAINER = document.querySelector('.rebilly-instruments-express-methods-container');
|
|
45
51
|
|
|
46
52
|
if(EXPRESS_METHODS.length) {
|
|
47
53
|
if (!methodSelectorElement) {
|
|
48
|
-
state.options.digitalWallet = generateDigitalWallet({
|
|
54
|
+
state.options.digitalWallet = generateDigitalWallet({ EXPRESS_METHODS });
|
|
49
55
|
mountExpressMethods({
|
|
50
|
-
state,
|
|
51
56
|
methods: EXPRESS_METHODS,
|
|
52
57
|
container: EXPRESS_METHODS_CONTAINER,
|
|
53
58
|
});
|
|
@@ -59,16 +64,16 @@ export async function mountMethodSelector({ state }) {
|
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
if (METHODS.length) {
|
|
67
|
+
const modelSafeState = state.toModel();
|
|
62
68
|
const model = {
|
|
63
|
-
options:
|
|
64
|
-
data:
|
|
65
|
-
mainStyleVars:
|
|
69
|
+
options: modelSafeState.options,
|
|
70
|
+
data: modelSafeState.data,
|
|
71
|
+
mainStyleVars: modelSafeState.mainStyleVars,
|
|
66
72
|
};
|
|
67
|
-
const { paymentMethodsUrl } = state.options
|
|
73
|
+
const { paymentMethodsUrl } = state.options?._computed;
|
|
68
74
|
|
|
69
75
|
const name = 'rebilly-instruments-form';
|
|
70
76
|
const iframe = await new ViewIframe({
|
|
71
|
-
state,
|
|
72
77
|
name,
|
|
73
78
|
url: `${paymentMethodsUrl}`,
|
|
74
79
|
container: METHODS_CONTAINER,
|
|
@@ -89,35 +94,49 @@ export async function mountMethodSelector({ state }) {
|
|
|
89
94
|
.forEach(el => {
|
|
90
95
|
el.style.height = 'auto';
|
|
91
96
|
});
|
|
97
|
+
document.querySelectorAll('[data-rebilly-instruments="bump-offer"]')
|
|
98
|
+
.forEach(el => {
|
|
99
|
+
el.style.height = 'auto';
|
|
100
|
+
el.style.marginBottom = 'calc(var(--rebilly-spacingM) + var(--rebilly-fontSizeS))';
|
|
101
|
+
});
|
|
92
102
|
|
|
93
103
|
iframe.component.call('route', {
|
|
94
104
|
name: 'method-switch'
|
|
95
105
|
});
|
|
96
106
|
|
|
97
107
|
if (state.data.isPurchase) {
|
|
98
|
-
updateSummary(
|
|
108
|
+
updateSummary();
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
iframe.component.call('update', model);
|
|
102
112
|
});
|
|
103
113
|
|
|
104
|
-
|
|
114
|
+
iframes.form = iframe;
|
|
105
115
|
} else {
|
|
106
116
|
METHODS_CONTAINER.style.display = 'none';
|
|
107
117
|
document.querySelectorAll('[data-rebilly-instruments="divider"]')
|
|
108
118
|
.forEach(el => { el.style.display = 'none' });
|
|
109
119
|
}
|
|
120
|
+
|
|
121
|
+
if (state.options.bumpOffer.length) {
|
|
122
|
+
mountBumpOffer({
|
|
123
|
+
container: BUMPOFFER_CONTAINER,
|
|
124
|
+
});
|
|
125
|
+
} else if (BUMPOFFER_CONTAINER?.style) {
|
|
126
|
+
BUMPOFFER_CONTAINER.style.display = 'none';
|
|
127
|
+
}
|
|
110
128
|
}
|
|
111
129
|
|
|
112
|
-
export async function updateMethodSelector(
|
|
130
|
+
export async function updateMethodSelector() {
|
|
113
131
|
state.loader.startLoading({ id: 'rebilly-instruments-methods' });
|
|
114
132
|
|
|
115
133
|
const { riskMetadata } = await collectData();
|
|
116
|
-
state.data = await fetchData({
|
|
134
|
+
state.data = await fetchData({ riskMetadata });
|
|
135
|
+
state.updateModel();
|
|
117
136
|
|
|
118
137
|
if (state.data.transaction && state.data.transaction?.type === 'setup') {
|
|
119
138
|
state.options.transactionType = 'setup';
|
|
120
139
|
}
|
|
121
140
|
|
|
122
|
-
mountMethodSelector(
|
|
141
|
+
mountMethodSelector();
|
|
123
142
|
}
|
|
@@ -1,120 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { Loader } from '../../loader';
|
|
4
|
-
import { Translate } from '../../i18n';
|
|
5
|
-
import { mountMethodSelector, updateMethodSelector } from './index';
|
|
6
|
-
import { avoidUnhandledPromises } from 'tests/async-utilities';
|
|
7
|
-
import { MockStorefront } from 'tests/mocks/storefront-mock';
|
|
8
|
-
import { DataInstance } from '../../functions/mount/fetch-data';
|
|
9
|
-
import setupOptions from '../../functions/mount/setup-options';
|
|
1
|
+
import { RenderMockRebillyInstruments } from 'tests/mocks/rebilly-instruments-mock';
|
|
2
|
+
import { updateMethodSelector } from './index';
|
|
10
3
|
|
|
11
|
-
describe('
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
document.body.append(formElement);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
class TestMountMethodSelectorInstance {
|
|
19
|
-
constructor({
|
|
20
|
-
options = {},
|
|
21
|
-
form = formElement,
|
|
22
|
-
loader = new Loader(),
|
|
23
|
-
translate = new Translate()
|
|
24
|
-
} = {}) {
|
|
25
|
-
this.options = setupOptions({options});
|
|
26
|
-
this.form = form;
|
|
27
|
-
this.loader = loader;
|
|
28
|
-
this.translate = translate;
|
|
29
|
-
this.storefront = MockStorefront();
|
|
30
|
-
this.data = new DataInstance({
|
|
31
|
-
state: {options},
|
|
32
|
-
previewPurchase: new SummaryModel({
|
|
33
|
-
currency: 'USD',
|
|
34
|
-
lineItems: [
|
|
35
|
-
{
|
|
36
|
-
type: 'debit',
|
|
37
|
-
description: 'My Awesome Product',
|
|
38
|
-
unitPrice: 30,
|
|
39
|
-
quantity: 1,
|
|
40
|
-
price: 30,
|
|
41
|
-
productId: 'my-awesome-product',
|
|
42
|
-
planId: 'my-awesome-product'
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
type: 'debit',
|
|
46
|
-
description: 'Awesome T-Shirt',
|
|
47
|
-
unitPrice: 20,
|
|
48
|
-
quantity: 2,
|
|
49
|
-
price: 40,
|
|
50
|
-
productId: 'my-app',
|
|
51
|
-
planId: 'awesome-t-shirt'
|
|
52
|
-
}
|
|
53
|
-
],
|
|
54
|
-
subtotalAmount: 70,
|
|
55
|
-
taxAmount: 0,
|
|
56
|
-
shippingAmount: 0,
|
|
57
|
-
discountsAmount: 0,
|
|
58
|
-
total: 70
|
|
59
|
-
}),
|
|
60
|
-
readyToPay: [
|
|
61
|
-
new ReadyToPayModel({
|
|
62
|
-
method: 'payment-card',
|
|
63
|
-
feature: {
|
|
64
|
-
name: 'Google Pay',
|
|
65
|
-
merchantName: 'google-pay-merchant-name',
|
|
66
|
-
merchantOrigin: 'google-pay-merchant-origin'
|
|
67
|
-
},
|
|
68
|
-
brands: ['Visa'],
|
|
69
|
-
filters: []
|
|
70
|
-
}),
|
|
71
|
-
]
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const options = {
|
|
77
|
-
websiteId: 'test-website-id',
|
|
78
|
-
countryCode: 'US',
|
|
79
|
-
items: [
|
|
80
|
-
{
|
|
81
|
-
planId: 'my-awesome-product',
|
|
82
|
-
quantity: 1
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
planId: 'awesome-t-shirt',
|
|
86
|
-
quantity: 2
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
_computed: {
|
|
90
|
-
paymentMethodsUrl: ''
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
it('should inject the proper HTML for express methods', async () => {
|
|
95
|
-
const mountSummaryInstance = new TestMountMethodSelectorInstance({
|
|
96
|
-
options
|
|
4
|
+
describe('Methods Selector Component', () => {
|
|
5
|
+
it ('should inject the proper HTML for express methods', async () => {
|
|
6
|
+
await RenderMockRebillyInstruments({
|
|
7
|
+
form: '.rebilly-instruments-form'
|
|
97
8
|
});
|
|
98
9
|
|
|
99
|
-
mountSummaryInstance.loader.DOM.form = mountSummaryInstance.form;
|
|
100
|
-
|
|
101
|
-
mountMethodSelector({ state: mountSummaryInstance });
|
|
102
|
-
|
|
103
10
|
const form = document.querySelector('.rebilly-instruments-form');
|
|
104
11
|
expect(form).toMatchSnapshot();
|
|
105
|
-
await avoidUnhandledPromises();
|
|
106
12
|
});
|
|
107
13
|
|
|
108
|
-
it('should allow updating method selector', async () => {
|
|
109
|
-
|
|
110
|
-
options
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
state.loader.DOM.form = state.form;
|
|
114
|
-
|
|
14
|
+
it.only ('should allow updating method selector', async () => {
|
|
15
|
+
await RenderMockRebillyInstruments();
|
|
115
16
|
await updateMethodSelector({
|
|
116
|
-
state,
|
|
117
17
|
mainStyleVars: 'any main style'
|
|
118
18
|
});
|
|
119
19
|
});
|
|
120
|
-
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import state from '../../state';
|
|
2
|
+
import formatCurrency from '../../utils/format-currency';
|
|
3
|
+
import {fetchSummary} from '../../storefront/summary'
|
|
4
|
+
|
|
5
|
+
function lineItem({offer}) {
|
|
6
|
+
const plan = state.data.plans.find(item => item.id === offer.planId);
|
|
7
|
+
const product = state.data.products.find(item => item.id === plan.productId);
|
|
8
|
+
|
|
9
|
+
const rif = (condition, template) => condition ? template : '';
|
|
10
|
+
|
|
11
|
+
function unitPrice() {
|
|
12
|
+
const planPricing = plan.pricing.isBracket
|
|
13
|
+
? plan.pricing.brackets[0].price
|
|
14
|
+
: plan.pricing.price;
|
|
15
|
+
|
|
16
|
+
const basePrice = formatCurrency(planPricing, plan.currency);
|
|
17
|
+
return plan.pricing.isBracket ? `Starting at ${basePrice}` : basePrice;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const thumbnail = (item) => rif(item.thumbnail, `
|
|
21
|
+
<figure class="rebilly-instruments-bump-offer-line-item-figure">
|
|
22
|
+
<img src="${item.thumbnail}" :alt="${item.name}"/>
|
|
23
|
+
</figure>
|
|
24
|
+
`);
|
|
25
|
+
|
|
26
|
+
const synopsis = (item) => `
|
|
27
|
+
<div class="rebilly-instruments-bump-offer-line-item-synopsis">
|
|
28
|
+
<p class="rebilly-instruments-bump-offer-line-item-synopsis-title">
|
|
29
|
+
${item.name}
|
|
30
|
+
</p>
|
|
31
|
+
${rif(item.description, `
|
|
32
|
+
<p class="rebilly-instruments-bump-offer-line-item-synopsis-description">
|
|
33
|
+
${item.description}
|
|
34
|
+
</p>
|
|
35
|
+
`)}
|
|
36
|
+
</div>
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const breakdown = (item) => `
|
|
40
|
+
<div class="rebilly-instruments-bump-offer-line-item-price-breakdown">
|
|
41
|
+
${rif(item.quantity, `
|
|
42
|
+
<p class="rebilly-instruments-bump-offer-line-item-price-breakdown-quantity">
|
|
43
|
+
${item.quantity}
|
|
44
|
+
</p>
|
|
45
|
+
<svg class="rebilly-instruments-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
46
|
+
<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"/>
|
|
47
|
+
</svg>
|
|
48
|
+
`)}
|
|
49
|
+
<p class="rebilly-instruments-bump-offer-line-item-price-breakdown-unit-price">
|
|
50
|
+
${item.unitPrice}
|
|
51
|
+
</p>
|
|
52
|
+
<div>
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const line = {
|
|
56
|
+
...offer,
|
|
57
|
+
quantity: plan.pricing.isBracket ? null : offer.quantity,
|
|
58
|
+
name: product.name,
|
|
59
|
+
description: plan.name,
|
|
60
|
+
unitPrice: unitPrice(),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return `
|
|
64
|
+
<div class="rebilly-instruments-bump-offer-line-item">
|
|
65
|
+
${thumbnail(line)}
|
|
66
|
+
${synopsis(line)}
|
|
67
|
+
${breakdown(line)}
|
|
68
|
+
</div>
|
|
69
|
+
`
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function mountBumpOffer ({container}) {
|
|
73
|
+
container.insertAdjacentHTML('beforeEnd', `
|
|
74
|
+
<label for="rebilly-instruments-bump-offer" class="rebilly-instruments-form-field-checkbox">
|
|
75
|
+
<div class="rebilly-instruments-bump-offer-label">Yes, I want to upgrade!</div>
|
|
76
|
+
<input
|
|
77
|
+
type="checkbox"
|
|
78
|
+
id="rebilly-instruments-bump-offer"
|
|
79
|
+
/>
|
|
80
|
+
<span></span>
|
|
81
|
+
</label>
|
|
82
|
+
`);
|
|
83
|
+
|
|
84
|
+
const checkbox = document.getElementById('rebilly-instruments-bump-offer')
|
|
85
|
+
checkbox.addEventListener('click', async () => {
|
|
86
|
+
state.data.acceptBumpOffer = checkbox.checked;
|
|
87
|
+
await fetchSummary();
|
|
88
|
+
state.updateModel();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
checkbox.checked = state.data.acceptBumpOffer;
|
|
92
|
+
|
|
93
|
+
state.options.bumpOffer.forEach(offer => {
|
|
94
|
+
const node = document.createElement('div');
|
|
95
|
+
node.classList.add('rebilly-instruments-bump-offer');
|
|
96
|
+
node.insertAdjacentHTML('beforeEnd', lineItem({offer}));
|
|
97
|
+
container.appendChild(node);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -2,11 +2,11 @@ import mountExpressMethod from './express-methods';
|
|
|
2
2
|
import {generateFramepayConfig} from './generate-framepay-config'
|
|
3
3
|
import { getMethodData } from './get-method-data';
|
|
4
4
|
import Events from '../../events';
|
|
5
|
+
import state from '../../state';
|
|
5
6
|
|
|
6
7
|
const browserIsSafari = () => window.ApplePaySession;
|
|
7
8
|
|
|
8
9
|
export async function mountExpressMethods({
|
|
9
|
-
state,
|
|
10
10
|
methods,
|
|
11
11
|
container
|
|
12
12
|
}) {
|
|
@@ -19,7 +19,6 @@ export async function mountExpressMethods({
|
|
|
19
19
|
if(!Rebilly?.initialized) {
|
|
20
20
|
await Rebilly?.initialize(
|
|
21
21
|
generateFramepayConfig({
|
|
22
|
-
state,
|
|
23
22
|
methodIds
|
|
24
23
|
})
|
|
25
24
|
);
|
package/src/views/modal.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import state from '../state';
|
|
1
2
|
import { ModalIframe } from './common/iframe';
|
|
2
3
|
|
|
3
4
|
const modalTemplate = (isRedirect, method) => `
|
|
@@ -21,7 +22,6 @@ export async function mountModal({
|
|
|
21
22
|
model = {},
|
|
22
23
|
classListArray = [],
|
|
23
24
|
close = () => {},
|
|
24
|
-
state = null
|
|
25
25
|
} = {}) {
|
|
26
26
|
const method = model?.method?.method;
|
|
27
27
|
const isRedirect = name === 'rebilly-instruments-approval-url';
|
|
@@ -48,13 +48,13 @@ export async function mountModal({
|
|
|
48
48
|
state.loader.addDOMElement({ section: 'modal', el: modalContent });
|
|
49
49
|
state.loader.startLoading({ section: 'modal', id: name });
|
|
50
50
|
|
|
51
|
+
const modelSafeState = state.toModel();
|
|
51
52
|
const injectedModel = {
|
|
52
|
-
options:
|
|
53
|
+
options: modelSafeState.options,
|
|
53
54
|
...model
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
const iframe = await new ModalIframe({
|
|
57
|
-
state,
|
|
58
58
|
name,
|
|
59
59
|
url,
|
|
60
60
|
model: injectedModel,
|
package/src/views/result.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ViewIframe } from './common/iframe';
|
|
2
2
|
import { replaceContent } from './common/render-utilities';
|
|
3
|
+
import state from '../state';
|
|
4
|
+
import iframes from '../state/iframes';
|
|
3
5
|
|
|
4
|
-
export async function mountResult({ payload
|
|
6
|
+
export async function mountResult({ payload }) {
|
|
5
7
|
const resultContainerClassName = 'rebilly-instruments-result';
|
|
6
8
|
replaceContent(state.form, `<div class="${resultContainerClassName}"></div>`);
|
|
7
9
|
|
|
@@ -11,14 +13,14 @@ export async function mountResult({ payload, state }) {
|
|
|
11
13
|
const container = document.querySelector(`.${resultContainerClassName}`);
|
|
12
14
|
const { paymentMethodsUrl } = state.options._computed;
|
|
13
15
|
|
|
16
|
+
const modelSafeState = state.toModel();
|
|
14
17
|
const model = {
|
|
15
|
-
options:
|
|
16
|
-
mainStyleVars:
|
|
18
|
+
options: modelSafeState.options,
|
|
19
|
+
mainStyleVars: modelSafeState.mainStyleVars,
|
|
17
20
|
[state.options.transactionType]: payload
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
const iframe = await new ViewIframe({
|
|
21
|
-
state,
|
|
22
24
|
name: 'rebilly-instruments-result',
|
|
23
25
|
url: `${paymentMethodsUrl}/result`,
|
|
24
26
|
container,
|
|
@@ -28,5 +30,5 @@ export async function mountResult({ payload, state }) {
|
|
|
28
30
|
loader: state.loader
|
|
29
31
|
});
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
iframes.form = iframe;
|
|
32
34
|
}
|
package/src/views/summary.js
CHANGED
|
@@ -1,33 +1,29 @@
|
|
|
1
|
+
import state from '../state';
|
|
2
|
+
import iframes from '../state/iframes';
|
|
1
3
|
import { ViewIframe } from './common/iframe';
|
|
2
4
|
import { fetchSummary } from '../storefront/summary';
|
|
3
5
|
|
|
4
|
-
export async function mountSummary(
|
|
6
|
+
export async function mountSummary() {
|
|
7
|
+
const modelSafeState = state.toModel();
|
|
5
8
|
const model = {
|
|
6
|
-
options:
|
|
7
|
-
data:
|
|
8
|
-
mainStyleVars:
|
|
9
|
+
options: modelSafeState.options,
|
|
10
|
+
data: modelSafeState.data,
|
|
11
|
+
mainStyleVars: modelSafeState.mainStyleVars,
|
|
9
12
|
};
|
|
10
|
-
const { paymentMethodsUrl } = state.options
|
|
13
|
+
const { paymentMethodsUrl } = state.options?._computed;
|
|
11
14
|
|
|
12
15
|
const iframe = await new ViewIframe({
|
|
13
|
-
state,
|
|
14
16
|
name: 'rebilly-instruments-summary',
|
|
15
17
|
url: `${paymentMethodsUrl}/summary`,
|
|
16
18
|
container: state.summary,
|
|
17
19
|
model
|
|
18
20
|
});
|
|
19
21
|
iframe.bindEventListeners({loader: state.loader});
|
|
20
|
-
|
|
22
|
+
iframes.summary = iframe;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
export async function updateSummary({
|
|
24
|
-
await fetchSummary({data: instrument
|
|
25
|
-
|
|
26
|
-
data: state.data.toPostmatesModel(),
|
|
27
|
-
options: state.options
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
state.iframeComponents.summary.component.call('update', updateModel);
|
|
31
|
-
state.iframeComponents.form.component.call('update', updateModel);
|
|
25
|
+
export async function updateSummary({ instrument } = {}) {
|
|
26
|
+
await fetchSummary({ data: instrument });
|
|
27
|
+
state.updateModel();
|
|
32
28
|
}
|
|
33
29
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import RebillyInstruments from 'src/index';
|
|
2
2
|
import { createFramepayMock } from 'tests/mocks/framepay-mock';
|
|
3
3
|
import { get, ok, post } from 'msw-when-then';
|
|
4
4
|
import { when } from 'tests/msw/server';
|
|
@@ -42,7 +42,6 @@ export async function RenderMockRebillyInstruments(options = {}) {
|
|
|
42
42
|
}
|
|
43
43
|
]
|
|
44
44
|
});
|
|
45
|
-
const framePayStyleUrl = 'https://dev.framepay.rebilly.com/rebilly.css';
|
|
46
45
|
|
|
47
46
|
when(get(`${storefrontURL}/invoices/*`)).thenReturn(
|
|
48
47
|
(() => ok(testInvoice))()
|
|
@@ -80,7 +79,8 @@ export async function RenderMockRebillyInstruments(options = {}) {
|
|
|
80
79
|
summary: '.summary-selector',
|
|
81
80
|
locale: 'auto',
|
|
82
81
|
_dev: {
|
|
83
|
-
|
|
82
|
+
paymentMethodsUrl: 'https://forms.test.rebilly.dev',
|
|
83
|
+
framePayStyleLink: 'https://dev.framepay.rebilly.com/rebilly.css'
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
|
|
@@ -105,26 +105,24 @@ export async function RenderMockRebillyInstruments(options = {}) {
|
|
|
105
105
|
const framepayMock = createFramepayMock();
|
|
106
106
|
global.Rebilly = framepayMock;
|
|
107
107
|
|
|
108
|
-
const
|
|
108
|
+
const form = document.createElement('div');
|
|
109
|
+
form.classList.add(`${mergedOptions.form.replace('.', '')}`);
|
|
110
|
+
document.body.appendChild(form);
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
`;
|
|
112
|
+
const summary = document.createElement('div');
|
|
113
|
+
summary.classList.add(`${mergedOptions.summary.replace('.', '')}`);
|
|
114
|
+
document.body.appendChild(summary);
|
|
114
115
|
|
|
115
|
-
await
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
await RebillyInstruments.mount({
|
|
117
|
+
setupFramepay: setupFramepayMock,
|
|
118
|
+
...mergedOptions,
|
|
119
|
+
});
|
|
119
120
|
|
|
120
|
-
|
|
121
|
+
RebillyInstruments.mock = {
|
|
121
122
|
data: (data) => {
|
|
122
|
-
|
|
123
|
-
state: rebillyInstruments.state,
|
|
124
|
-
...data
|
|
125
|
-
});
|
|
123
|
+
RebillyInstruments.state.data = new DataInstance(data);
|
|
126
124
|
}
|
|
127
125
|
};
|
|
128
126
|
|
|
129
|
-
return
|
|
130
|
-
}
|
|
127
|
+
return RebillyInstruments;
|
|
128
|
+
}
|