@internetarchive/donation-form 0.5.8 → 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/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 +2 -1
- 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":"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":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAC9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,6DAA6D,CAAC;AAC7G,OAAO,EAAE,iBAAiB,EAAE,MAAM,0EAA0E,CAAC;AAC7G,OAAO,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,yFAAyF,CAAC;AACnI,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,uCAAuC,CAAC;AAE/C,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;AAEtC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAS,EAAE;QAC9C,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,CAAC;YACxC,8BAA8B,EAAE,8BAA8B;SAC/D,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;SACzC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,oBAAoB,EAAE,CAAC;QAErD,MAAM,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAS,EAAE;QACrC,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC5C,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;SACzC,CAAC,CAAC;QACH,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IAC/D,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAS,EAAE;QACvC,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC5C,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;SACzC,CAAC,CAAC;QACH,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IACjE,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAS,EAAE;QAC1C,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC5C,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;SACzC,CAAC,CAAC;QACH,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC3B,MAAM,CAAC,wBAAwB,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IACrE,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAS,EAAE;QAC1C,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC5C,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;SACzC,CAAC,CAAC;QACH,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC3B,MAAM,CAAC,wBAAwB,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IACrE,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAS,EAAE;QACnE,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAE5C,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE;YAC1C,UAAU,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,wBAAwB,EAAE,mBAAmB,CAAC,CAAC;QAEjF,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;YACxC,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,CAAC;YAChB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,IAAI;YACF,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;SAC5C;QAAC,OAAO,CAAC,EAAE,GAAE;QAEd,2BAA2B;QAC3B,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAS,EAAE;QAC/D,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAE5C,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE;YAC1C,IAAI,UAAU,GAAG,CAAC,EAAE;gBAClB,UAAU,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;aAC1B;YACD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;YACxC,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,CAAC;YAChB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QAC9C,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;QAChC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAS,EAAE;QACvD,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAE5C,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE;YAC1C,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChE,MAAM,qBAAqB,GAA6B,IAAI,wBAAwB,CAAC;YACnF,gBAAgB,EAAE,oBAAoB;YACtC,uBAAuB,EAAE,2BAA2B;YACpD,oBAAoB,EAAE,wBAAwB;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,gBAAgB,EAAE,gBAAgB;YAClC,iBAAiB,EAAE,MAAM;YACzB,iBAAiB,EAAE,qBAAqB;YACxC,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,CAAC;YAChB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,IAAI,eAAe,GAAG,CAAC,CAAC;QACxB,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YACnC,eAAe,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YACpC,gBAAgB,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,IAAI;YACF,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;SAC9B;QAAC,OAAO,CAAC,EAAE,GAAE;QAEd,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAA,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","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",
|
|
@@ -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>;
|
|
@@ -9,12 +9,13 @@ import { PaymentClientsInterface } from './payment-clients';
|
|
|
9
9
|
import { GooglePayHandler } from './payment-providers/google-pay';
|
|
10
10
|
import { BraintreeManagerInterface, HostingEnvironment } from './braintree-interfaces';
|
|
11
11
|
import { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';
|
|
12
|
-
import { PaymentProvidersInterface } from './payment-providers-interface';
|
|
12
|
+
import { PaymentProvidersEvents, PaymentProvidersInterface } from './payment-providers-interface';
|
|
13
13
|
import { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';
|
|
14
14
|
import { CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';
|
|
15
15
|
import { VenmoHandlerInterface } from './payment-providers/venmo-interface';
|
|
16
16
|
import { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';
|
|
17
17
|
import { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';
|
|
18
|
+
import { createNanoEvents, Emitter, Unsubscribe } from 'nanoevents';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* The PaymentProviders class contains the IA-specific handlers for each of the
|
|
@@ -28,14 +29,31 @@ import { GooglePayHandlerInterface } from './payment-providers/google-pay-interf
|
|
|
28
29
|
* @implements {PaymentProvidersInterface}
|
|
29
30
|
*/
|
|
30
31
|
export class PaymentProviders implements PaymentProvidersInterface {
|
|
32
|
+
on<E extends keyof PaymentProvidersEvents>(
|
|
33
|
+
event: E,
|
|
34
|
+
callback: PaymentProvidersEvents[E],
|
|
35
|
+
): Unsubscribe {
|
|
36
|
+
return this.emitter.on(event, callback);
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
creditCardHandler = new PromisedSingleton<CreditCardHandlerInterface>({
|
|
32
40
|
generator: async (): Promise<CreditCardHandlerInterface> => {
|
|
33
41
|
const client = await this.paymentClients.hostedFields.get();
|
|
34
|
-
|
|
42
|
+
const handler = new CreditCardHandler({
|
|
35
43
|
braintreeManager: this.braintreeManager,
|
|
36
44
|
hostedFieldClient: client,
|
|
37
45
|
hostedFieldConfig: this.hostedFieldConfig,
|
|
38
46
|
});
|
|
47
|
+
|
|
48
|
+
handler.on('hostedFieldsRetry', (retryNumber: number) => {
|
|
49
|
+
this.emitter.emit('hostedFieldsRetry', retryNumber);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
handler.on('hostedFieldsFailed', (error: unknown) => {
|
|
53
|
+
this.emitter.emit('hostedFieldsFailed', error);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return handler;
|
|
39
57
|
},
|
|
40
58
|
});
|
|
41
59
|
|
|
@@ -109,6 +127,8 @@ export class PaymentProviders implements PaymentProvidersInterface {
|
|
|
109
127
|
|
|
110
128
|
private paymentClients: PaymentClientsInterface;
|
|
111
129
|
|
|
130
|
+
private emitter = createNanoEvents<PaymentProvidersEvents>();
|
|
131
|
+
|
|
112
132
|
constructor(options: {
|
|
113
133
|
braintreeManager: BraintreeManagerInterface;
|
|
114
134
|
paymentClients: PaymentClientsInterface;
|
|
@@ -109,11 +109,11 @@ export class DonationFormController extends LitElement {
|
|
|
109
109
|
|
|
110
110
|
@query('donation-form') private donationForm!: DonationForm;
|
|
111
111
|
|
|
112
|
-
@query('#braintree-creditcard') private braintreeNumberInput!:
|
|
112
|
+
@query('#braintree-creditcard') private braintreeNumberInput!: HTMLDivElement;
|
|
113
113
|
|
|
114
|
-
@query('#braintree-cvv') private braintreeCVVInput!:
|
|
114
|
+
@query('#braintree-cvv') private braintreeCVVInput!: HTMLDivElement;
|
|
115
115
|
|
|
116
|
-
@query('#braintree-expiration') private braintreeExpirationDateInput!:
|
|
116
|
+
@query('#braintree-expiration') private braintreeExpirationDateInput!: HTMLDivElement;
|
|
117
117
|
|
|
118
118
|
@query('#braintree-error-message') private braintreeErrorMessage!: HTMLDivElement;
|
|
119
119
|
|
|
@@ -195,6 +195,20 @@ export class DonationFormController extends LitElement {
|
|
|
195
195
|
loggedInUser: this.loggedInUser,
|
|
196
196
|
origin: this.origin,
|
|
197
197
|
});
|
|
198
|
+
|
|
199
|
+
this.braintreeManager.on('paymentProvidersHostedFieldsRetry', (retryNumber: number) => {
|
|
200
|
+
const event = new CustomEvent('paymentProvidersHostedFieldsRetry', {
|
|
201
|
+
detail: { retryNumber },
|
|
202
|
+
});
|
|
203
|
+
this.dispatchEvent(event);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
this.braintreeManager.on('paymentProvidersHostedFieldsFailed', (error: unknown) => {
|
|
207
|
+
const event = new CustomEvent('paymentProvidersHostedFieldsFailed', {
|
|
208
|
+
detail: { error },
|
|
209
|
+
});
|
|
210
|
+
this.dispatchEvent(event);
|
|
211
|
+
});
|
|
198
212
|
}
|
|
199
213
|
}
|
|
200
214
|
|