Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support New displayOnly Confg Option #2252

Merged
merged 12 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
"@paypal/common-components": "^1.0.35",
"@paypal/funding-components": "^1.0.31",
"@paypal/sdk-client": "^4.0.176",
"@paypal/sdk-constants": "^1.0.128",
"@paypal/sdk-constants": "^1.0.133",
"@paypal/sdk-logos": "^2.2.6"
},
"lint-staged": {
Expand Down
54 changes: 52 additions & 2 deletions src/funding/funding.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
/* @flow */

import type { FundingEligibilityType } from "@paypal/sdk-client/src";
import { PLATFORM, FUNDING, COMPONENTS } from "@paypal/sdk-constants/src";
import type {
FundingEligibilityType,
CardEligibility,
} from "@paypal/sdk-client/src";
import {
PLATFORM,
FUNDING,
COMPONENTS,
DISPLAY_ONLY_VALUES,
} from "@paypal/sdk-constants/src";
import { SUPPORTED_FUNDING_SOURCES } from "@paypal/funding-components/src";

import type { Wallet, Experiment } from "../types";
Expand Down Expand Up @@ -30,8 +38,36 @@ type IsFundingEligibleOptions = {|
supportsPopups: boolean,
supportedNativeBrowser: boolean,
experiment?: Experiment,
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|};

function isFundingVaultable({
fundingEligibility,
fundingSource,
}: {|
fundingEligibility: FundingEligibilityType,
fundingSource: $Values<typeof FUNDING>,
|}): boolean {
// fundingEligibility.card doesn't give vaultable property like other funding sources
if (
fundingSource === FUNDING.CARD &&
fundingEligibility[fundingSource]?.vendors
) {
const { vendors } = (fundingEligibility[fundingSource]: CardEligibility);

// If any vendors are both eligible & vaultable, card is vaultable
return Object.keys(vendors).some(
(vendor) => vendors[vendor]?.eligible && vendors[vendor]?.vaultable
);
}

if (!fundingEligibility[fundingSource]?.vaultable) {
return false;
}

return true;
}

export function isFundingEligible(
source: $Values<typeof FUNDING>,
{
Expand All @@ -50,6 +86,7 @@ export function isFundingEligible(
supportsPopups,
supportedNativeBrowser,
experiment,
displayOnly,
}: IsFundingEligibleOptions
): boolean {
if (!fundingEligibility[source] || !fundingEligibility[source].eligible) {
Expand All @@ -70,6 +107,16 @@ export function isFundingEligible(
return false;
}

const shouldDisplayOnlyVaultableButtons =
displayOnly && displayOnly.includes("vaultable");

if (
shouldDisplayOnlyVaultableButtons &&
!isFundingVaultable({ fundingEligibility, fundingSource: source })
) {
return false;
}

if (
fundingConfig.eligible &&
!fundingConfig.eligible({
Expand Down Expand Up @@ -152,6 +199,7 @@ export function determineEligibleFunding({
supportsPopups,
supportedNativeBrowser,
experiment,
displayOnly = [],
}: {|
fundingSource: ?$Values<typeof FUNDING>,
remembered: $ReadOnlyArray<$Values<typeof FUNDING>>,
Expand All @@ -169,6 +217,7 @@ export function determineEligibleFunding({
supportsPopups: boolean,
supportedNativeBrowser: boolean,
experiment: Experiment,
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|}): $ReadOnlyArray<$Values<typeof FUNDING>> {
if (fundingSource) {
return [fundingSource];
Expand All @@ -191,6 +240,7 @@ export function determineEligibleFunding({
supportsPopups,
supportedNativeBrowser,
experiment,
displayOnly,
})
);

Expand Down
140 changes: 140 additions & 0 deletions src/funding/funding.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* @flow */
import { COMPONENTS, FUNDING } from "@paypal/sdk-constants/src";
import { describe, expect } from "vitest";

import { BUTTON_FLOW } from "../constants";

import { isFundingEligible } from "./funding";

const defaultMockFundingOptions = {
platform: "desktop",
components: [COMPONENTS.BUTTONS],
flow: BUTTON_FLOW.PURCHASE,
fundingSource: FUNDING.SEPA,
fundingEligibility: {
paylater: {
eligible: true,
vaultable: false,
},
venmo: {
eligible: true,
vaultable: true,
branded: false,
},
sepa: {
eligible: false,
branded: false,
},
oxxo: {
eligible: false,
vaultable: true,
branded: false,
},
card: {
eligible: true,
branded: false,
vendors: {
visa: {
eligible: true,
vaultable: false,
},
mastercard: {
eligible: true,
vaultable: false,
},
amex: {
eligible: true,
vaultable: false,
},
},
},
},
applePaySupport: false,
supportsPopups: true,
supportedNativeBrowser: true,
onShippingChange: null,
onShippingAddressChange: null,
onShippingOptionsChange: null,
};

describe("Funding eligibility", () => {
test("should not be eligible if funding source is missing from fundingEligibility", () => {
const fundingEligible = isFundingEligible(
FUNDING.WECHATPAY,
defaultMockFundingOptions
);

expect(fundingEligible).toBe(false);
});

test("should not be eligible if displayOnly includes 'vaultable' and vaultable is false", () => {
const options = {
...defaultMockFundingOptions,
displayOnly: ["vaultable"],
fundingSource: FUNDING.PAYLATER,
};
const fundingEligible = isFundingEligible(FUNDING.PAYLATER, options);

expect(fundingEligible).toBe(false);
});

test("card should not be eligible if displayOnly includes 'vaultable' and no vendors are vaultable", () => {
const options = {
...defaultMockFundingOptions,
displayOnly: ["vaultable"],
components: [COMPONENTS.BUTTONS],
fundingSource: FUNDING.CARD,
};
const fundingEligible = isFundingEligible(FUNDING.CARD, options);

expect(fundingEligible).toBe(false);
});

test("card should be eligible if displayOnly includes 'vaultable' and any vendor is vaultable", () => {
spencersablan marked this conversation as resolved.
Show resolved Hide resolved
const options = {
...defaultMockFundingOptions,
displayOnly: ["vaultable"],
fundingSource: FUNDING.CARD,
components: [COMPONENTS.BUTTONS],
platform: "desktop",
fundingEligibility: {
card: {
eligible: true,
branded: false,
vendors: {
visa: {
eligible: true,
vaultable: true,
},
mastercard: {
eligible: true,
vaultable: false,
},
},
},
},
};

const fundingEligible = isFundingEligible(FUNDING.CARD, options);

expect(fundingEligible).toBe(true);
});

test("should not be eligible if fundingSource.eligible is false", () => {
const fundingEligible = isFundingEligible(
FUNDING.SEPA,
defaultMockFundingOptions
);

expect(fundingEligible).toBe(false);
});

test("should not be eligible if fundingSource.eligible is false and fundingSource.vaultable is true", () => {
const fundingEligible = isFundingEligible(
FUNDING.OXXO,
defaultMockFundingOptions
);

expect(fundingEligible).toBe(false);
});
});
2 changes: 2 additions & 0 deletions src/ui/buttons/buttons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
supportsPopups,
supportedNativeBrowser,
showPayLabel,
displayOnly,
} = normalizeButtonProps(props);
const { layout, shape, tagline } = style;

Expand All @@ -196,6 +197,7 @@ export function Buttons(props: ButtonsProps): ElementNode {
supportsPopups,
supportedNativeBrowser,
experiment,
displayOnly,
});
const multiple = fundingSources.length > 1;

Expand Down
7 changes: 7 additions & 0 deletions src/ui/buttons/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
type LocaleType,
CARD,
COMPONENTS,
DISPLAY_ONLY_VALUES,
} from "@paypal/sdk-constants/src";
import { type CrossDomainWindowType } from "@krakenjs/cross-domain-utils/src";
import { LOGO_COLOR } from "@paypal/sdk-logos/src";
Expand Down Expand Up @@ -461,6 +462,7 @@ export type RenderButtonProps = {|
supportsPopups: boolean,
supportedNativeBrowser: boolean,
showPayLabel: boolean,
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|};

export type PrerenderDetails = {|
Expand Down Expand Up @@ -518,6 +520,7 @@ export type ButtonProps = {|
meta: {||},
renderedButtons: $ReadOnlyArray<$Values<typeof FUNDING>>,
createVaultSetupToken: CreateVaultSetupToken,
displayOnly?: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
|};

// eslint-disable-next-line flowtype/require-exact-type
Expand Down Expand Up @@ -559,6 +562,7 @@ export type ButtonPropsInputs = {
supportsPopups: boolean,
supportedNativeBrowser: boolean,
showPayLabel: boolean,
displayOnly: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
};

export const DEFAULT_STYLE = {
Expand Down Expand Up @@ -744,6 +748,7 @@ export function normalizeButtonProps(
supportsPopups = false,
supportedNativeBrowser = false,
showPayLabel = true,
displayOnly = [],
} = props;

const { country, lang } = locale;
Expand Down Expand Up @@ -794,6 +799,7 @@ export function normalizeButtonProps(
applePaySupport,
supportsPopups,
supportedNativeBrowser,
displayOnly,
})
) {
throw new Error(`Funding Source not eligible: ${fundingSource}`);
Expand Down Expand Up @@ -833,5 +839,6 @@ export function normalizeButtonProps(
supportsPopups,
supportedNativeBrowser,
showPayLabel,
displayOnly,
};
}
9 changes: 9 additions & 0 deletions src/zoid/buttons/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,15 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
required: false,
value: getExperimentation,
},

displayOnly: {
type: "array",
queryParam: true,
required: false,
value: ({ props }) => {
return props?.displayOnly || [];
},
},
},
});
});