@paypal/checkout-components 5.0.386 → 5.0.387
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/button.js +1 -1
- package/dist/test/button.js +1 -1
- package/package.json +2 -1
- package/src/funding/card/config.jsx +1 -0
- package/src/funding/credit/config.jsx +37 -3
- package/src/funding/funding.js +17 -4
- package/src/funding/funding.test.js +304 -16
- package/src/funding/paylater/config.jsx +2 -2
- package/src/funding/util.js +99 -0
- package/src/funding/util.test.js +282 -0
- package/src/funding/venmo/config.jsx +7 -8
- package/src/funding/venmo/config.test.js +17 -37
- package/src/marks/component.jsx +5 -0
- package/src/ui/buttons/buttons.jsx +2 -0
- package/src/ui/buttons/props.js +8 -1
- package/src/ui/buttons/props.test.js +2 -8
- package/src/ui/buttons/script.jsx +53 -2
- package/src/ui/buttons/styles/button.js +1 -26
- package/src/ui/buttons/styles/responsive.js +104 -24
- package/src/zoid/buttons/component.jsx +37 -2
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
|
|
3
|
+
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
isWebView,
|
|
6
|
+
isIosWebview,
|
|
7
|
+
isAndroidWebview,
|
|
8
|
+
isFacebookWebView,
|
|
9
|
+
isOperaMini,
|
|
10
|
+
isFirefoxIOS,
|
|
11
|
+
isEdgeIOS,
|
|
12
|
+
isQQBrowser,
|
|
13
|
+
isElectron,
|
|
14
|
+
supportsPopups,
|
|
15
|
+
isTablet,
|
|
16
|
+
isIos,
|
|
17
|
+
isSafari,
|
|
18
|
+
isAndroid,
|
|
19
|
+
isChrome,
|
|
20
|
+
isFirefox,
|
|
21
|
+
} from "@krakenjs/belter/src";
|
|
22
|
+
|
|
23
|
+
import { supportsVenmoPopups, isSupportedNativeVenmoBrowser } from "./util";
|
|
24
|
+
|
|
25
|
+
// Mock all the browser detection functions from belter
|
|
26
|
+
vi.mock("@krakenjs/belter/src", () => ({
|
|
27
|
+
isWebView: vi.fn(),
|
|
28
|
+
isIosWebview: vi.fn(),
|
|
29
|
+
isAndroidWebview: vi.fn(),
|
|
30
|
+
isFacebookWebView: vi.fn(),
|
|
31
|
+
isOperaMini: vi.fn(),
|
|
32
|
+
isFirefoxIOS: vi.fn(),
|
|
33
|
+
isEdgeIOS: vi.fn(),
|
|
34
|
+
isQQBrowser: vi.fn(),
|
|
35
|
+
isElectron: vi.fn(),
|
|
36
|
+
supportsPopups: vi.fn(),
|
|
37
|
+
isTablet: vi.fn(),
|
|
38
|
+
isIos: vi.fn(),
|
|
39
|
+
isSafari: vi.fn(),
|
|
40
|
+
isAndroid: vi.fn(),
|
|
41
|
+
isChrome: vi.fn(),
|
|
42
|
+
isFirefox: vi.fn(),
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
describe("funding/util", () => {
|
|
46
|
+
const defaultUserAgent =
|
|
47
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
// Reset all mocks before each test
|
|
51
|
+
vi.clearAllMocks();
|
|
52
|
+
|
|
53
|
+
// Reset window.popupBridge
|
|
54
|
+
delete window.popupBridge;
|
|
55
|
+
|
|
56
|
+
// Set default mock return values
|
|
57
|
+
vi.mocked(isWebView).mockReturnValue(false);
|
|
58
|
+
vi.mocked(isIosWebview).mockReturnValue(false);
|
|
59
|
+
vi.mocked(isAndroidWebview).mockReturnValue(false);
|
|
60
|
+
vi.mocked(isFacebookWebView).mockReturnValue(false);
|
|
61
|
+
vi.mocked(isOperaMini).mockReturnValue(false);
|
|
62
|
+
vi.mocked(isFirefoxIOS).mockReturnValue(false);
|
|
63
|
+
vi.mocked(isEdgeIOS).mockReturnValue(false);
|
|
64
|
+
vi.mocked(isQQBrowser).mockReturnValue(false);
|
|
65
|
+
vi.mocked(isElectron).mockReturnValue(false);
|
|
66
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
67
|
+
vi.mocked(isTablet).mockReturnValue(false);
|
|
68
|
+
vi.mocked(isIos).mockReturnValue(false);
|
|
69
|
+
vi.mocked(isSafari).mockReturnValue(false);
|
|
70
|
+
vi.mocked(isAndroid).mockReturnValue(false);
|
|
71
|
+
vi.mocked(isChrome).mockReturnValue(false);
|
|
72
|
+
vi.mocked(isFirefox).mockReturnValue(false);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
afterEach(() => {
|
|
76
|
+
vi.resetAllMocks();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe("supportsVenmoPopups", () => {
|
|
80
|
+
describe("when in supported webview", () => {
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
vi.mocked(isWebView).mockReturnValue(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should return true when popupBridge is available", () => {
|
|
86
|
+
window.popupBridge = {};
|
|
87
|
+
|
|
88
|
+
expect(supportsVenmoPopups({}, true, defaultUserAgent)).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should return false when popupBridge is not available", () => {
|
|
92
|
+
expect(supportsVenmoPopups({}, true, defaultUserAgent)).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe("when not in supported webview", () => {
|
|
97
|
+
it("should return true when experiment flag is enabled and user agent supports popups", () => {
|
|
98
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
99
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
100
|
+
|
|
101
|
+
expect(supportsVenmoPopups(experiment, true, defaultUserAgent)).toBe(
|
|
102
|
+
true
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isOperaMini", () => {
|
|
107
|
+
vi.mocked(isOperaMini).mockReturnValue(true);
|
|
108
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
109
|
+
|
|
110
|
+
expect(supportsVenmoPopups(experiment, false, defaultUserAgent)).toBe(
|
|
111
|
+
false
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isFirefoxIOS", () => {
|
|
116
|
+
vi.mocked(isFirefoxIOS).mockReturnValue(true);
|
|
117
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
118
|
+
|
|
119
|
+
expect(supportsVenmoPopups(experiment, false, defaultUserAgent)).toBe(
|
|
120
|
+
false
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isEdgeIOS", () => {
|
|
125
|
+
vi.mocked(isEdgeIOS).mockReturnValue(true);
|
|
126
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
127
|
+
|
|
128
|
+
expect(supportsVenmoPopups(experiment, false, defaultUserAgent)).toBe(
|
|
129
|
+
false
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isQQBrowser", () => {
|
|
134
|
+
vi.mocked(isQQBrowser).mockReturnValue(true);
|
|
135
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
136
|
+
|
|
137
|
+
expect(supportsVenmoPopups(experiment, false, defaultUserAgent)).toBe(
|
|
138
|
+
false
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should return false when experiment flag is enabled but user agent doesn't support popups due to isElectron", () => {
|
|
143
|
+
vi.mocked(isElectron).mockReturnValue(true);
|
|
144
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
145
|
+
|
|
146
|
+
expect(supportsVenmoPopups(experiment, false, defaultUserAgent)).toBe(
|
|
147
|
+
false
|
|
148
|
+
);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("should fall back to supportsPopups when experiment flag is not enabled", () => {
|
|
152
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
153
|
+
const experiment = {};
|
|
154
|
+
|
|
155
|
+
expect(supportsVenmoPopups(experiment, true, defaultUserAgent)).toBe(
|
|
156
|
+
true
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("should fall back to supportsPopups when experiment flag is false", () => {
|
|
161
|
+
vi.mocked(supportsPopups).mockReturnValue(false);
|
|
162
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: false };
|
|
163
|
+
|
|
164
|
+
expect(supportsVenmoPopups(experiment, false, defaultUserAgent)).toBe(
|
|
165
|
+
false
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should handle undefined experiment", () => {
|
|
170
|
+
vi.mocked(supportsPopups).mockReturnValue(true);
|
|
171
|
+
|
|
172
|
+
expect(supportsVenmoPopups(undefined, true, defaultUserAgent)).toBe(
|
|
173
|
+
true
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe("isSupportedNativeVenmoBrowser", () => {
|
|
180
|
+
describe("when in supported webview", () => {
|
|
181
|
+
beforeEach(() => {
|
|
182
|
+
vi.mocked(isWebView).mockReturnValue(true);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("should return true when popupBridge is available", () => {
|
|
186
|
+
window.popupBridge = {};
|
|
187
|
+
|
|
188
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("should return false when popupBridge is not available", () => {
|
|
192
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe("when not in supported webview", () => {
|
|
197
|
+
it("should return false when on tablet", () => {
|
|
198
|
+
vi.mocked(isTablet).mockReturnValue(true);
|
|
199
|
+
|
|
200
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("should return true for iOS Safari by default", () => {
|
|
204
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
205
|
+
vi.mocked(isSafari).mockReturnValue(true);
|
|
206
|
+
|
|
207
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("should return true for Android Chrome by default", () => {
|
|
211
|
+
vi.mocked(isAndroid).mockReturnValue(true);
|
|
212
|
+
vi.mocked(isChrome).mockReturnValue(true);
|
|
213
|
+
|
|
214
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("should return false for iOS Chrome without experiment flag", () => {
|
|
218
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
219
|
+
vi.mocked(isChrome).mockReturnValue(true);
|
|
220
|
+
|
|
221
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("should return true for iOS Chrome with experiment flag", () => {
|
|
225
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
226
|
+
vi.mocked(isChrome).mockReturnValue(true);
|
|
227
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
228
|
+
|
|
229
|
+
expect(
|
|
230
|
+
isSupportedNativeVenmoBrowser(experiment, defaultUserAgent)
|
|
231
|
+
).toBe(true);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should return false for Android Firefox without experiment flag", () => {
|
|
235
|
+
vi.mocked(isAndroid).mockReturnValue(true);
|
|
236
|
+
vi.mocked(isFirefox).mockReturnValue(true);
|
|
237
|
+
|
|
238
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("should return true for Android Firefox with experiment flag", () => {
|
|
242
|
+
vi.mocked(isAndroid).mockReturnValue(true);
|
|
243
|
+
vi.mocked(isFirefox).mockReturnValue(true);
|
|
244
|
+
const experiment = { venmoEnableWebOnNonNativeBrowser: true };
|
|
245
|
+
|
|
246
|
+
expect(
|
|
247
|
+
isSupportedNativeVenmoBrowser(experiment, defaultUserAgent)
|
|
248
|
+
).toBe(true);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("should return false for unsupported browser combinations", () => {
|
|
252
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
253
|
+
vi.mocked(isFirefox).mockReturnValue(true); // iOS Firefox (not Chrome)
|
|
254
|
+
|
|
255
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it("should return false for desktop browsers", () => {
|
|
259
|
+
// No mobile flags set, simulating desktop
|
|
260
|
+
|
|
261
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("should handle undefined experiment", () => {
|
|
265
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
266
|
+
vi.mocked(isSafari).mockReturnValue(true);
|
|
267
|
+
|
|
268
|
+
expect(isSupportedNativeVenmoBrowser(undefined, defaultUserAgent)).toBe(
|
|
269
|
+
true
|
|
270
|
+
);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("should prioritize tablet check over browser checks", () => {
|
|
274
|
+
vi.mocked(isTablet).mockReturnValue(true);
|
|
275
|
+
vi.mocked(isIos).mockReturnValue(true);
|
|
276
|
+
vi.mocked(isSafari).mockReturnValue(true);
|
|
277
|
+
|
|
278
|
+
expect(isSupportedNativeVenmoBrowser({}, defaultUserAgent)).toBe(false);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
});
|
|
@@ -48,19 +48,18 @@ export function getVenmoConfig(): FundingSourceConfig {
|
|
|
48
48
|
return true;
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
-
requires: ({
|
|
52
|
-
const isNonNativeSupported =
|
|
53
|
-
experiment?.venmoEnableWebOnNonNativeBrowser === true ||
|
|
54
|
-
(__WEB__ && window.popupBridge);
|
|
55
|
-
|
|
51
|
+
requires: ({ platform }) => {
|
|
56
52
|
if (platform === PLATFORM.MOBILE) {
|
|
57
53
|
return {
|
|
58
|
-
native:
|
|
59
|
-
popup:
|
|
54
|
+
native: true,
|
|
55
|
+
popup: true,
|
|
60
56
|
};
|
|
61
57
|
}
|
|
62
58
|
|
|
63
|
-
return {
|
|
59
|
+
return {
|
|
60
|
+
native: false,
|
|
61
|
+
popup: false,
|
|
62
|
+
};
|
|
64
63
|
},
|
|
65
64
|
|
|
66
65
|
Logo: ({ logoColor, optional, shouldApplyRebrandedStyles }) => {
|
|
@@ -8,6 +8,9 @@ import { BUTTON_FLOW } from "../../constants";
|
|
|
8
8
|
import { getVenmoConfig } from "./config";
|
|
9
9
|
|
|
10
10
|
describe("Venmo eligibility", () => {
|
|
11
|
+
window.navigator.mockUserAgent =
|
|
12
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
|
|
13
|
+
|
|
11
14
|
const baseEligibilityProps = {
|
|
12
15
|
fundingSource: undefined,
|
|
13
16
|
components: ["buttons"],
|
|
@@ -102,58 +105,35 @@ describe("Venmo eligibility", () => {
|
|
|
102
105
|
});
|
|
103
106
|
|
|
104
107
|
describe("requires", () => {
|
|
105
|
-
test("should
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const isVenmoEligible = venmoConfig.requires?.({
|
|
109
|
-
experiment: {
|
|
110
|
-
venmoEnableWebOnNonNativeBrowser: true,
|
|
111
|
-
},
|
|
108
|
+
test("should require native and popup support when platform is mobile", () => {
|
|
109
|
+
const venmoRequires = venmoConfig.requires?.({
|
|
112
110
|
platform: PLATFORM.MOBILE,
|
|
113
111
|
});
|
|
114
112
|
|
|
115
|
-
expect(
|
|
116
|
-
native:
|
|
117
|
-
popup:
|
|
113
|
+
expect(venmoRequires).toEqual({
|
|
114
|
+
native: true,
|
|
115
|
+
popup: true,
|
|
118
116
|
});
|
|
119
|
-
|
|
120
|
-
window.popupBridge = undefined;
|
|
121
117
|
});
|
|
122
118
|
|
|
123
|
-
test("should not
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
venmoEnableWebOnNonNativeBrowser: true,
|
|
127
|
-
},
|
|
128
|
-
platform: PLATFORM.MOBILE,
|
|
119
|
+
test("should not require native or popup support when platform is desktop", () => {
|
|
120
|
+
const venmoRequires = venmoConfig.requires?.({
|
|
121
|
+
platform: PLATFORM.DESKTOP,
|
|
129
122
|
});
|
|
130
123
|
|
|
131
|
-
expect(
|
|
124
|
+
expect(venmoRequires).toEqual({
|
|
132
125
|
native: false,
|
|
133
126
|
popup: false,
|
|
134
127
|
});
|
|
135
128
|
});
|
|
136
129
|
|
|
137
|
-
test("should
|
|
138
|
-
const
|
|
139
|
-
experiment: {
|
|
140
|
-
venmoEnableWebOnNonNativeBrowser: false,
|
|
141
|
-
},
|
|
142
|
-
platform: PLATFORM.MOBILE,
|
|
143
|
-
});
|
|
130
|
+
test("should not require native or popup support when platform is not specified", () => {
|
|
131
|
+
const venmoRequires = venmoConfig.requires?.({});
|
|
144
132
|
|
|
145
|
-
expect(
|
|
146
|
-
native:
|
|
147
|
-
popup:
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("should not check for native and popup eligibility if platform is not mobile", () => {
|
|
152
|
-
const isVenmoEligible = venmoConfig.requires?.({
|
|
153
|
-
platform: PLATFORM.DESKTOP,
|
|
133
|
+
expect(venmoRequires).toEqual({
|
|
134
|
+
native: false,
|
|
135
|
+
popup: false,
|
|
154
136
|
});
|
|
155
|
-
|
|
156
|
-
expect(isVenmoEligible).toEqual({});
|
|
157
137
|
});
|
|
158
138
|
});
|
|
159
139
|
});
|
package/src/marks/component.jsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
memoize,
|
|
10
10
|
isApplePaySupported,
|
|
11
11
|
supportsPopups as userAgentSupportsPopups,
|
|
12
|
+
getUserAgent,
|
|
12
13
|
} from "@krakenjs/belter/src";
|
|
13
14
|
import {
|
|
14
15
|
PLATFORM,
|
|
@@ -51,6 +52,7 @@ type MarksProps = {|
|
|
|
51
52
|
onShippingAddressChange?: OnShippingAddressChange,
|
|
52
53
|
onShippingOptionsChange?: OnShippingOptionsChange,
|
|
53
54
|
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|
|
55
|
+
userAgent: string,
|
|
54
56
|
|};
|
|
55
57
|
|
|
56
58
|
export type MarksComponent = (MarksProps) => MarksInstance;
|
|
@@ -62,6 +64,7 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
62
64
|
onShippingAddressChange,
|
|
63
65
|
onShippingOptionsChange,
|
|
64
66
|
displayOnly,
|
|
67
|
+
userAgent = getUserAgent(),
|
|
65
68
|
}: MarksProps = {}): MarksInstance {
|
|
66
69
|
const height = DEFAULT_HEIGHT;
|
|
67
70
|
const fundingEligibility = getFundingEligibility();
|
|
@@ -99,6 +102,7 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
99
102
|
supportedNativeBrowser,
|
|
100
103
|
experiment,
|
|
101
104
|
displayOnly,
|
|
105
|
+
userAgent,
|
|
102
106
|
});
|
|
103
107
|
const env = getEnv();
|
|
104
108
|
|
|
@@ -123,6 +127,7 @@ export const getMarksComponent: () => MarksComponent = memoize(() => {
|
|
|
123
127
|
supportedNativeBrowser,
|
|
124
128
|
experiment,
|
|
125
129
|
displayOnly,
|
|
130
|
+
userAgent,
|
|
126
131
|
});
|
|
127
132
|
};
|
|
128
133
|
|
|
@@ -168,6 +168,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
168
168
|
userIDToken,
|
|
169
169
|
vault,
|
|
170
170
|
wallet,
|
|
171
|
+
userAgent,
|
|
171
172
|
} = normalizeButtonProps(props);
|
|
172
173
|
const { layout, shape, tagline } = style;
|
|
173
174
|
|
|
@@ -190,6 +191,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
|
|
|
190
191
|
supportedNativeBrowser,
|
|
191
192
|
experiment,
|
|
192
193
|
displayOnly,
|
|
194
|
+
userAgent,
|
|
193
195
|
});
|
|
194
196
|
const multiple = fundingSources.length > 1;
|
|
195
197
|
|
package/src/ui/buttons/props.js
CHANGED
|
@@ -491,6 +491,7 @@ export type RenderButtonProps = {|
|
|
|
491
491
|
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|
|
492
492
|
message?: ButtonMessage,
|
|
493
493
|
messageMarkup?: string,
|
|
494
|
+
userAgent: string,
|
|
494
495
|
|};
|
|
495
496
|
|
|
496
497
|
export type PrerenderDetails = {|
|
|
@@ -633,6 +634,7 @@ export type ButtonProps = {|
|
|
|
633
634
|
message?: ButtonMessage,
|
|
634
635
|
messageMarkup?: string,
|
|
635
636
|
hideSubmitButtonForCardForm?: boolean,
|
|
637
|
+
userAgent: string,
|
|
636
638
|
|};
|
|
637
639
|
|
|
638
640
|
// eslint-disable-next-line flowtype/require-exact-type
|
|
@@ -683,6 +685,7 @@ export type ButtonPropsInputs = {
|
|
|
683
685
|
messageMarkup?: string | void,
|
|
684
686
|
renderedButtons: $ReadOnlyArray<$Values<typeof FUNDING>>,
|
|
685
687
|
buttonColor: ButtonColor,
|
|
688
|
+
userAgent: string,
|
|
686
689
|
};
|
|
687
690
|
|
|
688
691
|
export const DEFAULT_STYLE = {
|
|
@@ -754,6 +757,7 @@ export function hasInvalidScriptOptionsForFullRedesign({
|
|
|
754
757
|
fundingSource?: ?$Values<typeof FUNDING>,
|
|
755
758
|
|}): boolean {
|
|
756
759
|
const validFundingSourcesForRedesign = [
|
|
760
|
+
undefined,
|
|
757
761
|
FUNDING.PAYPAL,
|
|
758
762
|
FUNDING.VENMO,
|
|
759
763
|
FUNDING.PAYLATER,
|
|
@@ -882,7 +886,7 @@ export function getColorForFullRedesign({
|
|
|
882
886
|
style,
|
|
883
887
|
});
|
|
884
888
|
|
|
885
|
-
buttonColor = rebrandColorMap[defaultButtonColor];
|
|
889
|
+
buttonColor = rebrandColorMap[defaultButtonColor] || defaultButtonColor;
|
|
886
890
|
}
|
|
887
891
|
|
|
888
892
|
return {
|
|
@@ -1262,6 +1266,7 @@ export function normalizeButtonProps(
|
|
|
1262
1266
|
messageMarkup,
|
|
1263
1267
|
renderedButtons,
|
|
1264
1268
|
shopperSessionId,
|
|
1269
|
+
userAgent,
|
|
1265
1270
|
} = props;
|
|
1266
1271
|
|
|
1267
1272
|
const { country, lang } = locale;
|
|
@@ -1315,6 +1320,7 @@ export function normalizeButtonProps(
|
|
|
1315
1320
|
supportsPopups,
|
|
1316
1321
|
supportedNativeBrowser,
|
|
1317
1322
|
displayOnly,
|
|
1323
|
+
userAgent,
|
|
1318
1324
|
})
|
|
1319
1325
|
) {
|
|
1320
1326
|
throw new Error(`Funding Source not eligible: ${fundingSource}`);
|
|
@@ -1366,5 +1372,6 @@ export function normalizeButtonProps(
|
|
|
1366
1372
|
displayOnly,
|
|
1367
1373
|
message,
|
|
1368
1374
|
messageMarkup,
|
|
1375
|
+
userAgent,
|
|
1369
1376
|
};
|
|
1370
1377
|
}
|
|
@@ -160,12 +160,6 @@ describe("hasInvalidScriptOptionsForFullRedesign", () => {
|
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
it("should return true when no funding source is provided", () => {
|
|
164
|
-
const result = hasInvalidScriptOptionsForFullRedesign({});
|
|
165
|
-
|
|
166
|
-
expect(result).toBe(true);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
163
|
it("should return true when funding source is null", () => {
|
|
170
164
|
const result = hasInvalidScriptOptionsForFullRedesign({
|
|
171
165
|
fundingSource: null,
|
|
@@ -681,7 +675,7 @@ describe("getButtonColorExperience", () => {
|
|
|
681
675
|
expect(result).toBe("fullRebrand");
|
|
682
676
|
});
|
|
683
677
|
|
|
684
|
-
it("should return
|
|
678
|
+
it("should return fullRebrand for smart stack (fundingSource is undefined)", () => {
|
|
685
679
|
const result = getButtonColorExperience({
|
|
686
680
|
experiment: {
|
|
687
681
|
isPaypalRebrandEnabled: true,
|
|
@@ -692,7 +686,7 @@ describe("getButtonColorExperience", () => {
|
|
|
692
686
|
style: { color: BUTTON_COLOR.GOLD },
|
|
693
687
|
});
|
|
694
688
|
|
|
695
|
-
expect(result).toBe("
|
|
689
|
+
expect(result).toBe("fullRebrand");
|
|
696
690
|
});
|
|
697
691
|
});
|
|
698
692
|
|
|
@@ -199,10 +199,59 @@ export function getComponentScript(): () => void {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
function toggleLogos() {
|
|
203
|
+
const LOGO_CLASS = {
|
|
204
|
+
PAYPAL_LOGO: ".paypal-logo-paypal-rebrand",
|
|
205
|
+
PP_LOGO: ".paypal-logo-pp-rebrand",
|
|
206
|
+
PAYPAL_BUTTON: ".paypal-button-rebrand",
|
|
207
|
+
BUTTON_LABEL: ".paypal-button-label-container",
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const paylaterButtons = getElements(LOGO_CLASS.PAYPAL_BUTTON);
|
|
211
|
+
|
|
212
|
+
for (const button of paylaterButtons) {
|
|
213
|
+
const paypalLogo = button.querySelector(LOGO_CLASS.PAYPAL_LOGO);
|
|
214
|
+
const ppLogo = button.querySelector(LOGO_CLASS.PP_LOGO);
|
|
215
|
+
const buttonLabel = button.querySelector(LOGO_CLASS.BUTTON_LABEL);
|
|
216
|
+
|
|
217
|
+
if (!buttonLabel || !paypalLogo || !ppLogo) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const buttonWidth = buttonLabel.offsetWidth;
|
|
222
|
+
const gap = calculateGap(buttonLabel);
|
|
223
|
+
|
|
224
|
+
// temporarily hide PayPal logos
|
|
225
|
+
hideElement(paypalLogo);
|
|
226
|
+
hideElement(ppLogo);
|
|
227
|
+
|
|
228
|
+
const allElements = getAllChildren(buttonLabel);
|
|
229
|
+
const textElements = allElements.filter(
|
|
230
|
+
(el) => !el.classList.contains("paypal-logo-pp-rebrand")
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
const totalWidth = getElementsTotalWidth(textElements) + gap;
|
|
234
|
+
|
|
235
|
+
if (totalWidth > buttonWidth) {
|
|
236
|
+
hideElement(paypalLogo);
|
|
237
|
+
showElement(ppLogo);
|
|
238
|
+
} else {
|
|
239
|
+
showElement(paypalLogo);
|
|
240
|
+
hideElement(ppLogo);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
202
245
|
const setDomReady = once(
|
|
203
246
|
debounce(() => {
|
|
204
|
-
window.addEventListener("resize",
|
|
205
|
-
|
|
247
|
+
window.addEventListener("resize", () => {
|
|
248
|
+
toggleOptionals();
|
|
249
|
+
toggleLogos();
|
|
250
|
+
});
|
|
251
|
+
setTimeout(() => {
|
|
252
|
+
toggleOptionals();
|
|
253
|
+
toggleLogos();
|
|
254
|
+
});
|
|
206
255
|
if (document.body) {
|
|
207
256
|
document.body.classList.add(CLASS.DOM_READY);
|
|
208
257
|
}
|
|
@@ -211,10 +260,12 @@ export function getComponentScript(): () => void {
|
|
|
211
260
|
|
|
212
261
|
const load = () => {
|
|
213
262
|
toggleOptionals();
|
|
263
|
+
toggleLogos();
|
|
214
264
|
setDomReady();
|
|
215
265
|
};
|
|
216
266
|
|
|
217
267
|
toggleOptionals();
|
|
268
|
+
toggleLogos();
|
|
218
269
|
document.addEventListener("DOMContentLoaded", load);
|
|
219
270
|
window.addEventListener("load", load);
|
|
220
271
|
window.addEventListener("resize", load);
|
|
@@ -5,7 +5,7 @@ import { LOGO_CLASS } from "@paypal/sdk-logos/src";
|
|
|
5
5
|
|
|
6
6
|
import { CLASS, ATTRIBUTE } from "../../../constants";
|
|
7
7
|
|
|
8
|
-
import { HIDDEN
|
|
8
|
+
import { HIDDEN } from "./labels";
|
|
9
9
|
|
|
10
10
|
const MIN_VAULT_BUTTON_WIDTH = 250;
|
|
11
11
|
|
|
@@ -210,29 +210,4 @@ export const buttonRebrandStyle = `
|
|
|
210
210
|
text-align: center;
|
|
211
211
|
width: auto;
|
|
212
212
|
}
|
|
213
|
-
|
|
214
|
-
/* Hide/show credit/paylater logos based on button width */
|
|
215
|
-
@media only screen and (min-width: 0px) and (max-width: 150px) {
|
|
216
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="credit"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_REBRAND},
|
|
217
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="paylater"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_REBRAND} {
|
|
218
|
-
${HIDDEN}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="credit"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_PP_REBRAND},
|
|
222
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="paylater"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_PP_REBRAND} {
|
|
223
|
-
${VISIBLE}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
@media only screen and (min-width: 150px) {
|
|
228
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="credit"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_REBRAND},
|
|
229
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="paylater"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_REBRAND} {
|
|
230
|
-
${VISIBLE}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="credit"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_PP_REBRAND},
|
|
234
|
-
[${ATTRIBUTE.FUNDING_SOURCE}="paylater"].${CLASS.BUTTON_REBRAND} .${CLASS.BUTTON_LABEL} .${CLASS.LOGO_PP_REBRAND} {
|
|
235
|
-
${HIDDEN}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
213
|
`;
|