@rebilly/framepay-react 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/CHANGELOG.md +8 -0
- package/README.md +7 -6
- package/env.js +7 -0
- package/package.json +23 -17
- package/src/index.spec.ts +19 -0
- package/src/index.ts +42 -0
- package/src/lib/components/elements/applepay-element.tsx +36 -0
- package/src/lib/components/elements/bank-element.spec.tsx +119 -0
- package/src/lib/components/elements/bank-element.tsx +74 -0
- package/src/lib/components/elements/base-element.tsx +100 -0
- package/src/lib/components/elements/card-element.spec.tsx +113 -0
- package/src/lib/components/elements/card-element.tsx +73 -0
- package/src/lib/components/elements/googlepay-element.tsx +36 -0
- package/src/lib/components/elements/iban-element.spec.tsx +104 -0
- package/src/lib/components/elements/iban-element.tsx +75 -0
- package/src/lib/components/elements/paypal-element.tsx +36 -0
- package/src/lib/components/injector.spec.tsx +162 -0
- package/src/lib/components/injector.tsx +495 -0
- package/src/lib/components/provider.spec.tsx +98 -0
- package/src/lib/components/provider.tsx +111 -0
- package/src/lib/constants.ts +43 -0
- package/src/lib/context.ts +24 -0
- package/src/lib/dom-util.ts +35 -0
- package/src/lib/framepay-error.ts +59 -0
- package/src/lib/get-rebilly-api.ts +11 -0
- package/test/e2e/assets/prop-types.js +849 -0
- package/test/e2e/assets/react-0.14.0.js +18759 -0
- package/test/e2e/assets/react-15.0.0.js +19309 -0
- package/test/e2e/assets/react-16.js +3318 -0
- package/test/e2e/assets/react-17.js +3357 -0
- package/test/e2e/assets/react-18.js +3342 -0
- package/test/e2e/assets/react-dom-0.14.0.js +42 -0
- package/test/e2e/assets/react-dom-15.0.0.js +42 -0
- package/test/e2e/assets/react-dom-16.js +25147 -0
- package/test/e2e/assets/react-dom-17.js +26292 -0
- package/test/e2e/assets/react-dom-18.js +29869 -0
- package/test/e2e/cypress-support.js +2 -0
- package/test/e2e/cypress.d.ts +1 -0
- package/test/e2e/fixtures/apple-pay.html +15 -0
- package/test/e2e/fixtures/apple-pay.js +63 -0
- package/test/e2e/fixtures/bank-separate.html +12 -0
- package/test/e2e/fixtures/bank-separate.js +323 -0
- package/test/e2e/fixtures/card-separate-brands.html +12 -0
- package/test/e2e/fixtures/card-separate-brands.js +260 -0
- package/test/e2e/fixtures/card-separate-rebilly-fields.html +12 -0
- package/test/e2e/fixtures/card-separate-rebilly-fields.js +281 -0
- package/test/e2e/fixtures/card-separate.html +12 -0
- package/test/e2e/fixtures/card-separate.js +227 -0
- package/test/e2e/fixtures/checkout-combined.html +12 -0
- package/test/e2e/fixtures/checkout-combined.js +199 -0
- package/test/e2e/fixtures/google-pay.html +15 -0
- package/test/e2e/fixtures/google-pay.js +63 -0
- package/test/e2e/fixtures/iban.html +12 -0
- package/test/e2e/fixtures/iban.js +239 -0
- package/test/e2e/fixtures/multiple-methods.html +12 -0
- package/test/e2e/fixtures/multiple-methods.js +470 -0
- package/test/e2e/fixtures/nav.js +20 -0
- package/test/e2e/fixtures/paypal.html +15 -0
- package/test/e2e/fixtures/paypal.js +62 -0
- package/test/e2e/fixtures/style.css +55 -0
- package/test/e2e/fixtures/util.js +71 -0
- package/test/e2e/local-server.mjs +12 -0
- package/test/e2e/server.mjs +43 -0
- package/test/e2e/specs/bank-separate.cy.ts +27 -0
- package/test/e2e/specs/card-separate-brands.cy.ts +70 -0
- package/test/e2e/specs/card-separate.cy.ts +27 -0
- package/test/e2e/specs/checkout-combined.cy.ts +24 -0
- package/test/e2e/specs/google-pay.cy.ts +13 -0
- package/test/e2e/specs/iban.cy.ts +17 -0
- package/test/e2e/specs/multiple-methods.cy.ts +130 -0
- package/test/e2e/specs/paypal.cy.ts +13 -0
- package/test/e2e/specs/react-version.cy.ts +12 -0
- package/test/e2e/switch-react-version.js +42 -0
- package/test/e2e/tsconfig.json +8 -0
- package/test/unit/jest.config.js +29 -0
- package/test/unit/specs/declaration-mock.spec.tsx +143 -0
- package/tsconfig.json +31 -0
- package/tsconfig.spec.json +13 -0
- package/tslint.json +36 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
// tslint:disable:max-classes-per-file
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ContextConsumer } from '../context';
|
|
5
|
+
import ApplePayElementComponent from './elements/applepay-element';
|
|
6
|
+
import BankElementComponent from './elements/bank-element';
|
|
7
|
+
import CardElementComponent from './elements/card-element';
|
|
8
|
+
import GooglePayElementComponent from './elements/googlepay-element';
|
|
9
|
+
import IBANElementComponent from './elements/iban-element';
|
|
10
|
+
import PaypalElementComponent from './elements/paypal-element';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
FramePayApplePayProps,
|
|
14
|
+
FramePayBankProps,
|
|
15
|
+
FramePayCardProps,
|
|
16
|
+
FramePayComponentProps,
|
|
17
|
+
FramePayGooglePayProps,
|
|
18
|
+
FramePayIBANProps,
|
|
19
|
+
FramePayPaypalProps
|
|
20
|
+
} from '../../../types/injector';
|
|
21
|
+
|
|
22
|
+
const makeRebillyProps = (data: FramePayContext): RebillyProps =>
|
|
23
|
+
Object.assign(Object.create(data.api || {}), {
|
|
24
|
+
error: data.error,
|
|
25
|
+
ready: data.ready
|
|
26
|
+
}) as RebillyProps;
|
|
27
|
+
|
|
28
|
+
function Hoc<P extends object>(
|
|
29
|
+
name: string,
|
|
30
|
+
WrappedComponent: React.ComponentType<P>,
|
|
31
|
+
provider: (data: FramePayContext) => object
|
|
32
|
+
) {
|
|
33
|
+
return class extends React.Component<P, {}> {
|
|
34
|
+
static readonly displayName = `withFramePay${name}(${WrappedComponent.displayName ||
|
|
35
|
+
WrappedComponent.name ||
|
|
36
|
+
'Component'})`;
|
|
37
|
+
|
|
38
|
+
render() {
|
|
39
|
+
return (
|
|
40
|
+
<ContextConsumer>
|
|
41
|
+
{(data: FramePayContext) => {
|
|
42
|
+
const provided = provider(data);
|
|
43
|
+
return (
|
|
44
|
+
<WrappedComponent
|
|
45
|
+
{...{ ...this.props, ...provided }}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}}
|
|
49
|
+
</ContextConsumer>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns the PaymentElementWrapper elements.
|
|
57
|
+
*
|
|
58
|
+
* @param type {string} PaymentElements
|
|
59
|
+
*/
|
|
60
|
+
const elementsFabric = (type: PaymentElements): object => {
|
|
61
|
+
if (type === 'iban') {
|
|
62
|
+
/**
|
|
63
|
+
* IBAN
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* IBAN number element
|
|
68
|
+
*/
|
|
69
|
+
const IBANElement = Hoc(
|
|
70
|
+
'IBANElement',
|
|
71
|
+
IBANElementComponent,
|
|
72
|
+
(data: FramePayContext) =>
|
|
73
|
+
({
|
|
74
|
+
Rebilly: makeRebillyProps(data),
|
|
75
|
+
elementType: 'iban'
|
|
76
|
+
} as IBANProps)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
IBANElement
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (type === 'bankAccount') {
|
|
85
|
+
/**
|
|
86
|
+
* BankAccount
|
|
87
|
+
* @see https://rebilly.github.io/framepay-docs/reference/rebilly.html#rebilly-bankaccount-mount
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Bank AccountType Element
|
|
92
|
+
*/
|
|
93
|
+
const BankAccountTypeElement = Hoc(
|
|
94
|
+
'BankAccountTypeElement',
|
|
95
|
+
BankElementComponent,
|
|
96
|
+
(data: FramePayContext) =>
|
|
97
|
+
({
|
|
98
|
+
Rebilly: makeRebillyProps(data),
|
|
99
|
+
elementType: 'bankAccountType'
|
|
100
|
+
} as BankProps)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* BankRoutingNumber Element
|
|
105
|
+
*/
|
|
106
|
+
const BankRoutingNumberElement = Hoc(
|
|
107
|
+
'BankRoutingNumberElement',
|
|
108
|
+
BankElementComponent,
|
|
109
|
+
(data: FramePayContext) =>
|
|
110
|
+
({
|
|
111
|
+
Rebilly: makeRebillyProps(data),
|
|
112
|
+
elementType: 'bankRoutingNumber'
|
|
113
|
+
} as BankProps)
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Bank AccountNumber Element
|
|
118
|
+
*/
|
|
119
|
+
const BankAccountNumberElement = Hoc(
|
|
120
|
+
'BankAccountNumberElement',
|
|
121
|
+
BankElementComponent,
|
|
122
|
+
(data: FramePayContext) =>
|
|
123
|
+
({
|
|
124
|
+
Rebilly: makeRebillyProps(data),
|
|
125
|
+
elementType: 'bankAccountNumber'
|
|
126
|
+
} as BankProps)
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
BankAccountNumberElement,
|
|
131
|
+
BankAccountTypeElement,
|
|
132
|
+
BankRoutingNumberElement
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (type === 'card') {
|
|
137
|
+
/**
|
|
138
|
+
* Default Card Element
|
|
139
|
+
* @see https://rebilly.github.io/framepay-docs/reference/rebilly.html#rebilly-card-mount
|
|
140
|
+
*/
|
|
141
|
+
const CardElement = Hoc(
|
|
142
|
+
'CardElement',
|
|
143
|
+
CardElementComponent,
|
|
144
|
+
(data: FramePayContext) =>
|
|
145
|
+
({
|
|
146
|
+
Rebilly: makeRebillyProps(data)
|
|
147
|
+
} as CardProps)
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Card CVV Element
|
|
152
|
+
*/
|
|
153
|
+
const CardCvvElement = Hoc(
|
|
154
|
+
'CardCvvElement',
|
|
155
|
+
CardElementComponent,
|
|
156
|
+
(data: FramePayContext) =>
|
|
157
|
+
({
|
|
158
|
+
Rebilly: makeRebillyProps(data),
|
|
159
|
+
elementType: 'cardCvv'
|
|
160
|
+
} as CardProps)
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Card Expiry Element
|
|
165
|
+
*/
|
|
166
|
+
const CardExpiryElement = Hoc(
|
|
167
|
+
'CardExpiryElement',
|
|
168
|
+
CardElementComponent,
|
|
169
|
+
(data: FramePayContext) =>
|
|
170
|
+
({
|
|
171
|
+
Rebilly: makeRebillyProps(data),
|
|
172
|
+
elementType: 'cardExpiry'
|
|
173
|
+
} as CardProps)
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Card Number Element
|
|
178
|
+
*/
|
|
179
|
+
const CardNumberElement = Hoc(
|
|
180
|
+
'CardNumberElement',
|
|
181
|
+
CardElementComponent,
|
|
182
|
+
(data: FramePayContext) =>
|
|
183
|
+
({
|
|
184
|
+
Rebilly: makeRebillyProps(data),
|
|
185
|
+
elementType: 'cardNumber'
|
|
186
|
+
} as CardProps)
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
CardCvvElement,
|
|
191
|
+
CardElement,
|
|
192
|
+
CardExpiryElement,
|
|
193
|
+
CardNumberElement
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (type === 'applePay') {
|
|
198
|
+
/**
|
|
199
|
+
* Apple Pay
|
|
200
|
+
*/
|
|
201
|
+
|
|
202
|
+
const ApplePayElement = Hoc(
|
|
203
|
+
'ApplePayElement',
|
|
204
|
+
ApplePayElementComponent,
|
|
205
|
+
(data: FramePayContext) =>
|
|
206
|
+
({
|
|
207
|
+
Rebilly: makeRebillyProps(data)
|
|
208
|
+
} as ApplePayProps)
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
ApplePayElement
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (type === 'googlePay') {
|
|
217
|
+
/**
|
|
218
|
+
* Google Pay
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
const GooglePayElement = Hoc(
|
|
222
|
+
'GooglePayElement',
|
|
223
|
+
GooglePayElementComponent,
|
|
224
|
+
(data: FramePayContext) =>
|
|
225
|
+
({
|
|
226
|
+
Rebilly: makeRebillyProps(data)
|
|
227
|
+
} as GooglePayProps)
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
GooglePayElement
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (type === 'paypal') {
|
|
236
|
+
/**
|
|
237
|
+
* Paypal
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
const PaypalElement = Hoc(
|
|
241
|
+
'PaypalElement',
|
|
242
|
+
PaypalElementComponent,
|
|
243
|
+
(data: FramePayContext) =>
|
|
244
|
+
({
|
|
245
|
+
Rebilly: makeRebillyProps(data)
|
|
246
|
+
} as PaypalProps)
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
PaypalElement
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Throw the error by default.
|
|
256
|
+
*/
|
|
257
|
+
throw new Error(
|
|
258
|
+
`Invalid PaymentMethod type, see PaymentMethodTypes declaration`
|
|
259
|
+
);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export function withFramePay<OriginalProps extends object>(
|
|
263
|
+
WrappedComponent: React.ComponentType<
|
|
264
|
+
OriginalProps & FramePayComponentProps
|
|
265
|
+
>
|
|
266
|
+
) {
|
|
267
|
+
const elements = {
|
|
268
|
+
...elementsFabric('card'),
|
|
269
|
+
...elementsFabric('bankAccount'),
|
|
270
|
+
...elementsFabric('iban'),
|
|
271
|
+
...elementsFabric('applePay'),
|
|
272
|
+
...elementsFabric('googlePay'),
|
|
273
|
+
...elementsFabric('paypal')
|
|
274
|
+
};
|
|
275
|
+
return class extends React.Component<
|
|
276
|
+
OriginalProps & FramePayComponentProps,
|
|
277
|
+
{}
|
|
278
|
+
> {
|
|
279
|
+
static readonly displayName = `withFramePay${name}(${WrappedComponent.displayName ||
|
|
280
|
+
WrappedComponent.name ||
|
|
281
|
+
'Component'})`;
|
|
282
|
+
|
|
283
|
+
render() {
|
|
284
|
+
return (
|
|
285
|
+
<ContextConsumer>
|
|
286
|
+
{(data: FramePayContext) => {
|
|
287
|
+
return (
|
|
288
|
+
<WrappedComponent
|
|
289
|
+
{...{
|
|
290
|
+
...this.props,
|
|
291
|
+
...elements,
|
|
292
|
+
Rebilly: makeRebillyProps(data)
|
|
293
|
+
}}
|
|
294
|
+
/>
|
|
295
|
+
);
|
|
296
|
+
}}
|
|
297
|
+
</ContextConsumer>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function withFramePayCardComponent<OriginalProps extends object>(
|
|
304
|
+
WrappedComponent: React.ComponentType<OriginalProps & FramePayCardProps>
|
|
305
|
+
) {
|
|
306
|
+
const elements = elementsFabric('card');
|
|
307
|
+
return class extends React.Component<
|
|
308
|
+
OriginalProps & FramePayCardProps,
|
|
309
|
+
{}
|
|
310
|
+
> {
|
|
311
|
+
static readonly displayName = `withFramePayCardComponent${name}(${WrappedComponent.displayName ||
|
|
312
|
+
WrappedComponent.name ||
|
|
313
|
+
'Component'})`;
|
|
314
|
+
|
|
315
|
+
render() {
|
|
316
|
+
return (
|
|
317
|
+
<ContextConsumer>
|
|
318
|
+
{(data: FramePayContext) => {
|
|
319
|
+
return (
|
|
320
|
+
<WrappedComponent
|
|
321
|
+
{...{
|
|
322
|
+
...this.props,
|
|
323
|
+
...elements,
|
|
324
|
+
Rebilly: makeRebillyProps(data)
|
|
325
|
+
}}
|
|
326
|
+
/>
|
|
327
|
+
);
|
|
328
|
+
}}
|
|
329
|
+
</ContextConsumer>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function withFramePayBankComponent<OriginalProps extends object>(
|
|
336
|
+
WrappedComponent: React.ComponentType<OriginalProps & FramePayBankProps>
|
|
337
|
+
) {
|
|
338
|
+
const elements = elementsFabric('bankAccount');
|
|
339
|
+
return class extends React.Component<
|
|
340
|
+
OriginalProps & FramePayBankProps,
|
|
341
|
+
{}
|
|
342
|
+
> {
|
|
343
|
+
static readonly displayName = `withFramePayBankComponent${name}(${WrappedComponent.displayName ||
|
|
344
|
+
WrappedComponent.name ||
|
|
345
|
+
'Component'})`;
|
|
346
|
+
|
|
347
|
+
render() {
|
|
348
|
+
return (
|
|
349
|
+
<ContextConsumer>
|
|
350
|
+
{(data: FramePayContext) => {
|
|
351
|
+
return (
|
|
352
|
+
<WrappedComponent
|
|
353
|
+
{...{
|
|
354
|
+
...this.props,
|
|
355
|
+
...elements,
|
|
356
|
+
Rebilly: makeRebillyProps(data)
|
|
357
|
+
}}
|
|
358
|
+
/>
|
|
359
|
+
);
|
|
360
|
+
}}
|
|
361
|
+
</ContextConsumer>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export function withFramePayIBANComponent<OriginalProps extends object>(
|
|
368
|
+
WrappedComponent: React.ComponentType<OriginalProps & FramePayIBANProps>
|
|
369
|
+
) {
|
|
370
|
+
const elements = elementsFabric('iban');
|
|
371
|
+
return class extends React.Component<
|
|
372
|
+
OriginalProps & FramePayIBANProps,
|
|
373
|
+
{}
|
|
374
|
+
> {
|
|
375
|
+
static readonly displayName = `withFramePayIBANComponent${name}(${WrappedComponent.displayName ||
|
|
376
|
+
WrappedComponent.name ||
|
|
377
|
+
'Component'})`;
|
|
378
|
+
|
|
379
|
+
render() {
|
|
380
|
+
return (
|
|
381
|
+
<ContextConsumer>
|
|
382
|
+
{(data: FramePayContext) => {
|
|
383
|
+
return (
|
|
384
|
+
<WrappedComponent
|
|
385
|
+
{...{
|
|
386
|
+
...this.props,
|
|
387
|
+
...elements,
|
|
388
|
+
Rebilly: makeRebillyProps(data)
|
|
389
|
+
}}
|
|
390
|
+
/>
|
|
391
|
+
);
|
|
392
|
+
}}
|
|
393
|
+
</ContextConsumer>
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function withFramePayApplePayComponent<OriginalProps extends object>(
|
|
400
|
+
WrappedComponent: React.ComponentType<OriginalProps & FramePayApplePayProps>
|
|
401
|
+
) {
|
|
402
|
+
const elements = elementsFabric('applePay');
|
|
403
|
+
return class extends React.Component<
|
|
404
|
+
OriginalProps & FramePayApplePayProps,
|
|
405
|
+
{}
|
|
406
|
+
> {
|
|
407
|
+
static readonly displayName = `withFramePayApplePayComponent${name}(${WrappedComponent.displayName ||
|
|
408
|
+
WrappedComponent.name ||
|
|
409
|
+
'Component'})`;
|
|
410
|
+
|
|
411
|
+
render() {
|
|
412
|
+
return (
|
|
413
|
+
<ContextConsumer>
|
|
414
|
+
{(data: FramePayContext) => {
|
|
415
|
+
return (
|
|
416
|
+
<WrappedComponent
|
|
417
|
+
{...{
|
|
418
|
+
...this.props,
|
|
419
|
+
...elements,
|
|
420
|
+
Rebilly: makeRebillyProps(data)
|
|
421
|
+
}}
|
|
422
|
+
/>
|
|
423
|
+
);
|
|
424
|
+
}}
|
|
425
|
+
</ContextConsumer>
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function withFramePayGooglePayComponent<OriginalProps extends object>(
|
|
432
|
+
WrappedComponent: React.ComponentType<
|
|
433
|
+
OriginalProps & FramePayGooglePayProps
|
|
434
|
+
>
|
|
435
|
+
) {
|
|
436
|
+
const elements = elementsFabric('googlePay');
|
|
437
|
+
return class extends React.Component<
|
|
438
|
+
OriginalProps & FramePayGooglePayProps,
|
|
439
|
+
{}
|
|
440
|
+
> {
|
|
441
|
+
static readonly displayName = `withFramePayGooglePayComponent${name}(${WrappedComponent.displayName ||
|
|
442
|
+
WrappedComponent.name ||
|
|
443
|
+
'Component'})`;
|
|
444
|
+
|
|
445
|
+
render() {
|
|
446
|
+
return (
|
|
447
|
+
<ContextConsumer>
|
|
448
|
+
{(data: FramePayContext) => {
|
|
449
|
+
return (
|
|
450
|
+
<WrappedComponent
|
|
451
|
+
{...{
|
|
452
|
+
...this.props,
|
|
453
|
+
...elements,
|
|
454
|
+
Rebilly: makeRebillyProps(data)
|
|
455
|
+
}}
|
|
456
|
+
/>
|
|
457
|
+
);
|
|
458
|
+
}}
|
|
459
|
+
</ContextConsumer>
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export function withFramePayPaypalComponent<OriginalProps extends object>(
|
|
466
|
+
WrappedComponent: React.ComponentType<OriginalProps & FramePayPaypalProps>
|
|
467
|
+
) {
|
|
468
|
+
const elements = elementsFabric('paypal');
|
|
469
|
+
return class extends React.Component<
|
|
470
|
+
OriginalProps & FramePayPaypalProps,
|
|
471
|
+
{}
|
|
472
|
+
> {
|
|
473
|
+
static readonly displayName = `withFramePayPaypalComponent${name}(${WrappedComponent.displayName ||
|
|
474
|
+
WrappedComponent.name ||
|
|
475
|
+
'Component'})`;
|
|
476
|
+
|
|
477
|
+
render() {
|
|
478
|
+
return (
|
|
479
|
+
<ContextConsumer>
|
|
480
|
+
{(data: FramePayContext) => {
|
|
481
|
+
return (
|
|
482
|
+
<WrappedComponent
|
|
483
|
+
{...{
|
|
484
|
+
...this.props,
|
|
485
|
+
...elements,
|
|
486
|
+
Rebilly: makeRebillyProps(data)
|
|
487
|
+
}}
|
|
488
|
+
/>
|
|
489
|
+
);
|
|
490
|
+
}}
|
|
491
|
+
</ContextConsumer>
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// tslint:disable:max-classes-per-file
|
|
2
|
+
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { FRAMEPAY_SCRIPT_LINK, FRAMEPAY_STYLE_LINK } from '../constants';
|
|
6
|
+
import Provider from './provider';
|
|
7
|
+
|
|
8
|
+
describe('Provider', () => {
|
|
9
|
+
it('should add the FramePay script on the page', () => {
|
|
10
|
+
const props = { publishableKey: 'pk_sandbox_1234567890' };
|
|
11
|
+
|
|
12
|
+
class ChildComponent extends React.Component {
|
|
13
|
+
render() {
|
|
14
|
+
return <div>child</div>;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
expect(document.head.innerHTML).not.toContain(FRAMEPAY_SCRIPT_LINK);
|
|
19
|
+
|
|
20
|
+
render(
|
|
21
|
+
<Provider {...props}>
|
|
22
|
+
<ChildComponent />
|
|
23
|
+
</Provider>
|
|
24
|
+
);
|
|
25
|
+
expect(document.head.innerHTML).toContain(FRAMEPAY_SCRIPT_LINK);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should add the FramePay styles on the page', () => {
|
|
29
|
+
const props = {
|
|
30
|
+
injectStyle: true,
|
|
31
|
+
publishableKey: 'pk_sandbox_1234567890'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
class ChildComponent extends React.Component {
|
|
35
|
+
render() {
|
|
36
|
+
return <div>child</div>;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
expect(document.head.innerHTML).not.toContain(FRAMEPAY_STYLE_LINK);
|
|
41
|
+
render(
|
|
42
|
+
<Provider {...props}>
|
|
43
|
+
<ChildComponent />
|
|
44
|
+
</Provider>
|
|
45
|
+
);
|
|
46
|
+
expect(document.head.innerHTML).toContain(FRAMEPAY_STYLE_LINK);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should render with single child component', () => {
|
|
50
|
+
const props = { publishableKey: 'pk_sandbox_1234567890' };
|
|
51
|
+
|
|
52
|
+
class ChildComponent extends React.Component {
|
|
53
|
+
render() {
|
|
54
|
+
return <div>child</div>;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const { container } = render(
|
|
59
|
+
<Provider {...props}>
|
|
60
|
+
<ChildComponent />
|
|
61
|
+
</Provider>
|
|
62
|
+
);
|
|
63
|
+
expect(container.firstChild).toMatchInlineSnapshot(`
|
|
64
|
+
<div>
|
|
65
|
+
child
|
|
66
|
+
</div>
|
|
67
|
+
`);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should render with multiple child components', () => {
|
|
71
|
+
const props = { publishableKey: 'pk_sandbox_1234567890' };
|
|
72
|
+
|
|
73
|
+
class ChildComponent extends React.Component<{
|
|
74
|
+
readonly title: string;
|
|
75
|
+
}> {
|
|
76
|
+
render() {
|
|
77
|
+
return <div>{this.props.title}</div>;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { container } = render(
|
|
82
|
+
<Provider {...props}>
|
|
83
|
+
<ChildComponent title="child-1" />
|
|
84
|
+
<ChildComponent title="child-2" />
|
|
85
|
+
</Provider>
|
|
86
|
+
);
|
|
87
|
+
expect(container).toMatchInlineSnapshot(`
|
|
88
|
+
<div>
|
|
89
|
+
<div>
|
|
90
|
+
child-1
|
|
91
|
+
</div>
|
|
92
|
+
<div>
|
|
93
|
+
child-2
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
`);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { FRAMEPAY_SCRIPT_LINK } from '../constants';
|
|
3
|
+
import { ContextProvider } from '../context';
|
|
4
|
+
import { injectScript, injectStyle } from '../dom-util';
|
|
5
|
+
import FramePayError from '../framepay-error';
|
|
6
|
+
import getRebillyApi from '../get-rebilly-api';
|
|
7
|
+
|
|
8
|
+
export default class Provider extends React.Component<
|
|
9
|
+
ProviderProps,
|
|
10
|
+
FramePayContext
|
|
11
|
+
> {
|
|
12
|
+
static readonly defaultProps = {
|
|
13
|
+
injectScript: true,
|
|
14
|
+
injectStyle: false,
|
|
15
|
+
onError: () => ({}),
|
|
16
|
+
onReady: () => ({}),
|
|
17
|
+
onTokenReady: () => ({})
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
readonly state: FramePayContext = {
|
|
21
|
+
api: getRebillyApi(),
|
|
22
|
+
error: null,
|
|
23
|
+
ready: false
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
componentDidMount() {
|
|
27
|
+
if (this.props.injectScript) {
|
|
28
|
+
injectScript({
|
|
29
|
+
onError: () => this.onApiError(),
|
|
30
|
+
onReady: () => this.onApiReady()
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (this.props.injectStyle) {
|
|
34
|
+
injectStyle();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
onApiError() {
|
|
39
|
+
return this.setState(
|
|
40
|
+
{
|
|
41
|
+
error: FramePayError.codes.remoteScriptError,
|
|
42
|
+
ready: false
|
|
43
|
+
},
|
|
44
|
+
() => {
|
|
45
|
+
const error = FramePayError({
|
|
46
|
+
code: FramePayError.codes.remoteScriptError,
|
|
47
|
+
details: `Remote CDN link "${FRAMEPAY_SCRIPT_LINK}"`
|
|
48
|
+
});
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async onApiReady() {
|
|
55
|
+
const api = getRebillyApi();
|
|
56
|
+
try {
|
|
57
|
+
// tslint:disable:no-shadowed-variable
|
|
58
|
+
const { injectStyle, children, ...settings } = this.props;
|
|
59
|
+
// tslint:enable:no-shadowed-variable
|
|
60
|
+
api.initialize(settings);
|
|
61
|
+
api.on('ready', () => {
|
|
62
|
+
this.setState({ ready: true, api, error: null });
|
|
63
|
+
|
|
64
|
+
// call onReady callback
|
|
65
|
+
if (this.props.onReady) {
|
|
66
|
+
this.props.onReady();
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
api.on('error', error => {
|
|
70
|
+
this.setState({
|
|
71
|
+
api,
|
|
72
|
+
error: (error as any).code,
|
|
73
|
+
ready: false
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// call error callback
|
|
77
|
+
if (this.props.onError) {
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
this.props.onError(error);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
api.on('token-ready', token => {
|
|
83
|
+
if (this.props.onTokenReady) {
|
|
84
|
+
this.props.onTokenReady(token);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
} catch (e) {
|
|
88
|
+
return this.setState(
|
|
89
|
+
{
|
|
90
|
+
error: FramePayError.codes.initializeError,
|
|
91
|
+
ready: false
|
|
92
|
+
},
|
|
93
|
+
() => {
|
|
94
|
+
throw FramePayError({
|
|
95
|
+
code: FramePayError.codes.initializeError,
|
|
96
|
+
details: 'Api initialize error',
|
|
97
|
+
trace: e
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
render() {
|
|
105
|
+
return (
|
|
106
|
+
<ContextProvider value={this.state}>
|
|
107
|
+
{this.props.children}
|
|
108
|
+
</ContextProvider>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|