@rebilly/instruments 3.14.5-beta.0 → 3.15.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,10 +14,14 @@ describe('Storefront API Plan', () => {
14
14
 
15
15
  const instance = new StorefontTestingInstance({
16
16
  data: {
17
- plans: [{
18
- productId: 'test-product-id'
19
- }
20
- ]}
17
+ invoice: {
18
+ items: [
19
+ {
20
+ productId: 'test-product-id'
21
+ },
22
+ ],
23
+ },
24
+ },
21
25
  });
22
26
 
23
27
  jest.spyOn(instance.storefront.products, 'getAll');
@@ -36,15 +40,17 @@ describe('Storefront API Plan', () => {
36
40
  it('can fetch products with filter', async () => {
37
41
  const instance = new StorefontTestingInstance({
38
42
  data: {
39
- plans: [
40
- {
41
- productId: 'test-product-1'
42
- },
43
- {
44
- productId: 'test-product-2'
45
- }
46
- ]
47
- }
43
+ invoice: {
44
+ items: [
45
+ {
46
+ productId: 'test-product-1'
47
+ },
48
+ {
49
+ productId: 'test-product-2'
50
+ },
51
+ ],
52
+ },
53
+ },
48
54
  });
49
55
 
50
56
  jest.spyOn(instance.storefront.products, 'getAll');
@@ -2,7 +2,7 @@ import { collectData } from '@rebilly/risk-data-collector';
2
2
  import ReadyToPayModel from './models/ready-to-pay-model';
3
3
  import { Endpoint } from './index';
4
4
 
5
- export async function fetchReadyToPay({ state, riskMetadata = null }) {
5
+ export async function fetchReadyToPay({ state, riskMetadata = null, paymentMethodsMetadata = []}) {
6
6
  return Endpoint({state}, async () => {
7
7
  if (!riskMetadata) {
8
8
  const { riskMetadata: data } = await collectData();
@@ -37,15 +37,7 @@ export async function fetchReadyToPay({ state, riskMetadata = null }) {
37
37
  data.billingAddress = state.data.account.address;
38
38
  }
39
39
 
40
- const [
41
- { fields: readyToPayFields },
42
- { items: paymentMethodsMetadataItems }
43
- ] = await Promise.all([
44
- state.storefront.purchase.readyToPay({ data }),
45
- state.storefront.rebilly.paymentMethods.getAll()
46
- ]);
47
-
48
- const paymentMethodsMetadata = paymentMethodsMetadataItems.map(({fields}) => fields);
40
+ const { fields: readyToPayFields } = await state.storefront.purchase.readyToPay({ data });
49
41
 
50
42
  return Object.values(readyToPayFields)
51
43
  // Remove result for "old" paypal method
@@ -1,7 +1,5 @@
1
- import { MethodIframe as method } from './method-iframe';
2
1
  import { ViewIframe as view } from './view-iframe';
3
2
  import { ModalIframe as modal } from './modal-iframe';
4
3
 
5
- export const MethodIframe = method;
6
4
  export const ViewIframe = view;
7
5
  export const ModalIframe = modal;
@@ -1,7 +1,3 @@
1
- import { purchase } from '../functions/purchase';
2
- import { setup } from '../functions/setup';
3
- import { ViewIframe } from './common/iframe';
4
- import { updateMethodSelector } from './method-selector';
5
1
  import { updateSummary } from './summary';
6
2
 
7
3
  export const baseConfirmationHTML =
@@ -15,58 +11,23 @@ export async function mountConfirmation({ payload: instrument, state }) {
15
11
  updateSummary({ state, instrument });
16
12
  }
17
13
 
18
- const contentElement = state.form.querySelector('.rebilly-instruments-content');
19
- contentElement.insertAdjacentHTML('afterend', baseConfirmationHTML);
20
-
21
- const methodSelectorElement = state.form.querySelector('.rebilly-instruments-method-selector');
22
- methodSelectorElement.style.visibility = 'hidden';
23
- methodSelectorElement.style.height = '0px';
24
-
25
- state.loader.startLoading({ id: 'rebilly-instruments-confirmation' });
26
-
27
- const container = document.querySelector('.rebilly-instruments-confirmation');
28
-
29
- const { paymentMethodsUrl } = state.options._computed;
30
-
14
+ const iframe = state.iframeComponents.form;
31
15
  const model = {
32
16
  options: state.options,
33
17
  data: state.data.toPostmatesModel(),
34
18
  mainStyleVars: state.mainStyleVars,
35
19
  instrument
36
20
  };
37
- const name = 'rebilly-instruments-confirmation';
38
- const iframe = await new ViewIframe({
39
- name,
40
- url: `${paymentMethodsUrl}/confirmation`,
41
- container,
42
- model
43
- });
44
- iframe.bindEventListeners({
45
- loader: state.loader
46
- });
47
21
 
48
- iframe.component.on(`${name}-confirm-purchase`, (confirmedInstrument) => {
49
- purchase({ state, payload: confirmedInstrument });
22
+ iframe?.component?.call('route', {
23
+ name: 'confirmation'
50
24
  });
51
25
 
52
- iframe.component.on(`${name}-confirm-setup`, (confirmedInstrument) => {
53
- setup({ state, payload: confirmedInstrument });
54
- });
26
+ iframe?.component?.call('update', model);
55
27
 
56
- iframe.component.on('choose-another-method', () => {
57
- state.iframeComponents.form = state.iframeComponents.form.filter((item) => {
58
- if (item.name === iframe.name) {
59
- item.destroy();
60
- return false;
61
- }
62
- return true;
28
+ document.querySelectorAll('[data-rebilly-instruments="express-method"]')
29
+ .forEach(el => {
30
+ el.style.overflow = 'hidden';
31
+ el.style.height = '0px';
63
32
  });
64
- if (state.data.isPurchase) {
65
- updateSummary({ state });
66
- }
67
- updateMethodSelector({ state, mainStyleVars: state.mainStyleVars });
68
- state.form.querySelector('.rebilly-instruments-confirmation').remove();
69
- });
70
-
71
- state.iframeComponents.form.push(iframe);
72
33
  }
@@ -3,13 +3,16 @@ import { collectData } from '@rebilly/risk-data-collector';
3
3
  import { getPaymentMethods } from './get-payment-methods';
4
4
  import { fetchData } from '../../functions/mount/fetch-data';
5
5
  import { ViewIframe } from '../common/iframe';
6
+ import { purchase } from '../../functions/purchase';
7
+ import { setup } from '../../functions/setup';
6
8
  import { mountExpressMethods } from './mount-express-methods';
7
9
  import { generateDigitalWallet } from './generate-digital-wallet';
10
+ import { updateSummary } from '../summary';
8
11
 
9
12
  export const baseMethodSelectorHTML = (compactExpressInstruments) => `
10
13
  <div class="rebilly-instruments-content">
11
14
  <div id="rebilly-instruments-error"></div>
12
- <div class="rebilly-instruments-method-selector ${compactExpressInstruments ? 'has-express-compact' : ''}">
15
+ <div data-rebilly-instruments="express-method" class="rebilly-instruments-method-selector ${compactExpressInstruments ? 'has-express-compact' : ''}">
13
16
  <div class="rebilly-instruments-express-methods ${
14
17
  compactExpressInstruments ? 'is-compact' : ''
15
18
  }">
@@ -19,8 +22,8 @@ export const baseMethodSelectorHTML = (compactExpressInstruments) => `
19
22
  <div data-rebilly-instruments="divider" class="rebilly-instruments-divider">
20
23
  <span class="rebilly-instruments-divider-label" data-rebilly-i18n="form.or">Or</span>
21
24
  </div>
22
- <div class="rebilly-instruments-methods"></div>
23
25
  </div>
26
+ <div class="rebilly-instruments-methods"></div>
24
27
  </div>
25
28
  `;
26
29
 
@@ -63,14 +66,41 @@ export async function mountMethodSelector({ state }) {
63
66
  };
64
67
  const { paymentMethodsUrl } = state.options._computed;
65
68
 
69
+ const name = 'rebilly-instruments-form';
66
70
  const iframe = await new ViewIframe({
67
- name: 'rebilly-instruments-methods',
71
+ name,
68
72
  url: `${paymentMethodsUrl}`,
69
73
  container: METHODS_CONTAINER,
70
74
  model
71
75
  });
72
76
  iframe.bindEventListeners({loader: state.loader});
73
- state.iframeComponents.form.push(iframe);
77
+
78
+ iframe.component.on(`${name}-confirm-purchase`, (confirmedInstrument) => {
79
+ purchase({ state, payload: confirmedInstrument });
80
+ });
81
+
82
+ iframe.component.on(`${name}-confirm-setup`, (confirmedInstrument) => {
83
+ setup({ state, payload: confirmedInstrument });
84
+ });
85
+
86
+ iframe.component.on('choose-another-method', () => {
87
+ document.querySelectorAll('[data-rebilly-instruments="express-method"]')
88
+ .forEach(el => {
89
+ el.style.height = 'auto';
90
+ });
91
+
92
+ iframe.component.call('route', {
93
+ name: 'method-switch'
94
+ });
95
+
96
+ if (state.data.isPurchase) {
97
+ updateSummary({ state });
98
+ }
99
+
100
+ iframe.component.call('update', model);
101
+ });
102
+
103
+ state.iframeComponents.form = iframe;
74
104
  } else {
75
105
  METHODS_CONTAINER.style.display = 'none';
76
106
  document.querySelectorAll('[data-rebilly-instruments="divider"]')
@@ -27,5 +27,5 @@ export async function mountResult({ payload, state }) {
27
27
  loader: state.loader
28
28
  });
29
29
 
30
- state.iframeComponents.form.push(iframe);
30
+ state.iframeComponents.form = iframe;
31
31
  }
@@ -16,7 +16,7 @@ export async function mountSummary({ state }) {
16
16
  model
17
17
  });
18
18
  iframe.bindEventListeners({loader: state.loader});
19
- state.iframeComponents.summary.push(iframe);
19
+ state.iframeComponents.summary = iframe;
20
20
  }
21
21
 
22
22
  export async function updateSummary({ state, instrument }) {
@@ -25,10 +25,8 @@ export async function updateSummary({ state, instrument }) {
25
25
  data: state.data.toPostmatesModel(),
26
26
  options: state.options
27
27
  }
28
- Object.values(state.iframeComponents).forEach(components => {
29
- components.forEach(frame => {
30
- frame.component.call('update', updateModel);
31
- });
32
- });
28
+
29
+ state.iframeComponents.summary.component.call('update', updateModel);
30
+ state.iframeComponents.form.component.call('update', updateModel);
33
31
  }
34
32
 
@@ -1,27 +0,0 @@
1
- import PlanModel from './models/plan-model';
2
- import { Endpoint } from './index';
3
-
4
- export async function fetchPlans({ state = {}, data = {} }) {
5
- return Endpoint({state}, async () => {
6
- const lineItems = data.lineItems || state.data.summaryLineItems;
7
-
8
- const filterByPlanId = {
9
- filter: ''
10
- };
11
-
12
- if (lineItems.length) {
13
- filterByPlanId.filter = `id:${lineItems
14
- .map((item) => item.planId)
15
- .join(',')}`;
16
- }
17
-
18
- // Only fetch plans if we hae specific plans to fetch
19
- if (filterByPlanId.filter.length) {
20
- const { items: planItems } = await state.storefront.plans.getAll(
21
- filterByPlanId
22
- );
23
- return planItems.map(({ fields }) => new PlanModel(fields));
24
- }
25
- return [];
26
- });
27
- }
@@ -1,68 +0,0 @@
1
- import { StorefontTestingInstance } from 'tests/mocks/storefront-mock';
2
- import { ok, get } from 'msw-when-then';
3
- import { when } from 'tests/msw/server';
4
- import { storefrontURL } from 'tests/mocks/storefront-api-mock';
5
- import { fetchPlans } from './plans';
6
- import PlanModel from './models/plan-model';
7
- import { expectConfigurationError } from 'tests/async-utilities';
8
-
9
- describe('Storefront API Plan', () => {
10
- it('can fetch plans', async () => {
11
- const testPlan = { name: 'Test Plan', id: 'test-plan-id-1' };
12
-
13
- when(get(`${storefrontURL}/plans`)).thenReturn(ok([testPlan]));
14
-
15
- const instance = new StorefontTestingInstance();
16
-
17
- jest.spyOn(instance.storefront.plans, 'getAll');
18
-
19
- const response = await fetchPlans({ state: instance, data: {
20
- lineItems: [
21
- {
22
- planId: 'test-plan-id'
23
- }
24
- ]
25
- } });
26
-
27
- expect(instance.storefront.plans.getAll).toBeCalledTimes(1);
28
- expect(instance.storefront.plans.getAll).toBeCalledWith({
29
- filter: 'id:test-plan-id'
30
- });
31
- expect(response).toBeInstanceOf(Array);
32
- expect(response[0]).toBeInstanceOf(PlanModel);
33
- expect(response).toEqual([new PlanModel(testPlan)]);
34
- });
35
-
36
- it('can fetch plans with filter', async () => {
37
- const instance = new StorefontTestingInstance();
38
-
39
- jest.spyOn(instance.storefront.plans, 'getAll');
40
-
41
- await fetchPlans({
42
- state: instance,
43
- data: {
44
- lineItems: [
45
- {
46
- planId: 'test-plan-id-1'
47
- },
48
- {
49
- planId: 'test-plan-id-2'
50
- }
51
- ]
52
- }
53
- });
54
-
55
- expect(instance.storefront.plans.getAll).toBeCalledWith({
56
- filter: 'id:test-plan-id-1,test-plan-id-2'
57
- });
58
- });
59
-
60
- it('should throw errors with no options', async () => {
61
- const noConfigOrOptionsInstance = new StorefontTestingInstance({
62
- options: null
63
- });
64
- await expectConfigurationError(
65
- fetchPlans({ state: noConfigOrOptionsInstance })
66
- );
67
- });
68
- });
@@ -1,25 +0,0 @@
1
- import BaseIframe from './base-iframe';
2
- import {
3
- dispatchRebillyInsturmentEventHandler,
4
- resizeComponentHandler,
5
- stopLoaderHandler,
6
- displayOverlay,
7
- showErrorHandler
8
- } from './event-listeners';
9
-
10
- export class MethodIframe extends BaseIframe {
11
- constructor(args = {}) {
12
- super(args);
13
- }
14
-
15
- bindEventListeners({ loader, id } = {}) {
16
- dispatchRebillyInsturmentEventHandler(this);
17
- resizeComponentHandler(this);
18
- stopLoaderHandler(this, {
19
- loader,
20
- id
21
- });
22
- displayOverlay(this);
23
- showErrorHandler(this);
24
- }
25
- }