@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.
Files changed (54) hide show
  1. package/dist/index.js +10 -17
  2. package/dist/index.min.js +49 -56
  3. package/package.json +3 -1
  4. package/src/functions/destroy.js +11 -9
  5. package/src/functions/mount/fetch-data.js +14 -16
  6. package/src/functions/mount/fetch-data.spec.js +140 -93
  7. package/src/functions/mount/index.js +9 -10
  8. package/src/functions/mount/mount.spec.js +5 -7
  9. package/src/functions/mount/setup-framepay-theme.js +2 -1
  10. package/src/functions/mount/setup-framepay.js +3 -1
  11. package/src/functions/mount/setup-i18n.js +4 -2
  12. package/src/functions/mount/setup-options.js +6 -4
  13. package/src/functions/on.spec.js +3 -2
  14. package/src/functions/purchase.js +16 -5
  15. package/src/functions/setup.js +3 -4
  16. package/src/functions/show.js +7 -6
  17. package/src/functions/show.spec.js +11 -7
  18. package/src/functions/update.js +3 -3
  19. package/src/functions/update.spec.js +4 -3
  20. package/src/instance.js +11 -31
  21. package/src/state/iframes.js +23 -0
  22. package/src/state/index.js +61 -0
  23. package/src/storefront/account-and-website.js +3 -2
  24. package/src/storefront/{fetch-plans-from-addons-bumpOffers.js → fetch-plans-from-addons-bumpOffer.js} +5 -4
  25. package/src/storefront/fetch-products-from-plans.js +5 -4
  26. package/src/storefront/index.js +3 -4
  27. package/src/storefront/invoices.js +6 -4
  28. package/src/storefront/payment-instruments.js +5 -4
  29. package/src/storefront/purchase.js +5 -4
  30. package/src/storefront/ready-to-pay.js +2 -2
  31. package/src/storefront/summary.js +8 -3
  32. package/src/storefront/transactions.js +3 -2
  33. package/src/style/base/index.js +243 -0
  34. package/src/views/common/iframe/base-iframe.js +0 -2
  35. package/src/views/common/iframe/events/update-addons-handler.js +8 -13
  36. package/src/views/common/iframe/events/update-coupons-handler.js +5 -11
  37. package/src/views/confirmation.js +16 -6
  38. package/src/views/method-selector/__snapshots__/method-selector.spec.js.snap +182 -1
  39. package/src/views/method-selector/generate-digital-wallet.js +2 -1
  40. package/src/views/method-selector/generate-digital-wallet.spec.js +32 -37
  41. package/src/views/method-selector/generate-framepay-config.js +1 -1
  42. package/src/views/method-selector/generate-framepay-config.spec.js +9 -12
  43. package/src/views/method-selector/get-payment-methods.js +3 -1
  44. package/src/views/method-selector/get-payment-methods.spec.js +25 -34
  45. package/src/views/method-selector/index.js +39 -20
  46. package/src/views/method-selector/method-selector.spec.js +9 -109
  47. package/src/views/method-selector/mount-bump-offer.js +99 -0
  48. package/src/views/method-selector/mount-express-methods.js +1 -2
  49. package/src/views/modal.js +3 -3
  50. package/src/views/result.js +7 -5
  51. package/src/views/summary.js +12 -16
  52. package/tests/mocks/rebilly-instruments-mock.js +17 -19
  53. package/tests/mocks/storefront-mock.js +10 -9
  54. 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
- options: {
9
- themeFramepay: {},
10
- locale: 'en-CA',
11
- organizationId: 'test-organization-id',
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({ state }) {
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
- const instance = new TestInstance();
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({ state: instance });
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({ state }) {
31
- const { EXPRESS_METHODS, METHODS } = getPaymentMethods({ state });
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 METHODS_CONTAINER = document.querySelector('.rebilly-instruments-methods');
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({state, EXPRESS_METHODS});
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: state.options,
64
- data: state.data.toPostmatesModel(),
65
- mainStyleVars: state.mainStyleVars,
69
+ options: modelSafeState.options,
70
+ data: modelSafeState.data,
71
+ mainStyleVars: modelSafeState.mainStyleVars,
66
72
  };
67
- const { paymentMethodsUrl } = state.options._computed;
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({ state });
108
+ updateSummary();
99
109
  }
100
110
 
101
111
  iframe.component.call('update', model);
102
112
  });
103
113
 
104
- state.iframeComponents.form = iframe;
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({ state }) {
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({ state, riskMetadata });
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({ state });
141
+ mountMethodSelector();
123
142
  }
@@ -1,120 +1,20 @@
1
- import SummaryModel from '@/storefront/models/summary-model';
2
- import ReadyToPayModel from '@/storefront/models/ready-to-pay-model';
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('Summary component', () => {
12
- let formElement;
13
- beforeEach(() => {
14
- formElement = document.createElement('div');
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
- const state = new TestMountMethodSelectorInstance({
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
  );
@@ -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: state.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,
@@ -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, state }) {
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: state.options,
16
- mainStyleVars: state.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
- state.iframeComponents.form = iframe;
33
+ iframes.form = iframe;
32
34
  }
@@ -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({ state }) {
6
+ export async function mountSummary() {
7
+ const modelSafeState = state.toModel();
5
8
  const model = {
6
- options: state.options,
7
- data: state.data.toPostmatesModel(),
8
- mainStyleVars: state.mainStyleVars,
9
+ options: modelSafeState.options,
10
+ data: modelSafeState.data,
11
+ mainStyleVars: modelSafeState.mainStyleVars,
9
12
  };
10
- const { paymentMethodsUrl } = state.options._computed;
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
- state.iframeComponents.summary = iframe;
22
+ iframes.summary = iframe;
21
23
  }
22
24
 
23
- export async function updateSummary({ state, instrument }) {
24
- await fetchSummary({data: instrument, state});
25
- const updateModel = {
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 RebillyInstrumentsInstance from '@rebilly/instruments';
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
- framePayStyleLink: framePayStyleUrl
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 rebillyInstruments = RebillyInstrumentsInstance;
108
+ const form = document.createElement('div');
109
+ form.classList.add(`${mergedOptions.form.replace('.', '')}`);
110
+ document.body.appendChild(form);
109
111
 
110
- document.body.innerHTML = `
111
- <div class="${mergedOptions.form.replace('.', '')}"></div>
112
- <div class="${mergedOptions.summary.replace('.', '')}"></div>
113
- `;
112
+ const summary = document.createElement('div');
113
+ summary.classList.add(`${mergedOptions.summary.replace('.', '')}`);
114
+ document.body.appendChild(summary);
114
115
 
115
- await rebillyInstruments.mount({
116
- setupFramepay: setupFramepayMock,
117
- ...mergedOptions,
118
- });
116
+ await RebillyInstruments.mount({
117
+ setupFramepay: setupFramepayMock,
118
+ ...mergedOptions,
119
+ });
119
120
 
120
- rebillyInstruments.mock = {
121
+ RebillyInstruments.mock = {
121
122
  data: (data) => {
122
- rebillyInstruments.state.data = new DataInstance({
123
- state: rebillyInstruments.state,
124
- ...data
125
- });
123
+ RebillyInstruments.state.data = new DataInstance(data);
126
124
  }
127
125
  };
128
126
 
129
- return rebillyInstruments;
130
- }
127
+ return RebillyInstruments;
128
+ }