@paypal/checkout-components 5.0.282 → 5.0.283

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.282",
3
+ "version": "5.0.283",
4
4
  "description": "PayPal Checkout components, for integrating checkout products.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -110,7 +110,7 @@
110
110
  "@paypal/common-components": "^1.0.35",
111
111
  "@paypal/funding-components": "^1.0.31",
112
112
  "@paypal/sdk-client": "^4.0.176",
113
- "@paypal/sdk-constants": "^1.0.128",
113
+ "@paypal/sdk-constants": "^1.0.133",
114
114
  "@paypal/sdk-logos": "^2.2.6"
115
115
  },
116
116
  "lint-staged": {
@@ -1,7 +1,15 @@
1
1
  /* @flow */
2
2
 
3
- import type { FundingEligibilityType } from "@paypal/sdk-client/src";
4
- import { PLATFORM, FUNDING, COMPONENTS } from "@paypal/sdk-constants/src";
3
+ import type {
4
+ FundingEligibilityType,
5
+ CardEligibility,
6
+ } from "@paypal/sdk-client/src";
7
+ import {
8
+ PLATFORM,
9
+ FUNDING,
10
+ COMPONENTS,
11
+ DISPLAY_ONLY_VALUES,
12
+ } from "@paypal/sdk-constants/src";
5
13
  import { SUPPORTED_FUNDING_SOURCES } from "@paypal/funding-components/src";
6
14
 
7
15
  import type { Wallet, Experiment } from "../types";
@@ -30,8 +38,36 @@ type IsFundingEligibleOptions = {|
30
38
  supportsPopups: boolean,
31
39
  supportedNativeBrowser: boolean,
32
40
  experiment?: Experiment,
41
+ displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
33
42
  |};
34
43
 
44
+ function isFundingVaultable({
45
+ fundingEligibility,
46
+ fundingSource,
47
+ }: {|
48
+ fundingEligibility: FundingEligibilityType,
49
+ fundingSource: $Values<typeof FUNDING>,
50
+ |}): boolean {
51
+ // fundingEligibility.card doesn't give vaultable property like other funding sources
52
+ if (
53
+ fundingSource === FUNDING.CARD &&
54
+ fundingEligibility[fundingSource]?.vendors
55
+ ) {
56
+ const { vendors } = (fundingEligibility[fundingSource]: CardEligibility);
57
+
58
+ // If any vendors are both eligible & vaultable, card is vaultable
59
+ return Object.keys(vendors).some(
60
+ (vendor) => vendors[vendor]?.eligible && vendors[vendor]?.vaultable
61
+ );
62
+ }
63
+
64
+ if (!fundingEligibility[fundingSource]?.vaultable) {
65
+ return false;
66
+ }
67
+
68
+ return true;
69
+ }
70
+
35
71
  export function isFundingEligible(
36
72
  source: $Values<typeof FUNDING>,
37
73
  {
@@ -50,6 +86,7 @@ export function isFundingEligible(
50
86
  supportsPopups,
51
87
  supportedNativeBrowser,
52
88
  experiment,
89
+ displayOnly,
53
90
  }: IsFundingEligibleOptions
54
91
  ): boolean {
55
92
  if (!fundingEligibility[source] || !fundingEligibility[source].eligible) {
@@ -70,6 +107,16 @@ export function isFundingEligible(
70
107
  return false;
71
108
  }
72
109
 
110
+ const shouldDisplayOnlyVaultableButtons =
111
+ displayOnly && displayOnly.includes("vaultable");
112
+
113
+ if (
114
+ shouldDisplayOnlyVaultableButtons &&
115
+ !isFundingVaultable({ fundingEligibility, fundingSource: source })
116
+ ) {
117
+ return false;
118
+ }
119
+
73
120
  if (
74
121
  fundingConfig.eligible &&
75
122
  !fundingConfig.eligible({
@@ -152,6 +199,7 @@ export function determineEligibleFunding({
152
199
  supportsPopups,
153
200
  supportedNativeBrowser,
154
201
  experiment,
202
+ displayOnly = [],
155
203
  }: {|
156
204
  fundingSource: ?$Values<typeof FUNDING>,
157
205
  remembered: $ReadOnlyArray<$Values<typeof FUNDING>>,
@@ -169,6 +217,7 @@ export function determineEligibleFunding({
169
217
  supportsPopups: boolean,
170
218
  supportedNativeBrowser: boolean,
171
219
  experiment: Experiment,
220
+ displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
172
221
  |}): $ReadOnlyArray<$Values<typeof FUNDING>> {
173
222
  if (fundingSource) {
174
223
  return [fundingSource];
@@ -191,6 +240,7 @@ export function determineEligibleFunding({
191
240
  supportsPopups,
192
241
  supportedNativeBrowser,
193
242
  experiment,
243
+ displayOnly,
194
244
  })
195
245
  );
196
246
 
@@ -0,0 +1,140 @@
1
+ /* @flow */
2
+ import { COMPONENTS, FUNDING } from "@paypal/sdk-constants/src";
3
+ import { describe, expect } from "vitest";
4
+
5
+ import { BUTTON_FLOW } from "../constants";
6
+
7
+ import { isFundingEligible } from "./funding";
8
+
9
+ const defaultMockFundingOptions = {
10
+ platform: "desktop",
11
+ components: [COMPONENTS.BUTTONS],
12
+ flow: BUTTON_FLOW.PURCHASE,
13
+ fundingSource: FUNDING.SEPA,
14
+ fundingEligibility: {
15
+ paylater: {
16
+ eligible: true,
17
+ vaultable: false,
18
+ },
19
+ venmo: {
20
+ eligible: true,
21
+ vaultable: true,
22
+ branded: false,
23
+ },
24
+ sepa: {
25
+ eligible: false,
26
+ branded: false,
27
+ },
28
+ oxxo: {
29
+ eligible: false,
30
+ vaultable: true,
31
+ branded: false,
32
+ },
33
+ card: {
34
+ eligible: true,
35
+ branded: false,
36
+ vendors: {
37
+ visa: {
38
+ eligible: true,
39
+ vaultable: false,
40
+ },
41
+ mastercard: {
42
+ eligible: true,
43
+ vaultable: false,
44
+ },
45
+ amex: {
46
+ eligible: true,
47
+ vaultable: false,
48
+ },
49
+ },
50
+ },
51
+ },
52
+ applePaySupport: false,
53
+ supportsPopups: true,
54
+ supportedNativeBrowser: true,
55
+ onShippingChange: null,
56
+ onShippingAddressChange: null,
57
+ onShippingOptionsChange: null,
58
+ };
59
+
60
+ describe("Funding eligibility", () => {
61
+ test("should not be eligible if funding source is missing from fundingEligibility", () => {
62
+ const fundingEligible = isFundingEligible(
63
+ FUNDING.WECHATPAY,
64
+ defaultMockFundingOptions
65
+ );
66
+
67
+ expect(fundingEligible).toBe(false);
68
+ });
69
+
70
+ test("should not be eligible if displayOnly includes 'vaultable' and vaultable is false", () => {
71
+ const options = {
72
+ ...defaultMockFundingOptions,
73
+ displayOnly: ["vaultable"],
74
+ fundingSource: FUNDING.PAYLATER,
75
+ };
76
+ const fundingEligible = isFundingEligible(FUNDING.PAYLATER, options);
77
+
78
+ expect(fundingEligible).toBe(false);
79
+ });
80
+
81
+ test("card should not be eligible if displayOnly includes 'vaultable' and no vendors are vaultable", () => {
82
+ const options = {
83
+ ...defaultMockFundingOptions,
84
+ displayOnly: ["vaultable"],
85
+ components: [COMPONENTS.BUTTONS],
86
+ fundingSource: FUNDING.CARD,
87
+ };
88
+ const fundingEligible = isFundingEligible(FUNDING.CARD, options);
89
+
90
+ expect(fundingEligible).toBe(false);
91
+ });
92
+
93
+ test("card should be eligible if displayOnly includes 'vaultable' and any vendor is vaultable", () => {
94
+ const options = {
95
+ ...defaultMockFundingOptions,
96
+ displayOnly: ["vaultable"],
97
+ fundingSource: FUNDING.CARD,
98
+ components: [COMPONENTS.BUTTONS],
99
+ platform: "desktop",
100
+ fundingEligibility: {
101
+ card: {
102
+ eligible: true,
103
+ branded: false,
104
+ vendors: {
105
+ visa: {
106
+ eligible: true,
107
+ vaultable: true,
108
+ },
109
+ mastercard: {
110
+ eligible: true,
111
+ vaultable: false,
112
+ },
113
+ },
114
+ },
115
+ },
116
+ };
117
+
118
+ const fundingEligible = isFundingEligible(FUNDING.CARD, options);
119
+
120
+ expect(fundingEligible).toBe(true);
121
+ });
122
+
123
+ test("should not be eligible if fundingSource.eligible is false", () => {
124
+ const fundingEligible = isFundingEligible(
125
+ FUNDING.SEPA,
126
+ defaultMockFundingOptions
127
+ );
128
+
129
+ expect(fundingEligible).toBe(false);
130
+ });
131
+
132
+ test("should not be eligible if fundingSource.eligible is false and fundingSource.vaultable is true", () => {
133
+ const fundingEligible = isFundingEligible(
134
+ FUNDING.OXXO,
135
+ defaultMockFundingOptions
136
+ );
137
+
138
+ expect(fundingEligible).toBe(false);
139
+ });
140
+ });
@@ -178,6 +178,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
178
178
  supportsPopups,
179
179
  supportedNativeBrowser,
180
180
  showPayLabel,
181
+ displayOnly,
181
182
  } = normalizeButtonProps(props);
182
183
  const { layout, shape, tagline } = style;
183
184
 
@@ -196,6 +197,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
196
197
  supportsPopups,
197
198
  supportedNativeBrowser,
198
199
  experiment,
200
+ displayOnly,
199
201
  });
200
202
  const multiple = fundingSources.length > 1;
201
203
 
@@ -24,6 +24,7 @@ import {
24
24
  type LocaleType,
25
25
  CARD,
26
26
  COMPONENTS,
27
+ DISPLAY_ONLY_VALUES,
27
28
  } from "@paypal/sdk-constants/src";
28
29
  import { type CrossDomainWindowType } from "@krakenjs/cross-domain-utils/src";
29
30
  import { LOGO_COLOR } from "@paypal/sdk-logos/src";
@@ -461,6 +462,7 @@ export type RenderButtonProps = {|
461
462
  supportsPopups: boolean,
462
463
  supportedNativeBrowser: boolean,
463
464
  showPayLabel: boolean,
465
+ displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
464
466
  |};
465
467
 
466
468
  export type PrerenderDetails = {|
@@ -518,6 +520,7 @@ export type ButtonProps = {|
518
520
  meta: {||},
519
521
  renderedButtons: $ReadOnlyArray<$Values<typeof FUNDING>>,
520
522
  createVaultSetupToken: CreateVaultSetupToken,
523
+ displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
521
524
  |};
522
525
 
523
526
  // eslint-disable-next-line flowtype/require-exact-type
@@ -559,6 +562,7 @@ export type ButtonPropsInputs = {
559
562
  supportsPopups: boolean,
560
563
  supportedNativeBrowser: boolean,
561
564
  showPayLabel: boolean,
565
+ displayOnly: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
562
566
  };
563
567
 
564
568
  export const DEFAULT_STYLE = {
@@ -744,6 +748,7 @@ export function normalizeButtonProps(
744
748
  supportsPopups = false,
745
749
  supportedNativeBrowser = false,
746
750
  showPayLabel = true,
751
+ displayOnly = [],
747
752
  } = props;
748
753
 
749
754
  const { country, lang } = locale;
@@ -794,6 +799,7 @@ export function normalizeButtonProps(
794
799
  applePaySupport,
795
800
  supportsPopups,
796
801
  supportedNativeBrowser,
802
+ displayOnly,
797
803
  })
798
804
  ) {
799
805
  throw new Error(`Funding Source not eligible: ${fundingSource}`);
@@ -833,5 +839,6 @@ export function normalizeButtonProps(
833
839
  supportsPopups,
834
840
  supportedNativeBrowser,
835
841
  showPayLabel,
842
+ displayOnly,
836
843
  };
837
844
  }
@@ -833,6 +833,15 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
833
833
  required: false,
834
834
  value: getExperimentation,
835
835
  },
836
+
837
+ displayOnly: {
838
+ type: "array",
839
+ queryParam: true,
840
+ required: false,
841
+ value: ({ props }) => {
842
+ return props?.displayOnly || [];
843
+ },
844
+ },
836
845
  },
837
846
  });
838
847
  });