@paypal/checkout-components 5.0.310 → 5.0.312

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paypal/checkout-components",
3
- "version": "5.0.310",
3
+ "version": "5.0.312",
4
4
  "description": "PayPal Checkout components, for integrating checkout products.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -119,6 +119,6 @@
119
119
  "@paypal/sdk-logos": "^2.2.6"
120
120
  },
121
121
  "lint-staged": {
122
- "**/{src,test,scripts}/**/*.{js,jsx,json,sh}": "prettier --write"
122
+ "**/*": "prettier --write --ignore-unknown"
123
123
  }
124
124
  }
@@ -55,6 +55,14 @@ const getHostedButtonDetailsResponse = {
55
55
  name: "button_type",
56
56
  value: "FIXED_PRICE",
57
57
  },
58
+ {
59
+ name: "tagline",
60
+ value: "true",
61
+ },
62
+ {
63
+ name: "height",
64
+ value: "40",
65
+ },
58
66
  ],
59
67
  },
60
68
  },
@@ -78,6 +86,7 @@ describe("HostedButtons", () => {
78
86
  expect(Buttons).toHaveBeenCalledWith(
79
87
  expect.objectContaining({
80
88
  hostedButtonId: "B1234567890",
89
+ style: expect.objectContaining({ tagline: true }),
81
90
  })
82
91
  );
83
92
  expect(Buttons).toHaveBeenCalledTimes(1);
@@ -150,5 +159,65 @@ describe("HostedButtons", () => {
150
159
  expect(renderMock).toHaveBeenCalledTimes(0);
151
160
  expect.assertions(3);
152
161
  });
162
+
163
+ test("tagline is rendered based on hosted button response", async () => {
164
+ const renderMock = vi.fn();
165
+
166
+ const Buttons = vi.fn(() => ({
167
+ render: renderMock,
168
+ isEligible: vi.fn(() => false),
169
+ }));
170
+ // $FlowIssue
171
+ getButtonsComponent.mockImplementationOnce(() => Buttons);
172
+ const HostedButtons = getHostedButtonsComponent();
173
+ // $FlowIssue
174
+ request.mockImplementationOnce(() =>
175
+ // eslint-disable-next-line compat/compat
176
+ Promise.resolve({
177
+ body: {
178
+ button_details: {
179
+ link_variables: [
180
+ {
181
+ name: "shape",
182
+ value: "rect",
183
+ },
184
+ {
185
+ name: "layout",
186
+ value: "vertical",
187
+ },
188
+ {
189
+ name: "color",
190
+ value: "gold",
191
+ },
192
+ {
193
+ name: "button_text",
194
+ value: "paypal",
195
+ },
196
+ {
197
+ name: "button_type",
198
+ value: "FIXED_PRICE",
199
+ },
200
+ {
201
+ name: "tagline",
202
+ value: "false",
203
+ },
204
+ ],
205
+ },
206
+ },
207
+ })
208
+ );
209
+ await HostedButtons({
210
+ hostedButtonId: "B1234567890",
211
+ }).render("#example");
212
+ expect(Buttons).toHaveBeenCalledWith(
213
+ expect.objectContaining({
214
+ hostedButtonId: "B1234567890",
215
+ style: expect.objectContaining({ tagline: false }),
216
+ })
217
+ );
218
+ expect(Buttons).toHaveBeenCalledTimes(1);
219
+ expect(renderMock).toHaveBeenCalledTimes(1);
220
+ expect.assertions(3);
221
+ });
153
222
  });
154
223
  /* eslint-enable no-restricted-globals, promise/no-native */
