@paypal/checkout-components 5.0.386 → 5.0.388
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/hosted-buttons/types.js +1 -0
- package/src/hosted-buttons/utils.js +20 -4
- package/src/hosted-buttons/utils.test.js +88 -8
- 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 -28
- package/src/ui/buttons/styles/responsive.js +104 -24
- package/src/zoid/buttons/component.jsx +46 -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
|
});
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
buildDPoPHeaders,
|
|
7
7
|
getSDKHost,
|
|
8
8
|
getClientID,
|
|
9
|
+
getFirstRenderExperiments,
|
|
9
10
|
getLocale,
|
|
10
11
|
getMerchantID as getSDKMerchantID,
|
|
11
12
|
} from "@paypal/sdk-client/src";
|
|
@@ -14,6 +15,7 @@ import { SUPPORTED_FUNDING_SOURCES } from "@paypal/funding-components/src";
|
|
|
14
15
|
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
|
|
15
16
|
|
|
16
17
|
import { getButtonsComponent, type ButtonsComponent } from "../zoid/buttons";
|
|
18
|
+
import type { Experiment as EligibilityExperiment } from "../types";
|
|
17
19
|
|
|
18
20
|
import type {
|
|
19
21
|
ButtonVariables,
|
|
@@ -155,6 +157,12 @@ export const getButtonPreferences = ({
|
|
|
155
157
|
};
|
|
156
158
|
};
|
|
157
159
|
|
|
160
|
+
function getButtonExperiments(): EligibilityExperiment {
|
|
161
|
+
return {
|
|
162
|
+
...getFirstRenderExperiments(),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
158
166
|
const getButtonVariable = (variables: ButtonVariables, key: string): string =>
|
|
159
167
|
variables?.find((variable) => variable.name === key)?.value ?? "";
|
|
160
168
|
|
|
@@ -185,6 +193,8 @@ export const getHostedButtonDetails: HostedButtonDetailsParams = async ({
|
|
|
185
193
|
getButtonVariable(variables, "tax_rate_preference") ===
|
|
186
194
|
"tax_rate_from_profile";
|
|
187
195
|
|
|
196
|
+
const { isPaypalRebrandEnabled } = getButtonExperiments();
|
|
197
|
+
|
|
188
198
|
return {
|
|
189
199
|
style: {
|
|
190
200
|
layout: getButtonVariable(variables, "layout"),
|
|
@@ -193,6 +203,7 @@ export const getHostedButtonDetails: HostedButtonDetailsParams = async ({
|
|
|
193
203
|
label: getButtonVariable(variables, "button_text"),
|
|
194
204
|
tagline: getButtonVariable(variables, "tagline") === "true",
|
|
195
205
|
height: parseInt(getButtonVariable(variables, "height"), 10) || undefined,
|
|
206
|
+
shouldApplyRebrandedStyles: isPaypalRebrandEnabled,
|
|
196
207
|
},
|
|
197
208
|
enableDPoP: getButtonVariable(variables, "enable_dpop") === "true",
|
|
198
209
|
shouldIncludeShippingCallbacks: shippingFromProfile || taxRateFromProfile,
|
|
@@ -445,7 +456,8 @@ export const getFlexDirection = ({
|
|
|
445
456
|
|
|
446
457
|
export const getButtonColor = (
|
|
447
458
|
color: Color,
|
|
448
|
-
fundingSource: FundingSources
|
|
459
|
+
fundingSource: FundingSources,
|
|
460
|
+
shouldApplyRebrandedStyles?: boolean
|
|
449
461
|
): Color => {
|
|
450
462
|
const colorMap = {
|
|
451
463
|
gold: {
|
|
@@ -455,7 +467,7 @@ export const getButtonColor = (
|
|
|
455
467
|
},
|
|
456
468
|
blue: {
|
|
457
469
|
paypal: "blue",
|
|
458
|
-
venmo: "silver",
|
|
470
|
+
venmo: shouldApplyRebrandedStyles ? "blue" : "silver",
|
|
459
471
|
paylater: "blue",
|
|
460
472
|
},
|
|
461
473
|
black: {
|
|
@@ -470,7 +482,7 @@ export const getButtonColor = (
|
|
|
470
482
|
},
|
|
471
483
|
silver: {
|
|
472
484
|
paypal: "silver",
|
|
473
|
-
venmo: "blue",
|
|
485
|
+
venmo: shouldApplyRebrandedStyles ? "silver" : "blue",
|
|
474
486
|
paylater: "silver",
|
|
475
487
|
},
|
|
476
488
|
};
|
|
@@ -525,7 +537,11 @@ export const getButtons = ({
|
|
|
525
537
|
style: {
|
|
526
538
|
...style,
|
|
527
539
|
// $FlowFixMe
|
|
528
|
-
color: getButtonColor(
|
|
540
|
+
color: getButtonColor(
|
|
541
|
+
style.color,
|
|
542
|
+
fundingSource,
|
|
543
|
+
style.shouldApplyRebrandedStyles
|
|
544
|
+
),
|
|
529
545
|
},
|
|
530
546
|
});
|
|
531
547
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable no-restricted-globals, promise/no-native, max-lines */
|
|
3
3
|
import { test, expect, vi } from "vitest";
|
|
4
4
|
import { request } from "@krakenjs/belter/src";
|
|
5
|
-
import { getLogger } from "@paypal/sdk-client/src";
|
|
5
|
+
import { getFirstRenderExperiments, getLogger } from "@paypal/sdk-client/src";
|
|
6
6
|
|
|
7
7
|
import { getButtonsComponent } from "../zoid/buttons";
|
|
8
8
|
|
|
@@ -38,6 +38,9 @@ vi.mock("@paypal/sdk-client/src", async () => {
|
|
|
38
38
|
getClientID: () => "client_id_123",
|
|
39
39
|
getMerchantID: () => ["merchant_id_123"],
|
|
40
40
|
getLocale: () => ({ lang: "en", country: "US" }),
|
|
41
|
+
getFirstRenderExperiments: vi.fn(() => ({
|
|
42
|
+
isPaypalRebrandEnabled: false,
|
|
43
|
+
})),
|
|
41
44
|
getLogger: vi.fn(() => ({
|
|
42
45
|
error: vi.fn(),
|
|
43
46
|
track: vi.fn().mockImplementation(() => ({
|
|
@@ -149,6 +152,7 @@ describe("getHostedButtonDetails", () => {
|
|
|
149
152
|
color: "gold",
|
|
150
153
|
label: "paypal",
|
|
151
154
|
tagline: true,
|
|
155
|
+
shouldApplyRebrandedStyles: false,
|
|
152
156
|
});
|
|
153
157
|
});
|
|
154
158
|
expect.assertions(1);
|
|
@@ -176,6 +180,42 @@ describe("getHostedButtonDetails", () => {
|
|
|
176
180
|
expect.assertions(5);
|
|
177
181
|
});
|
|
178
182
|
|
|
183
|
+
describe("Returns appropriate rebrand styles flag", () => {
|
|
184
|
+
test("should handle when rebrand experiment returns false", async () => {
|
|
185
|
+
// $FlowIssue
|
|
186
|
+
request.mockImplementationOnce(() =>
|
|
187
|
+
// eslint-disable-next-line compat/compat
|
|
188
|
+
Promise.resolve(getHostedButtonDetailsResponse.v2)
|
|
189
|
+
);
|
|
190
|
+
await getHostedButtonDetails({
|
|
191
|
+
hostedButtonId,
|
|
192
|
+
fundingSources: [],
|
|
193
|
+
}).then(({ style }) => {
|
|
194
|
+
expect(style.shouldApplyRebrandedStyles).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
expect.assertions(1);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("should handle when rebrand experiment returns true", async () => {
|
|
200
|
+
vi.mocked(getFirstRenderExperiments).mockReturnValueOnce({
|
|
201
|
+
isPaypalRebrandEnabled: true,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// $FlowIssue
|
|
205
|
+
request.mockImplementationOnce(() =>
|
|
206
|
+
// eslint-disable-next-line compat/compat
|
|
207
|
+
Promise.resolve(getHostedButtonDetailsResponse.v2)
|
|
208
|
+
);
|
|
209
|
+
await getHostedButtonDetails({
|
|
210
|
+
hostedButtonId,
|
|
211
|
+
fundingSources: [],
|
|
212
|
+
}).then(({ style }) => {
|
|
213
|
+
expect(style.shouldApplyRebrandedStyles).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
expect.assertions(1);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
179
219
|
test("handles false tagline values", async () => {
|
|
180
220
|
// $FlowIssue
|
|
181
221
|
request.mockImplementationOnce(() =>
|
|
@@ -778,10 +818,10 @@ test("getFlexDirection", () => {
|
|
|
778
818
|
});
|
|
779
819
|
});
|
|
780
820
|
|
|
781
|
-
|
|
821
|
+
describe("getButtonColor", () => {
|
|
782
822
|
const colors = ["gold", "blue", "silver", "white", "black"];
|
|
783
823
|
const fundingSources = ["paypal", "venmo", "paylater"];
|
|
784
|
-
const
|
|
824
|
+
const colorMapLegacy = {
|
|
785
825
|
gold: {
|
|
786
826
|
paypal: "gold",
|
|
787
827
|
venmo: "blue",
|
|
@@ -809,11 +849,51 @@ test("getButtonColor", () => {
|
|
|
809
849
|
},
|
|
810
850
|
};
|
|
811
851
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
852
|
+
const colorMapRebrand = {
|
|
853
|
+
gold: {
|
|
854
|
+
paypal: "gold",
|
|
855
|
+
venmo: "blue",
|
|
856
|
+
paylater: "gold",
|
|
857
|
+
},
|
|
858
|
+
blue: {
|
|
859
|
+
paypal: "blue",
|
|
860
|
+
venmo: "blue",
|
|
861
|
+
paylater: "blue",
|
|
862
|
+
},
|
|
863
|
+
black: {
|
|
864
|
+
paypal: "black",
|
|
865
|
+
venmo: "black",
|
|
866
|
+
paylater: "black",
|
|
867
|
+
},
|
|
868
|
+
white: {
|
|
869
|
+
paypal: "white",
|
|
870
|
+
venmo: "white",
|
|
871
|
+
paylater: "white",
|
|
872
|
+
},
|
|
873
|
+
silver: {
|
|
874
|
+
paypal: "silver",
|
|
875
|
+
venmo: "silver",
|
|
876
|
+
paylater: "silver",
|
|
877
|
+
},
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
test("legacy button colors", () => {
|
|
881
|
+
colors.forEach((color) => {
|
|
882
|
+
fundingSources.forEach((fundingSource) => {
|
|
883
|
+
expect(getButtonColor(color, fundingSource)).toBe(
|
|
884
|
+
colorMapLegacy[color][fundingSource]
|
|
885
|
+
);
|
|
886
|
+
});
|
|
887
|
+
});
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
test("rebrand button colors", () => {
|
|
891
|
+
colors.forEach((color) => {
|
|
892
|
+
fundingSources.forEach((fundingSource) => {
|
|
893
|
+
expect(getButtonColor(color, fundingSource, true)).toBe(
|
|
894
|
+
colorMapRebrand[color][fundingSource]
|
|
895
|
+
);
|
|
896
|
+
});
|
|
817
897
|
});
|
|
818
898
|
});
|
|
819
899
|
});
|
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
|
|