@rebilly/instruments 4.5.0 → 4.6.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 +24 -26
- package/CHANGELOG.md +7 -0
- package/dist/index.js +8 -8
- package/dist/index.min.js +8 -8
- package/package.json +14 -3
- package/project.json +9 -0
- package/rollup.config.mjs +21 -26
- package/src/data/options-schema/index.js +94 -78
- package/src/data/options-schema/schemas/options-schema.js +419 -411
- package/src/events/base-event.js +34 -34
- package/src/events/events.spec.js +6 -6
- package/src/events/index.js +5 -5
- package/src/functions/destroy.js +19 -19
- package/src/functions/destroy.spec.js +41 -41
- package/src/functions/mount/fetch-data.js +200 -193
- package/src/functions/mount/fetch-data.spec.js +287 -285
- package/src/functions/mount/get-lead-source-data.js +31 -31
- package/src/functions/mount/get-lead-source-data.spec.js +19 -19
- package/src/functions/mount/index.js +73 -65
- package/src/functions/mount/mount.spec.js +77 -66
- package/src/functions/mount/setup-element.js +23 -23
- package/src/functions/mount/setup-framepay-theme.js +86 -68
- package/src/functions/mount/setup-framepay.js +9 -5
- package/src/functions/mount/setup-i18n.js +15 -15
- package/src/functions/mount/setup-options.js +74 -74
- package/src/functions/mount/setup-options.spec.js +323 -287
- package/src/functions/mount/setup-storefront.js +15 -20
- package/src/functions/mount/setup-styles-vars.js +19 -22
- package/src/functions/mount/setup-user-flow.js +51 -47
- package/src/functions/on.js +5 -5
- package/src/functions/on.spec.js +60 -51
- package/src/functions/purchase.js +151 -146
- package/src/functions/purchase.spec.js +59 -56
- package/src/functions/setup.js +53 -53
- package/src/functions/setup.spec.js +88 -75
- package/src/functions/show.js +13 -14
- package/src/functions/show.spec.js +53 -53
- package/src/functions/update.js +30 -28
- package/src/functions/update.spec.js +94 -93
- package/src/i18n/en.json +32 -32
- package/src/i18n/es.json +29 -29
- package/src/i18n/i18n.spec.js +18 -18
- package/src/i18n/index.js +48 -48
- package/src/instance.js +36 -36
- package/src/instance.spec.js +29 -27
- package/src/loader/index.js +95 -70
- package/src/loader/loader.spec.js +63 -63
- package/src/state/iframes.js +21 -21
- package/src/state/index.js +56 -54
- package/src/storefront/account-and-website.js +10 -8
- package/src/storefront/account-and-website.spec.js +55 -55
- package/src/storefront/deposit-requests.js +6 -6
- package/src/storefront/fetch-plans-from-addons-bumpOffer.js +21 -19
- package/src/storefront/fetch-products-from-plans.js +52 -51
- package/src/storefront/fetch-products-from-plans.spec.js +90 -87
- package/src/storefront/index.js +56 -49
- package/src/storefront/invoices.js +15 -15
- package/src/storefront/invoices.spec.js +69 -65
- package/src/storefront/models/account-model.js +29 -32
- package/src/storefront/models/base-model.js +6 -9
- package/src/storefront/models/deposit-request-model.js +22 -13
- package/src/storefront/models/invoice-model.js +16 -16
- package/src/storefront/models/payment-metadata.js +4 -4
- package/src/storefront/models/plan-model.js +73 -64
- package/src/storefront/models/ready-to-pay-model.js +59 -59
- package/src/storefront/models/summary-model.js +43 -46
- package/src/storefront/models/transaction-model.js +11 -14
- package/src/storefront/payment-instruments.js +38 -35
- package/src/storefront/payment-instruments.spec.js +81 -62
- package/src/storefront/purchase.js +50 -44
- package/src/storefront/purchase.spec.js +40 -40
- package/src/storefront/ready-to-pay.js +75 -77
- package/src/storefront/ready-to-pay.spec.js +59 -54
- package/src/storefront/storefront.spec.js +9 -9
- package/src/storefront/summary.js +93 -67
- package/src/storefront/summary.spec.js +108 -106
- package/src/storefront/transactions.js +6 -6
- package/src/style/base/default-theme.js +928 -923
- package/src/style/base/theme.js +21 -21
- package/src/style/base/theme.spec.js +13 -13
- package/src/style/index.js +3 -3
- package/src/style/utils/border.js +40 -27
- package/src/style/utils/color-values.js +18 -18
- package/src/style/utils/minifyCss.js +6 -6
- package/src/utils/add-dom-element.js +14 -14
- package/src/utils/format-currency.js +6 -5
- package/src/utils/has-valid-css-selector.js +2 -2
- package/src/utils/index.js +6 -6
- package/src/utils/is-dom-element.js +1 -1
- package/src/utils/process-property-as-dom-element.js +22 -22
- package/src/utils/quantity.js +26 -28
- package/src/utils/sleep.js +3 -1
- package/src/views/amount-selector.js +37 -36
- package/src/views/common/iframe/base-iframe.js +53 -52
- package/src/views/common/iframe/events/change-iframe-src-handler.js +5 -5
- package/src/views/common/iframe/events/dispatch-event-handler.js +4 -4
- package/src/views/common/iframe/events/resize-component-handler.js +8 -8
- package/src/views/common/iframe/events/show-error-handler.js +2 -2
- package/src/views/common/iframe/events/stop-loader-handler.js +8 -8
- package/src/views/common/iframe/events/update-addons-handler.js +20 -13
- package/src/views/common/iframe/events/update-coupons-handler.js +9 -9
- package/src/views/common/iframe/events/update-items-handler.js +26 -22
- package/src/views/common/iframe/modal-iframe.js +67 -56
- package/src/views/common/iframe/view-iframe.js +11 -11
- package/src/views/common/render-utilities.js +2 -2
- package/src/views/confirmation.js +33 -30
- package/src/views/errors.js +89 -79
- package/src/views/form.js +41 -37
- package/src/views/method-selector/express-methods.js +46 -46
- package/src/views/method-selector/generate-digital-wallet.js +46 -45
- package/src/views/method-selector/generate-digital-wallet.spec.js +104 -102
- package/src/views/method-selector/generate-framepay-config.js +53 -51
- package/src/views/method-selector/generate-framepay-config.spec.js +197 -173
- package/src/views/method-selector/get-method-data.js +5 -6
- package/src/views/method-selector/get-payment-methods.js +18 -16
- package/src/views/method-selector/get-payment-methods.spec.js +29 -27
- package/src/views/method-selector/index.js +154 -139
- package/src/views/method-selector/method-selector.spec.js +13 -13
- package/src/views/method-selector/mount-bump-offer.js +65 -49
- package/src/views/method-selector/mount-express-methods.js +89 -85
- package/src/views/modal.js +74 -67
- package/src/views/result.js +14 -14
- package/src/views/summary.js +25 -26
- package/tests/async-utilities.js +13 -13
- package/tests/mocks/framepay-mock.js +9 -8
- package/tests/mocks/rebilly-api-mock.js +5 -3
- package/tests/mocks/rebilly-instruments-mock.js +121 -117
- package/tests/mocks/storefront-api-mock.js +55 -48
- package/tests/mocks/storefront-mock.js +10 -14
- package/tests/msw/server.js +6 -6
- package/tests/setup-test.js +14 -16
- package/vitest.config.js +14 -14
- package/.eslintrc.js +0 -34
- package/.prettierrc.js +0 -11
|
@@ -3,26 +3,28 @@ import { Endpoint } from './index';
|
|
|
3
3
|
import state from '../state';
|
|
4
4
|
|
|
5
5
|
export async function fetchPlansFromAddonsBumpOffer() {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
return Endpoint(async () => {
|
|
7
|
+
let ids = [];
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
9
|
+
if (state.options?.addons) {
|
|
10
|
+
ids = ids.concat(state.options.addons.map((item) => item.planId));
|
|
11
|
+
}
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if (state.options?.bumpOffer) {
|
|
14
|
+
ids = ids.concat(
|
|
15
|
+
state.options.bumpOffer.map((item) => item.planId),
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
if (ids.length > 0) {
|
|
20
|
+
const { items: planItems } = await state.storefront.plans.getAll({
|
|
21
|
+
filter: `id:${ids.join(',')}`,
|
|
22
|
+
});
|
|
23
|
+
return planItems.map(({ fields }) =>
|
|
24
|
+
new PlanModel(fields).toPayload(),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
28
|
+
return [];
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -3,56 +3,57 @@ import { Endpoint } from './index';
|
|
|
3
3
|
import state from '../state';
|
|
4
4
|
|
|
5
5
|
export async function fetchProductsFromPlans() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.map((item) => item.planId));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (state.options?.bumpOffer) {
|
|
28
|
-
ids = ids.concat(state.options.bumpOffer
|
|
29
|
-
.map((item) => item.planId));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
filterByPlanId.filter = `id:${[...new Set(ids)].join(',')}`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Only fetch plans if we have specific plans to fetch
|
|
36
|
-
if (filterByPlanId.filter.length) {
|
|
37
|
-
try
|
|
38
|
-
{
|
|
39
|
-
const { items: planItems } = await state.storefront.plans.getAll(
|
|
40
|
-
filterByPlanId
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const products = []
|
|
44
|
-
planItems
|
|
45
|
-
.map(({ fields }) => new ProductModel(fields._embedded.product))
|
|
46
|
-
.forEach(product => {
|
|
47
|
-
if (products.every(item => item.id !== product.id)) {
|
|
48
|
-
products.push(product)
|
|
6
|
+
return Endpoint(async () => {
|
|
7
|
+
let lineItems = state.data.summaryLineItems;
|
|
8
|
+
if (lineItems.length === 0) {
|
|
9
|
+
lineItems = state.options?.items ?? [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const filterByPlanId = {
|
|
13
|
+
filter: '',
|
|
14
|
+
expand: 'product',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
if (lineItems.length) {
|
|
18
|
+
let ids = lineItems.map((item) => item.planId);
|
|
19
|
+
|
|
20
|
+
if (state.options?.addons) {
|
|
21
|
+
ids = ids.concat(
|
|
22
|
+
state.options.addons.map((item) => item.planId),
|
|
23
|
+
);
|
|
49
24
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
25
|
+
|
|
26
|
+
if (state.options?.bumpOffer) {
|
|
27
|
+
ids = ids.concat(
|
|
28
|
+
state.options.bumpOffer.map((item) => item.planId),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
filterByPlanId.filter = `id:${[...new Set(ids)].join(',')}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Only fetch plans if we have specific plans to fetch
|
|
36
|
+
if (filterByPlanId.filter.length) {
|
|
37
|
+
try {
|
|
38
|
+
const { items: planItems } =
|
|
39
|
+
await state.storefront.plans.getAll(filterByPlanId);
|
|
40
|
+
|
|
41
|
+
const products = [];
|
|
42
|
+
planItems
|
|
43
|
+
.map(
|
|
44
|
+
({ fields }) =>
|
|
45
|
+
new ProductModel(fields._embedded.product),
|
|
46
|
+
)
|
|
47
|
+
.forEach((product) => {
|
|
48
|
+
if (products.every((item) => item.id !== product.id)) {
|
|
49
|
+
products.push(product);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return products;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
// Ignore and return empty items
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return [];
|
|
58
|
+
});
|
|
58
59
|
}
|
|
@@ -7,104 +7,107 @@ import ProductModel from './models/product-model';
|
|
|
7
7
|
import { expectConfigurationError } from 'tests/async-utilities';
|
|
8
8
|
|
|
9
9
|
describe('Storefront API Plan', () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
it('can fetch products from a single plan', async () => {
|
|
11
|
+
const testPlan = {
|
|
12
|
+
name: 'Test Plan',
|
|
13
|
+
id: 'test-plan-id-1',
|
|
14
|
+
_embedded: {
|
|
15
|
+
product: {
|
|
16
|
+
id: 'test-product-id',
|
|
17
|
+
requiresShipping: true,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
when(get(`${storefrontURL}/plans`)).thenReturn(ok([testPlan]));
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
const instance = new StorefontTestingInstance({
|
|
25
|
+
options: {
|
|
26
|
+
items: [
|
|
27
|
+
{
|
|
28
|
+
planId: 'test-plan-id-1',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
vi.spyOn(instance.storefront.plans, 'getAll');
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const products = await fetchProductsFromPlans({
|
|
37
|
+
state: instance,
|
|
38
|
+
});
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
expect(instance.storefront.plans.getAll).toBeCalledTimes(1);
|
|
41
|
+
expect(instance.storefront.plans.getAll).toBeCalledWith({
|
|
42
|
+
filter: 'id:test-plan-id-1',
|
|
43
|
+
expand: 'product',
|
|
44
|
+
});
|
|
45
|
+
expect(products).toEqual([
|
|
46
|
+
new ProductModel(testPlan._embedded.product),
|
|
47
|
+
]);
|
|
44
48
|
});
|
|
45
|
-
expect(products).toEqual([new ProductModel(testPlan._embedded.product)]);
|
|
46
|
-
});
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
50
|
+
it('can fetch multiple plans with multiple filters', async () => {
|
|
51
|
+
const testPlans = [
|
|
52
|
+
{
|
|
53
|
+
name: 'Test Plan 1',
|
|
54
|
+
id: 'test-plan-id-1',
|
|
55
|
+
_embedded: {
|
|
56
|
+
product: {
|
|
57
|
+
id: 'test-product-id-1',
|
|
58
|
+
requiresShipping: true,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'Test Plan 2',
|
|
64
|
+
id: 'test-plan-id-2',
|
|
65
|
+
_embedded: {
|
|
66
|
+
product: {
|
|
67
|
+
id: 'test-product-id-2',
|
|
68
|
+
requiresShipping: true,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
when(get(`${storefrontURL}/plans`)).thenReturn(ok(testPlans));
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
const instance = new StorefontTestingInstance({
|
|
76
|
+
options: {
|
|
77
|
+
items: [
|
|
78
|
+
{
|
|
79
|
+
planId: 'test-plan-id-1',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
planId: 'test-plan-id-2',
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
});
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
vi.spyOn(instance.storefront.plans, 'getAll');
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
const products = await fetchProductsFromPlans({
|
|
91
|
+
state: instance,
|
|
92
|
+
});
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
expect(instance.storefront.plans.getAll).toBeCalledWith(
|
|
95
|
+
expect.objectContaining({
|
|
96
|
+
filter: 'id:test-plan-id-1,test-plan-id-2',
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
expect(products).toEqual([
|
|
100
|
+
new ProductModel(testPlans[0]._embedded.product),
|
|
101
|
+
new ProductModel(testPlans[1]._embedded.product),
|
|
102
|
+
]);
|
|
103
|
+
});
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
it('should throw errors with no options', async () => {
|
|
106
|
+
const noConfigOrOptionsInstance = new StorefontTestingInstance({
|
|
107
|
+
options: null,
|
|
108
|
+
});
|
|
109
|
+
await expectConfigurationError(
|
|
110
|
+
fetchProductsFromPlans({ state: noConfigOrOptionsInstance }),
|
|
111
|
+
);
|
|
105
112
|
});
|
|
106
|
-
await expectConfigurationError(
|
|
107
|
-
fetchProductsFromPlans({ state: noConfigOrOptionsInstance })
|
|
108
|
-
);
|
|
109
|
-
});
|
|
110
113
|
});
|
package/src/storefront/index.js
CHANGED
|
@@ -1,71 +1,78 @@
|
|
|
1
|
-
import RebillyApi, {
|
|
1
|
+
import RebillyApi, {
|
|
2
|
+
RebillyStorefrontAPI,
|
|
3
|
+
RebillyExperimentalAPI,
|
|
4
|
+
} from 'rebilly-js-sdk';
|
|
2
5
|
import { showError } from '../views/errors';
|
|
3
6
|
import state from '../state';
|
|
4
7
|
|
|
5
8
|
const TIMEOUT = 60000;
|
|
6
9
|
|
|
7
10
|
export function validateStateForStorefront() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
if (!state.storefront) {
|
|
12
|
+
throw new Error('Could not access rebilly-js-sdk instance');
|
|
13
|
+
}
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (!state.options) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'Could not use Rebilly Instruments mount options to fetch Rebilly data',
|
|
18
|
+
);
|
|
19
|
+
}
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export async function Endpoint(callback) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
try {
|
|
24
|
+
validateStateForStorefront({ state });
|
|
25
|
+
return await callback();
|
|
26
|
+
} catch (error) {
|
|
27
|
+
showError(error);
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export class StorefrontInstance {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
constructor({
|
|
34
|
+
publishableKey = null,
|
|
35
|
+
jwt = null,
|
|
36
|
+
organizationId = null,
|
|
37
|
+
mode = 'live',
|
|
38
|
+
timeout = TIMEOUT,
|
|
39
|
+
liveUrl = null,
|
|
40
|
+
sandboxUrl = null,
|
|
41
|
+
} = {}) {
|
|
42
|
+
const urls = {
|
|
43
|
+
live: liveUrl || 'https://api.rebilly.com',
|
|
44
|
+
sandbox: sandboxUrl || 'https://api-sandbox.rebilly.com',
|
|
45
|
+
};
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const config = {
|
|
48
|
+
organizationId,
|
|
49
|
+
sandbox: mode === 'sandbox',
|
|
50
|
+
timeout: Number.isNaN(parseInt(timeout, 10))
|
|
51
|
+
? TIMEOUT
|
|
52
|
+
: parseInt(timeout, 10),
|
|
53
|
+
urls,
|
|
54
|
+
};
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
const api = RebillyStorefrontAPI(config);
|
|
57
|
+
// TODO: Check why Rollup is making the default as an named export
|
|
58
|
+
const rebilly =
|
|
59
|
+
typeof RebillyApi.default === 'function'
|
|
60
|
+
? RebillyApi.default(config)
|
|
61
|
+
: RebillyApi(config);
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
const experimental = RebillyExperimentalAPI(config);
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
api.setSessionToken(publishableKey || jwt);
|
|
66
|
+
rebilly.setSessionToken(publishableKey || jwt);
|
|
67
|
+
experimental.setSessionToken(publishableKey || jwt);
|
|
62
68
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
this.api = api;
|
|
70
|
+
this.api.rebilly = rebilly;
|
|
71
|
+
this.api.rebilly.experimental = experimental;
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
// eslint-disable-next-line no-constructor-return
|
|
74
|
+
return this.api;
|
|
75
|
+
}
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
export default (config = {}) => new StorefrontInstance(config);
|
|
@@ -4,20 +4,20 @@ import { Endpoint } from './index';
|
|
|
4
4
|
import state from '../state';
|
|
5
5
|
|
|
6
6
|
export async function fetchInvoiceAndProducts({ data = null }) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
return Endpoint(async () => {
|
|
8
|
+
state.storefront.setSessionToken(state.options.jwt);
|
|
9
|
+
const { fields } = await state.storefront.invoices.get({
|
|
10
|
+
...data,
|
|
11
|
+
expand: 'items.*.product',
|
|
12
|
+
});
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const products = fields.items
|
|
15
|
+
.filter((item) => item._embedded)
|
|
16
|
+
.map((items) => new ProductModel(items._embedded.product));
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
18
|
+
return {
|
|
19
|
+
products,
|
|
20
|
+
invoice: new InvoiceModel(fields),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -7,82 +7,86 @@ import ProductModel from './models/product-model';
|
|
|
7
7
|
import InvoiceModel from './models/invoice-model';
|
|
8
8
|
|
|
9
9
|
describe('Storefront Invoices', () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
it('can fetch an invoice and its embedded products', async () => {
|
|
11
|
+
const id = '1234';
|
|
12
|
+
const testInvoice = {
|
|
13
|
+
id: 'test-invoice-id-1',
|
|
14
|
+
items: [
|
|
15
|
+
{
|
|
16
|
+
_embedded: {
|
|
17
|
+
product: {
|
|
18
|
+
id: 'test-product-id',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
when(get(`${storefrontURL}/invoices/${id}`)).thenReturn(
|
|
26
|
+
ok(testInvoice),
|
|
27
|
+
);
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
const instance = new StorefontTestingInstance({
|
|
30
|
+
data: {
|
|
31
|
+
invoice: {
|
|
32
|
+
id,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
vi.spyOn(instance.storefront.invoices, 'get');
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
const { invoice, products } = await fetchInvoiceAndProducts({
|
|
40
|
+
data: { id },
|
|
41
|
+
state: instance,
|
|
42
|
+
});
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
expect(instance.storefront.invoices.get).toBeCalledTimes(1);
|
|
45
|
+
expect(instance.storefront.invoices.get).toBeCalledWith({
|
|
46
|
+
id,
|
|
47
|
+
expand: 'items.*.product',
|
|
48
|
+
});
|
|
49
|
+
expect(invoice).toBeInstanceOf(InvoiceModel);
|
|
50
|
+
expect(products).toBeInstanceOf(Array);
|
|
51
|
+
expect(products[0]).toBeInstanceOf(ProductModel);
|
|
52
|
+
expect(products[0]).toMatchInlineSnapshot(`
|
|
51
53
|
ProductModel {
|
|
52
54
|
"id": "test-product-id",
|
|
53
55
|
}
|
|
54
56
|
`);
|
|
55
|
-
|
|
57
|
+
});
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
it('can fetch an invoice when it does not have any products', async () => {
|
|
60
|
+
const id = '1234';
|
|
61
|
+
const testInvoice = {
|
|
62
|
+
id: 'test-invoice-id-1',
|
|
63
|
+
items: [
|
|
64
|
+
{
|
|
65
|
+
id: 'test',
|
|
66
|
+
price: 0.99,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
when(get(`${storefrontURL}/invoices/${id}`)).thenReturn(
|
|
72
|
+
ok(testInvoice),
|
|
73
|
+
);
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const { invoice, products } = await fetchInvoiceAndProducts({
|
|
80
|
-
data: { id },
|
|
81
|
-
state: instance
|
|
82
|
-
});
|
|
75
|
+
const instance = new StorefontTestingInstance({
|
|
76
|
+
data: {
|
|
77
|
+
invoice: {
|
|
78
|
+
id,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
const { invoice, products } = await fetchInvoiceAndProducts({
|
|
84
|
+
data: { id },
|
|
85
|
+
state: instance,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(invoice).toBeInstanceOf(InvoiceModel);
|
|
89
|
+
expect(products).toBeInstanceOf(Array);
|
|
90
|
+
expect(products.length).toBe(0);
|
|
91
|
+
});
|
|
88
92
|
});
|