@@ -21,7 +21,7 @@ export interface BuildButtonContainerArgs {
21
21
 
22
22
  export type HostedButtonsComponentProps = {|
23
23
  hostedButtonId: string,
24
- fundingSources: $ReadOnlyArray<FundingSources>,
24
+ fundingSources?: $ReadOnlyArray<FundingSources>,
25
25
  |};
26
26
 
27
27
  export type GetCallbackProps = {|
@@ -34,6 +34,13 @@ export type HostedButtonsInstance = {|
34
34
  render: (string | HTMLElement) => Promise<void>,
35
35
  |};
36
36
 
37
+ export type EligibleHostedButtons = "paypal" | "venmo" | "paylater";
38
+
39
+ export type HostedButtonPreferences = {|
40
+ buttonPreferences: $ReadOnlyArray<EligibleHostedButtons & "default">,
41
+ eligibleFundingMethods: $ReadOnlyArray<EligibleHostedButtons>,
42
+ |};
43
+
37
44
  export type HostedButtonDetailsParams =
38
45
  (HostedButtonsComponentProps) => Promise<{|
39
46
  html: string,
@@ -43,7 +50,12 @@ export type HostedButtonDetailsParams =
43
50
  shape: string,
44
51
  color: string,
45
52
  label: string,
53
+ height: ?number,
54
+ tagline: boolean,
46
55
  |},
56
+ version: ?string,
57
+ buttonContainerId: ?string,
58
+ preferences?: HostedButtonPreferences,
47
59
  |}>;
48
60
 
49
61
  export type ButtonVariables = $ReadOnlyArray<{|
@@ -90,16 +90,27 @@ export const getHostedButtonDetails: HostedButtonDetailsParams = async ({
90
90
 
91
91
  // $FlowIssue request returns ZalgoPromise
92
92
  const { body } = response;
93
- const variables = body.button_details.link_variables;
93
+ const { link_variables: variables, preferences } = body.button_details;
94
+
94
95
  return {
95
96
  style: {
96
97
  layout: getButtonVariable(variables, "layout"),
97
98
  shape: getButtonVariable(variables, "shape"),
98
99
  color: getButtonVariable(variables, "color"),
99
100
  label: getButtonVariable(variables, "button_text"),
101
+ tagline: getButtonVariable(variables, "tagline") === "true",
102
+ height: parseInt(getButtonVariable(variables, "height"), 10) || undefined,
100
103
  },
104
+ version: body.version,
105
+ buttonContainerId: body.button_container_id,
101
106
  html: body.html,
102
107
  htmlScript: body.html_script,
108
+ ...(preferences && {
109
+ preferences: {
110
+ buttonPreferences: preferences.button_preferences,
111
+ eligibleFundingMethods: preferences.eligible_funding_methods,
112
+ },
113
+ }),
103
114
  };
104
115
  };
105
116
 
@@ -37,35 +37,6 @@ const merchantId = "M1234567890";
37
37
  const orderID = "EC-1234567890";
38
38
  const clientId = "C1234567890";
39
39
 
40
- const getHostedButtonDetailsResponse = {
41
- body: {
42
- button_details: {
43
- link_variables: [
44
- {
45
- name: "business",
46
- value: merchantId,
47
- },
48
- {
49
- name: "shape",
50
- value: "rect",
51
- },
52
- {
53
- name: "layout",
54
- value: "vertical",
55
- },
56
- {
57
- name: "color",
58
- value: "gold",
59
- },
60
- {
61
- name: "button_text",
62
- value: "paypal",
63
- },
64
- ],
65
- },
66
- },
67
- };
68
-
69
40
  const mockCreateAccessTokenRequest = () =>
70
41
  // eslint-disable-next-line compat/compat
71
42
  Promise.resolve({
@@ -74,24 +45,245 @@ const mockCreateAccessTokenRequest = () =>
74
45
  },
75
46
  });
76
47
 
77
- test("getHostedButtonDetails", async () => {
78
- // $FlowIssue
79
- request.mockImplementationOnce(() =>
80
- // eslint-disable-next-line compat/compat
81
- Promise.resolve(getHostedButtonDetailsResponse)
82
- );
83
- await getHostedButtonDetails({
84
- hostedButtonId,
85
- fundingSources: [],
86
- }).then(({ style }) => {
87
- expect(style).toEqual({
88
- layout: "vertical",
89
- shape: "rect",
90
- color: "gold",
91
- label: "paypal",
48
+ describe("getHostedButtonDetails", () => {
49
+ const getHostedButtonDetailsResponse = {
50
+ v1: {
51
+ body: {
52
+ button_details: {
53
+ link_variables: [
54
+ {
55
+ name: "business",
56
+ value: merchantId,
57
+ },
58
+ {
59
+ name: "shape",
60
+ value: "rect",
61
+ },
62
+ {
63
+ name: "layout",
64
+ value: "vertical",
65
+ },
66
+ {
67
+ name: "color",
68
+ value: "gold",
69
+ },
70
+ {
71
+ name: "button_text",
72
+ value: "paypal",
73
+ },
74
+ {
75
+ name: "tagline",
76
+ value: "true",
77
+ },
78
+ ],
79
+ },
80
+ },
81
+ },
82
+
83
+ v2: {
84
+ body: {
85
+ button_details: {
86
+ link_variables: [
87
+ {
88
+ name: "height",
89
+ value: "50",
90
+ },
91
+ {
92
+ name: "tagline",
93
+ value: "true",
94
+ },
95
+ ],
96
+ preferences: {
97
+ button_preferences: ["paypal", "paylater"],
98
+ eligible_funding_methods: ["paypal", "venmo", "paylater"],
99
+ },
100
+ },
101
+ version: "2",
102
+ },
103
+ },
104
+ };
105
+
106
+ test("version 1", async () => {
107
+ // $FlowIssue
108
+ request.mockImplementationOnce(() =>
109
+ // eslint-disable-next-line compat/compat
110
+ Promise.resolve(getHostedButtonDetailsResponse.v1)
111
+ );
112
+ await getHostedButtonDetails({
113
+ hostedButtonId,
114
+ fundingSources: [],
115
+ }).then(({ style }) => {
116
+ expect(style).toEqual({
117
+ layout: "vertical",
118
+ shape: "rect",
119
+ color: "gold",
120
+ label: "paypal",
121
+ tagline: true,
122
+ });
92
123
  });
124
+ expect.assertions(1);
125
+ });
126
+
127
+ test("version 2", async () => {
128
+ // $FlowIssue
129
+ request.mockImplementationOnce(() =>
130
+ // eslint-disable-next-line compat/compat
131
+ Promise.resolve(getHostedButtonDetailsResponse.v2)
132
+ );
133
+ await getHostedButtonDetails({
134
+ hostedButtonId,
135
+ fundingSources: [],
136
+ }).then(({ style, preferences, version }) => {
137
+ expect(style.height).toEqual(50);
138
+ expect(style.tagline).toEqual(true);
139
+ expect(preferences).toEqual({
140
+ buttonPreferences: ["paypal", "paylater"],
141
+ eligibleFundingMethods: ["paypal", "venmo", "paylater"],
142
+ });
143
+ expect(version).toEqual("2");
144
+ });
145
+ expect.assertions(4);
146
+ });
147
+
148
+ test("handles false tagline values", async () => {
149
+ // $FlowIssue
150
+ request.mockImplementationOnce(() =>
151
+ // eslint-disable-next-line compat/compat
152
+ Promise.resolve({
153
+ body: {
154
+ button_details: {
155
+ link_variables: [
156
+ {
157
+ name: "business",
158
+ value: merchantId,
159
+ },
160
+ {
161
+ name: "layout",
162
+ value: "horizontal",
163
+ },
164
+ {
165
+ name: "tagline",
166
+ value: "false",
167
+ },
168
+ ],
169
+ },
170
+ },
171
+ })
172
+ );
173
+ await getHostedButtonDetails({
174
+ hostedButtonId,
175
+ }).then(({ style }) => {
176
+ expect(style).toEqual(
177
+ expect.objectContaining({
178
+ tagline: false,
179
+ })
180
+ );
181
+ });
182
+
183
+ // $FlowIssue
184
+ request.mockImplementationOnce(() =>
185
+ // eslint-disable-next-line compat/compat
186
+ Promise.resolve({
187
+ body: {
188
+ button_details: {
189
+ link_variables: [
190
+ {
191
+ name: "height",
192
+ value: 50,
193
+ },
194
+ {
195
+ name: "tagline",
196
+ value: "false",
197
+ },
198
+ ],
199
+ preferences: {
200
+ button_preferences: ["paypal", "paylater"],
201
+ eligible_funding_methods: ["paypal", "venmo", "paylater"],
202
+ },
203
+ },
204
+ version: "2",
205
+ },
206
+ })
207
+ );
208
+ await getHostedButtonDetails({
209
+ hostedButtonId,
210
+ }).then(({ style, preferences, version }) => {
211
+ expect(style.height).toEqual(50);
212
+ expect(style.tagline).toEqual(false);
213
+ expect(preferences).toEqual({
214
+ buttonPreferences: ["paypal", "paylater"],
215
+ eligibleFundingMethods: ["paypal", "venmo", "paylater"],
216
+ });
217
+ expect(version).toEqual("2");
218
+ });
219
+ expect.assertions(5);
220
+ });
221
+
222
+ test("handles undefined tagline values", async () => {
223
+ // $FlowIssue
224
+ request.mockImplementationOnce(() =>
225
+ // eslint-disable-next-line compat/compat
226
+ Promise.resolve({
227
+ body: {
228
+ button_details: {
229
+ link_variables: [
230
+ {
231
+ name: "business",
232
+ value: merchantId,
233
+ },
234
+ {
235
+ name: "layout",
236
+ value: "horizontal",
237
+ },
238
+ ],
239
+ },
240
+ },
241
+ })
242
+ );
243
+ await getHostedButtonDetails({
244
+ hostedButtonId,
245
+ }).then(({ style }) => {
246
+ expect(style).toEqual(
247
+ expect.objectContaining({
248
+ tagline: false,
249
+ })
250
+ );
251
+ });
252
+
253
+ // $FlowIssue
254
+ request.mockImplementationOnce(() =>
255
+ // eslint-disable-next-line compat/compat
256
+ Promise.resolve({
257
+ body: {
258
+ button_details: {
259
+ link_variables: [
260
+ {
261
+ name: "height",
262
+ value: 50,
263
+ },
264
+ ],
265
+ preferences: {
266
+ button_preferences: ["paypal", "paylater"],
267
+ eligible_funding_methods: ["paypal", "venmo", "paylater"],
268
+ },
269
+ },
270
+ version: "2",
271
+ },
272
+ })
273
+ );
274
+ await getHostedButtonDetails({
275
+ hostedButtonId,
276
+ }).then(({ style, preferences, version }) => {
277
+ expect(style.height).toEqual(50);
278
+ expect(style.tagline).toEqual(false);
279
+ expect(preferences).toEqual({
280
+ buttonPreferences: ["paypal", "paylater"],
281
+ eligibleFundingMethods: ["paypal", "venmo", "paylater"],
282
+ });
283
+ expect(version).toEqual("2");
284
+ });
285
+ expect.assertions(5);
93
286
  });
94
- expect.assertions(1);
95
287
  });
96
288
 
97
289
  describe("createAccessToken", () => {
@@ -54,6 +54,7 @@ type IndividualButtonProps = {|
54
54
  i: number,
55
55
  nonce: string,
56
56
  userIDToken: ?string,
57
+ customerId: ?string,
57
58
  personalization: ?Personalization,
58
59
  content: ?ContentType,
59
60
  tagline: ?boolean,
@@ -78,6 +79,7 @@ export function Button({
78
79
  flow,
79
80
  vault,
80
81
  userIDToken,
82
+ customerId,
81
83
  personalization,
82
84
  onClick = noop,
83
85
  content,
@@ -206,7 +208,7 @@ export function Button({
206
208
  flow === BUTTON_FLOW.VAULT_WITHOUT_PURCHASE) &&
207
209
  (instrument ||
208
210
  (__WEB__ &&
209
- userIDToken &&
211
+ (userIDToken || customerId) &&
210
212
  (fundingSource === FUNDING.PAYPAL || fundingSource === FUNDING.VENMO)))
211
213
  ) {
212
214
  labelNode = (
@@ -172,6 +172,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
172
172
  onShippingOptionsChange,
173
173
  personalization,
174
174
  userIDToken,
175
+ customerId,
175
176
  content,
176
177
  flow,
177
178
  experiment,
@@ -291,6 +292,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
291
292
  onShippingOptionsChange={onShippingOptionsChange}
292
293
  onClick={onClick}
293
294
  userIDToken={userIDToken}
295
+ customerId={customerId}
294
296
  personalization={personalization}
295
297
  tagline={tagline}
296
298
  commit={commit}
@@ -467,6 +467,7 @@ export type RenderButtonProps = {|
467
467
  onShippingOptionsChange: ?OnShippingOptionsChange,
468
468
  personalization: ?Personalization,
469
469
  clientAccessToken: ?string,
470
+ customerId: ?string,
470
471
  content?: ContentType,
471
472
  flow: $Values<typeof BUTTON_FLOW>,
472
473
  experiment: Experiment,
@@ -521,6 +522,7 @@ export type ButtonProps = {|
521
522
  onShippingAddressChange: ?OnShippingAddressChange,
522
523
  onShippingOptionsChange: ?OnShippingOptionsChange,
523
524
  clientAccessToken?: ?string,
525
+ customerId?: ?string,
524
526
  nonce: string,
525
527
  merchantID?: $ReadOnlyArray<string>,
526
528
  merchantRequestedPopupsDisabled: ?boolean,
@@ -568,6 +570,7 @@ export type ButtonPropsInputs = {
568
570
  onShippingOptionsChange: ?Function,
569
571
  personalization?: Personalization,
570
572
  clientAccessToken?: ?string,
573
+ customerId?: ?string,
571
574
  wallet?: ?Wallet,
572
575
  csp: {|
573
576
  nonce: string,
@@ -842,6 +845,7 @@ export function normalizeButtonProps(
842
845
  onShippingOptionsChange,
843
846
  personalization,
844
847
  clientAccessToken,
848
+ customerId,
845
849
  content,
846
850
  wallet,
847
851
  flow = BUTTON_FLOW.PURCHASE,
@@ -947,6 +951,7 @@ export function normalizeButtonProps(
947
951
  experiment,
948
952
  vault,
949
953
  userIDToken,
954
+ customerId,
950
955
  applePay,
951
956
  applePaySupport,
952
957
  supportsPopups,
@@ -19,6 +19,7 @@ import {
19
19
  getCSPNonce,
20
20
  getBuyerCountry,
21
21
  getClientAccessToken,
22
+ getCustomerId,
22
23
  getPlatform,
23
24
  getPartnerAttributionID,
24
25
  getCorrelationID,
@@ -336,6 +337,13 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
336
337
  value: getClientAccessToken,
337
338
  },
338
339
 
340
+ customerId: {
341
+ type: "string",
342
+ required: false,
343
+ queryParam: true,
344
+ value: getCustomerId,
345
+ },
346
+
339
347
  clientID: {
340
348
  type: "string",
341
349
  value: getClientID,