@internetarchive/donation-form 0.5.8-alpha.3 → 0.5.9-alpha.1
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/src/braintree-manager/braintree-interfaces.d.ts +6 -0
- package/dist/src/braintree-manager/braintree-interfaces.js.map +1 -1
- package/dist/src/braintree-manager/braintree-manager.d.ts +4 -1
- package/dist/src/braintree-manager/braintree-manager.js +11 -0
- package/dist/src/braintree-manager/braintree-manager.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card-interface.d.ts +6 -0
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.d.ts +12 -2
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.js +60 -8
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.d.ts +18 -5
- package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.js +15 -0
- package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers-interface.d.ts +4 -1
- package/dist/src/braintree-manager/payment-providers-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers.d.ts +4 -1
- package/dist/src/braintree-manager/payment-providers.js +13 -1
- package/dist/src/braintree-manager/payment-providers.js.map +1 -1
- package/dist/src/donation-form-controller.js +12 -0
- package/dist/src/donation-form-controller.js.map +1 -1
- package/dist/src/util/promisedSleep.d.ts +1 -0
- package/dist/src/util/promisedSleep.js +4 -0
- package/dist/src/util/promisedSleep.js.map +1 -0
- package/dist/test/mocks/mock-braintree-manager.d.ts +4 -1
- package/dist/test/mocks/mock-braintree-manager.js +5 -0
- package/dist/test/mocks/mock-braintree-manager.js.map +1 -1
- package/dist/test/mocks/mock-hosted-fields-container.d.ts +2 -0
- package/dist/test/mocks/mock-hosted-fields-container.js +6 -0
- package/dist/test/mocks/mock-hosted-fields-container.js.map +1 -1
- package/dist/test/mocks/mock-lazy-loader.js +0 -13
- package/dist/test/mocks/mock-lazy-loader.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.d.ts +4 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js +5 -0
- package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js.map +1 -1
- package/dist/test/mocks/payment-providers/mock-payment-providers.d.ts +4 -1
- package/dist/test/mocks/payment-providers/mock-payment-providers.js +5 -0
- package/dist/test/mocks/payment-providers/mock-payment-providers.js.map +1 -1
- package/dist/test/tests/donation-form-controller.test.js +1 -1
- package/dist/test/tests/donation-form-controller.test.js.map +1 -1
- package/dist/test/tests/donation-form.test.js +1 -1
- package/dist/test/tests/donation-form.test.js.map +1 -1
- package/dist/test/tests/form-elements/payment-selector.test.js +1 -1
- package/dist/test/tests/form-elements/payment-selector.test.js.map +1 -1
- package/dist/test/tests/payment-providers/creditcard.test.js +101 -0
- package/dist/test/tests/payment-providers/creditcard.test.js.map +1 -1
- package/package.json +3 -2
- package/src/braintree-manager/braintree-interfaces.ts +11 -0
- package/src/braintree-manager/braintree-manager.ts +19 -0
- package/src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts +10 -0
- package/src/braintree-manager/payment-providers/credit-card/credit-card.ts +79 -12
- package/src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts +35 -8
- package/src/braintree-manager/payment-providers-interface.ts +12 -1
- package/src/braintree-manager/payment-providers.ts +22 -2
- package/src/donation-form-controller.ts +17 -3
- package/src/util/promisedSleep.ts +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"donation-form.test.js","sourceRoot":"","sources":["../../../test/tests/donation-form.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, fixture, expect, elementUpdated, oneEvent } from '@open-wc/testing';\n\nimport '../../src/donation-form';\nimport { DonationForm } from '../../src/donation-form';\nimport {\n DonationType,\n DonationPaymentInfo,\n PaymentProvider,\n} from '@internetarchive/donation-form-data-models';\nimport { PaymentSelector } from '../../src/form-elements/payment-selector';\nimport { MockBraintreeManager } from '../mocks/mock-braintree-manager';\nimport { MockPaymentFlowHandlers } from '../mocks/flow-handlers/mock-payment-flow-handlers';\nimport { promisedSleep } from '../helpers/promisedSleep';\nimport { MockDonationInfo } from '../mocks/mock-donation-info';\n\ndescribe('Donation Form', () => {\n describe('Configuration', () => {\n it('has no configuration', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n\n expect(el.braintreeManager).to.equal(undefined);\n expect(el.donationRequest).to.equal(undefined);\n });\n\n it('updates donationInfo when user changes donation info', async () => {\n const el = (await fixture(html`\n <donation-form .donationInfo=${new MockDonationInfo()}></donation-form>\n `)) as DonationForm;\n const donationHeader = el.shadowRoot?.querySelector('donation-form-header');\n const editDonation = donationHeader?.shadowRoot?.querySelector('donation-form-edit-donation');\n const monthlyOption = editDonation?.shadowRoot?.querySelector('#donationType-monthly-option');\n const clickEvent = new MouseEvent('click');\n monthlyOption?.dispatchEvent(clickEvent);\n await elementUpdated(el);\n expect(el.donationInfo?.donationType).to.equal(DonationType.Monthly);\n });\n });\n\n it('shows the contact form when Credit Card is selected', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n const contactFormSection = el.shadowRoot?.querySelector('.contact-form-section');\n const paymentSelector = el.shadowRoot?.querySelector('payment-selector') as PaymentSelector;\n const creditCardButton = paymentSelector.shadowRoot?.querySelector(\n '.credit-card-button',\n ) as HTMLButtonElement;\n expect(contactFormSection?.classList.contains('hidden')).to.be.true;\n const clickEvent = new MouseEvent('click');\n creditCardButton.dispatchEvent(clickEvent);\n await elementUpdated(el);\n expect(contactFormSection?.classList.contains('hidden')).to.be.false;\n });\n\n it('shows the contact form when Venmo is selected', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n const braintreeManager = new MockBraintreeManager();\n el.braintreeManager = braintreeManager;\n await elementUpdated(el);\n const contactFormSection = el.shadowRoot?.querySelector('.contact-form-section');\n const paymentSelector = el.shadowRoot?.querySelector('payment-selector') as PaymentSelector;\n const venmoButton = paymentSelector.shadowRoot?.querySelector('.venmo') as HTMLButtonElement;\n expect(contactFormSection?.classList.contains('hidden')).to.be.true;\n const clickEvent = new MouseEvent('click');\n venmoButton.dispatchEvent(clickEvent);\n await elementUpdated(el);\n expect(contactFormSection?.classList.contains('hidden')).to.be.false;\n });\n\n it('properly configures the flow handlers when they are set', async () => {\n const donationInfo = new DonationPaymentInfo({\n donationType: DonationType.Monthly,\n amount: 3.5,\n coverFees: false,\n });\n const el = (await fixture(html`\n <donation-form .donationInfo=${donationInfo}></donation-form>\n `)) as DonationForm;\n const flowHandlers = new MockPaymentFlowHandlers();\n el.paymentFlowHandlers = flowHandlers;\n await elementUpdated(el);\n await promisedSleep(250);\n expect(flowHandlers.paypalHandler.donationInfo).to.equal(donationInfo);\n });\n\n it('emits paymentProviderSelected when the selected provider changes', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n const braintreeManager = new MockBraintreeManager();\n el.braintreeManager = braintreeManager;\n await elementUpdated(el);\n const paymentSelector = el.shadowRoot?.querySelector('payment-selector') as PaymentSelector;\n const creditCardButton = paymentSelector.shadowRoot?.querySelector(\n '.credit-card-button',\n ) as HTMLButtonElement;\n\n // on the first payment provider chosen, the previousPaymentProvider is undefined\n setTimeout(() => {\n const ccClickEvent = new MouseEvent('click');\n creditCardButton.dispatchEvent(ccClickEvent);\n });\n const ccResponse = await oneEvent(el, 'paymentProviderSelected');\n expect(ccResponse).to.exist;\n expect(ccResponse.detail.paymentProvider).to.equal(PaymentProvider.CreditCard);\n expect(ccResponse.detail.previousPaymentProvider).to.equal(undefined);\n\n // on subsequent payment provider choices, the previousPaymentProvider is populated\n setTimeout(() => {\n const venmoButton = paymentSelector.shadowRoot?.querySelector('.venmo') as HTMLButtonElement;\n const venmoClickEvent = new MouseEvent('click');\n venmoButton.dispatchEvent(venmoClickEvent);\n });\n const venmoResponse = await oneEvent(el, 'paymentProviderSelected');\n expect(venmoResponse).to.exist;\n expect(venmoResponse.detail.paymentProvider).to.equal(PaymentProvider.Venmo);\n expect(venmoResponse.detail.previousPaymentProvider).to.equal(PaymentProvider.CreditCard);\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"donation-form.test.js","sourceRoot":"","sources":["../../../test/tests/donation-form.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, fixture, expect, elementUpdated, oneEvent } from '@open-wc/testing';\n\nimport '../../src/donation-form';\nimport { DonationForm } from '../../src/donation-form';\nimport {\n DonationType,\n DonationPaymentInfo,\n PaymentProvider,\n} from '@internetarchive/donation-form-data-models';\nimport { PaymentSelector } from '../../src/form-elements/payment-selector';\nimport { MockBraintreeManager } from '../mocks/mock-braintree-manager';\nimport { MockPaymentFlowHandlers } from '../mocks/flow-handlers/mock-payment-flow-handlers';\nimport { promisedSleep } from '../../src/util/promisedSleep';\nimport { MockDonationInfo } from '../mocks/mock-donation-info';\n\ndescribe('Donation Form', () => {\n describe('Configuration', () => {\n it('has no configuration', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n\n expect(el.braintreeManager).to.equal(undefined);\n expect(el.donationRequest).to.equal(undefined);\n });\n\n it('updates donationInfo when user changes donation info', async () => {\n const el = (await fixture(html`\n <donation-form .donationInfo=${new MockDonationInfo()}></donation-form>\n `)) as DonationForm;\n const donationHeader = el.shadowRoot?.querySelector('donation-form-header');\n const editDonation = donationHeader?.shadowRoot?.querySelector('donation-form-edit-donation');\n const monthlyOption = editDonation?.shadowRoot?.querySelector('#donationType-monthly-option');\n const clickEvent = new MouseEvent('click');\n monthlyOption?.dispatchEvent(clickEvent);\n await elementUpdated(el);\n expect(el.donationInfo?.donationType).to.equal(DonationType.Monthly);\n });\n });\n\n it('shows the contact form when Credit Card is selected', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n const contactFormSection = el.shadowRoot?.querySelector('.contact-form-section');\n const paymentSelector = el.shadowRoot?.querySelector('payment-selector') as PaymentSelector;\n const creditCardButton = paymentSelector.shadowRoot?.querySelector(\n '.credit-card-button',\n ) as HTMLButtonElement;\n expect(contactFormSection?.classList.contains('hidden')).to.be.true;\n const clickEvent = new MouseEvent('click');\n creditCardButton.dispatchEvent(clickEvent);\n await elementUpdated(el);\n expect(contactFormSection?.classList.contains('hidden')).to.be.false;\n });\n\n it('shows the contact form when Venmo is selected', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n const braintreeManager = new MockBraintreeManager();\n el.braintreeManager = braintreeManager;\n await elementUpdated(el);\n const contactFormSection = el.shadowRoot?.querySelector('.contact-form-section');\n const paymentSelector = el.shadowRoot?.querySelector('payment-selector') as PaymentSelector;\n const venmoButton = paymentSelector.shadowRoot?.querySelector('.venmo') as HTMLButtonElement;\n expect(contactFormSection?.classList.contains('hidden')).to.be.true;\n const clickEvent = new MouseEvent('click');\n venmoButton.dispatchEvent(clickEvent);\n await elementUpdated(el);\n expect(contactFormSection?.classList.contains('hidden')).to.be.false;\n });\n\n it('properly configures the flow handlers when they are set', async () => {\n const donationInfo = new DonationPaymentInfo({\n donationType: DonationType.Monthly,\n amount: 3.5,\n coverFees: false,\n });\n const el = (await fixture(html`\n <donation-form .donationInfo=${donationInfo}></donation-form>\n `)) as DonationForm;\n const flowHandlers = new MockPaymentFlowHandlers();\n el.paymentFlowHandlers = flowHandlers;\n await elementUpdated(el);\n await promisedSleep(250);\n expect(flowHandlers.paypalHandler.donationInfo).to.equal(donationInfo);\n });\n\n it('emits paymentProviderSelected when the selected provider changes', async () => {\n const el = (await fixture(html`\n <donation-form></donation-form>\n `)) as DonationForm;\n const braintreeManager = new MockBraintreeManager();\n el.braintreeManager = braintreeManager;\n await elementUpdated(el);\n const paymentSelector = el.shadowRoot?.querySelector('payment-selector') as PaymentSelector;\n const creditCardButton = paymentSelector.shadowRoot?.querySelector(\n '.credit-card-button',\n ) as HTMLButtonElement;\n\n // on the first payment provider chosen, the previousPaymentProvider is undefined\n setTimeout(() => {\n const ccClickEvent = new MouseEvent('click');\n creditCardButton.dispatchEvent(ccClickEvent);\n });\n const ccResponse = await oneEvent(el, 'paymentProviderSelected');\n expect(ccResponse).to.exist;\n expect(ccResponse.detail.paymentProvider).to.equal(PaymentProvider.CreditCard);\n expect(ccResponse.detail.previousPaymentProvider).to.equal(undefined);\n\n // on subsequent payment provider choices, the previousPaymentProvider is populated\n setTimeout(() => {\n const venmoButton = paymentSelector.shadowRoot?.querySelector('.venmo') as HTMLButtonElement;\n const venmoClickEvent = new MouseEvent('click');\n venmoButton.dispatchEvent(venmoClickEvent);\n });\n const venmoResponse = await oneEvent(el, 'paymentProviderSelected');\n expect(venmoResponse).to.exist;\n expect(venmoResponse.detail.paymentProvider).to.equal(PaymentProvider.Venmo);\n expect(venmoResponse.detail.previousPaymentProvider).to.equal(PaymentProvider.CreditCard);\n });\n});\n"]}
|
|
@@ -2,7 +2,7 @@ import { __awaiter } from "tslib";
|
|
|
2
2
|
import { html, fixture, expect, elementUpdated, oneEvent } from '@open-wc/testing';
|
|
3
3
|
import '../../../src/form-elements/payment-selector';
|
|
4
4
|
import { MockPaymentProviders } from '../../mocks/payment-providers/mock-payment-providers';
|
|
5
|
-
import { promisedSleep } from '
|
|
5
|
+
import { promisedSleep } from '../../../src/util/promisedSleep';
|
|
6
6
|
describe('Payment Selector', () => {
|
|
7
7
|
it('shows Venmo if it is available', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
8
8
|
var _a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-selector.test.js","sourceRoot":"","sources":["../../../../test/tests/form-elements/payment-selector.test.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEnF,OAAO,6CAA6C,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"payment-selector.test.js","sourceRoot":"","sources":["../../../../test/tests/form-elements/payment-selector.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, fixture, expect, elementUpdated, oneEvent } from '@open-wc/testing';\nimport { PaymentSelector } from '../../../src/form-elements/payment-selector';\nimport '../../../src/form-elements/payment-selector';\nimport { MockPaymentProviders } from '../../mocks/payment-providers/mock-payment-providers';\nimport { promisedSleep } from '../../../src/util/promisedSleep';\n\ndescribe('Payment Selector', () => {\n it('shows Venmo if it is available', async () => {\n const el = (await fixture(html`\n <payment-selector></payment-selector>\n `)) as PaymentSelector;\n\n const paymentProviders = new MockPaymentProviders();\n el.paymentProviders = paymentProviders;\n await elementUpdated(el);\n await promisedSleep(250);\n\n const venmoButton = el.shadowRoot?.querySelector('.venmo.provider-button');\n expect(venmoButton?.classList.contains('available')).to.be.true;\n });\n\n it('can show PayPal when called', async () => {\n const el = (await fixture(html`\n <payment-selector></payment-selector>\n `)) as PaymentSelector;\n el.showPaypalButton();\n await elementUpdated(el);\n const paypalButton = el.shadowRoot?.querySelector('.paypal-container.provider-button');\n expect(paypalButton?.classList.contains('available')).to.be.true;\n });\n\n it('emits paypalBlockerSelected event when paypal is selected in an error state', async () => {\n const el = (await fixture(html`\n <payment-selector></payment-selector>\n `)) as PaymentSelector;\n const paypalBlocker = el.shadowRoot?.querySelector('.paypal-local-button');\n const clickEvent = new MouseEvent('click');\n setTimeout(() => {\n paypalBlocker?.dispatchEvent(clickEvent);\n });\n const response = await oneEvent(el, 'paypalBlockerSelected');\n expect(response).to.exist;\n });\n\n it('emits applePaySelected event with original click event when ApplePay is selected', async () => {\n const el = (await fixture(html`\n <payment-selector></payment-selector>\n `)) as PaymentSelector;\n const paypalBlocker = el.shadowRoot?.querySelector('.applepay.provider-button');\n const clickEvent = new MouseEvent('click');\n setTimeout(() => {\n paypalBlocker?.dispatchEvent(clickEvent);\n });\n const response = await oneEvent(el, 'applePaySelected');\n const event = response.detail.originalEvent;\n expect(event).to.equal(clickEvent);\n });\n\n it('emits googlePaySelected when GooglePay is selected', async () => {\n const el = (await fixture(html`\n <payment-selector></payment-selector>\n `)) as PaymentSelector;\n const paypalBlocker = el.shadowRoot?.querySelector('.googlepay.provider-button');\n const clickEvent = new MouseEvent('click');\n setTimeout(() => {\n paypalBlocker?.dispatchEvent(clickEvent);\n });\n const response = await oneEvent(el, 'googlePaySelected');\n expect(response).to.exist;\n });\n});\n"]}
|
|
@@ -6,8 +6,13 @@ import { mockHostedFieldTokenizePayload } from '../../mocks/payment-clients/mock
|
|
|
6
6
|
import { CreditCardHandler } from '../../../src/braintree-manager/payment-providers/credit-card/credit-card';
|
|
7
7
|
import { MockHostedFieldContainer } from '../../mocks/mock-hosted-fields-container';
|
|
8
8
|
import { HostedFieldConfiguration } from '../../../src/braintree-manager/payment-providers/credit-card/hosted-field-configuration';
|
|
9
|
+
import Sinon from 'sinon';
|
|
9
10
|
import { mockHostedFieldStyle, mockHostedFieldFieldOptions, mockHostedFieldConfig, } from '../../mocks/mock-hosted-fields-config';
|
|
11
|
+
const sandbox = Sinon.createSandbox();
|
|
10
12
|
describe('CreditCardHandler', () => {
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
sandbox.restore();
|
|
15
|
+
});
|
|
11
16
|
it('can tokenize the hosted fields', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
12
17
|
const braintreeManager = new MockBraintreeManager();
|
|
13
18
|
const client = new MockHostedFieldsClient({
|
|
@@ -89,5 +94,101 @@ describe('CreditCardHandler', () => {
|
|
|
89
94
|
handler.hideErrorMessage();
|
|
90
95
|
expect(mockHostedFieldContainer.hideErrorMessageCalled).to.be.true;
|
|
91
96
|
}));
|
|
97
|
+
it('retries the expected number of times before failure', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
+
const braintreeManager = new MockBraintreeManager();
|
|
99
|
+
const client = new MockHostedFieldsClient();
|
|
100
|
+
let retryCount = 0;
|
|
101
|
+
Sinon.stub(client, 'create').callsFake(() => {
|
|
102
|
+
retryCount++;
|
|
103
|
+
throw new Error('Error');
|
|
104
|
+
});
|
|
105
|
+
const mockHostedFieldContainer = new MockHostedFieldContainer();
|
|
106
|
+
const hostedFieldsSpy = Sinon.spy(mockHostedFieldContainer, 'resetHostedFields');
|
|
107
|
+
const mockHostedFieldConfig = new HostedFieldConfiguration({
|
|
108
|
+
hostedFieldStyle: mockHostedFieldStyle,
|
|
109
|
+
hostedFieldFieldOptions: mockHostedFieldFieldOptions,
|
|
110
|
+
hostedFieldContainer: mockHostedFieldContainer,
|
|
111
|
+
});
|
|
112
|
+
const handler = new CreditCardHandler({
|
|
113
|
+
braintreeManager: braintreeManager,
|
|
114
|
+
hostedFieldClient: client,
|
|
115
|
+
hostedFieldConfig: mockHostedFieldConfig,
|
|
116
|
+
retryInverval: 0.01,
|
|
117
|
+
maxRetryCount: 3,
|
|
118
|
+
loadTimeout: 0.01,
|
|
119
|
+
});
|
|
120
|
+
try {
|
|
121
|
+
yield handler.instance.get();
|
|
122
|
+
expect.fail('Should have thrown an error');
|
|
123
|
+
}
|
|
124
|
+
catch (e) { }
|
|
125
|
+
// initial call + 3 retries
|
|
126
|
+
expect(retryCount).to.equal(4);
|
|
127
|
+
expect(hostedFieldsSpy.callCount).to.equal(4);
|
|
128
|
+
}));
|
|
129
|
+
it('retries creating the hosted fields if they fail', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
130
|
+
const braintreeManager = new MockBraintreeManager();
|
|
131
|
+
const client = new MockHostedFieldsClient();
|
|
132
|
+
let retryCount = 0;
|
|
133
|
+
Sinon.stub(client, 'create').callsFake(() => {
|
|
134
|
+
if (retryCount < 2) {
|
|
135
|
+
retryCount++;
|
|
136
|
+
throw new Error('Error');
|
|
137
|
+
}
|
|
138
|
+
return Promise.resolve(client);
|
|
139
|
+
});
|
|
140
|
+
const mockHostedFieldContainer = new MockHostedFieldContainer();
|
|
141
|
+
const mockHostedFieldConfig = new HostedFieldConfiguration({
|
|
142
|
+
hostedFieldStyle: mockHostedFieldStyle,
|
|
143
|
+
hostedFieldFieldOptions: mockHostedFieldFieldOptions,
|
|
144
|
+
hostedFieldContainer: mockHostedFieldContainer,
|
|
145
|
+
});
|
|
146
|
+
const handler = new CreditCardHandler({
|
|
147
|
+
braintreeManager: braintreeManager,
|
|
148
|
+
hostedFieldClient: client,
|
|
149
|
+
hostedFieldConfig: mockHostedFieldConfig,
|
|
150
|
+
retryInverval: 0.01,
|
|
151
|
+
maxRetryCount: 3,
|
|
152
|
+
loadTimeout: 0.01,
|
|
153
|
+
});
|
|
154
|
+
const instance = yield handler.instance.get();
|
|
155
|
+
expect(instance).to.not.be.null;
|
|
156
|
+
expect(retryCount).to.equal(2);
|
|
157
|
+
}));
|
|
158
|
+
it('emits an event when retrying or failing', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
159
|
+
const braintreeManager = new MockBraintreeManager();
|
|
160
|
+
const client = new MockHostedFieldsClient();
|
|
161
|
+
Sinon.stub(client, 'create').callsFake(() => {
|
|
162
|
+
throw new Error('Error');
|
|
163
|
+
});
|
|
164
|
+
const mockHostedFieldContainer = new MockHostedFieldContainer();
|
|
165
|
+
const mockHostedFieldConfig = new HostedFieldConfiguration({
|
|
166
|
+
hostedFieldStyle: mockHostedFieldStyle,
|
|
167
|
+
hostedFieldFieldOptions: mockHostedFieldFieldOptions,
|
|
168
|
+
hostedFieldContainer: mockHostedFieldContainer,
|
|
169
|
+
});
|
|
170
|
+
const handler = new CreditCardHandler({
|
|
171
|
+
braintreeManager: braintreeManager,
|
|
172
|
+
hostedFieldClient: client,
|
|
173
|
+
hostedFieldConfig: mockHostedFieldConfig,
|
|
174
|
+
retryInverval: 0.01,
|
|
175
|
+
maxRetryCount: 3,
|
|
176
|
+
loadTimeout: 0.01,
|
|
177
|
+
});
|
|
178
|
+
let retryCountEvent = 0;
|
|
179
|
+
let retryFailedEvent = 0;
|
|
180
|
+
handler.on('hostedFieldsRetry', () => {
|
|
181
|
+
retryCountEvent++;
|
|
182
|
+
});
|
|
183
|
+
handler.on('hostedFieldsFailed', () => {
|
|
184
|
+
retryFailedEvent++;
|
|
185
|
+
});
|
|
186
|
+
try {
|
|
187
|
+
yield handler.instance.get();
|
|
188
|
+
}
|
|
189
|
+
catch (e) { }
|
|
190
|
+
expect(retryCountEvent).to.equal(3);
|
|
191
|
+
expect(retryFailedEvent).to.equal(1);
|
|
192
|
+
}));
|
|
92
193
|
});
|
|
93
194
|
//# sourceMappingURL=creditcard.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"creditcard.test.js","sourceRoot":"","sources":["../../../../test/tests/payment-providers/creditcard.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { MockBraintreeManager } from '../../mocks/mock-braintree-manager';\nimport { MockHostedFieldsClient } from '../../mocks/payment-clients/mock-hostedfields-client';\nimport { mockHostedFieldTokenizePayload } from '../../mocks/payment-clients/mock-hostedfieldtokenizepayload';\nimport { CreditCardHandler } from '../../../src/braintree-manager/payment-providers/credit-card/credit-card';\nimport { MockHostedFieldContainer } from '../../mocks/mock-hosted-fields-container';\nimport { HostedFieldConfiguration } from '../../../src/braintree-manager/payment-providers/credit-card/hosted-field-configuration';\nimport {\n mockHostedFieldStyle,\n mockHostedFieldFieldOptions,\n mockHostedFieldConfig,\n} from '../../mocks/mock-hosted-fields-config';\n\ndescribe('CreditCardHandler', () => {\n it('can tokenize the hosted fields', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient({\n mockHostedFieldTokenizePayload: mockHostedFieldTokenizePayload,\n });\n\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n\n const payload = await handler.tokenizeHostedFields();\n\n expect(payload?.nonce).to.equal(mockHostedFieldTokenizePayload.nonce);\n });\n\n it('can mark field errors', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.markFieldErrors([]);\n expect(mockHostedFieldContainer.markErrorsCalled).to.be.true;\n });\n\n it('can remove field errors', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.removeFieldErrors([]);\n expect(mockHostedFieldContainer.removeErrorsCalled).to.be.true;\n });\n\n it('can show the error message', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.showErrorMessage();\n expect(mockHostedFieldContainer.showErrorMessageCalled).to.be.true;\n });\n\n it('can hide the error message', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.hideErrorMessage();\n expect(mockHostedFieldContainer.hideErrorMessageCalled).to.be.true;\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"creditcard.test.js","sourceRoot":"","sources":["../../../../test/tests/payment-providers/creditcard.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { MockBraintreeManager } from '../../mocks/mock-braintree-manager';\nimport { MockHostedFieldsClient } from '../../mocks/payment-clients/mock-hostedfields-client';\nimport { mockHostedFieldTokenizePayload } from '../../mocks/payment-clients/mock-hostedfieldtokenizepayload';\nimport { CreditCardHandler } from '../../../src/braintree-manager/payment-providers/credit-card/credit-card';\nimport { MockHostedFieldContainer } from '../../mocks/mock-hosted-fields-container';\nimport { HostedFieldConfiguration } from '../../../src/braintree-manager/payment-providers/credit-card/hosted-field-configuration';\nimport Sinon from 'sinon';\nimport {\n mockHostedFieldStyle,\n mockHostedFieldFieldOptions,\n mockHostedFieldConfig,\n} from '../../mocks/mock-hosted-fields-config';\n\nconst sandbox = Sinon.createSandbox();\n\ndescribe('CreditCardHandler', () => {\n afterEach(() => {\n sandbox.restore();\n });\n\n it('can tokenize the hosted fields', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient({\n mockHostedFieldTokenizePayload: mockHostedFieldTokenizePayload,\n });\n\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n\n const payload = await handler.tokenizeHostedFields();\n\n expect(payload?.nonce).to.equal(mockHostedFieldTokenizePayload.nonce);\n });\n\n it('can mark field errors', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.markFieldErrors([]);\n expect(mockHostedFieldContainer.markErrorsCalled).to.be.true;\n });\n\n it('can remove field errors', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.removeFieldErrors([]);\n expect(mockHostedFieldContainer.removeErrorsCalled).to.be.true;\n });\n\n it('can show the error message', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.showErrorMessage();\n expect(mockHostedFieldContainer.showErrorMessageCalled).to.be.true;\n });\n\n it('can hide the error message', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n });\n handler.hideErrorMessage();\n expect(mockHostedFieldContainer.hideErrorMessageCalled).to.be.true;\n });\n\n it('retries the expected number of times before failure', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n\n let retryCount = 0;\n Sinon.stub(client, 'create').callsFake(() => {\n retryCount++;\n throw new Error('Error');\n });\n\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const hostedFieldsSpy = Sinon.spy(mockHostedFieldContainer, 'resetHostedFields');\n\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n retryInverval: 0.01,\n maxRetryCount: 3,\n loadTimeout: 0.01,\n });\n\n try {\n await handler.instance.get();\n expect.fail('Should have thrown an error');\n } catch (e) {}\n\n // initial call + 3 retries\n expect(retryCount).to.equal(4);\n expect(hostedFieldsSpy.callCount).to.equal(4);\n });\n\n it('retries creating the hosted fields if they fail', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n\n let retryCount = 0;\n Sinon.stub(client, 'create').callsFake(() => {\n if (retryCount < 2) {\n retryCount++;\n throw new Error('Error');\n }\n return Promise.resolve(client);\n });\n\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n retryInverval: 0.01,\n maxRetryCount: 3,\n loadTimeout: 0.01,\n });\n\n const instance = await handler.instance.get();\n expect(instance).to.not.be.null;\n expect(retryCount).to.equal(2);\n });\n\n it('emits an event when retrying or failing', async () => {\n const braintreeManager = new MockBraintreeManager();\n const client = new MockHostedFieldsClient();\n\n Sinon.stub(client, 'create').callsFake(() => {\n throw new Error('Error');\n });\n\n const mockHostedFieldContainer = new MockHostedFieldContainer();\n const mockHostedFieldConfig: HostedFieldConfiguration = new HostedFieldConfiguration({\n hostedFieldStyle: mockHostedFieldStyle,\n hostedFieldFieldOptions: mockHostedFieldFieldOptions,\n hostedFieldContainer: mockHostedFieldContainer,\n });\n const handler = new CreditCardHandler({\n braintreeManager: braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: mockHostedFieldConfig,\n retryInverval: 0.01,\n maxRetryCount: 3,\n loadTimeout: 0.01,\n });\n\n let retryCountEvent = 0;\n let retryFailedEvent = 0;\n handler.on('hostedFieldsRetry', () => {\n retryCountEvent++;\n });\n handler.on('hostedFieldsFailed', () => {\n retryFailedEvent++;\n });\n\n try {\n await handler.instance.get();\n } catch (e) {}\n\n expect(retryCountEvent).to.equal(3);\n expect(retryFailedEvent).to.equal(1);\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/donation-form",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9-alpha.1",
|
|
4
4
|
"description": "The Internet Archive Donation Form",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@internetarchive/icon-paypal": "^1.3.2",
|
|
43
43
|
"@internetarchive/icon-user": "^1.3.2",
|
|
44
44
|
"@internetarchive/icon-venmo": "^1.3.2",
|
|
45
|
-
"@internetarchive/lazy-loader-service": "0.2.0
|
|
45
|
+
"@internetarchive/lazy-loader-service": "^0.2.0",
|
|
46
46
|
"@internetarchive/modal-manager": "^0.2.1",
|
|
47
47
|
"@internetarchive/promised-singleton": "^0.2.1",
|
|
48
48
|
"currency.js": "^2.0.2",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"lit-html": "^2.0.2",
|
|
73
73
|
"madge": "^4.0.1",
|
|
74
74
|
"polymer-cli": "^1.9.11",
|
|
75
|
+
"sinon": "^12.0.1",
|
|
75
76
|
"typescript": "^3.9.5",
|
|
76
77
|
"webpack-merge": "^4.1.5"
|
|
77
78
|
},
|
|
@@ -8,8 +8,14 @@ import {
|
|
|
8
8
|
BillingInfo,
|
|
9
9
|
} from '@internetarchive/donation-form-data-models';
|
|
10
10
|
import { PromisedSingleton } from '@internetarchive/promised-singleton';
|
|
11
|
+
import { Unsubscribe } from 'nanoevents';
|
|
11
12
|
import { PaymentProvidersInterface } from './payment-providers-interface';
|
|
12
13
|
|
|
14
|
+
export interface BraintreeManagerEvents {
|
|
15
|
+
paymentProvidersHostedFieldsRetry: (retryNumber: number) => void;
|
|
16
|
+
paymentProvidersHostedFieldsFailed: (error: unknown) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
/**
|
|
14
20
|
* The BraintreeManager is the main entrypoint for much of the common braintree functionality.
|
|
15
21
|
*
|
|
@@ -19,6 +25,11 @@ import { PaymentProvidersInterface } from './payment-providers-interface';
|
|
|
19
25
|
* @interface BraintreeManagerInterface
|
|
20
26
|
*/
|
|
21
27
|
export interface BraintreeManagerInterface {
|
|
28
|
+
on<E extends keyof BraintreeManagerEvents>(
|
|
29
|
+
event: E,
|
|
30
|
+
callback: BraintreeManagerEvents[E],
|
|
31
|
+
): Unsubscribe;
|
|
32
|
+
|
|
22
33
|
/**
|
|
23
34
|
* The PaymentProviders class contains the IA-specific handlers for each of the
|
|
24
35
|
* different payment providers.
|
|
@@ -16,10 +16,12 @@ import {
|
|
|
16
16
|
BraintreeManagerInterface,
|
|
17
17
|
BraintreeEndpointManagerInterface,
|
|
18
18
|
HostingEnvironment,
|
|
19
|
+
BraintreeManagerEvents,
|
|
19
20
|
} from './braintree-interfaces';
|
|
20
21
|
import { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';
|
|
21
22
|
import { PromisedSingleton } from '@internetarchive/promised-singleton';
|
|
22
23
|
import { PaymentProvidersInterface } from './payment-providers-interface';
|
|
24
|
+
import { createNanoEvents, Emitter, Unsubscribe } from 'nanoevents';
|
|
23
25
|
|
|
24
26
|
/** @inheritdoc */
|
|
25
27
|
export class BraintreeManager implements BraintreeManagerInterface {
|
|
@@ -58,6 +60,15 @@ export class BraintreeManager implements BraintreeManagerInterface {
|
|
|
58
60
|
*/
|
|
59
61
|
private deviceData?: string;
|
|
60
62
|
|
|
63
|
+
private emitter = createNanoEvents<BraintreeManagerEvents>();
|
|
64
|
+
|
|
65
|
+
on<E extends keyof BraintreeManagerEvents>(
|
|
66
|
+
event: E,
|
|
67
|
+
callback: BraintreeManagerEvents[E],
|
|
68
|
+
): Unsubscribe {
|
|
69
|
+
return this.emitter.on(event, callback);
|
|
70
|
+
}
|
|
71
|
+
|
|
61
72
|
/** @inheritdoc */
|
|
62
73
|
paymentProviders: PaymentProvidersInterface;
|
|
63
74
|
|
|
@@ -245,6 +256,14 @@ export class BraintreeManager implements BraintreeManagerInterface {
|
|
|
245
256
|
hostingEnvironment: options.hostingEnvironment,
|
|
246
257
|
hostedFieldConfig: options.hostedFieldConfig,
|
|
247
258
|
});
|
|
259
|
+
|
|
260
|
+
this.paymentProviders.on('hostedFieldsRetry', (retryNumber: number) => {
|
|
261
|
+
this.emitter.emit('paymentProvidersHostedFieldsRetry', retryNumber);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
this.paymentProviders.on('hostedFieldsFailed', (error: unknown) => {
|
|
265
|
+
this.emitter.emit('paymentProvidersHostedFieldsFailed', error);
|
|
266
|
+
});
|
|
248
267
|
}
|
|
249
268
|
|
|
250
269
|
/** @inheritdoc */
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { PromisedSingleton } from '@internetarchive/promised-singleton';
|
|
2
|
+
import { Unsubscribe } from 'nanoevents';
|
|
2
3
|
import { HostedFieldName } from './hosted-field-container';
|
|
3
4
|
|
|
5
|
+
export interface CreditCardHandlerEvents {
|
|
6
|
+
hostedFieldsRetry: (retryNumber: number) => void;
|
|
7
|
+
hostedFieldsFailed: (error: unknown) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
export interface CreditCardHandlerInterface {
|
|
5
11
|
instance: PromisedSingleton<braintree.HostedFields | undefined>;
|
|
6
12
|
tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined>;
|
|
@@ -8,4 +14,8 @@ export interface CreditCardHandlerInterface {
|
|
|
8
14
|
removeFieldErrors(fields: HostedFieldName[]): void;
|
|
9
15
|
showErrorMessage(message?: string): void;
|
|
10
16
|
hideErrorMessage(): void;
|
|
17
|
+
on<E extends keyof CreditCardHandlerEvents>(
|
|
18
|
+
event: E,
|
|
19
|
+
callback: CreditCardHandlerEvents[E],
|
|
20
|
+
): Unsubscribe;
|
|
11
21
|
}
|
|
@@ -2,35 +2,102 @@ import { PromisedSingleton } from '@internetarchive/promised-singleton';
|
|
|
2
2
|
import { BraintreeManagerInterface } from '../../braintree-interfaces';
|
|
3
3
|
import { HostedFieldConfiguration } from './hosted-field-configuration';
|
|
4
4
|
import { HostedFieldName } from './hosted-field-container';
|
|
5
|
-
import { CreditCardHandlerInterface } from './credit-card-interface';
|
|
5
|
+
import { CreditCardHandlerEvents, CreditCardHandlerInterface } from './credit-card-interface';
|
|
6
|
+
import { promisedSleep } from '../../../util/promisedSleep';
|
|
7
|
+
import { createNanoEvents, Unsubscribe } from 'nanoevents';
|
|
6
8
|
|
|
7
9
|
export class CreditCardHandler implements CreditCardHandlerInterface {
|
|
8
|
-
|
|
10
|
+
on<E extends keyof CreditCardHandlerEvents>(
|
|
11
|
+
event: E,
|
|
12
|
+
callback: CreditCardHandlerEvents[E],
|
|
13
|
+
): Unsubscribe {
|
|
14
|
+
return this.emitter.on(event, callback);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
instance = new PromisedSingleton<braintree.HostedFields | undefined>({
|
|
18
|
+
generator: async (): Promise<braintree.HostedFields | undefined> => {
|
|
19
|
+
const braintreeClient = await this.braintreeManager.instance.get();
|
|
20
|
+
const hostedFields = await this.createHostedFields(braintreeClient);
|
|
21
|
+
return hostedFields;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
private emitter = createNanoEvents<CreditCardHandlerEvents>();
|
|
26
|
+
|
|
27
|
+
private maxRetryCount: number;
|
|
28
|
+
|
|
29
|
+
private retryInverval: number;
|
|
30
|
+
|
|
31
|
+
private loadTimeout: number;
|
|
9
32
|
|
|
10
33
|
constructor(options: {
|
|
11
34
|
braintreeManager: BraintreeManagerInterface;
|
|
12
35
|
hostedFieldClient: braintree.HostedFields;
|
|
13
36
|
hostedFieldConfig: HostedFieldConfiguration;
|
|
37
|
+
maxRetryCount?: number;
|
|
38
|
+
retryInverval?: number;
|
|
39
|
+
loadTimeout?: number;
|
|
14
40
|
}) {
|
|
15
41
|
this.braintreeManager = options.braintreeManager;
|
|
16
42
|
this.hostedFieldClient = options.hostedFieldClient;
|
|
17
43
|
this.hostedFieldConfig = options.hostedFieldConfig;
|
|
44
|
+
this.maxRetryCount = options.maxRetryCount ?? 2;
|
|
45
|
+
this.retryInverval = (options.retryInverval ?? 1) * 1000;
|
|
46
|
+
this.loadTimeout = (options.loadTimeout ?? 6) * 1000;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private braintreeManager: BraintreeManagerInterface;
|
|
50
|
+
private hostedFieldClient: braintree.HostedFields;
|
|
51
|
+
private hostedFieldConfig: HostedFieldConfiguration;
|
|
52
|
+
|
|
53
|
+
private async createHostedFields(
|
|
54
|
+
braintreeClient: braintree.Client,
|
|
55
|
+
retryCount = 0,
|
|
56
|
+
): Promise<braintree.HostedFields | undefined> {
|
|
57
|
+
// we mainly want to do this for retry events, but it doesn't
|
|
58
|
+
// hurt to do it on the first try
|
|
59
|
+
this.hostedFieldConfig.hostedFieldContainer.resetHostedFields();
|
|
60
|
+
try {
|
|
61
|
+
// The hosted fields have a 60 second timeout internally, but braintree
|
|
62
|
+
// support recommended setting a shorter timeout because 99% of users
|
|
63
|
+
// load the hosted fields in under 4 seconds.
|
|
64
|
+
// What we're doing here is creating a "timeout" promise
|
|
65
|
+
// and a "create hosted fields" promise and doing a `Promise.race()` to
|
|
66
|
+
// resolve when the first one finishes. If the timeout finishes first,
|
|
67
|
+
// we throw an error to trigger the retry logic. If the hosted fields
|
|
68
|
+
// finishes first, we cancel the timeout promise since we're done.
|
|
69
|
+
let timeout: number;
|
|
70
|
+
const timeoutPromise = new Promise<void>((resolve, reject) => {
|
|
71
|
+
timeout = window.setTimeout(() => {
|
|
72
|
+
reject(new Error('Timeout loading Hosted Fields'));
|
|
73
|
+
}, this.loadTimeout);
|
|
74
|
+
});
|
|
18
75
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const braintreeClient = await this.braintreeManager.instance.get();
|
|
22
|
-
return this.hostedFieldClient.create({
|
|
76
|
+
const hostedFieldsPromise = new Promise<braintree.HostedFields | undefined>(async resolve => {
|
|
77
|
+
const fields = await this.hostedFieldClient.create({
|
|
23
78
|
client: braintreeClient,
|
|
24
79
|
styles: this.hostedFieldConfig.hostedFieldStyle,
|
|
25
80
|
fields: this.hostedFieldConfig.hostedFieldFieldOptions,
|
|
26
81
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
82
|
+
// clear the timeout when this finishes so we don't also get the timeout rejection
|
|
83
|
+
window.clearTimeout(timeout);
|
|
84
|
+
resolve(fields);
|
|
85
|
+
});
|
|
30
86
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
87
|
+
const result = await Promise.race([timeoutPromise, hostedFieldsPromise]);
|
|
88
|
+
|
|
89
|
+
return result as braintree.HostedFields;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (retryCount >= this.maxRetryCount) {
|
|
92
|
+
this.emitter.emit('hostedFieldsFailed', error);
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
await promisedSleep(this.retryInverval); // wait before retrying
|
|
96
|
+
const newRetryCount = retryCount + 1;
|
|
97
|
+
this.emitter.emit('hostedFieldsRetry', newRetryCount);
|
|
98
|
+
return this.createHostedFields(braintreeClient, newRetryCount);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
34
101
|
|
|
35
102
|
async tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined> {
|
|
36
103
|
const hostedFields = await this.instance.get();
|
|
@@ -7,23 +7,33 @@ export enum HostedFieldName {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export interface HostedFieldContainerInterface {
|
|
10
|
-
fieldFor(field: HostedFieldName):
|
|
10
|
+
fieldFor(field: HostedFieldName): HTMLDivElement;
|
|
11
11
|
markFieldErrors(fields: HostedFieldName[]): void;
|
|
12
12
|
removeFieldErrors(fields: HostedFieldName[]): void;
|
|
13
13
|
showErrorMessage(message?: string): void;
|
|
14
14
|
hideErrorMessage(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Determine if the hosted fields have loaded.
|
|
17
|
+
*
|
|
18
|
+
* This is used to detect timeouts on the credit card hosted fields.
|
|
19
|
+
*/
|
|
20
|
+
allHostedFieldsAreLoaded(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Reset the hosted fields to retry in case of timeout
|
|
23
|
+
*/
|
|
24
|
+
resetHostedFields(): void;
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
export class HostedFieldContainer implements HostedFieldContainerInterface {
|
|
18
|
-
private number:
|
|
28
|
+
private number: HTMLDivElement;
|
|
19
29
|
|
|
20
|
-
private cvv:
|
|
30
|
+
private cvv: HTMLDivElement;
|
|
21
31
|
|
|
22
|
-
private expirationDate:
|
|
32
|
+
private expirationDate: HTMLDivElement;
|
|
23
33
|
|
|
24
34
|
private errorContainer: HTMLDivElement;
|
|
25
35
|
|
|
26
|
-
fieldFor(field: HostedFieldName):
|
|
36
|
+
fieldFor(field: HostedFieldName): HTMLDivElement {
|
|
27
37
|
switch (field) {
|
|
28
38
|
case HostedFieldName.Number:
|
|
29
39
|
return this.number;
|
|
@@ -58,10 +68,27 @@ export class HostedFieldContainer implements HostedFieldContainerInterface {
|
|
|
58
68
|
this.errorContainer.style.display = 'none';
|
|
59
69
|
}
|
|
60
70
|
|
|
71
|
+
/** @inheritdoc */
|
|
72
|
+
allHostedFieldsAreLoaded(): boolean {
|
|
73
|
+
const elements = [this.number, this.cvv, this.expirationDate];
|
|
74
|
+
return elements.every(element => {
|
|
75
|
+
return element.firstChild !== null;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
resetHostedFields(): void {
|
|
80
|
+
const elements = [this.number, this.cvv, this.expirationDate];
|
|
81
|
+
elements.forEach(element => {
|
|
82
|
+
while (element.firstChild) {
|
|
83
|
+
element.firstChild.remove();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
61
88
|
constructor(options: {
|
|
62
|
-
number:
|
|
63
|
-
cvv:
|
|
64
|
-
expirationDate:
|
|
89
|
+
number: HTMLDivElement;
|
|
90
|
+
cvv: HTMLDivElement;
|
|
91
|
+
expirationDate: HTMLDivElement;
|
|
65
92
|
errorContainer: HTMLDivElement;
|
|
66
93
|
}) {
|
|
67
94
|
this.number = options.number;
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { PromisedSingleton } from '@internetarchive/promised-singleton';
|
|
2
2
|
import { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CreditCardHandlerEvents,
|
|
5
|
+
CreditCardHandlerInterface,
|
|
6
|
+
} from './payment-providers/credit-card/credit-card-interface';
|
|
4
7
|
import { VenmoHandlerInterface } from './payment-providers/venmo-interface';
|
|
5
8
|
import { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';
|
|
6
9
|
import { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';
|
|
10
|
+
import { Unsubscribe } from 'nanoevents';
|
|
11
|
+
|
|
12
|
+
// this will bubble up child events
|
|
13
|
+
export type PaymentProvidersEvents = CreditCardHandlerEvents;
|
|
7
14
|
|
|
8
15
|
export interface PaymentProvidersInterface {
|
|
16
|
+
on<E extends keyof PaymentProvidersEvents>(
|
|
17
|
+
event: E,
|
|
18
|
+
callback: PaymentProvidersEvents[E],
|
|
19
|
+
): Unsubscribe;
|
|
9
20
|
creditCardHandler: PromisedSingleton<CreditCardHandlerInterface>;
|
|
10
21
|
applePayHandler: PromisedSingleton<ApplePayHandlerInterface>;
|
|
11
22
|
venmoHandler: PromisedSingleton<VenmoHandlerInterface | undefined>;
|