@rebilly/instruments 2.0.0-beta → 3.0.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/dist/events/index.js +2 -1
- package/dist/functions/mount/fetch-data.js +187 -0
- package/dist/functions/mount/fetch-data.spec.js +189 -0
- package/dist/functions/mount/index.js +132 -164
- package/dist/functions/mount/mount.spec.js +2 -4
- package/dist/functions/mount/setup-element.js +40 -0
- package/dist/functions/mount/setup-framepay-theme.js +95 -0
- package/dist/functions/mount/setup-framepay.js +5 -1
- package/dist/functions/mount/setup-i18n.js +33 -0
- package/dist/functions/mount/setup-options.js +68 -47
- package/dist/functions/mount/setup-options.spec.js +66 -0
- package/dist/functions/mount/setup-storefront.js +6 -4
- package/dist/functions/mount/setup-styles.js +4 -2
- package/dist/functions/purchase.js +129 -24
- package/dist/functions/purchase.spec.js +13 -10
- package/dist/functions/setup.js +85 -0
- package/dist/functions/setup.spec.js +87 -0
- package/dist/functions/show.js +8 -4
- package/dist/functions/show.spec.js +9 -5
- package/dist/functions/update.js +39 -24
- package/dist/functions/update.spec.js +0 -4
- package/dist/i18n/en.json +5 -2
- package/dist/i18n/es.json +4 -1
- package/dist/index.js +17 -3
- package/dist/index.spec.js +3 -16
- 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 +10 -18
- package/dist/storefront/plans.spec.js +3 -13
- package/dist/storefront/products.js +10 -13
- package/dist/storefront/products.spec.js +12 -19
- package/dist/storefront/purchase.js +23 -12
- package/dist/storefront/purchase.spec.js +1 -20
- package/dist/storefront/ready-to-pay.js +18 -15
- package/dist/storefront/ready-to-pay.spec.js +2 -12
- package/dist/storefront/summary.js +21 -17
- package/dist/storefront/summary.spec.js +4 -15
- package/dist/storefront/transactions.js +27 -0
- package/dist/style/base/__snapshots__/theme.spec.js.snap +188 -45
- package/dist/style/base/default-theme.js +699 -0
- package/dist/style/base/index.js +48 -16
- package/dist/style/base/theme.js +16 -48
- package/dist/style/base/theme.spec.js +4 -15
- package/dist/style/components/address.js +3 -3
- package/dist/style/components/button.js +32 -22
- package/dist/style/components/divider.js +9 -9
- package/dist/style/components/forms/checkbox.js +12 -9
- package/dist/style/components/forms/field.js +18 -6
- package/dist/style/components/forms/form.js +2 -2
- package/dist/style/components/forms/input.js +54 -13
- package/dist/style/components/forms/label.js +39 -18
- package/dist/style/components/forms/select.js +54 -22
- package/dist/style/components/forms/validation.js +53 -6
- package/dist/style/components/icons.js +4 -4
- package/dist/style/components/loader.js +5 -3
- package/dist/style/components/methods.js +18 -15
- package/dist/style/components/overlay.js +5 -5
- package/dist/style/helpers/index.js +46 -46
- package/dist/style/index.js +3 -1
- package/dist/style/payment-instruments/payment-card.js +4 -4
- package/dist/style/utils/border.js +47 -0
- package/dist/style/utils/color-values.js +39 -3
- package/dist/style/utils/remove-empty-null.js +20 -0
- package/dist/style/vendor/framepay.js +11 -8
- package/dist/style/vendor/postmate.js +2 -2
- package/dist/style/views/confirmation.js +13 -13
- package/dist/style/views/method-selector.js +2 -2
- package/dist/style/views/modal.js +6 -6
- package/dist/style/views/result.js +4 -4
- package/dist/style/views/summary.js +26 -22
- package/dist/views/__snapshots__/summary.spec.js.snap +77 -119
- package/dist/views/common/iframe/base-iframe.js +2 -0
- package/dist/views/common/iframe/modal-iframe.js +50 -4
- package/dist/views/confirmation.js +19 -8
- package/dist/views/method-selector/generate-digital-wallet.js +12 -3
- package/dist/views/method-selector/generate-digital-wallet.spec.js +11 -0
- package/dist/views/method-selector/get-payment-methods.js +13 -2
- package/dist/views/method-selector/get-payment-methods.spec.js +21 -19
- package/dist/views/method-selector/index.js +23 -34
- package/dist/views/method-selector/method-selector.spec.js +50 -55
- package/dist/views/method-selector/mount-methods.js +5 -8
- package/dist/views/modal.js +8 -2
- package/dist/views/result.js +3 -4
- package/dist/views/summary.js +156 -97
- package/dist/views/summary.spec.js +53 -58
- package/package.json +4 -2
- package/src/events/index.js +2 -1
- package/src/functions/mount/fetch-data.js +152 -0
- package/src/functions/mount/fetch-data.spec.js +238 -0
- package/src/functions/mount/index.js +101 -158
- package/src/functions/mount/mount.spec.js +3 -5
- package/src/functions/mount/setup-element.js +26 -0
- package/src/functions/mount/setup-framepay-theme.js +82 -0
- package/src/functions/mount/setup-framepay.js +5 -1
- package/src/functions/mount/setup-i18n.js +19 -0
- package/src/functions/mount/setup-options.js +78 -48
- package/src/functions/mount/setup-options.spec.js +60 -0
- package/src/functions/mount/setup-storefront.js +6 -4
- package/src/functions/mount/setup-styles.js +4 -2
- package/src/functions/on.spec.js +1 -1
- package/src/functions/purchase.js +99 -23
- package/src/functions/purchase.spec.js +10 -10
- package/src/functions/setup.js +48 -0
- package/src/functions/setup.spec.js +98 -0
- package/src/functions/show.js +2 -4
- package/src/functions/show.spec.js +3 -4
- package/src/functions/update.js +40 -25
- package/src/functions/update.spec.js +0 -4
- package/src/i18n/en.json +5 -2
- package/src/i18n/es.json +4 -1
- package/src/index.js +9 -3
- package/src/index.spec.js +3 -21
- package/src/loader/index.js +3 -3
- package/src/storefront/index.js +28 -0
- 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/summary-model.js +12 -19
- 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 +6 -17
- package/src/storefront/plans.spec.js +4 -11
- package/src/storefront/products.js +8 -16
- package/src/storefront/products.spec.js +16 -22
- package/src/storefront/purchase.js +14 -16
- package/src/storefront/purchase.spec.js +2 -14
- package/src/storefront/ready-to-pay.js +13 -16
- package/src/storefront/ready-to-pay.spec.js +3 -10
- package/src/storefront/summary.js +19 -17
- package/src/storefront/summary.spec.js +5 -12
- package/src/storefront/transactions.js +11 -0
- package/src/style/base/__snapshots__/theme.spec.js.snap +188 -45
- package/src/style/base/default-theme.js +674 -0
- package/src/style/base/index.js +48 -16
- package/src/style/base/theme.js +17 -47
- package/src/style/base/theme.spec.js +4 -16
- package/src/style/components/address.js +3 -3
- package/src/style/components/button.js +32 -24
- package/src/style/components/divider.js +9 -9
- package/src/style/components/forms/checkbox.js +11 -11
- package/src/style/components/forms/field.js +18 -6
- package/src/style/components/forms/form.js +2 -2
- package/src/style/components/forms/input.js +54 -13
- package/src/style/components/forms/label.js +39 -18
- package/src/style/components/forms/select.js +54 -22
- package/src/style/components/forms/validation.js +53 -6
- package/src/style/components/icons.js +4 -4
- package/src/style/components/loader.js +4 -5
- package/src/style/components/methods.js +18 -15
- package/src/style/components/overlay.js +5 -5
- package/src/style/helpers/index.js +46 -46
- package/src/style/index.js +2 -1
- package/src/style/payment-instruments/payment-card.js +4 -4
- package/src/style/utils/border.js +34 -0
- package/src/style/utils/color-values.js +27 -1
- package/src/style/utils/remove-empty-null.js +10 -0
- package/src/style/vendor/framepay.js +11 -8
- package/src/style/vendor/postmate.js +2 -2
- package/src/style/views/confirmation.js +13 -13
- package/src/style/views/method-selector.js +2 -2
- package/src/style/views/modal.js +6 -6
- package/src/style/views/result.js +4 -4
- package/src/style/views/summary.js +26 -22
- package/src/views/__snapshots__/summary.spec.js.snap +77 -119
- package/src/views/common/iframe/base-iframe.js +2 -0
- package/src/views/common/iframe/modal-iframe.js +45 -3
- package/src/views/confirmation.js +15 -5
- package/src/views/method-selector/generate-digital-wallet.js +10 -3
- package/src/views/method-selector/generate-digital-wallet.spec.js +10 -0
- package/src/views/method-selector/get-payment-methods.js +7 -2
- package/src/views/method-selector/get-payment-methods.spec.js +26 -23
- package/src/views/method-selector/index.js +21 -28
- package/src/views/method-selector/method-selector.spec.js +49 -64
- package/src/views/method-selector/mount-methods.js +5 -8
- package/src/views/modal.js +6 -2
- package/src/views/result.js +4 -3
- package/src/views/summary.js +161 -117
- package/src/views/summary.spec.js +60 -75
- package/tests/mocks/rebilly-instruments-mock.js +37 -7
- package/tests/mocks/storefront-api-mock.js +8 -0
- package/tests/mocks/storefront-mock.js +17 -0
- package/dist/functions/mount/fetch-summary-data.js +0 -46
- package/dist/functions/mount/fetch-summary-data.spec.js +0 -43
- package/src/functions/mount/fetch-summary-data.js +0 -29
- package/src/functions/mount/fetch-summary-data.spec.js +0 -40
package/src/index.spec.js
CHANGED
|
@@ -4,14 +4,6 @@ import { avoidUnhandledPromises } from 'tests/async-utilities';
|
|
|
4
4
|
describe('RebillyInstruments instance', () => {
|
|
5
5
|
let rebillyInstruments;
|
|
6
6
|
|
|
7
|
-
function setupInstance(
|
|
8
|
-
options = {
|
|
9
|
-
test: 'value'
|
|
10
|
-
}
|
|
11
|
-
) {
|
|
12
|
-
rebillyInstruments.mount(options);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
7
|
beforeEach(() => {
|
|
16
8
|
rebillyInstruments = RebillyInstruments;
|
|
17
9
|
});
|
|
@@ -30,24 +22,14 @@ describe('RebillyInstruments instance', () => {
|
|
|
30
22
|
|
|
31
23
|
const options = {
|
|
32
24
|
form: '.form-selector',
|
|
33
|
-
|
|
25
|
+
summary: '.summary-selector',
|
|
26
|
+
items: []
|
|
34
27
|
};
|
|
35
28
|
|
|
36
|
-
|
|
29
|
+
await rebillyInstruments.mount(options);
|
|
37
30
|
|
|
38
31
|
expect(rebillyInstruments.mount).toHaveBeenCalledTimes(1);
|
|
39
32
|
expect(rebillyInstruments.mount).toHaveBeenCalledWith(options);
|
|
40
33
|
await avoidUnhandledPromises();
|
|
41
34
|
});
|
|
42
|
-
|
|
43
|
-
it('should be able to trigger a purchase', () => {
|
|
44
|
-
jest.spyOn(rebillyInstruments, 'purchase');
|
|
45
|
-
|
|
46
|
-
const instrument = {};
|
|
47
|
-
|
|
48
|
-
setupInstance();
|
|
49
|
-
rebillyInstruments.purchase(instrument);
|
|
50
|
-
|
|
51
|
-
expect(rebillyInstruments.purchase).toHaveBeenCalledTimes(1);
|
|
52
|
-
});
|
|
53
35
|
});
|
package/src/loader/index.js
CHANGED
|
@@ -15,17 +15,15 @@ export class Loader {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
addDOMElement({ section = 'form', el = null } = {}) {
|
|
18
|
-
const minHeight = '200px';
|
|
19
|
-
|
|
20
18
|
if (isDOMElement(el)) {
|
|
21
19
|
el.style.position = 'relative';
|
|
22
|
-
el.style.minHeight = minHeight;
|
|
23
20
|
|
|
24
21
|
this.DOM[section] = el;
|
|
25
22
|
}
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
startLoading({ section = 'form', id = '' } = {}) {
|
|
26
|
+
const minHeight = '200px';
|
|
29
27
|
this[section].push(id);
|
|
30
28
|
|
|
31
29
|
if (this.DOM?.[section]) {
|
|
@@ -36,6 +34,7 @@ export class Loader {
|
|
|
36
34
|
.querySelector('.rebilly-instruments-loader')
|
|
37
35
|
.classList.add('is-active');
|
|
38
36
|
}
|
|
37
|
+
this.DOM[section].style.minHeight = minHeight;
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -53,6 +52,7 @@ export class Loader {
|
|
|
53
52
|
this.DOM[section]
|
|
54
53
|
.querySelector('.rebilly-instruments-loader')
|
|
55
54
|
.classList.remove('is-active');
|
|
55
|
+
this.DOM[section].style.minHeight = '';
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
package/src/storefront/index.js
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
import { RebillyStorefrontAPI } from 'rebilly-js-sdk';
|
|
2
2
|
|
|
3
|
+
export function validateStateForStorefront({state}) {
|
|
4
|
+
if (!state.storefront) {
|
|
5
|
+
throw new Error('Could not access rebilly-js-sdk instance');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!state.options) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
'Could not use Rebilly Instruments mount options to fetch Rebilly data'
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function Endpoint({
|
|
16
|
+
state
|
|
17
|
+
} = {}, callback) {
|
|
18
|
+
try {
|
|
19
|
+
validateStateForStorefront({state});
|
|
20
|
+
return await callback();
|
|
21
|
+
} catch(error) {
|
|
22
|
+
// TODO: standard error handling for all endpoints
|
|
23
|
+
// console.error(error);
|
|
24
|
+
if(error.status === 422) {
|
|
25
|
+
error.details.forEach(e => console.error(e));
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
3
31
|
export class StorefrontInstance {
|
|
4
32
|
constructor({
|
|
5
33
|
publishableKey = null,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import InvoiceModel from './models/invoice-model';
|
|
2
|
+
import { Endpoint } from './index';
|
|
3
|
+
|
|
4
|
+
export async function fetchInvoice({ data = null, state = null }) {
|
|
5
|
+
return Endpoint({state}, async () => {
|
|
6
|
+
state.storefront.setSessionToken(state.options.customerJwt);
|
|
7
|
+
const {fields} = await state.storefront.invoices.get(data);
|
|
8
|
+
|
|
9
|
+
return new InvoiceModel(fields);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -1,35 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
name = '',
|
|
5
|
-
productId = '',
|
|
6
|
-
productOptions = {},
|
|
7
|
-
currency = '',
|
|
8
|
-
currencySign = '',
|
|
9
|
-
pricing = {},
|
|
10
|
-
recurringInterval = {},
|
|
11
|
-
trial = null,
|
|
12
|
-
isTrialOnly = false,
|
|
13
|
-
setup = null,
|
|
14
|
-
customFields = {},
|
|
15
|
-
createdTime = '',
|
|
16
|
-
updatedTime = '',
|
|
17
|
-
invoiceTimeShift = {}
|
|
18
|
-
} = {}) {
|
|
19
|
-
this.id = id;
|
|
20
|
-
this.name = name;
|
|
21
|
-
this.productId = productId;
|
|
22
|
-
this.productOptions = productOptions;
|
|
23
|
-
this.currency = currency;
|
|
24
|
-
this.currencySign = currencySign;
|
|
25
|
-
this.pricing = pricing;
|
|
26
|
-
this.recurringInterval = recurringInterval;
|
|
27
|
-
this.trial = trial;
|
|
28
|
-
this.isTrialOnly = isTrialOnly;
|
|
29
|
-
this.setup = setup;
|
|
30
|
-
this.customFields = customFields;
|
|
31
|
-
this.createdTime = createdTime;
|
|
32
|
-
this.updatedTime = updatedTime;
|
|
33
|
-
this.invoiceTimeShift = invoiceTimeShift;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
1
|
+
import BaseModel from './base-model';
|
|
2
|
+
|
|
3
|
+
export default class PlanModel extends BaseModel {}
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
name = '',
|
|
5
|
-
unitLabel = '',
|
|
6
|
-
description = {},
|
|
7
|
-
requiresShipping = false,
|
|
8
|
-
options = [],
|
|
9
|
-
customFields = {},
|
|
10
|
-
createdTime = '',
|
|
11
|
-
updatedTime = ''
|
|
12
|
-
} = {}) {
|
|
13
|
-
this.id = id;
|
|
14
|
-
this.name = name;
|
|
15
|
-
this.unitLabel = unitLabel;
|
|
16
|
-
this.description = description;
|
|
17
|
-
this.requiresShipping = requiresShipping;
|
|
18
|
-
this.options = options;
|
|
19
|
-
this.customFields = customFields;
|
|
20
|
-
this.createdTime = createdTime;
|
|
21
|
-
this.updatedTime = updatedTime;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
1
|
+
import BaseModel from './base-model';
|
|
2
|
+
|
|
3
|
+
export default class ProductModel extends BaseModel {}
|
|
@@ -1,35 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
import BaseModel from './base-model';
|
|
2
|
+
|
|
3
|
+
export class SummaryLineItemModel extends BaseModel {
|
|
2
4
|
constructor({
|
|
3
|
-
type = '',
|
|
4
|
-
description = '',
|
|
5
5
|
unitPrice = 0.0,
|
|
6
6
|
quantity = 0,
|
|
7
7
|
price = 0.0,
|
|
8
|
-
|
|
9
|
-
productId = ''
|
|
8
|
+
...fields
|
|
10
9
|
} = {}) {
|
|
11
|
-
|
|
12
|
-
this.description = description;
|
|
10
|
+
super(fields);
|
|
13
11
|
this.unitPrice = unitPrice;
|
|
14
12
|
this.quantity = quantity;
|
|
15
13
|
this.price = price;
|
|
16
|
-
this.planId = planId;
|
|
17
|
-
this.productId = productId;
|
|
18
14
|
}
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
export class SummaryTaxModel {
|
|
22
|
-
constructor({ amount = '', description = '' } = {}) {
|
|
23
|
-
this.amount = amount;
|
|
24
|
-
this.description = description;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
17
|
+
export class SummaryTaxModel extends BaseModel {}
|
|
27
18
|
|
|
28
|
-
export class SummaryDiscountModel {
|
|
29
|
-
constructor({
|
|
30
|
-
|
|
19
|
+
export class SummaryDiscountModel extends BaseModel {
|
|
20
|
+
constructor({
|
|
21
|
+
amount = 0,
|
|
22
|
+
...fields
|
|
23
|
+
}) {
|
|
24
|
+
super(fields);
|
|
31
25
|
this.amount = amount;
|
|
32
|
-
this.description = description;
|
|
33
26
|
}
|
|
34
27
|
}
|
|
35
28
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import BaseModel from './base-model';
|
|
2
|
+
|
|
3
|
+
export default class TransactionModel extends BaseModel {
|
|
4
|
+
constructor({
|
|
5
|
+
invoiceIds = [],
|
|
6
|
+
...fields
|
|
7
|
+
}) {
|
|
8
|
+
super(fields);
|
|
9
|
+
this.invoiceIds = invoiceIds || [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get invoiceId () {
|
|
13
|
+
return this.invoiceIds[0] || null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get hasInvoice () {
|
|
17
|
+
return !!this.invoiceId;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Endpoint } from './index';
|
|
2
|
+
|
|
3
|
+
export async function setupPaymentInstrument({ data, state }) {
|
|
4
|
+
return Endpoint({state}, async () => {
|
|
5
|
+
// Create payment instrument
|
|
6
|
+
const { fields: instrument } = await state.storefront.paymentInstruments.create({data});
|
|
7
|
+
|
|
8
|
+
// Setup the payment instrument
|
|
9
|
+
state.storefront.setSessionToken(instrument.token);
|
|
10
|
+
|
|
11
|
+
const setupPayload = {
|
|
12
|
+
id: instrument.id,
|
|
13
|
+
data: {
|
|
14
|
+
websiteId: state.options.websiteId,
|
|
15
|
+
...data
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if(state.data.getAmountAndCurrency) {
|
|
20
|
+
setupPayload.data = {
|
|
21
|
+
...setupPayload.data,
|
|
22
|
+
...state.data.getAmountAndCurrency
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const { fields: transaction } = await state.storefront.paymentInstruments.setup(setupPayload);
|
|
27
|
+
|
|
28
|
+
return {instrument, transaction};
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
|
|
2
|
+
import { ok, post } from 'msw-when-then';
|
|
3
|
+
import { when } from 'tests/msw/server';
|
|
4
|
+
import { storefrontURL } from 'tests/mocks/storefront-api-mock';
|
|
5
|
+
|
|
6
|
+
describe('Storefront API Setup', () => {
|
|
7
|
+
it('can make purchase', async () => {
|
|
8
|
+
const instance = new StorefontTestingInstance();
|
|
9
|
+
|
|
10
|
+
const paymentInstrumentFields = {
|
|
11
|
+
id: 'payment-instrument-id'
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const paymentInstrumentSetupFields = {
|
|
15
|
+
id: 'payment-instrument-id',
|
|
16
|
+
approvalUrl: null
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const paymentInstrumentPayload = {
|
|
20
|
+
data: {
|
|
21
|
+
token: 'test-token'
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const paymentInstrumentSetupPayload = {
|
|
26
|
+
id: paymentInstrumentFields.id,
|
|
27
|
+
data: {
|
|
28
|
+
websiteId: 'website-id',
|
|
29
|
+
currency: 'USD',
|
|
30
|
+
amount: 30
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
when(post(`${storefrontURL}/payment-instruments`)).thenReturn(ok(paymentInstrumentFields));
|
|
35
|
+
when(post(`${storefrontURL}/payment-instruments/*/setup`)).thenReturn(ok(paymentInstrumentSetupFields));
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
jest.spyOn(instance.storefront.paymentInstruments, 'create');
|
|
39
|
+
jest.spyOn(instance.storefront.paymentInstruments, 'setup');
|
|
40
|
+
|
|
41
|
+
const paymentInstrumentResponse = await instance.storefront.paymentInstruments.create(
|
|
42
|
+
paymentInstrumentPayload
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const paymentInstrumentSetupResponse = await instance.storefront.paymentInstruments.setup(
|
|
46
|
+
paymentInstrumentSetupPayload
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(instance.storefront.paymentInstruments.create).toBeCalledTimes(1);
|
|
50
|
+
expect(instance.storefront.paymentInstruments.create).toBeCalledWith(paymentInstrumentPayload);
|
|
51
|
+
|
|
52
|
+
expect(instance.storefront.paymentInstruments.setup).toBeCalledTimes(1);
|
|
53
|
+
expect(instance.storefront.paymentInstruments.setup).toBeCalledWith(paymentInstrumentSetupPayload);
|
|
54
|
+
|
|
55
|
+
expect(paymentInstrumentResponse.config).toBeInstanceOf(Object);
|
|
56
|
+
expect(paymentInstrumentResponse.fields).toBeInstanceOf(Object);
|
|
57
|
+
expect(paymentInstrumentResponse.response).toBeInstanceOf(Object);
|
|
58
|
+
|
|
59
|
+
expect(paymentInstrumentResponse.fields).toEqual(paymentInstrumentFields);
|
|
60
|
+
expect(paymentInstrumentResponse.fields).toMatchObject(paymentInstrumentFields);
|
|
61
|
+
|
|
62
|
+
expect(paymentInstrumentSetupResponse.config).toBeInstanceOf(Object);
|
|
63
|
+
expect(paymentInstrumentSetupResponse.fields).toBeInstanceOf(Object);
|
|
64
|
+
expect(paymentInstrumentSetupResponse.response).toBeInstanceOf(Object);
|
|
65
|
+
|
|
66
|
+
expect(paymentInstrumentSetupResponse.fields).toEqual(paymentInstrumentSetupFields);
|
|
67
|
+
expect(paymentInstrumentSetupResponse.fields).toMatchObject(paymentInstrumentSetupFields);
|
|
68
|
+
});
|
|
69
|
+
});
|
package/src/storefront/plans.js
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import PlanModel from './models/plan-model';
|
|
2
|
+
import { Endpoint } from './index';
|
|
2
3
|
|
|
3
|
-
export async function fetchPlans({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
if (!state.options) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
'Could not use Rebilly Instruments mount options to fetch Rebilly data'
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
const { lineItems } = data || {};
|
|
4
|
+
export async function fetchPlans({ state = {}, data = {} }) {
|
|
5
|
+
return Endpoint({state}, async () => {
|
|
6
|
+
const lineItems = data.lineItems || state.data.summaryLineItems;
|
|
16
7
|
|
|
17
8
|
const filterByPlanId = {
|
|
18
9
|
filter: ''
|
|
19
10
|
};
|
|
20
11
|
|
|
21
|
-
if (lineItems) {
|
|
12
|
+
if (lineItems.length) {
|
|
22
13
|
filterByPlanId.filter = `id:${lineItems
|
|
23
14
|
.map((item) => item.planId)
|
|
24
15
|
.join(',')}`;
|
|
@@ -28,7 +19,5 @@ export async function fetchPlans({ data = null, state = null }) {
|
|
|
28
19
|
filterByPlanId
|
|
29
20
|
);
|
|
30
21
|
return planItems.map(({ fields }) => new PlanModel(fields));
|
|
31
|
-
}
|
|
32
|
-
throw error;
|
|
33
|
-
}
|
|
22
|
+
});
|
|
34
23
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
|
|
2
2
|
import { ok, get } from 'msw-when-then';
|
|
3
3
|
import { when } from 'tests/msw/server';
|
|
4
4
|
import { storefrontURL } from 'tests/mocks/storefront-api-mock';
|
|
@@ -7,19 +7,12 @@ import PlanModel from './models/plan-model';
|
|
|
7
7
|
import { expectConfigurationError } from 'tests/async-utilities';
|
|
8
8
|
|
|
9
9
|
describe('Storefront API Plan', () => {
|
|
10
|
-
class TestPlansInstance {
|
|
11
|
-
constructor({ options = {} } = {}) {
|
|
12
|
-
this.options = options;
|
|
13
|
-
this.storefront = MockStorefront();
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
10
|
it('can fetch plans', async () => {
|
|
18
11
|
const testPlan = { name: 'Test Plan', id: 'test-plan-id-1' };
|
|
19
12
|
|
|
20
13
|
when(get(`${storefrontURL}/plans`)).thenReturn(ok([testPlan]));
|
|
21
14
|
|
|
22
|
-
const instance = new
|
|
15
|
+
const instance = new StorefontTestingInstance();
|
|
23
16
|
|
|
24
17
|
jest.spyOn(instance.storefront.plans, 'getAll');
|
|
25
18
|
|
|
@@ -35,7 +28,7 @@ describe('Storefront API Plan', () => {
|
|
|
35
28
|
});
|
|
36
29
|
|
|
37
30
|
it('can fetch plans with filter', async () => {
|
|
38
|
-
const instance = new
|
|
31
|
+
const instance = new StorefontTestingInstance();
|
|
39
32
|
|
|
40
33
|
jest.spyOn(instance.storefront.plans, 'getAll');
|
|
41
34
|
|
|
@@ -59,7 +52,7 @@ describe('Storefront API Plan', () => {
|
|
|
59
52
|
});
|
|
60
53
|
|
|
61
54
|
it('should throw errors with no options', async () => {
|
|
62
|
-
const noConfigOrOptionsInstance = new
|
|
55
|
+
const noConfigOrOptionsInstance = new StorefontTestingInstance({
|
|
63
56
|
options: null
|
|
64
57
|
});
|
|
65
58
|
await expectConfigurationError(
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import ProductModel from './models/product-model';
|
|
2
|
+
import { Endpoint } from './index';
|
|
2
3
|
|
|
3
|
-
export async function fetchProducts({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (!state.options) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
'Could not use Rebilly Instruments mount options to fetch Rebilly data'
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
const plansData = data || [];
|
|
4
|
+
export async function fetchProducts({ state }) {
|
|
5
|
+
return Endpoint({state}, async () => {
|
|
6
|
+
if (state.data.plans === null) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
16
9
|
|
|
10
|
+
const plansData = state.data.plans || [];
|
|
17
11
|
const filterByProductId = {
|
|
18
12
|
filter: ''
|
|
19
13
|
};
|
|
@@ -28,7 +22,5 @@ export async function fetchProducts({ data = null, state }) {
|
|
|
28
22
|
filterByProductId
|
|
29
23
|
);
|
|
30
24
|
return productItems.map(({ fields }) => new ProductModel(fields));
|
|
31
|
-
}
|
|
32
|
-
throw error;
|
|
33
|
-
}
|
|
25
|
+
});
|
|
34
26
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
|
|
2
2
|
import { ok, get } from 'msw-when-then';
|
|
3
3
|
import { when } from 'tests/msw/server';
|
|
4
4
|
import { storefrontURL } from 'tests/mocks/storefront-api-mock';
|
|
@@ -7,19 +7,12 @@ import ProductModel from './models/product-model';
|
|
|
7
7
|
import { expectConfigurationError } from 'tests/async-utilities';
|
|
8
8
|
|
|
9
9
|
describe('Storefront API Plan', () => {
|
|
10
|
-
class TestProductsInstance {
|
|
11
|
-
constructor({ options = {} } = {}) {
|
|
12
|
-
this.options = options;
|
|
13
|
-
this.storefront = MockStorefront();
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
10
|
it('can fetch products', async () => {
|
|
18
11
|
const testProduct = { name: 'Test Product', id: 'test-product-id-1' };
|
|
19
12
|
|
|
20
13
|
when(get(`${storefrontURL}/products`)).thenReturn(ok([testProduct]));
|
|
21
14
|
|
|
22
|
-
const instance = new
|
|
15
|
+
const instance = new StorefontTestingInstance();
|
|
23
16
|
|
|
24
17
|
jest.spyOn(instance.storefront.products, 'getAll');
|
|
25
18
|
|
|
@@ -35,21 +28,22 @@ describe('Storefront API Plan', () => {
|
|
|
35
28
|
});
|
|
36
29
|
|
|
37
30
|
it('can fetch products with filter', async () => {
|
|
38
|
-
const instance = new
|
|
31
|
+
const instance = new StorefontTestingInstance({
|
|
32
|
+
data: {
|
|
33
|
+
plans: [
|
|
34
|
+
{
|
|
35
|
+
productId: 'test-product-1'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
productId: 'test-product-2'
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
});
|
|
39
43
|
|
|
40
44
|
jest.spyOn(instance.storefront.products, 'getAll');
|
|
41
45
|
|
|
42
|
-
await fetchProducts({
|
|
43
|
-
state: instance,
|
|
44
|
-
data: [
|
|
45
|
-
{
|
|
46
|
-
productId: 'test-product-1'
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
productId: 'test-product-2'
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
});
|
|
46
|
+
await fetchProducts({ state: instance });
|
|
53
47
|
|
|
54
48
|
expect(instance.storefront.products.getAll).toBeCalledWith({
|
|
55
49
|
filter: 'id:test-product-1,test-product-2'
|
|
@@ -57,7 +51,7 @@ describe('Storefront API Plan', () => {
|
|
|
57
51
|
});
|
|
58
52
|
|
|
59
53
|
it('should throw errors with no options', async () => {
|
|
60
|
-
const noConfigOrOptionsInstance = new
|
|
54
|
+
const noConfigOrOptionsInstance = new StorefontTestingInstance({
|
|
61
55
|
options: null
|
|
62
56
|
});
|
|
63
57
|
await expectConfigurationError(
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
if (!state.storefront) {
|
|
3
|
-
throw new Error('Could not access rebilly-js-sdk instance');
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
if (!state.options) {
|
|
7
|
-
throw new Error(
|
|
8
|
-
'Could not use Rebilly Instruments mount options to fetch Rebilly data'
|
|
9
|
-
);
|
|
10
|
-
}
|
|
1
|
+
import { Endpoint } from './index';
|
|
11
2
|
|
|
12
|
-
|
|
3
|
+
export async function postPurchase({ data, state }) {
|
|
4
|
+
return Endpoint({state}, async () => {
|
|
13
5
|
if (data._raw) {
|
|
14
6
|
delete data._raw;
|
|
15
7
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} catch (error) {
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
8
|
+
return state.storefront.purchase.purchase({ data });
|
|
9
|
+
});
|
|
21
10
|
}
|
|
11
|
+
|
|
12
|
+
export async function postPayment({ data, state }) {
|
|
13
|
+
return Endpoint({state}, async () => {
|
|
14
|
+
if (data._raw) {
|
|
15
|
+
delete data._raw;
|
|
16
|
+
}
|
|
17
|
+
return state.storefront.purchase.payment({ data });
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
|
|
2
2
|
import { ok, post } from 'msw-when-then';
|
|
3
3
|
import { when } from 'tests/msw/server';
|
|
4
4
|
import { storefrontURL } from 'tests/mocks/storefront-api-mock';
|
|
5
|
-
import { postPurchase } from './purchase';
|
|
6
5
|
|
|
7
6
|
describe('Storefront API Purchase', () => {
|
|
8
|
-
class TestPurchaseInstance {
|
|
9
|
-
constructor({ options = {} } = {}) {
|
|
10
|
-
this.options = options;
|
|
11
|
-
this.storefront = MockStorefront();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
postPurchase(...args) {
|
|
15
|
-
return postPurchase({ state: this, data: args });
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
7
|
it('can make purchase', async () => {
|
|
20
|
-
const instance =
|
|
8
|
+
const instance = StorefontTestingInstance();
|
|
21
9
|
const payload = {
|
|
22
10
|
websiteId: 'test-website-id',
|
|
23
11
|
items: [
|
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
import { collectData } from '@rebilly/risk-data-collector';
|
|
2
2
|
import ReadyToPayModel from './models/ready-to-pay-model';
|
|
3
|
+
import { Endpoint } from './index';
|
|
3
4
|
|
|
4
5
|
export async function fetchReadyToPay({ state, riskMetadata = null }) {
|
|
5
|
-
|
|
6
|
-
throw new Error('Could not access rebilly-js-sdk instance');
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
if (!state.options) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
'Could not use Rebilly Instruments mount options to fetch Rebilly data'
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
try {
|
|
6
|
+
return Endpoint({state}, async () => {
|
|
16
7
|
if (!riskMetadata) {
|
|
17
8
|
const { riskMetadata: data } = await collectData();
|
|
18
9
|
riskMetadata = data;
|
|
19
10
|
}
|
|
20
11
|
const websiteId = state.options?.websiteId || null;
|
|
21
|
-
const items = state.options?.items || [];
|
|
22
12
|
|
|
23
13
|
const data = {
|
|
24
|
-
items,
|
|
25
14
|
websiteId,
|
|
26
15
|
riskMetadata
|
|
27
16
|
};
|
|
28
17
|
|
|
18
|
+
if (state.options?.items) {
|
|
19
|
+
data.items = state.options.items;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (state.data?.amountAndCurrency) {
|
|
23
|
+
const money = state.data.amountAndCurrency;
|
|
24
|
+
data.amount = money.amount;
|
|
25
|
+
data.currency = money.currency;
|
|
26
|
+
}
|
|
27
|
+
|
|
29
28
|
const { fields: readyToPayFields } =
|
|
30
29
|
await state.storefront.purchase.readyToPay({ data });
|
|
31
30
|
|
|
@@ -36,7 +35,5 @@ export async function fetchReadyToPay({ state, riskMetadata = null }) {
|
|
|
36
35
|
...fields
|
|
37
36
|
})
|
|
38
37
|
);
|
|
39
|
-
}
|
|
40
|
-
throw error;
|
|
41
|
-
}
|
|
38
|
+
});
|
|
42
39
|
}
|