@paypal/checkout-components 5.0.295-alpha.2 → 5.0.295
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 -3
- package/src/api/shopper-insights/component.js +196 -0
- package/src/api/shopper-insights/component.test.js +343 -0
- package/src/api/shopper-insights/interface.js +5 -62
- package/src/api/shopper-insights/validation.js +74 -1
- package/src/api/shopper-insights/validation.test.js +42 -1
- package/src/api/shopper-insights/fingerprint.js +0 -52
- package/src/api/shopper-insights/shopperSession.js +0 -304
- package/src/api/shopper-insights/shopperSession.test.js +0 -320
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paypal/checkout-components",
|
|
3
|
-
"version": "5.0.295
|
|
3
|
+
"version": "5.0.295",
|
|
4
4
|
"description": "PayPal Checkout components, for integrating checkout products.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -102,7 +102,6 @@
|
|
|
102
102
|
"vitest": "^0.25.3"
|
|
103
103
|
},
|
|
104
104
|
"dependencies": {
|
|
105
|
-
"@fingerprintjs/fingerprintjs-pro": "^3.8.6",
|
|
106
105
|
"@krakenjs/belter": "^2.0.0",
|
|
107
106
|
"@krakenjs/cross-domain-utils": "^3.0.0",
|
|
108
107
|
"@krakenjs/jsx-pragmatic": "^3",
|
|
@@ -110,8 +109,8 @@
|
|
|
110
109
|
"@krakenjs/zalgo-promise": "^2.0.0",
|
|
111
110
|
"@krakenjs/zoid": "^10.3.1",
|
|
112
111
|
"@paypal/common-components": "^1.0.35",
|
|
113
|
-
"@paypal/connect-loader-component": "1.1.1",
|
|
114
112
|
"@paypal/funding-components": "^1.0.31",
|
|
113
|
+
"@paypal/connect-loader-component": "1.1.1",
|
|
115
114
|
"@paypal/sdk-client": "^4.0.179",
|
|
116
115
|
"@paypal/sdk-constants": "^1.0.133",
|
|
117
116
|
"@paypal/sdk-logos": "^2.2.6"
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getUserIDToken,
|
|
5
|
+
getPageType,
|
|
6
|
+
getClientToken,
|
|
7
|
+
getSDKToken,
|
|
8
|
+
getLogger,
|
|
9
|
+
getPayPalAPIDomain,
|
|
10
|
+
getCurrency,
|
|
11
|
+
getBuyerCountry,
|
|
12
|
+
getEnv,
|
|
13
|
+
getSessionState,
|
|
14
|
+
sendCountMetric,
|
|
15
|
+
} from "@paypal/sdk-client/src";
|
|
16
|
+
import { FPTI_KEY } from "@paypal/sdk-constants/src";
|
|
17
|
+
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
|
|
18
|
+
import { stringifyError } from "@krakenjs/belter/src";
|
|
19
|
+
|
|
20
|
+
import { callMemoizedRestAPI } from "../api";
|
|
21
|
+
import {
|
|
22
|
+
ELIGIBLE_PAYMENT_METHODS,
|
|
23
|
+
FPTI_TRANSITION,
|
|
24
|
+
SHOPPER_INSIGHTS_METRIC_NAME,
|
|
25
|
+
type MerchantPayloadData,
|
|
26
|
+
} from "../../constants/api";
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
validateMerchantConfig,
|
|
30
|
+
validateMerchantPayload,
|
|
31
|
+
hasEmail,
|
|
32
|
+
hasPhoneNumber,
|
|
33
|
+
} from "./validation";
|
|
34
|
+
|
|
35
|
+
type RecommendedPaymentMethods = {|
|
|
36
|
+
isPayPalRecommended: boolean,
|
|
37
|
+
isVenmoRecommended: boolean,
|
|
38
|
+
|};
|
|
39
|
+
|
|
40
|
+
type getRecommendedPaymentMethodsRequestPayload = {|
|
|
41
|
+
customer: {|
|
|
42
|
+
country_code?: string,
|
|
43
|
+
email?: string,
|
|
44
|
+
phone?: {|
|
|
45
|
+
country_code: string,
|
|
46
|
+
national_number: string,
|
|
47
|
+
|},
|
|
48
|
+
|},
|
|
49
|
+
purchase_units: $ReadOnlyArray<{|
|
|
50
|
+
amount: {|
|
|
51
|
+
currency_code: string,
|
|
52
|
+
|},
|
|
53
|
+
|}>,
|
|
54
|
+
preferences: {|
|
|
55
|
+
include_account_details: boolean,
|
|
56
|
+
|},
|
|
57
|
+
|};
|
|
58
|
+
|
|
59
|
+
export type ShopperInsightsComponent = {|
|
|
60
|
+
getRecommendedPaymentMethods: (MerchantPayloadData) => ZalgoPromise<RecommendedPaymentMethods>,
|
|
61
|
+
|};
|
|
62
|
+
|
|
63
|
+
function createRecommendedPaymentMethodsRequestPayload(
|
|
64
|
+
merchantPayload: MerchantPayloadData
|
|
65
|
+
): getRecommendedPaymentMethodsRequestPayload {
|
|
66
|
+
const isNonProdEnvironment = getEnv() !== "production";
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
customer: {
|
|
70
|
+
...(isNonProdEnvironment && {
|
|
71
|
+
country_code: getBuyerCountry() || "US",
|
|
72
|
+
}),
|
|
73
|
+
// $FlowIssue
|
|
74
|
+
...(hasEmail(merchantPayload) && {
|
|
75
|
+
email: merchantPayload?.email,
|
|
76
|
+
}),
|
|
77
|
+
...(hasPhoneNumber(merchantPayload) && {
|
|
78
|
+
phone: {
|
|
79
|
+
country_code: merchantPayload?.phone?.countryCode,
|
|
80
|
+
national_number: merchantPayload?.phone?.nationalNumber,
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
},
|
|
84
|
+
purchase_units: [
|
|
85
|
+
{
|
|
86
|
+
amount: {
|
|
87
|
+
currency_code: getCurrency(),
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
// getRecommendedPaymentMethods maps to include_account_details in the API
|
|
92
|
+
preferences: {
|
|
93
|
+
include_account_details: true,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function setShopperInsightsUsage() {
|
|
99
|
+
getSessionState((state) => {
|
|
100
|
+
return {
|
|
101
|
+
...state,
|
|
102
|
+
shopperInsights: {
|
|
103
|
+
getRecommendedPaymentMethodsUsed: true,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function getShopperInsightsComponent(): ShopperInsightsComponent {
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
|
|
112
|
+
sendCountMetric({
|
|
113
|
+
name: SHOPPER_INSIGHTS_METRIC_NAME,
|
|
114
|
+
event: "init",
|
|
115
|
+
dimensions: {},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const sdkToken = getSDKToken();
|
|
119
|
+
const pageType = getPageType();
|
|
120
|
+
const clientToken = getClientToken();
|
|
121
|
+
const userIDToken = getUserIDToken();
|
|
122
|
+
|
|
123
|
+
getLogger().track({
|
|
124
|
+
[FPTI_KEY.TRANSITION]: FPTI_TRANSITION.SHOPPER_INSIGHTS_API_INIT,
|
|
125
|
+
[FPTI_KEY.EVENT_NAME]: FPTI_TRANSITION.SHOPPER_INSIGHTS_API_INIT,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const shopperInsights = {
|
|
129
|
+
getRecommendedPaymentMethods: (merchantPayload) => {
|
|
130
|
+
validateMerchantConfig({ sdkToken, pageType, userIDToken, clientToken });
|
|
131
|
+
validateMerchantPayload(merchantPayload);
|
|
132
|
+
|
|
133
|
+
const requestPayload =
|
|
134
|
+
createRecommendedPaymentMethodsRequestPayload(merchantPayload);
|
|
135
|
+
|
|
136
|
+
return callMemoizedRestAPI({
|
|
137
|
+
method: "POST",
|
|
138
|
+
url: `${getPayPalAPIDomain()}/${ELIGIBLE_PAYMENT_METHODS}`,
|
|
139
|
+
data: requestPayload,
|
|
140
|
+
accessToken: sdkToken,
|
|
141
|
+
})
|
|
142
|
+
.then((body) => {
|
|
143
|
+
setShopperInsightsUsage();
|
|
144
|
+
|
|
145
|
+
const paypal = body?.eligible_methods?.paypal;
|
|
146
|
+
const venmo = body?.eligible_methods?.venmo;
|
|
147
|
+
|
|
148
|
+
const isPayPalRecommended =
|
|
149
|
+
(paypal?.eligible_in_paypal_network && paypal?.recommended) ||
|
|
150
|
+
false;
|
|
151
|
+
const isVenmoRecommended =
|
|
152
|
+
(venmo?.eligible_in_paypal_network && venmo?.recommended) || false;
|
|
153
|
+
|
|
154
|
+
getLogger().track({
|
|
155
|
+
[FPTI_KEY.TRANSITION]: FPTI_TRANSITION.SHOPPER_INSIGHTS_API_SUCCESS,
|
|
156
|
+
[FPTI_KEY.EVENT_NAME]: FPTI_TRANSITION.SHOPPER_INSIGHTS_API_SUCCESS,
|
|
157
|
+
[FPTI_KEY.RESPONSE_DURATION]: (Date.now() - startTime).toString(),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
sendCountMetric({
|
|
161
|
+
name: SHOPPER_INSIGHTS_METRIC_NAME,
|
|
162
|
+
event: "success",
|
|
163
|
+
dimensions: {
|
|
164
|
+
isPayPalRecommended: String(isPayPalRecommended),
|
|
165
|
+
isVenmoRecommended: String(isVenmoRecommended),
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return { isPayPalRecommended, isVenmoRecommended };
|
|
170
|
+
})
|
|
171
|
+
.catch((err) => {
|
|
172
|
+
sendCountMetric({
|
|
173
|
+
name: SHOPPER_INSIGHTS_METRIC_NAME,
|
|
174
|
+
event: "error",
|
|
175
|
+
dimensions: {
|
|
176
|
+
errorType: "api_error",
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
getLogger().track({
|
|
181
|
+
[FPTI_KEY.TRANSITION]: FPTI_TRANSITION.SHOPPER_INSIGHTS_API_ERROR,
|
|
182
|
+
[FPTI_KEY.EVENT_NAME]: FPTI_TRANSITION.SHOPPER_INSIGHTS_API_ERROR,
|
|
183
|
+
[FPTI_KEY.RESPONSE_DURATION]: (Date.now() - startTime).toString(),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
getLogger().error("shopper_insights_api_error", {
|
|
187
|
+
err: stringifyError(err),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
throw err;
|
|
191
|
+
});
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
return shopperInsights;
|
|
196
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
|
|
3
|
+
import { getEnv, getBuyerCountry, getSDKToken } from "@paypal/sdk-client/src";
|
|
4
|
+
import { vi, describe, expect } from "vitest";
|
|
5
|
+
import { request } from "@krakenjs/belter/src";
|
|
6
|
+
|
|
7
|
+
import { ValidationError } from "../../lib";
|
|
8
|
+
|
|
9
|
+
import { getShopperInsightsComponent } from "./component";
|
|
10
|
+
|
|
11
|
+
vi.mock("@paypal/sdk-client/src", () => {
|
|
12
|
+
return {
|
|
13
|
+
sendCountMetric: vi.fn(),
|
|
14
|
+
getSDKToken: vi.fn(() => "sdk-token"),
|
|
15
|
+
getPageType: vi.fn(() => "product-details"),
|
|
16
|
+
getClientToken: vi.fn(() => ""),
|
|
17
|
+
getUserIDToken: vi.fn(() => ""),
|
|
18
|
+
getEnv: vi.fn(() => "production"),
|
|
19
|
+
getCurrency: vi.fn(() => "USD"),
|
|
20
|
+
getBuyerCountry: vi.fn(() => "US"),
|
|
21
|
+
getPayPalAPIDomain: vi.fn(() => "https://api.paypal.com"),
|
|
22
|
+
getPartnerAttributionID: vi.fn(() => ""),
|
|
23
|
+
getSessionID: vi.fn(() => "sdk-session-ID-123"),
|
|
24
|
+
getSessionState: vi.fn(),
|
|
25
|
+
getLogger: vi.fn(() => ({ track: vi.fn(), error: vi.fn() })),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
vi.mock("@krakenjs/belter/src", async () => {
|
|
30
|
+
const actual = await vi.importActual("@krakenjs/belter/src");
|
|
31
|
+
return {
|
|
32
|
+
...actual,
|
|
33
|
+
request: vi.fn(() =>
|
|
34
|
+
ZalgoPromise.resolve({
|
|
35
|
+
status: 200,
|
|
36
|
+
headers: {},
|
|
37
|
+
body: {
|
|
38
|
+
eligible_methods: {
|
|
39
|
+
paypal: {
|
|
40
|
+
can_be_vaulted: false,
|
|
41
|
+
eligible_in_paypal_network: true,
|
|
42
|
+
recommended: true,
|
|
43
|
+
recommended_priority: 1,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
),
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("shopper insights component - getRecommendedPaymentMethods()", () => {
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
vi.clearAllMocks();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("should get recommended payment methods using the shopper insights API", async () => {
|
|
58
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
59
|
+
const recommendedPaymentMethods =
|
|
60
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
61
|
+
email: "email@test.com",
|
|
62
|
+
phone: {
|
|
63
|
+
countryCode: "1",
|
|
64
|
+
nationalNumber: "2345678901",
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(request).toHaveBeenCalled();
|
|
69
|
+
expect(recommendedPaymentMethods).toEqual({
|
|
70
|
+
isPayPalRecommended: true,
|
|
71
|
+
isVenmoRecommended: false,
|
|
72
|
+
});
|
|
73
|
+
expect.assertions(2);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("should get recommended payment methods from memoized request for the exact same payload", async () => {
|
|
77
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
78
|
+
const payload = {
|
|
79
|
+
email: "email-1.0@test.com",
|
|
80
|
+
phone: {
|
|
81
|
+
countryCode: "1",
|
|
82
|
+
nationalNumber: "2345678901",
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
const response1 =
|
|
86
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods(payload);
|
|
87
|
+
expect(request).toHaveBeenCalled();
|
|
88
|
+
expect(request).toHaveBeenCalledTimes(1);
|
|
89
|
+
const response2 =
|
|
90
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods(payload);
|
|
91
|
+
|
|
92
|
+
expect(request).toHaveBeenCalled();
|
|
93
|
+
// This should not change as the payload is same
|
|
94
|
+
expect(request).toHaveBeenCalledTimes(1);
|
|
95
|
+
expect(response1).toEqual({
|
|
96
|
+
isPayPalRecommended: true,
|
|
97
|
+
isVenmoRecommended: false,
|
|
98
|
+
});
|
|
99
|
+
expect(response2).toEqual({
|
|
100
|
+
isPayPalRecommended: true,
|
|
101
|
+
isVenmoRecommended: false,
|
|
102
|
+
});
|
|
103
|
+
expect.assertions(6);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("should not get recommended payment methods from memoized request for a different payload", async () => {
|
|
107
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
108
|
+
const response1 =
|
|
109
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
110
|
+
email: "email-1.1@test.com",
|
|
111
|
+
});
|
|
112
|
+
expect(request).toHaveBeenCalled();
|
|
113
|
+
expect(request).toHaveBeenCalledTimes(1);
|
|
114
|
+
const response2 =
|
|
115
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
116
|
+
email: "email-1.2@test.com",
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
expect(request).toHaveBeenCalled();
|
|
120
|
+
// This must change to 2 as the payload is different
|
|
121
|
+
expect(request).toHaveBeenCalledTimes(2);
|
|
122
|
+
expect(response1).toEqual({
|
|
123
|
+
isPayPalRecommended: true,
|
|
124
|
+
isVenmoRecommended: false,
|
|
125
|
+
});
|
|
126
|
+
expect(response2).toEqual({
|
|
127
|
+
isPayPalRecommended: true,
|
|
128
|
+
isVenmoRecommended: false,
|
|
129
|
+
});
|
|
130
|
+
expect.assertions(6);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("catch errors from the API", async () => {
|
|
134
|
+
// $FlowFixMe
|
|
135
|
+
request.mockImplementationOnce(() =>
|
|
136
|
+
ZalgoPromise.resolve({
|
|
137
|
+
status: 400,
|
|
138
|
+
headers: {},
|
|
139
|
+
body: {
|
|
140
|
+
name: "ERROR",
|
|
141
|
+
message: "This is an API error",
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
147
|
+
|
|
148
|
+
await expect(() =>
|
|
149
|
+
shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
150
|
+
email: "email@test.com",
|
|
151
|
+
phone: {
|
|
152
|
+
countryCode: "1",
|
|
153
|
+
nationalNumber: "2345678905",
|
|
154
|
+
},
|
|
155
|
+
})
|
|
156
|
+
).rejects.toThrow(
|
|
157
|
+
new Error(
|
|
158
|
+
`https://api.paypal.com/v2/payments/find-eligible-methods returned status 400\n\n{"name":"ERROR","message":"This is an API error"}`
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
expect(request).toHaveBeenCalled();
|
|
162
|
+
expect.assertions(2);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("create payload with email and phone number", async () => {
|
|
166
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
167
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
168
|
+
email: "email10@test.com",
|
|
169
|
+
phone: {
|
|
170
|
+
countryCode: "1",
|
|
171
|
+
nationalNumber: "2345678906",
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
expect(request).toHaveBeenCalledWith(
|
|
176
|
+
expect.objectContaining({
|
|
177
|
+
json: expect.objectContaining({
|
|
178
|
+
customer: expect.objectContaining({
|
|
179
|
+
email: "email10@test.com",
|
|
180
|
+
phone: expect.objectContaining({
|
|
181
|
+
country_code: "1",
|
|
182
|
+
national_number: "2345678906",
|
|
183
|
+
}),
|
|
184
|
+
}),
|
|
185
|
+
}),
|
|
186
|
+
})
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("create payload with email only", async () => {
|
|
191
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
192
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
193
|
+
email: "email2@test.com",
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect(request).toHaveBeenCalledWith(
|
|
197
|
+
expect.objectContaining({
|
|
198
|
+
json: expect.objectContaining({
|
|
199
|
+
customer: expect.objectContaining({
|
|
200
|
+
email: "email2@test.com",
|
|
201
|
+
}),
|
|
202
|
+
}),
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("create payload with phone only", async () => {
|
|
208
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
209
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
210
|
+
email: "email5@test.com",
|
|
211
|
+
phone: {
|
|
212
|
+
countryCode: "1",
|
|
213
|
+
nationalNumber: "2345678901",
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
expect(request).toHaveBeenCalledWith(
|
|
218
|
+
expect.objectContaining({
|
|
219
|
+
json: expect.objectContaining({
|
|
220
|
+
customer: expect.objectContaining({
|
|
221
|
+
phone: expect.objectContaining({
|
|
222
|
+
country_code: "1",
|
|
223
|
+
national_number: "2345678901",
|
|
224
|
+
}),
|
|
225
|
+
}),
|
|
226
|
+
}),
|
|
227
|
+
})
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("should default purchase units with currency code in the payload", async () => {
|
|
232
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
233
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
234
|
+
email: "email6@test.com",
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(request).toHaveBeenCalledWith(
|
|
238
|
+
expect.objectContaining({
|
|
239
|
+
json: expect.objectContaining({
|
|
240
|
+
purchase_units: expect.arrayContaining([
|
|
241
|
+
expect.objectContaining({
|
|
242
|
+
amount: expect.objectContaining({
|
|
243
|
+
currency_code: "USD",
|
|
244
|
+
}),
|
|
245
|
+
}),
|
|
246
|
+
]),
|
|
247
|
+
}),
|
|
248
|
+
})
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test("should use the SDK buyer-country parameter if country code is not passed in a non-prod env", async () => {
|
|
253
|
+
// $FlowFixMe
|
|
254
|
+
getEnv.mockImplementationOnce(() => "stage");
|
|
255
|
+
|
|
256
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
257
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
258
|
+
email: "email7@test.com",
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
expect(request).toHaveBeenCalledWith(
|
|
262
|
+
expect.objectContaining({
|
|
263
|
+
json: expect.objectContaining({
|
|
264
|
+
customer: expect.objectContaining({
|
|
265
|
+
country_code: "US",
|
|
266
|
+
}),
|
|
267
|
+
}),
|
|
268
|
+
})
|
|
269
|
+
);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("should default US country code if SDK buyer-country parameter not passed in a non-prod env", async () => {
|
|
273
|
+
// $FlowFixMe
|
|
274
|
+
getEnv.mockImplementationOnce(() => "stage");
|
|
275
|
+
// $FlowFixMe
|
|
276
|
+
getBuyerCountry.mockImplementationOnce(() => "");
|
|
277
|
+
|
|
278
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
279
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
280
|
+
email: "email9@test.com",
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
expect(request).toHaveBeenCalledWith(
|
|
284
|
+
expect.objectContaining({
|
|
285
|
+
json: expect.objectContaining({
|
|
286
|
+
customer: expect.objectContaining({
|
|
287
|
+
country_code: "US",
|
|
288
|
+
}),
|
|
289
|
+
}),
|
|
290
|
+
})
|
|
291
|
+
);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test("should not set country code in prod env in the payload", async () => {
|
|
295
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
296
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
297
|
+
email: "email@test.com",
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// $FlowIssue
|
|
301
|
+
expect(request.mock.calls[0][0].json.customer.country_code).toEqual(
|
|
302
|
+
undefined
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test("should request recommended payment methods by setting account details in the payload", async () => {
|
|
307
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
308
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
309
|
+
email: "email9@test.com",
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(request).toHaveBeenCalledWith(
|
|
313
|
+
expect.objectContaining({
|
|
314
|
+
json: expect.objectContaining({
|
|
315
|
+
preferences: expect.objectContaining({
|
|
316
|
+
include_account_details: true,
|
|
317
|
+
}),
|
|
318
|
+
}),
|
|
319
|
+
})
|
|
320
|
+
);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test("ensure sdk-token is passed when using the getRecommendedPaymentMethods", async () => {
|
|
324
|
+
// $FlowFixMe
|
|
325
|
+
getSDKToken.mockImplementationOnce(() => undefined);
|
|
326
|
+
// $FlowFixMe
|
|
327
|
+
const shopperInsightsComponent = getShopperInsightsComponent();
|
|
328
|
+
const error = new ValidationError(
|
|
329
|
+
`script data attribute sdk-client-token is required but was not passed`
|
|
330
|
+
);
|
|
331
|
+
await expect(
|
|
332
|
+
async () =>
|
|
333
|
+
await shopperInsightsComponent.getRecommendedPaymentMethods({
|
|
334
|
+
email: "email@test.com",
|
|
335
|
+
phone: {
|
|
336
|
+
countryCode: "1",
|
|
337
|
+
nationalNumber: "2345678905",
|
|
338
|
+
},
|
|
339
|
+
})
|
|
340
|
+
).rejects.toThrowError(error);
|
|
341
|
+
expect.assertions(1);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
@@ -1,69 +1,12 @@
|
|
|
1
1
|
/* @flow */
|
|
2
|
-
import {
|
|
3
|
-
getUserIDToken,
|
|
4
|
-
getPageType,
|
|
5
|
-
getClientToken,
|
|
6
|
-
getSDKToken,
|
|
7
|
-
getLogger,
|
|
8
|
-
getPayPalAPIDomain,
|
|
9
|
-
getCurrency,
|
|
10
|
-
getBuyerCountry,
|
|
11
|
-
getEnv,
|
|
12
|
-
getSessionState,
|
|
13
|
-
} from "@paypal/sdk-client/src";
|
|
14
2
|
|
|
15
3
|
import type { LazyExport } from "../../types";
|
|
16
|
-
import { callMemoizedRestAPI } from "../api";
|
|
17
4
|
|
|
18
|
-
import { fingerprint } from "./fingerprint";
|
|
19
5
|
import {
|
|
20
|
-
|
|
21
|
-
type
|
|
22
|
-
} from "./
|
|
23
|
-
|
|
24
|
-
const sessionState = {
|
|
25
|
-
get: (key) => {
|
|
26
|
-
let value;
|
|
27
|
-
getSessionState((state) => {
|
|
28
|
-
value = state[key];
|
|
29
|
-
return state;
|
|
30
|
-
});
|
|
31
|
-
return value;
|
|
32
|
-
},
|
|
33
|
-
set: (key, value) => {
|
|
34
|
-
getSessionState((state) => ({
|
|
35
|
-
...state,
|
|
36
|
-
[key]: value,
|
|
37
|
-
}));
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const ShopperInsights: LazyExport<ShopperInsightsInterface> = {
|
|
42
|
-
__get__: () => {
|
|
43
|
-
const shopperSession = new ShopperSession({
|
|
44
|
-
fingerprint,
|
|
45
|
-
logger: getLogger(),
|
|
46
|
-
// $FlowIssue ZalgoPromise vs Promise
|
|
47
|
-
request: callMemoizedRestAPI,
|
|
48
|
-
sdkConfig: {
|
|
49
|
-
sdkToken: getSDKToken(),
|
|
50
|
-
pageType: getPageType(),
|
|
51
|
-
userIDToken: getUserIDToken(),
|
|
52
|
-
clientToken: getClientToken(),
|
|
53
|
-
paypalApiDomain: getPayPalAPIDomain(),
|
|
54
|
-
environment: getEnv(),
|
|
55
|
-
buyerCountry: getBuyerCountry() || "US",
|
|
56
|
-
currency: getCurrency(),
|
|
57
|
-
},
|
|
58
|
-
sessionState,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
shopperSession.validateSdkConfig();
|
|
6
|
+
getShopperInsightsComponent,
|
|
7
|
+
type ShopperInsightsComponent,
|
|
8
|
+
} from "./component";
|
|
62
9
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
shopperSession.getRecommendedPaymentMethods(payload),
|
|
66
|
-
identify: () => shopperSession.identify(),
|
|
67
|
-
};
|
|
68
|
-
},
|
|
10
|
+
export const ShopperInsights: LazyExport<ShopperInsightsComponent> = {
|
|
11
|
+
__get__: () => getShopperInsightsComponent(),
|
|
69
12
|
};
|