@rebilly/framepay-react 14.45.6 → 14.46.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/CHANGELOG.md +2 -2
- package/build/index.d.ts +2 -2
- package/build/index.js +1 -1
- package/build/lib/constants.js +12 -10
- package/package.json +9 -9
- package/src/index.ts +8 -16
- package/src/lib/components/elements/bank-element.spec.tsx +62 -76
- package/src/lib/components/elements/card-element.spec.tsx +47 -59
- package/src/lib/components/elements/iban-element.spec.tsx +48 -52
- package/src/lib/components/injector.spec.tsx +13 -22
- package/src/lib/components/provider.spec.tsx +36 -30
- package/src/lib/constants.ts +11 -9
- package/tests/unit/element-props.ts +78 -0
- package/tests/unit/vitest-globals.d.ts +1 -0
- package/tsconfig.spec.json +7 -5
- package/vitest.config.mts +14 -0
- package/tests/unit/jest.config.js +0 -18
- package/tests/unit/specs/declaration-mock.spec.tsx +0 -144
package/CHANGELOG.md
CHANGED
package/build/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SUPPORTED_CARD_BRANDS } from './lib/constants';
|
|
2
2
|
import { withFramePay, withFramePayApplePayComponent, withFramePaySamsungPayComponent, withFramePayBankComponent, withFramePayCardComponent, withFramePayGooglePayComponent, withFramePayIBANComponent, withFramePayPaypalComponent } from './lib/components/injector';
|
|
3
3
|
import FramePayProvider from './lib/components/provider';
|
|
4
|
-
|
|
5
|
-
export {
|
|
4
|
+
export { SUPPORTED_CARD_BRANDS, FramePayProvider, withFramePay, withFramePayCardComponent, withFramePayBankComponent, withFramePayIBANComponent, withFramePayApplePayComponent, withFramePaySamsungPayComponent, withFramePayGooglePayComponent, withFramePayPaypalComponent, };
|
|
5
|
+
export type { FramePayApplePayProps, FramePaySamsungPayProps, FramePayBankProps, FramePayCardProps, FramePayComponentProps, FramePayGooglePayProps, FramePayIBANProps, FramePayPaypalProps, } from '../types/injector';
|
package/build/index.js
CHANGED
|
@@ -17,4 +17,4 @@ Object.defineProperty(exports, "withFramePayIBANComponent", { enumerable: true,
|
|
|
17
17
|
Object.defineProperty(exports, "withFramePayPaypalComponent", { enumerable: true, get: function () { return injector_1.withFramePayPaypalComponent; } });
|
|
18
18
|
const provider_1 = __importDefault(require("./lib/components/provider"));
|
|
19
19
|
exports.FramePayProvider = provider_1.default;
|
|
20
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsK0NBQXdEO0FBZ0JwRCxzR0FoQkssaUNBQXFCLE9BZ0JMO0FBZHpCLHdEQVNtQztBQU8vQiw2RkFmQSx1QkFBWSxPQWVBO0FBSVosOEdBbEJBLHdDQUE2QixPQWtCQTtBQUM3QixnSEFsQkEsMENBQStCLE9Ba0JBO0FBSC9CLDBHQWRBLG9DQUF5QixPQWNBO0FBRHpCLDBHQVpBLG9DQUF5QixPQVlBO0FBS3pCLCtHQWhCQSx5Q0FBOEIsT0FnQkE7QUFIOUIsMEdBWkEsb0NBQXlCLE9BWUE7QUFJekIsNEdBZkEsc0NBQTJCLE9BZUE7QUFaL0IseUVBQXlEO0FBSXJELDJCQUpHLGtCQUFnQixDQUlIIn0=
|
package/build/lib/constants.js
CHANGED
|
@@ -49,15 +49,17 @@ exports.REACT_VERSION = React.version;
|
|
|
49
49
|
/**
|
|
50
50
|
* Supported FramePay card types
|
|
51
51
|
*/
|
|
52
|
+
// Literals match SupportedCardBrands. Assertions keep the const enum type
|
|
53
|
+
// without requiring the test compiler to inline the enum.
|
|
52
54
|
exports.SUPPORTED_CARD_BRANDS = {
|
|
53
|
-
Amex:
|
|
54
|
-
AstroPayCard:
|
|
55
|
-
Cup:
|
|
56
|
-
DinersClub:
|
|
57
|
-
Discover:
|
|
58
|
-
JCB:
|
|
59
|
-
Maestro:
|
|
60
|
-
MasterCard:
|
|
61
|
-
Visa:
|
|
55
|
+
Amex: 'American Express',
|
|
56
|
+
AstroPayCard: 'AstroPay Card',
|
|
57
|
+
Cup: 'ChinaUnionPay',
|
|
58
|
+
DinersClub: 'Diners Club',
|
|
59
|
+
Discover: 'Discover',
|
|
60
|
+
JCB: 'JCB',
|
|
61
|
+
Maestro: 'Maestro',
|
|
62
|
+
MasterCard: 'MasterCard',
|
|
63
|
+
Visa: 'Visa',
|
|
62
64
|
};
|
|
63
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9jb25zdGFudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNkNBQStCO0FBRS9COzs7OztHQUtHO0FBRUg7OztHQUdHO0FBQ1UsUUFBQSxhQUFhLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztBQUUzQzs7R0FFRztBQUNILDBFQUEwRTtBQUMxRSwwREFBMEQ7QUFDN0MsUUFBQSxxQkFBcUIsR0FBOEI7SUFDNUQsSUFBSSxFQUFFLGtCQUF5QztJQUMvQyxZQUFZLEVBQUUsZUFBc0M7SUFDcEQsR0FBRyxFQUFFLGVBQXNDO0lBQzNDLFVBQVUsRUFBRSxhQUFvQztJQUNoRCxRQUFRLEVBQUUsVUFBaUM7SUFDM0MsR0FBRyxFQUFFLEtBQTRCO0lBQ2pDLE9BQU8sRUFBRSxTQUFnQztJQUN6QyxVQUFVLEVBQUUsWUFBbUM7SUFDL0MsSUFBSSxFQUFFLE1BQTZCO0NBQ3RDLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebilly/framepay-react",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.46.0",
|
|
4
4
|
"description": "A React wrapper for Rebilly's FramePay offering out-of-the-box support for Redux and other common React features",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"author": "Rebilly",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"LICENSE",
|
|
33
33
|
"env.js",
|
|
34
34
|
"tsconfig.json",
|
|
35
|
-
"tsconfig.spec.json"
|
|
35
|
+
"tsconfig.spec.json",
|
|
36
|
+
"vitest.config.mts"
|
|
36
37
|
],
|
|
37
38
|
"overrides": {
|
|
38
39
|
"@testing-library/react": {
|
|
@@ -52,11 +53,9 @@
|
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@playwright/test": "^1.63.0",
|
|
54
55
|
"@rebilly/playwright-config": "*",
|
|
55
|
-
"@fluffy-spoon/substitute": "^1.89.0",
|
|
56
56
|
"@rebilly/eslint-config": "*",
|
|
57
57
|
"@small-tech/auto-encrypt-localhost": "^8.4.0",
|
|
58
58
|
"@testing-library/react": "^15.0.7",
|
|
59
|
-
"@types/jest": "^29.5.1",
|
|
60
59
|
"@types/node": "^24.13.3",
|
|
61
60
|
"@types/react": "^19.2.7",
|
|
62
61
|
"core-js": "^3.50.0",
|
|
@@ -66,8 +65,7 @@
|
|
|
66
65
|
"express": "^5.1.0",
|
|
67
66
|
"globals": "^17.0.0",
|
|
68
67
|
"gud": "^1.0.0",
|
|
69
|
-
"
|
|
70
|
-
"jest-environment-jsdom": "^29.7.0",
|
|
68
|
+
"jsdom": "^21.1.1",
|
|
71
69
|
"npm-run-all2": "^8.0.4",
|
|
72
70
|
"parcel": "^2.0.0",
|
|
73
71
|
"portfinder": "^1.0.35",
|
|
@@ -76,8 +74,8 @@
|
|
|
76
74
|
"react-dom": "^19.2.8",
|
|
77
75
|
"react-dom-19": "npm:react-dom@^19.2.8",
|
|
78
76
|
"scheduler": "^0.26.0",
|
|
79
|
-
"ts-jest": "^29.4.12",
|
|
80
77
|
"typescript": "^6.0.3",
|
|
78
|
+
"vitest": "^4.1.0",
|
|
81
79
|
"warning": "^4.0.3"
|
|
82
80
|
},
|
|
83
81
|
"scripts": {
|
|
@@ -90,12 +88,14 @@
|
|
|
90
88
|
"clean-react-alias": "cross-env REACT_VERSION=clean node ./tests/e2e/switch-react-version",
|
|
91
89
|
"dotenv": "node ./env.js",
|
|
92
90
|
"build": "cross-env NODE_ENV=production tsc -p tsconfig.json",
|
|
93
|
-
"type:check": "tsc --noEmit -p tsconfig.json",
|
|
91
|
+
"type:check": "tsc --noEmit -p tsconfig.json && pnpm type:check:unit",
|
|
92
|
+
"type:check:unit": "tsc --noEmit -p tsconfig.spec.json",
|
|
94
93
|
"build:e2e": "cross-env NODE_ENV=production run-s dotenv build clean:e2e && parcel build ./tests/e2e/fixtures/* --no-optimize --no-cache --no-scope-hoist --dist-dir tests/e2e/build",
|
|
95
94
|
"dev:e2e": "cross-env NODE_ENV=development && run-s dotenv && parcel ./tests/e2e/fixtures/* --no-cache --dist-dir tests/e2e/build",
|
|
96
95
|
"serve:e2e": "run-s dotenv build:* && node tests/e2e/local-server.mjs",
|
|
97
96
|
"serve:e2e:no-build": "node tests/e2e/local-server.mjs",
|
|
98
|
-
"test:unit": "
|
|
97
|
+
"test:unit": "vitest run",
|
|
98
|
+
"test:unit:watch": "vitest",
|
|
99
99
|
"test:e2e:base": "pnpm test:e2e:run",
|
|
100
100
|
"test:e2e:react-14": "cross-env REACT_VERSION=0.14.0 run-s set-react-14 dotenv build:e2e test:e2e:base",
|
|
101
101
|
"test:e2e:react-15": "cross-env REACT_VERSION=15.0.0 run-s set-react-15 dotenv build:e2e test:e2e:base",
|
package/src/index.ts
CHANGED
|
@@ -13,17 +13,6 @@ import {
|
|
|
13
13
|
|
|
14
14
|
import FramePayProvider from './lib/components/provider';
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
FramePayApplePayProps,
|
|
18
|
-
FramePaySamsungPayProps,
|
|
19
|
-
FramePayBankProps,
|
|
20
|
-
FramePayCardProps,
|
|
21
|
-
FramePayComponentProps,
|
|
22
|
-
FramePayGooglePayProps,
|
|
23
|
-
FramePayIBANProps,
|
|
24
|
-
FramePayPaypalProps,
|
|
25
|
-
} from '../types/injector';
|
|
26
|
-
|
|
27
16
|
export {
|
|
28
17
|
SUPPORTED_CARD_BRANDS,
|
|
29
18
|
FramePayProvider,
|
|
@@ -35,12 +24,15 @@ export {
|
|
|
35
24
|
withFramePaySamsungPayComponent,
|
|
36
25
|
withFramePayGooglePayComponent,
|
|
37
26
|
withFramePayPaypalComponent,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
FramePayIBANProps,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type {
|
|
42
30
|
FramePayApplePayProps,
|
|
43
31
|
FramePaySamsungPayProps,
|
|
32
|
+
FramePayBankProps,
|
|
33
|
+
FramePayCardProps,
|
|
34
|
+
FramePayComponentProps,
|
|
44
35
|
FramePayGooglePayProps,
|
|
36
|
+
FramePayIBANProps,
|
|
45
37
|
FramePayPaypalProps,
|
|
46
|
-
};
|
|
38
|
+
} from '../types/injector';
|
|
@@ -1,136 +1,122 @@
|
|
|
1
|
-
import { Arg, Substitute } from '@fluffy-spoon/substitute';
|
|
2
1
|
import { render } from '@testing-library/react';
|
|
3
2
|
import * as React from 'react';
|
|
3
|
+
import { vi } from 'vitest';
|
|
4
4
|
import FramePayError from '../../framepay-error';
|
|
5
5
|
import BankElement from './bank-element';
|
|
6
|
-
import
|
|
7
|
-
import type { Bban, BankElement as BankElementType } from '@rebilly/framepay';
|
|
6
|
+
import { bankProps, fieldDouble } from '../../../../tests/unit/element-props';
|
|
8
7
|
|
|
9
8
|
describe('BankElement', () => {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks();
|
|
11
|
+
});
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'setupElement',
|
|
16
|
-
);
|
|
13
|
+
it('should not setup the element while api is not ready', () => {
|
|
14
|
+
const setupElementSpy = vi.spyOn(BankElement.prototype, 'setupElement');
|
|
17
15
|
|
|
18
16
|
render(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
bban: props.Framepay.bban,
|
|
24
|
-
ready: false,
|
|
25
|
-
}}
|
|
26
|
-
elementType="routingNumber"
|
|
27
|
-
/>,
|
|
17
|
+
React.createElement(
|
|
18
|
+
BankElement,
|
|
19
|
+
bankProps('routingNumber', { ready: false }),
|
|
20
|
+
),
|
|
28
21
|
);
|
|
29
22
|
|
|
30
23
|
expect(setupElementSpy).not.toHaveBeenCalled();
|
|
31
24
|
});
|
|
32
25
|
|
|
33
26
|
it('should setup the element when api is ready', () => {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const setupElementSpy = jest.spyOn(
|
|
37
|
-
BankElement.prototype,
|
|
38
|
-
'setupElement',
|
|
39
|
-
);
|
|
27
|
+
const setupElementSpy = vi.spyOn(BankElement.prototype, 'setupElement');
|
|
28
|
+
const mount = vi.fn(() => fieldDouble());
|
|
40
29
|
|
|
41
30
|
render(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
...props.Framepay,
|
|
46
|
-
bban: props.Framepay.bban,
|
|
31
|
+
React.createElement(
|
|
32
|
+
BankElement,
|
|
33
|
+
bankProps('accountType', {
|
|
47
34
|
ready: true,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
35
|
+
bban: { mount },
|
|
36
|
+
}),
|
|
37
|
+
),
|
|
51
38
|
);
|
|
52
39
|
|
|
53
40
|
expect(setupElementSpy).toHaveBeenCalled();
|
|
54
41
|
});
|
|
55
42
|
|
|
56
|
-
it('should destroy the element on component unmount', (
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
element.destroy().mimicks(() => {
|
|
61
|
-
done();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
props.Framepay.bban.mount(Arg.any(), Arg.any()).returns(element);
|
|
43
|
+
it('should destroy the element on component unmount', () => {
|
|
44
|
+
const element = fieldDouble();
|
|
45
|
+
const mount = vi.fn(() => element);
|
|
65
46
|
|
|
66
47
|
class TmpComponent extends React.Component {
|
|
67
48
|
render() {
|
|
68
|
-
return (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
ready: true,
|
|
75
|
-
}}
|
|
76
|
-
elementType="routingNumber"
|
|
77
|
-
/>
|
|
49
|
+
return React.createElement(
|
|
50
|
+
BankElement,
|
|
51
|
+
bankProps('routingNumber', {
|
|
52
|
+
ready: true,
|
|
53
|
+
bban: { mount },
|
|
54
|
+
}),
|
|
78
55
|
);
|
|
79
56
|
}
|
|
80
57
|
}
|
|
81
58
|
|
|
82
59
|
const { unmount } = render(<TmpComponent />);
|
|
83
60
|
unmount();
|
|
61
|
+
expect(element.destroy).toHaveBeenCalled();
|
|
84
62
|
});
|
|
85
63
|
|
|
86
64
|
it('should render the empty div element', () => {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
props.Framepay.ready.returns(true);
|
|
65
|
+
const mount = vi.fn(() => fieldDouble());
|
|
90
66
|
|
|
91
67
|
const { container } = render(
|
|
92
|
-
|
|
68
|
+
React.createElement(
|
|
69
|
+
BankElement,
|
|
70
|
+
bankProps('accountNumber', {
|
|
71
|
+
ready: true,
|
|
72
|
+
bban: { mount },
|
|
73
|
+
}),
|
|
74
|
+
),
|
|
93
75
|
);
|
|
94
76
|
expect(container.firstChild).toMatchInlineSnapshot('<div />');
|
|
95
77
|
});
|
|
96
78
|
|
|
97
79
|
it('should fail the element mount on remote error', () => {
|
|
98
|
-
const props = Substitute.for<BankProps>();
|
|
99
|
-
|
|
100
80
|
try {
|
|
101
81
|
render(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
82
|
+
React.createElement(
|
|
83
|
+
BankElement,
|
|
84
|
+
bankProps('accountNumber', {
|
|
85
|
+
ready: true,
|
|
106
86
|
bban: {
|
|
107
|
-
|
|
108
|
-
|
|
87
|
+
mount: () => {
|
|
88
|
+
throw new Error('remote mount failed');
|
|
89
|
+
},
|
|
109
90
|
},
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
elementType="accountNumber"
|
|
113
|
-
/>,
|
|
91
|
+
}),
|
|
92
|
+
),
|
|
114
93
|
);
|
|
115
94
|
// never
|
|
116
95
|
expect(true).toEqual(false);
|
|
117
96
|
} catch (error) {
|
|
118
|
-
expect(error
|
|
97
|
+
expect(error).toMatchObject({
|
|
98
|
+
code: FramePayError.codes.elementMountError,
|
|
99
|
+
});
|
|
119
100
|
}
|
|
120
101
|
});
|
|
121
102
|
|
|
122
103
|
it('mounts its element type through Framepay.bban', () => {
|
|
123
|
-
const
|
|
124
|
-
const bban = Substitute.for<Bban>();
|
|
104
|
+
const mount = vi.fn(() => fieldDouble());
|
|
125
105
|
|
|
126
106
|
render(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
107
|
+
React.createElement(
|
|
108
|
+
BankElement,
|
|
109
|
+
bankProps('accountNumber', {
|
|
110
|
+
ready: true,
|
|
111
|
+
bban: { mount },
|
|
112
|
+
}),
|
|
113
|
+
),
|
|
132
114
|
);
|
|
133
115
|
|
|
134
|
-
|
|
116
|
+
expect(mount).toHaveBeenCalledTimes(1);
|
|
117
|
+
expect(mount).toHaveBeenCalledWith(
|
|
118
|
+
expect.any(HTMLElement),
|
|
119
|
+
'accountNumber',
|
|
120
|
+
);
|
|
135
121
|
});
|
|
136
122
|
});
|
|
@@ -1,114 +1,102 @@
|
|
|
1
|
-
import { Substitute } from '@fluffy-spoon/substitute';
|
|
2
1
|
import { render } from '@testing-library/react';
|
|
3
2
|
import * as React from 'react';
|
|
3
|
+
import { vi } from 'vitest';
|
|
4
4
|
import FramePayError from '../../framepay-error';
|
|
5
5
|
import CardElement from './card-element';
|
|
6
|
-
import
|
|
6
|
+
import { cardProps, fieldDouble } from '../../../../tests/unit/element-props';
|
|
7
7
|
|
|
8
8
|
describe('CardElement', () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
props.Framepay.ready.returns(false);
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks();
|
|
11
|
+
});
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'setupElement',
|
|
17
|
-
);
|
|
13
|
+
it('should not setup the element while api is not ready', () => {
|
|
14
|
+
const setupElementSpy = vi.spyOn(CardElement.prototype, 'setupElement');
|
|
18
15
|
|
|
19
|
-
render(
|
|
16
|
+
render(React.createElement(CardElement, cardProps({ ready: false })));
|
|
20
17
|
|
|
21
18
|
expect(setupElementSpy).not.toHaveBeenCalled();
|
|
22
19
|
});
|
|
23
20
|
|
|
24
21
|
it('should setup the element when api is ready', () => {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
CardElement.prototype,
|
|
28
|
-
'setupElement',
|
|
29
|
-
);
|
|
22
|
+
const setupElementSpy = vi.spyOn(CardElement.prototype, 'setupElement');
|
|
23
|
+
const mount = vi.fn(() => fieldDouble());
|
|
30
24
|
|
|
31
25
|
const { rerender } = render(
|
|
32
|
-
|
|
33
|
-
Framepay={{
|
|
34
|
-
ready: false,
|
|
35
|
-
}}
|
|
36
|
-
/>,
|
|
26
|
+
React.createElement(CardElement, cardProps({ ready: false })),
|
|
37
27
|
);
|
|
38
28
|
|
|
39
29
|
expect(setupElementSpy).toHaveBeenCalledTimes(0);
|
|
40
30
|
|
|
41
31
|
rerender(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
React.createElement(
|
|
33
|
+
CardElement,
|
|
34
|
+
cardProps({
|
|
45
35
|
ready: true,
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
card: { mount },
|
|
37
|
+
}),
|
|
38
|
+
),
|
|
48
39
|
);
|
|
49
40
|
|
|
50
41
|
expect(setupElementSpy).toHaveBeenCalledTimes(1);
|
|
51
42
|
});
|
|
52
43
|
|
|
53
44
|
it('should render the empty div element', () => {
|
|
54
|
-
const
|
|
45
|
+
const mount = vi.fn(() => fieldDouble());
|
|
55
46
|
const { container } = render(
|
|
56
|
-
|
|
47
|
+
React.createElement(
|
|
48
|
+
CardElement,
|
|
49
|
+
cardProps({
|
|
50
|
+
ready: true,
|
|
51
|
+
card: { mount },
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
57
54
|
);
|
|
58
55
|
expect(container.firstChild).toMatchInlineSnapshot('<div />');
|
|
59
56
|
});
|
|
60
57
|
|
|
61
|
-
it('should destroy the element on component unmount', (
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
element.destroy().mimicks(() => {
|
|
66
|
-
done();
|
|
67
|
-
});
|
|
58
|
+
it('should destroy the element on component unmount', () => {
|
|
59
|
+
const element = fieldDouble();
|
|
60
|
+
const mount = vi.fn(() => element);
|
|
68
61
|
|
|
69
62
|
class TmpComponent extends React.Component {
|
|
70
63
|
render() {
|
|
71
|
-
return (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
...props.Framepay.card,
|
|
78
|
-
mount: () => element,
|
|
79
|
-
},
|
|
80
|
-
ready: true,
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
64
|
+
return React.createElement(
|
|
65
|
+
CardElement,
|
|
66
|
+
cardProps({
|
|
67
|
+
ready: true,
|
|
68
|
+
card: { mount },
|
|
69
|
+
}),
|
|
83
70
|
);
|
|
84
71
|
}
|
|
85
72
|
}
|
|
86
73
|
|
|
87
74
|
const { unmount } = render(<TmpComponent />);
|
|
88
75
|
unmount();
|
|
76
|
+
expect(element.destroy).toHaveBeenCalled();
|
|
89
77
|
});
|
|
90
78
|
|
|
91
79
|
it('should fail the element mount on remote error', () => {
|
|
92
|
-
const props = Substitute.for<CardProps>();
|
|
93
|
-
|
|
94
80
|
try {
|
|
95
81
|
render(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
82
|
+
React.createElement(
|
|
83
|
+
CardElement,
|
|
84
|
+
cardProps({
|
|
85
|
+
ready: true,
|
|
100
86
|
card: {
|
|
101
|
-
|
|
102
|
-
|
|
87
|
+
mount: () => {
|
|
88
|
+
throw new Error('remote mount failed');
|
|
89
|
+
},
|
|
103
90
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
/>,
|
|
91
|
+
}),
|
|
92
|
+
),
|
|
107
93
|
);
|
|
108
94
|
// never
|
|
109
95
|
expect(true).toEqual(false);
|
|
110
96
|
} catch (error) {
|
|
111
|
-
expect(error
|
|
97
|
+
expect(error).toMatchObject({
|
|
98
|
+
code: FramePayError.codes.elementMountError,
|
|
99
|
+
});
|
|
112
100
|
}
|
|
113
101
|
});
|
|
114
102
|
});
|
|
@@ -1,105 +1,101 @@
|
|
|
1
|
-
import { Substitute } from '@fluffy-spoon/substitute';
|
|
2
1
|
import { render } from '@testing-library/react';
|
|
3
2
|
import * as React from 'react';
|
|
3
|
+
import { vi } from 'vitest';
|
|
4
4
|
import FramePayError from '../../framepay-error';
|
|
5
5
|
import IBANElement from './iban-element';
|
|
6
|
-
import
|
|
6
|
+
import { fieldDouble, ibanProps } from '../../../../tests/unit/element-props';
|
|
7
7
|
|
|
8
8
|
describe('IBANElement', () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
props.Framepay.ready.returns(false);
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks();
|
|
11
|
+
});
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
it('should not setup the element while api is not ready', () => {
|
|
14
|
+
const spy = vi.spyOn(IBANElement.prototype, 'setupElement');
|
|
15
15
|
|
|
16
|
-
render(
|
|
16
|
+
render(React.createElement(IBANElement, ibanProps({ ready: false })));
|
|
17
17
|
expect(spy).not.toHaveBeenCalled();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
it('should setup the element when api is ready', () => {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
props.Framepay.ready.returns(false);
|
|
21
|
+
const spy = vi.spyOn(IBANElement.prototype, 'setupElement');
|
|
22
|
+
const mount = vi.fn(() => fieldDouble());
|
|
25
23
|
|
|
26
24
|
const { rerender } = render(
|
|
27
|
-
|
|
25
|
+
React.createElement(IBANElement, ibanProps({ ready: false })),
|
|
28
26
|
);
|
|
29
27
|
|
|
30
28
|
expect(spy).toHaveBeenCalledTimes(0);
|
|
31
29
|
|
|
32
|
-
const nextProps = Substitute.for<IBANProps>();
|
|
33
|
-
|
|
34
30
|
rerender(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
React.createElement(
|
|
32
|
+
IBANElement,
|
|
33
|
+
ibanProps({
|
|
34
|
+
ready: true,
|
|
35
|
+
iban: { mount },
|
|
36
|
+
}),
|
|
37
|
+
),
|
|
39
38
|
);
|
|
40
39
|
|
|
41
40
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
it('should render the empty div element', () => {
|
|
45
|
-
const
|
|
44
|
+
const mount = vi.fn(() => fieldDouble());
|
|
46
45
|
const { container } = render(
|
|
47
|
-
|
|
46
|
+
React.createElement(
|
|
47
|
+
IBANElement,
|
|
48
|
+
ibanProps({
|
|
49
|
+
ready: true,
|
|
50
|
+
iban: { mount },
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
48
53
|
);
|
|
49
54
|
expect(container.firstChild).toMatchInlineSnapshot('<div />');
|
|
50
55
|
});
|
|
51
56
|
|
|
52
|
-
it('should destroy the element on component unmount', (
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
element.destroy().mimicks(() => {
|
|
57
|
-
done();
|
|
58
|
-
});
|
|
57
|
+
it('should destroy the element on component unmount', () => {
|
|
58
|
+
const element = fieldDouble();
|
|
59
|
+
const mount = vi.fn(() => element);
|
|
59
60
|
|
|
60
61
|
class TmpComponent extends React.Component {
|
|
61
62
|
render() {
|
|
62
|
-
return (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
...props.Framepay.iban,
|
|
69
|
-
mount: () => element,
|
|
70
|
-
},
|
|
71
|
-
ready: true,
|
|
72
|
-
}}
|
|
73
|
-
/>
|
|
63
|
+
return React.createElement(
|
|
64
|
+
IBANElement,
|
|
65
|
+
ibanProps({
|
|
66
|
+
ready: true,
|
|
67
|
+
iban: { mount },
|
|
68
|
+
}),
|
|
74
69
|
);
|
|
75
70
|
}
|
|
76
71
|
}
|
|
77
72
|
|
|
78
73
|
const { unmount } = render(<TmpComponent />);
|
|
79
74
|
unmount();
|
|
75
|
+
expect(element.destroy).toHaveBeenCalled();
|
|
80
76
|
});
|
|
81
77
|
|
|
82
78
|
it('should fail the element mount on remote error', () => {
|
|
83
|
-
const props = Substitute.for<IBANProps>();
|
|
84
|
-
|
|
85
79
|
try {
|
|
86
80
|
render(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
React.createElement(
|
|
82
|
+
IBANElement,
|
|
83
|
+
ibanProps({
|
|
84
|
+
ready: true,
|
|
91
85
|
iban: {
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
mount: () => {
|
|
87
|
+
throw new Error('remote mount failed');
|
|
88
|
+
},
|
|
94
89
|
},
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
/>,
|
|
90
|
+
}),
|
|
91
|
+
),
|
|
98
92
|
);
|
|
99
93
|
// never
|
|
100
94
|
expect(true).toEqual(false);
|
|
101
95
|
} catch (error) {
|
|
102
|
-
expect(error
|
|
96
|
+
expect(error).toMatchObject({
|
|
97
|
+
code: FramePayError.codes.elementMountError,
|
|
98
|
+
});
|
|
103
99
|
}
|
|
104
100
|
});
|
|
105
101
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Substitute } from '@fluffy-spoon/substitute';
|
|
2
1
|
import { render } from '@testing-library/react';
|
|
3
2
|
import * as React from 'react';
|
|
4
3
|
|
|
@@ -7,6 +6,7 @@ import { withFramePay } from '../..';
|
|
|
7
6
|
import type { FramePayComponentProps } from '../../../types/injector';
|
|
8
7
|
|
|
9
8
|
import { ContextProvider } from '../context';
|
|
9
|
+
import { framepayContext } from '../../../tests/unit/element-props';
|
|
10
10
|
|
|
11
11
|
describe('Injector', () => {
|
|
12
12
|
it('withFramePay HOC the context data should be provided', () => {
|
|
@@ -29,20 +29,15 @@ describe('Injector', () => {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const context = Substitute.for<FramePayContext>();
|
|
33
32
|
const TMPWrapper = withFramePay(TMPComponent);
|
|
34
33
|
|
|
35
34
|
class App extends React.Component {
|
|
36
35
|
render() {
|
|
37
36
|
return (
|
|
38
37
|
<ContextProvider
|
|
39
|
-
value={
|
|
40
|
-
...context,
|
|
41
|
-
error: 'withFramePay',
|
|
42
|
-
ready: true,
|
|
43
|
-
}}
|
|
38
|
+
value={framepayContext('withFramePay', true)}
|
|
44
39
|
>
|
|
45
|
-
<TMPWrapper />
|
|
40
|
+
<TMPWrapper someProperty="value" />
|
|
46
41
|
</ContextProvider>
|
|
47
42
|
);
|
|
48
43
|
}
|
|
@@ -79,20 +74,18 @@ describe('Injector', () => {
|
|
|
79
74
|
}
|
|
80
75
|
}
|
|
81
76
|
|
|
82
|
-
const context = Substitute.for<FramePayContext>();
|
|
83
77
|
const TMPWrapper = withFramePay(TMPComponent);
|
|
84
78
|
|
|
85
79
|
class App extends React.Component {
|
|
86
80
|
render() {
|
|
87
81
|
return (
|
|
88
82
|
<ContextProvider
|
|
89
|
-
value={
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}}
|
|
83
|
+
value={framepayContext(
|
|
84
|
+
'withFramePayCardComponent',
|
|
85
|
+
true,
|
|
86
|
+
)}
|
|
94
87
|
>
|
|
95
|
-
<TMPWrapper />
|
|
88
|
+
<TMPWrapper someProperty="value" />
|
|
96
89
|
</ContextProvider>
|
|
97
90
|
);
|
|
98
91
|
}
|
|
@@ -129,20 +122,18 @@ describe('Injector', () => {
|
|
|
129
122
|
}
|
|
130
123
|
}
|
|
131
124
|
|
|
132
|
-
const context = Substitute.for<FramePayContext>();
|
|
133
125
|
const TMPWrapper = withFramePay(TMPComponent);
|
|
134
126
|
|
|
135
127
|
class App extends React.Component {
|
|
136
128
|
render() {
|
|
137
129
|
return (
|
|
138
130
|
<ContextProvider
|
|
139
|
-
value={
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}}
|
|
131
|
+
value={framepayContext(
|
|
132
|
+
'withFramePayBankComponent',
|
|
133
|
+
true,
|
|
134
|
+
)}
|
|
144
135
|
>
|
|
145
|
-
<TMPWrapper />
|
|
136
|
+
<TMPWrapper someProperty="value" />
|
|
146
137
|
</ContextProvider>
|
|
147
138
|
);
|
|
148
139
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { act, render } from '@testing-library/react';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { vi, type Mock } from 'vitest';
|
|
3
4
|
import Provider from './provider';
|
|
4
5
|
|
|
5
6
|
describe('Provider', () => {
|
|
@@ -57,10 +58,10 @@ describe('Provider', () => {
|
|
|
57
58
|
describe('Provider on a page where framepay.js is loaded', () => {
|
|
58
59
|
interface Api {
|
|
59
60
|
initialized: boolean;
|
|
60
|
-
initialize:
|
|
61
|
-
update:
|
|
62
|
-
on:
|
|
63
|
-
off:
|
|
61
|
+
initialize: Mock;
|
|
62
|
+
update: Mock;
|
|
63
|
+
on: Mock;
|
|
64
|
+
off: Mock;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
const page = window as unknown as { Framepay?: Api };
|
|
@@ -74,10 +75,10 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
74
75
|
beforeEach(() => {
|
|
75
76
|
api = {
|
|
76
77
|
initialized: false,
|
|
77
|
-
initialize:
|
|
78
|
-
update:
|
|
79
|
-
on:
|
|
80
|
-
off:
|
|
78
|
+
initialize: vi.fn(() => Promise.resolve()),
|
|
79
|
+
update: vi.fn(() => Promise.resolve()),
|
|
80
|
+
on: vi.fn(),
|
|
81
|
+
off: vi.fn(),
|
|
81
82
|
};
|
|
82
83
|
page.Framepay = api;
|
|
83
84
|
});
|
|
@@ -104,7 +105,7 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
104
105
|
handler();
|
|
105
106
|
}
|
|
106
107
|
});
|
|
107
|
-
const onReady =
|
|
108
|
+
const onReady = vi.fn();
|
|
108
109
|
const transactionData = { amount: 5, currency: 'USD', label: 'Plan' };
|
|
109
110
|
|
|
110
111
|
render(
|
|
@@ -132,8 +133,8 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
132
133
|
});
|
|
133
134
|
const rejection = { code: 'invalid-methods-configuration' };
|
|
134
135
|
api.update.mockImplementation(() => Promise.reject(rejection));
|
|
135
|
-
const onReady =
|
|
136
|
-
const onError =
|
|
136
|
+
const onReady = vi.fn();
|
|
137
|
+
const onError = vi.fn();
|
|
137
138
|
|
|
138
139
|
render(
|
|
139
140
|
<Provider
|
|
@@ -170,15 +171,24 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
170
171
|
handler();
|
|
171
172
|
}
|
|
172
173
|
});
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
174
|
+
const pendingUpdate = () => {
|
|
175
|
+
let captured:
|
|
176
|
+
| { resolve: () => void; reject: (error: object) => void }
|
|
177
|
+
| undefined;
|
|
178
|
+
const promise = new Promise<void>((resolve, reject) => {
|
|
179
|
+
captured = { resolve, reject };
|
|
180
|
+
});
|
|
181
|
+
if (captured === undefined) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
'FramePay update did not capture its settlement',
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
return { promise, settle: captured };
|
|
187
|
+
};
|
|
188
|
+
let pending = pendingUpdate();
|
|
189
|
+
api.update.mockImplementation(() => pending.promise);
|
|
190
|
+
const onReady = vi.fn();
|
|
191
|
+
const onError = vi.fn();
|
|
182
192
|
|
|
183
193
|
const { unmount } = render(
|
|
184
194
|
<Provider
|
|
@@ -189,17 +199,13 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
189
199
|
);
|
|
190
200
|
await flush();
|
|
191
201
|
unmount();
|
|
192
|
-
settle.resolve();
|
|
202
|
+
pending.settle.resolve();
|
|
193
203
|
await flush();
|
|
194
204
|
|
|
195
205
|
expect(onReady).not.toHaveBeenCalled();
|
|
196
206
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
new Promise<void>((resolve, reject) => {
|
|
200
|
-
settle = { resolve, reject };
|
|
201
|
-
}),
|
|
202
|
-
);
|
|
207
|
+
pending = pendingUpdate();
|
|
208
|
+
api.update.mockImplementation(() => pending.promise);
|
|
203
209
|
const second = render(
|
|
204
210
|
<Provider
|
|
205
211
|
publishableKey={publishableKey}
|
|
@@ -209,7 +215,7 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
209
215
|
);
|
|
210
216
|
await flush();
|
|
211
217
|
second.unmount();
|
|
212
|
-
settle.reject({ code: 'invalid-methods-configuration' });
|
|
218
|
+
pending.settle.reject({ code: 'invalid-methods-configuration' });
|
|
213
219
|
await flush();
|
|
214
220
|
|
|
215
221
|
expect(onError).not.toHaveBeenCalled();
|
|
@@ -231,8 +237,8 @@ describe('Provider on a page where framepay.js is loaded', () => {
|
|
|
231
237
|
}
|
|
232
238
|
},
|
|
233
239
|
);
|
|
234
|
-
const onError =
|
|
235
|
-
const onReady =
|
|
240
|
+
const onError = vi.fn();
|
|
241
|
+
const onReady = vi.fn();
|
|
236
242
|
|
|
237
243
|
render(
|
|
238
244
|
<Provider
|
package/src/lib/constants.ts
CHANGED
|
@@ -16,14 +16,16 @@ export const REACT_VERSION = React.version;
|
|
|
16
16
|
/**
|
|
17
17
|
* Supported FramePay card types
|
|
18
18
|
*/
|
|
19
|
+
// Literals match SupportedCardBrands. Assertions keep the const enum type
|
|
20
|
+
// without requiring the test compiler to inline the enum.
|
|
19
21
|
export const SUPPORTED_CARD_BRANDS: SupportedCardBrandsObject = {
|
|
20
|
-
Amex: SupportedCardBrands
|
|
21
|
-
AstroPayCard: SupportedCardBrands
|
|
22
|
-
Cup: SupportedCardBrands
|
|
23
|
-
DinersClub: SupportedCardBrands
|
|
24
|
-
Discover: SupportedCardBrands
|
|
25
|
-
JCB: SupportedCardBrands
|
|
26
|
-
Maestro: SupportedCardBrands
|
|
27
|
-
MasterCard: SupportedCardBrands
|
|
28
|
-
Visa: SupportedCardBrands
|
|
22
|
+
Amex: 'American Express' as SupportedCardBrands,
|
|
23
|
+
AstroPayCard: 'AstroPay Card' as SupportedCardBrands,
|
|
24
|
+
Cup: 'ChinaUnionPay' as SupportedCardBrands,
|
|
25
|
+
DinersClub: 'Diners Club' as SupportedCardBrands,
|
|
26
|
+
Discover: 'Discover' as SupportedCardBrands,
|
|
27
|
+
JCB: 'JCB' as SupportedCardBrands,
|
|
28
|
+
Maestro: 'Maestro' as SupportedCardBrands,
|
|
29
|
+
MasterCard: 'MasterCard' as SupportedCardBrands,
|
|
30
|
+
Visa: 'Visa' as SupportedCardBrands,
|
|
29
31
|
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { vi, type Mock } from 'vitest';
|
|
2
|
+
import type { FramePay } from '@rebilly/framepay';
|
|
3
|
+
import type { FramePayContext } from '../../types/context';
|
|
4
|
+
import type {
|
|
5
|
+
BankProps,
|
|
6
|
+
CardProps,
|
|
7
|
+
FramepayProps,
|
|
8
|
+
IBANProps,
|
|
9
|
+
} from '../../types/elements';
|
|
10
|
+
|
|
11
|
+
export type FieldDouble = {
|
|
12
|
+
readonly on: Mock;
|
|
13
|
+
readonly destroy: Mock;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function fieldDouble(): FieldDouble {
|
|
17
|
+
return {
|
|
18
|
+
on: vi.fn(),
|
|
19
|
+
destroy: vi.fn(),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type Mount = (node: HTMLElement, fieldType?: string) => FieldDouble;
|
|
24
|
+
|
|
25
|
+
export type FramepayStub = {
|
|
26
|
+
readonly ready: boolean;
|
|
27
|
+
readonly bban?: {
|
|
28
|
+
readonly mount: Mount;
|
|
29
|
+
};
|
|
30
|
+
readonly card?: {
|
|
31
|
+
readonly mount: Mount;
|
|
32
|
+
};
|
|
33
|
+
readonly iban?: {
|
|
34
|
+
readonly mount: (node: HTMLElement) => FieldDouble;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* FramepayProps extends the full FramePay API. These tests only touch
|
|
40
|
+
* `ready` and the mount method for one payment method.
|
|
41
|
+
*/
|
|
42
|
+
function framepayProps(stub: FramepayStub): FramepayProps {
|
|
43
|
+
return stub as unknown as FramepayProps;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function bankProps(
|
|
47
|
+
elementType: BankProps['elementType'],
|
|
48
|
+
framepay: FramepayStub,
|
|
49
|
+
): BankProps {
|
|
50
|
+
return {
|
|
51
|
+
Framepay: framepayProps(framepay),
|
|
52
|
+
elementType,
|
|
53
|
+
} as unknown as BankProps;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function cardProps(framepay: FramepayStub): CardProps {
|
|
57
|
+
return {
|
|
58
|
+
Framepay: framepayProps(framepay),
|
|
59
|
+
} as unknown as CardProps;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function ibanProps(framepay: FramepayStub): IBANProps {
|
|
63
|
+
return {
|
|
64
|
+
Framepay: framepayProps(framepay),
|
|
65
|
+
elementType: 'iban',
|
|
66
|
+
} as unknown as IBANProps;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function framepayContext(
|
|
70
|
+
error: string,
|
|
71
|
+
ready: boolean,
|
|
72
|
+
): FramePayContext {
|
|
73
|
+
return {
|
|
74
|
+
api: {} as unknown as FramePay,
|
|
75
|
+
error,
|
|
76
|
+
ready,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vitest/globals" />
|
package/tsconfig.spec.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "./tsconfig",
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"
|
|
4
|
+
"noEmit": true,
|
|
5
|
+
"rootDir": "."
|
|
5
6
|
},
|
|
6
7
|
"include": [
|
|
7
8
|
"src/**/*.ts",
|
|
8
9
|
"src/**/*.tsx",
|
|
9
|
-
"tests/**/*.ts",
|
|
10
|
-
"tests/**/*.tsx",
|
|
10
|
+
"tests/unit/**/*.ts",
|
|
11
|
+
"tests/unit/**/*.tsx",
|
|
11
12
|
"types/**/*.d.ts"
|
|
12
|
-
]
|
|
13
|
+
],
|
|
14
|
+
"exclude": ["node_modules/**"]
|
|
13
15
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
rootDir: '../..',
|
|
3
|
-
testEnvironment: 'jsdom',
|
|
4
|
-
testPathIgnorePatterns: ['.*/e2e/.*'],
|
|
5
|
-
transform: {
|
|
6
|
-
'.(ts|tsx)': [
|
|
7
|
-
'ts-jest',
|
|
8
|
-
{
|
|
9
|
-
tsconfig: 'tsconfig.spec.json',
|
|
10
|
-
diagnostics: {
|
|
11
|
-
warnOnly: true,
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
],
|
|
15
|
-
},
|
|
16
|
-
moduleFileExtensions: ['js', 'json', 'ts', 'tsx'],
|
|
17
|
-
moduleDirectories: ['node_modules', 'src', 'types'],
|
|
18
|
-
};
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { Arg, Substitute } from '@fluffy-spoon/substitute';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @see https://www.npmjs.com/package/@fluffy-spoon/substitute
|
|
7
|
-
*/
|
|
8
|
-
describe('Mock functionality works correctly', () => {
|
|
9
|
-
it('String property of interface', () => {
|
|
10
|
-
interface Example {
|
|
11
|
-
readonly bar: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const baz = 'baz';
|
|
15
|
-
const foo = Substitute.for<Example>();
|
|
16
|
-
|
|
17
|
-
foo.bar.returns(baz);
|
|
18
|
-
const call1 = foo.bar;
|
|
19
|
-
const call2 = foo.bar;
|
|
20
|
-
expect(call1).toEqual(baz);
|
|
21
|
-
expect(call2).toEqual(baz);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('Can mock parent interface', () => {
|
|
25
|
-
interface NestedApi {
|
|
26
|
-
readonly nestedMethod: () => boolean;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface SuperParent {
|
|
30
|
-
readonly property1: string;
|
|
31
|
-
readonly method1: () => number;
|
|
32
|
-
readonly api: NestedApi;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface Parent extends SuperParent {
|
|
36
|
-
readonly property2: string;
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
-
readonly method2: (arg: any) => string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface Child extends Parent {
|
|
42
|
-
readonly bar: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const params = Substitute.for<Child>();
|
|
46
|
-
|
|
47
|
-
params.property1.returns('property1-value');
|
|
48
|
-
params.property2.returns('property2-value');
|
|
49
|
-
params.method1().returns(10);
|
|
50
|
-
params.method2(Arg.any()).returns('method2-value');
|
|
51
|
-
|
|
52
|
-
params.api.nestedMethod().returns(false);
|
|
53
|
-
|
|
54
|
-
expect(params.property1).toEqual('property1-value');
|
|
55
|
-
expect(params.property2).toEqual('property2-value');
|
|
56
|
-
expect(params.method1()).toEqual(10);
|
|
57
|
-
expect(params.method2(10)).toEqual('method2-value');
|
|
58
|
-
|
|
59
|
-
expect(params.api.nestedMethod()).toEqual(false);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('Extended calls on the same level works correctly', () => {
|
|
63
|
-
interface Element {
|
|
64
|
-
readonly destroy: () => void;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
interface ParentMethod {
|
|
68
|
-
readonly mount: () => Element;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
interface ChildMethod1 extends ParentMethod {
|
|
72
|
-
readonly name: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface ChildMethod2 extends ParentMethod {
|
|
76
|
-
readonly name: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
interface Api {
|
|
80
|
-
readonly child1: ChildMethod1;
|
|
81
|
-
readonly child2: ChildMethod2;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const api = Substitute.for<Api>();
|
|
85
|
-
const spy1 = jest.fn();
|
|
86
|
-
const spy2 = jest.fn();
|
|
87
|
-
|
|
88
|
-
api.child1.mount().returns(Substitute.for<Element>());
|
|
89
|
-
|
|
90
|
-
api.child2.mount().returns(Substitute.for<Element>());
|
|
91
|
-
|
|
92
|
-
api.child1
|
|
93
|
-
.mount()
|
|
94
|
-
.destroy()
|
|
95
|
-
|
|
96
|
-
.mimicks(spy1);
|
|
97
|
-
|
|
98
|
-
api.child2
|
|
99
|
-
.mount()
|
|
100
|
-
.destroy()
|
|
101
|
-
|
|
102
|
-
.mimicks(spy2);
|
|
103
|
-
|
|
104
|
-
const el = api.child1.mount();
|
|
105
|
-
el.destroy();
|
|
106
|
-
|
|
107
|
-
expect(spy1).toBeCalledTimes(1);
|
|
108
|
-
expect(spy2).not.toHaveBeenCalled();
|
|
109
|
-
|
|
110
|
-
interface ComponentProps {
|
|
111
|
-
readonly api: Api;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
interface ComponentState {
|
|
115
|
-
readonly element: Element;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
class TmpParentComponent extends React.Component<
|
|
119
|
-
ComponentProps,
|
|
120
|
-
ComponentState
|
|
121
|
-
> {
|
|
122
|
-
componentDidMount() {
|
|
123
|
-
this.setState({ element: this.props.api.child1.mount() });
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
componentWillUnmount() {
|
|
127
|
-
this.state.element.destroy();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
render() {
|
|
131
|
-
return <div />;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const { unmount } = render(<TmpParentComponent api={api} />);
|
|
136
|
-
expect(spy1).toBeCalledTimes(1);
|
|
137
|
-
expect(spy2).not.toHaveBeenCalled();
|
|
138
|
-
|
|
139
|
-
unmount();
|
|
140
|
-
|
|
141
|
-
expect(spy1).toBeCalledTimes(2);
|
|
142
|
-
expect(spy2).not.toHaveBeenCalled();
|
|
143
|
-
});
|
|
144
|
-
});
|