@rebilly/framepay-react 2.0.1 → 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 +7 -0
- package/env.js +7 -0
- package/package.json +10 -2
- 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,104 @@
|
|
|
1
|
+
import { Substitute } from '@fluffy-spoon/substitute';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import FramePayError from '../../framepay-error';
|
|
5
|
+
import IBANElement from './iban-element';
|
|
6
|
+
|
|
7
|
+
describe('IBANElement', () => {
|
|
8
|
+
it('should not setup the element while api is not ready', () => {
|
|
9
|
+
const props = Substitute.for<IBANProps>();
|
|
10
|
+
|
|
11
|
+
props.Rebilly.ready.returns(false);
|
|
12
|
+
|
|
13
|
+
const spy = jest.spyOn(IBANElement.prototype, 'setupElement');
|
|
14
|
+
|
|
15
|
+
render(<IBANElement {...props} Rebilly={props.Rebilly} />);
|
|
16
|
+
expect(spy).not.toHaveBeenCalled();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should setup the element when api is ready', () => {
|
|
20
|
+
const props = Substitute.for<IBANProps>();
|
|
21
|
+
const spy = jest.spyOn(IBANElement.prototype, 'setupElement');
|
|
22
|
+
|
|
23
|
+
props.Rebilly.ready.returns(false);
|
|
24
|
+
|
|
25
|
+
const { rerender } = render(
|
|
26
|
+
<IBANElement {...props} Rebilly={props.Rebilly} />
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
expect(spy).toHaveBeenCalledTimes(0);
|
|
30
|
+
|
|
31
|
+
const nextProps = Substitute.for<IBANProps>();
|
|
32
|
+
|
|
33
|
+
rerender(
|
|
34
|
+
<IBANElement
|
|
35
|
+
{...nextProps}
|
|
36
|
+
Rebilly={{ iban: nextProps.Rebilly.iban, ready: true }}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should render the empty div element', () => {
|
|
44
|
+
const props = Substitute.for<IBANProps>();
|
|
45
|
+
const { container } = render(
|
|
46
|
+
<IBANElement {...props} Rebilly={props.Rebilly} />
|
|
47
|
+
);
|
|
48
|
+
expect(container.firstChild).toMatchInlineSnapshot(`<div />`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should destroy the element on component unmount', done => {
|
|
52
|
+
const props = Substitute.for<IBANProps>();
|
|
53
|
+
const element = Substitute.for<PaymentElement>();
|
|
54
|
+
|
|
55
|
+
element.destroy().mimicks(() => {
|
|
56
|
+
done();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
class TmpComponent extends React.Component {
|
|
60
|
+
render() {
|
|
61
|
+
return (
|
|
62
|
+
<IBANElement
|
|
63
|
+
{...props}
|
|
64
|
+
Rebilly={{
|
|
65
|
+
...props.Rebilly,
|
|
66
|
+
iban: {
|
|
67
|
+
...props.Rebilly.iban,
|
|
68
|
+
mount: () => element
|
|
69
|
+
},
|
|
70
|
+
ready: true
|
|
71
|
+
}}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const { unmount } = render(<TmpComponent />);
|
|
78
|
+
unmount();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should fail the element mount on remote error', () => {
|
|
82
|
+
const props = Substitute.for<IBANProps>();
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
render(
|
|
86
|
+
<IBANElement
|
|
87
|
+
{...props}
|
|
88
|
+
Rebilly={{
|
|
89
|
+
...props.Rebilly,
|
|
90
|
+
iban: {
|
|
91
|
+
...props.Rebilly.iban,
|
|
92
|
+
mount: null
|
|
93
|
+
},
|
|
94
|
+
ready: true
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
// never
|
|
99
|
+
expect(true).toEqual(false);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
expect(error.code).toEqual(FramePayError.codes.elementMountError);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import FramePayError from '../../framepay-error';
|
|
3
|
+
import BaseElement from './base-element';
|
|
4
|
+
|
|
5
|
+
export default class IBANElement extends BaseElement<IBANProps, IBANState> {
|
|
6
|
+
setupElement() {
|
|
7
|
+
const { onReady, onChange, onFocus, onBlur, elementType } = this.props;
|
|
8
|
+
|
|
9
|
+
const makeElement = () => {
|
|
10
|
+
// elementNode already checked in BaseElement.handleSetupElement
|
|
11
|
+
// just ts checks fix
|
|
12
|
+
if (!this.elementNode) {
|
|
13
|
+
throw FramePayError({
|
|
14
|
+
code: FramePayError.codes.elementMountError,
|
|
15
|
+
details: `IBANElement invalid elementNode, elementType: ${elementType ||
|
|
16
|
+
'default'}`
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
return this.props.Rebilly.iban.mount(this.elementNode);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
throw FramePayError({
|
|
24
|
+
code: FramePayError.codes.elementMountError,
|
|
25
|
+
details: `IBANElement error in remote api call, elementType: ${elementType ||
|
|
26
|
+
'default'}`,
|
|
27
|
+
trace: e
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const element = makeElement();
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
element.on('ready', () => {
|
|
36
|
+
this.setState({ ready: true }, () => {
|
|
37
|
+
if (onReady) {
|
|
38
|
+
onReady();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
element.on('change', (data: PaymentElementOnChangeEventData) => {
|
|
44
|
+
if (onChange) {
|
|
45
|
+
onChange(data);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
element.on('focus', () => {
|
|
50
|
+
if (onFocus) {
|
|
51
|
+
onFocus();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
element.on('blur', () => {
|
|
56
|
+
if (onBlur) {
|
|
57
|
+
onBlur();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.setState({ element });
|
|
62
|
+
} catch (e) {
|
|
63
|
+
throw FramePayError({
|
|
64
|
+
code: FramePayError.codes.elementMountError,
|
|
65
|
+
details: `IBANElement events binding error, elementType: ${elementType ||
|
|
66
|
+
'default'}`,
|
|
67
|
+
trace: e
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
render() {
|
|
73
|
+
return <div ref={node => (this.elementNode = node)} />;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import FramePayError from '../../framepay-error';
|
|
3
|
+
import BaseElement from './base-element';
|
|
4
|
+
|
|
5
|
+
export default class PaypalElement extends BaseElement<
|
|
6
|
+
PaypalProps,
|
|
7
|
+
PaypalState
|
|
8
|
+
> {
|
|
9
|
+
setupElement() {
|
|
10
|
+
const { Rebilly } = this.props;
|
|
11
|
+
|
|
12
|
+
const makeElement = () => {
|
|
13
|
+
// elementNode already checked in BaseElement.handleSetupElement
|
|
14
|
+
// just ts checks fix
|
|
15
|
+
if (!this.elementNode) {
|
|
16
|
+
throw FramePayError({
|
|
17
|
+
code: FramePayError.codes.elementMountError,
|
|
18
|
+
details: `PaypalElement invalid elementNode`
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
return Rebilly.paypal.mount(this.elementNode);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
throw FramePayError({
|
|
26
|
+
code: FramePayError.codes.elementMountError,
|
|
27
|
+
details: `PaypalElement error in remote api call`,
|
|
28
|
+
trace: e
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const element = makeElement();
|
|
34
|
+
this.setState({ element });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// tslint:disable:max-classes-per-file
|
|
2
|
+
import { Substitute } from '@fluffy-spoon/substitute';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
import { withFramePay } from '../..';
|
|
7
|
+
|
|
8
|
+
import { FramePayComponentProps } from '../../../types/injector';
|
|
9
|
+
|
|
10
|
+
import { ContextProvider } from '../context';
|
|
11
|
+
|
|
12
|
+
describe('Injector', () => {
|
|
13
|
+
it('withFramePay HOC the context data should be provided', () => {
|
|
14
|
+
expect(true).toEqual(true);
|
|
15
|
+
|
|
16
|
+
interface OriginalProps {
|
|
17
|
+
readonly someProperty: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class TMPComponent extends React.Component<
|
|
21
|
+
OriginalProps & FramePayComponentProps
|
|
22
|
+
> {
|
|
23
|
+
render() {
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
error: {this.props.Rebilly.error}
|
|
27
|
+
ready: {String(this.props.Rebilly.ready)}
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const context = Substitute.for<FramePayContext>();
|
|
34
|
+
const TMPWrapper = withFramePay(TMPComponent);
|
|
35
|
+
|
|
36
|
+
class App extends React.Component {
|
|
37
|
+
render() {
|
|
38
|
+
return (
|
|
39
|
+
<ContextProvider
|
|
40
|
+
value={{
|
|
41
|
+
...context,
|
|
42
|
+
error: 'withFramePay',
|
|
43
|
+
ready: true
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<TMPWrapper />
|
|
47
|
+
</ContextProvider>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { container } = render(<App />);
|
|
53
|
+
expect(container.firstChild).toMatchInlineSnapshot(`
|
|
54
|
+
<div>
|
|
55
|
+
error:
|
|
56
|
+
withFramePay
|
|
57
|
+
ready:
|
|
58
|
+
true
|
|
59
|
+
</div>
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('withFramePayCardComponent HOC the context data should be provided', () => {
|
|
64
|
+
expect(true).toEqual(true);
|
|
65
|
+
|
|
66
|
+
interface OriginalProps {
|
|
67
|
+
readonly someProperty: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class TMPComponent extends React.Component<
|
|
71
|
+
OriginalProps & FramePayComponentProps
|
|
72
|
+
> {
|
|
73
|
+
render() {
|
|
74
|
+
return (
|
|
75
|
+
<div>
|
|
76
|
+
error: {this.props.Rebilly.error}
|
|
77
|
+
ready: {String(this.props.Rebilly.ready)}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const context = Substitute.for<FramePayContext>();
|
|
84
|
+
const TMPWrapper = withFramePay(TMPComponent);
|
|
85
|
+
|
|
86
|
+
class App extends React.Component {
|
|
87
|
+
render() {
|
|
88
|
+
return (
|
|
89
|
+
<ContextProvider
|
|
90
|
+
value={{
|
|
91
|
+
...context,
|
|
92
|
+
error: 'withFramePayCardComponent',
|
|
93
|
+
ready: true
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<TMPWrapper />
|
|
97
|
+
</ContextProvider>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { container } = render(<App />);
|
|
103
|
+
expect(container.firstChild).toMatchInlineSnapshot(`
|
|
104
|
+
<div>
|
|
105
|
+
error:
|
|
106
|
+
withFramePayCardComponent
|
|
107
|
+
ready:
|
|
108
|
+
true
|
|
109
|
+
</div>
|
|
110
|
+
`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('withFramePayBankComponent HOC the context data should be provided', () => {
|
|
114
|
+
expect(true).toEqual(true);
|
|
115
|
+
|
|
116
|
+
interface OriginalProps {
|
|
117
|
+
readonly someProperty: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
class TMPComponent extends React.Component<
|
|
121
|
+
OriginalProps & FramePayComponentProps
|
|
122
|
+
> {
|
|
123
|
+
render() {
|
|
124
|
+
return (
|
|
125
|
+
<div>
|
|
126
|
+
error: {this.props.Rebilly.error}
|
|
127
|
+
ready: {String(this.props.Rebilly.ready)}
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const context = Substitute.for<FramePayContext>();
|
|
134
|
+
const TMPWrapper = withFramePay(TMPComponent);
|
|
135
|
+
|
|
136
|
+
class App extends React.Component {
|
|
137
|
+
render() {
|
|
138
|
+
return (
|
|
139
|
+
<ContextProvider
|
|
140
|
+
value={{
|
|
141
|
+
...context,
|
|
142
|
+
error: 'withFramePayBankComponent',
|
|
143
|
+
ready: true
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
<TMPWrapper />
|
|
147
|
+
</ContextProvider>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const { container } = render(<App />);
|
|
153
|
+
expect(container.firstChild).toMatchInlineSnapshot(`
|
|
154
|
+
<div>
|
|
155
|
+
error:
|
|
156
|
+
withFramePayBankComponent
|
|
157
|
+
ready:
|
|
158
|
+
true
|
|
159
|
+
</div>
|
|
160
|
+
`);
|
|
161
|
+
});
|
|
162
|
+
});
|