Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@paypal/checkout-components

Package Overview
Dependencies
Maintainers
20
Versions
506
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@paypal/checkout-components - npm Package Compare versions

Comparing version 5.0.309-alpha-7a6ed47.0 to 5.0.309-alpha-fcfe679.0

3

globals.js

@@ -35,6 +35,5 @@ /* eslint import/no-commonjs: off, flowtype/require-valid-file-annotation: off, flowtype/require-return-type: off */

__PAYMENT_FIELDS__: "/altpayfields",
__MESSAGE_MODAL__:
"https://www.paypalobjects.com/upstream/bizcomponents/js/modal.js",
__MESSAGE_MODAL__: "https://www.paypalobjects.com/upstream/bizcomponents/js/modal.js",
},
},
};
{
"name": "@paypal/checkout-components",
"version": "5.0.309-alpha-7a6ed47.0",
"version": "5.0.309-alpha-fcfe679.0",
"description": "PayPal Checkout components, for integrating checkout products.",

@@ -5,0 +5,0 @@ "main": "index.js",

/* @flow */
import { getLogger } from "@paypal/sdk-client/src";
import { getButtonsComponent } from "../zoid/buttons";

@@ -13,6 +11,2 @@

getMerchantID,
shouldRenderSDKButtons,
getFlexDirection,
appendButtonContainer,
getButtonColor,
} from "./utils";

@@ -29,3 +23,2 @@ import type {

hostedButtonId,
fundingSources = [],
}: HostedButtonsComponentProps): HostedButtonsInstance {

@@ -37,3 +30,2 @@ const Buttons = getButtonsComponent();

hostedButtonId,
fundingSources,
});

@@ -48,56 +40,20 @@

const createOrder = buildHostedButtonCreateOrder({
enableDPoP,
// $FlowFixMe
Buttons({
hostedButtonId,
merchantId,
});
const onApprove = buildHostedButtonOnApprove({
enableDPoP,
hostedButtonId,
merchantId,
});
const buttonOptions = {
createOrder,
hostedButtonId,
merchantId,
onApprove,
style,
onInit,
onClick,
onInit,
style,
};
if (shouldRenderSDKButtons(fundingSources)) {
const { flexDirection } = getFlexDirection({ ...style });
appendButtonContainer({ flexDirection, selector });
// Only render 2 buttons max
// This will be refactored in https://paypal.atlassian.net/browse/DTPPCPSDK-2112 when NCPS team updates their API response
fundingSources.slice(0, 2).forEach((fundingSource, index) => {
// $FlowFixMe
const standaloneButton = Buttons({
...buttonOptions,
fundingSource,
style: {
...style,
color: getButtonColor(style.color, fundingSource),
},
});
if (standaloneButton.isEligible()) {
standaloneButton.render(
index === 0 ? "#ncp-primary-button" : "#ncp-secondary-button"
);
} else {
getLogger().error(`ncps_standalone_${fundingSource}_ineligible`);
}
});
} else {
// V1 Experience
// $FlowFixMe
Buttons(buttonOptions).render(selector);
}
createOrder: buildHostedButtonCreateOrder({
enableDPoP,
hostedButtonId,
merchantId,
}),
onApprove: buildHostedButtonOnApprove({
enableDPoP,
hostedButtonId,
merchantId,
}),
}).render(selector);
};
return {

@@ -104,0 +60,0 @@ render,

@@ -76,3 +76,2 @@ /* @flow */

hostedButtonId: "B1234567890",
fundingSources: [],
}).render("#example");

@@ -84,73 +83,6 @@ expect(Buttons).toHaveBeenCalledWith(

);
expect(Buttons).toHaveBeenCalledTimes(1);
expect.assertions(2);
expect.assertions(1);
});
});
describe("NCP V2", () => {
beforeEach(() => {
const containerId = "#container-id";
const selector = document.createElement("div");
selector.setAttribute("id", containerId.slice(1));
vi.spyOn(document, "querySelector").mockReturnValue(selector);
});
test("paypal.Buttons calls getHostedButtonDetails, invokes v5 of the SDK", async () => {
const renderMock = vi.fn();
const Buttons = vi.fn(() => ({
render: renderMock,
isEligible: vi.fn(() => true),
}));
// $FlowIssue
getButtonsComponent.mockImplementationOnce(() => Buttons);
const HostedButtons = getHostedButtonsComponent();
// $FlowIssue
request.mockImplementationOnce(() =>
// eslint-disable-next-line compat/compat
Promise.resolve(getHostedButtonDetailsResponse)
);
await HostedButtons({
hostedButtonId: "B1234567890",
fundingSources: ["paypal", "venmo"],
}).render("#example");
expect(Buttons).toHaveBeenCalledWith(
expect.objectContaining({
hostedButtonId: "B1234567890",
})
);
expect(Buttons).toHaveBeenCalledTimes(2);
expect(renderMock).toHaveBeenCalledTimes(2);
expect.assertions(3);
});
});
test("only eligible buttons are rendered", async () => {
const renderMock = vi.fn();
const Buttons = vi.fn(() => ({
render: renderMock,
isEligible: vi.fn(() => false),
}));
// $FlowIssue
getButtonsComponent.mockImplementationOnce(() => Buttons);
const HostedButtons = getHostedButtonsComponent();
// $FlowIssue
request.mockImplementationOnce(() =>
// eslint-disable-next-line compat/compat
Promise.resolve(getHostedButtonDetailsResponse)
);
await HostedButtons({
hostedButtonId: "B1234567890",
fundingSources: ["paypal", "venmo"],
}).render("#example");
expect(Buttons).toHaveBeenCalledWith(
expect.objectContaining({
hostedButtonId: "B1234567890",
})
);
expect(Buttons).toHaveBeenCalledTimes(2);
expect(renderMock).toHaveBeenCalledTimes(0);
expect.assertions(3);
});
});
/* eslint-enable no-restricted-globals, promise/no-native */
/* @flow */
/* eslint-disable no-restricted-globals, promise/no-native */
export type Color = string;
export type FlexDirection = string;
export type Layout = string;
export type FundingSources = string;
export interface GetFlexDirection {
flexDirection: FlexDirection;
}
export interface GetFlexDirectionArgs {
layout: Layout;
}
export interface BuildButtonContainerArgs {
flexDirection: FlexDirection;
selector: string | HTMLElement;
}
export type HostedButtonsComponentProps = {|
hostedButtonId: string,
fundingSources: $ReadOnlyArray<FundingSources>,
|};

@@ -26,0 +7,0 @@

@@ -20,7 +20,2 @@ /* @flow */

RenderForm,
GetFlexDirectionArgs,
GetFlexDirection,
BuildButtonContainerArgs,
Color,
FundingSources,
} from "./types";

@@ -39,6 +34,5 @@

export const getMerchantID = (): string | void => {
// The SDK supports Multi-Seller Payments (MSP, i.e sending multiple merchant IDs), but hosted buttons
// does not support this. Only one merchant id can be passed as a query parameter to the SDK script
// The SDK supports mutiple merchant IDs, but hosted buttons only
// have one merchant id as a query parameter to the SDK script.
// https://github.com/paypal/paypal-sdk-client/blob/c58e35f8f7adbab76523eb25b9c10543449d2d29/src/script.js#L144
// https://developer.paypal.com/docs/multiparty/checkout/multiseller-payments/
const merchantIds = getSDKMerchantID();

@@ -108,10 +102,2 @@ if (merchantIds.length > 1) {

export function getElementFromSelector(
selector: string | HTMLElement
): HTMLElement | null {
return typeof selector === "string"
? document.querySelector(selector)
: selector;
}
/**

@@ -127,3 +113,4 @@ * Attaches form fields (html) to the given selector, and

}) => {
const elm = getElementFromSelector(selector);
const elm =
typeof selector === "string" ? document.querySelector(selector) : selector;
if (elm) {

@@ -245,79 +232,1 @@ elm.innerHTML = html + htmlScript;

};
export function getFlexDirection({
layout,
}: GetFlexDirectionArgs): GetFlexDirection {
return { flexDirection: layout === "horizontal" ? "row" : "column" };
}
export function getButtonColor(
color: Color,
fundingSource: FundingSources
): Color {
const colorMap = {
gold: {
paypal: "gold",
venmo: "blue",
paylater: "gold",
},
blue: {
paypal: "blue",
venmo: "silver",
paylater: "blue",
},
black: {
paypal: "black",
venmo: "black",
paylater: "black",
},
white: {
paypal: "white",
venmo: "white",
paylater: "white",
},
silver: {
paypal: "silver",
venmo: "blue",
paylater: "silver",
},
};
return colorMap[color][fundingSource];
}
export function shouldRenderSDKButtons(
fundingSources: $ReadOnlyArray<FundingSources>
): boolean {
return Boolean(fundingSources.length);
}
export function appendButtonContainer({
flexDirection,
selector,
}: BuildButtonContainerArgs) {
const elm = getElementFromSelector(selector);
if (!elm) {
throw new Error("PayPal button container selector was not found");
}
const buttonContainer = document.createElement("div");
buttonContainer.setAttribute(
"style",
`display: flex; flex-wrap: nowrap; gap: 16px; max-width: 750px; flex-direction: ${flexDirection}`
);
const primaryButton = document.createElement("div");
primaryButton.setAttribute("id", `ncp-primary-button`);
primaryButton.setAttribute("style", "flex-grow: 1");
const secondaryButton = document.createElement("div");
secondaryButton.setAttribute("id", `ncp-secondary-button`);
secondaryButton.setAttribute("style", "flex-grow: 1");
buttonContainer.appendChild(primaryButton);
buttonContainer.appendChild(secondaryButton);
elm?.appendChild(buttonContainer);
}

@@ -11,7 +11,2 @@ /* @flow */

getHostedButtonDetails,
getFlexDirection,
getButtonColor,
shouldRenderSDKButtons,
appendButtonContainer,
getElementFromSelector,
} from "./utils";

@@ -86,3 +81,2 @@

hostedButtonId,
fundingSources: [],
}).then(({ style }) => {

@@ -320,97 +314,2 @@ expect(style).toEqual({

test("getFlexDirection", () => {
expect(getFlexDirection({ layout: "horizontal" })).toStrictEqual({
flexDirection: "row",
});
expect(getFlexDirection({ layout: "vertical" })).toStrictEqual({
flexDirection: "column",
});
});
test("getButtonColor", () => {
const colors = ["gold", "blue", "silver", "white", "black"];
const fundingSources = ["paypal", "venmo", "paylater"];
const colorMap = {
gold: {
paypal: "gold",
venmo: "blue",
paylater: "gold",
},
blue: {
paypal: "blue",
venmo: "silver",
paylater: "blue",
},
black: {
paypal: "black",
venmo: "black",
paylater: "black",
},
white: {
paypal: "white",
venmo: "white",
paylater: "white",
},
silver: {
paypal: "silver",
venmo: "blue",
paylater: "silver",
},
};
colors.forEach((color) => {
fundingSources.forEach((fundingSource) => {
expect(getButtonColor(color, fundingSource)).toBe(
colorMap[color][fundingSource]
);
});
});
});
test("shouldRenderSDKButtons", () => {
expect(shouldRenderSDKButtons([])).toBe(false);
expect(shouldRenderSDKButtons(["paypal"])).toBe(true);
expect(shouldRenderSDKButtons(["paypal", "venmo"])).toBe(true);
});
test("buildButtonContainer", () => {
const containerId = "#container-id";
const selector = document.createElement("div");
selector.setAttribute("id", containerId.slice(1));
vi.spyOn(document, "querySelector").mockReturnValueOnce(selector);
expect(() =>
appendButtonContainer({ flexDirection: "row", selector: containerId })
).not.toThrow();
expect(() =>
appendButtonContainer({ flexDirection: "row", selector })
).not.toThrow();
expect(() =>
appendButtonContainer({
flexDirection: "row",
selector: `${containerId}-not-found`,
})
).toThrow("PayPal button container selector was not found");
});
test("getElementFromSelector", () => {
const containerId = "#container-id";
const selector = document.createElement("div");
selector.setAttribute("id", containerId.slice(1));
const mockQuerySelector = vi
.spyOn(document, "querySelector")
.mockReturnValueOnce(selector);
expect(getElementFromSelector(containerId)).toBe(selector);
expect(getElementFromSelector(selector)).toBe(selector);
expect(mockQuerySelector).toBeCalledTimes(1);
expect(mockQuerySelector).toHaveBeenCalledWith(containerId);
});
/* eslint-enable no-restricted-globals, promise/no-native */

@@ -433,3 +433,3 @@ /* eslint-disable eslint-comments/disable-enable-pair */

amount?: number,
offer?: $Values<typeof MESSAGE_OFFER> | string,
offer?: $ReadOnlyArray<$Values<typeof MESSAGE_OFFER>>,
color: $Values<typeof MESSAGE_COLOR>,

@@ -745,2 +745,3 @@ position: $Values<typeof MESSAGE_POSITION>,

amount,
offer,
color = MESSAGE_COLOR.BLACK,

@@ -750,3 +751,3 @@ position,

} = message;
let offer = message.offer;
if (typeof amount !== "undefined") {

@@ -767,10 +768,7 @@ if (typeof amount !== "number") {

if (!Array.isArray(offer)) {
if (typeof offer !== "string") {
throw new TypeError(
`Expected message.offer to be an array of strings, got: ${String(
offer
)}`
);
}
offer = offer.split(",");
throw new TypeError(
`Expected message.offer to be an array of strings, got: ${String(
offer
)}`
);
}

@@ -783,3 +781,2 @@ const invalidOffers = offer.filter(

}
offer = offer.join(",");
}

@@ -786,0 +783,0 @@

@@ -746,3 +746,7 @@ /* @flow */

const modalInstance = await getModal(clientID, merchantID);
const modalInstance = await getModal(
clientID,
merchantID,
buttonSessionID
);
return modalInstance?.show({

@@ -765,4 +769,4 @@ amount,

// lazy loads the modal, to be memoized and executed onMessageClick
const { clientID, merchantID } = props;
return getModal(clientID, merchantID);
const { buttonSessionID, clientID, merchantID } = props;
return getModal(clientID, merchantID, buttonSessionID);
};

@@ -769,0 +773,0 @@ },

@@ -18,3 +18,2 @@ /* @flow */

} from "@krakenjs/belter/src";
import { FUNDING } from "@paypal/sdk-constants/src";
import {

@@ -30,2 +29,3 @@ getEnableFunding,

} from "@paypal/sdk-client/src";
import { FUNDING, FPTI_KEY } from "@paypal/sdk-constants/src";
import { getRefinedFundingEligibility } from "@paypal/funding-components/src";

@@ -378,4 +378,5 @@

clientID: string,
merchantID: $ReadOnlyArray<string> | void
) => Object = memoize(async (clientID, merchantID) => {
merchantID: $ReadOnlyArray<string> | void,
buttonSessionID: string
) => Object = memoize(async (clientID, merchantID, buttonSessionID) => {
try {

@@ -401,2 +402,36 @@ const namespace = getNamespace();

return window[namespace].MessagesModal({
onReady: () =>
getLogger()
.info("button_message_modal_render")
.track({
[FPTI_KEY.TRANSITION]: "button_message_modal_render",
[FPTI_KEY.STATE]: "BUTTON_MESSAGE",
[FPTI_KEY.BUTTON_SESSION_UID]: buttonSessionID,
[FPTI_KEY.CONTEXT_ID]: buttonSessionID,
[FPTI_KEY.CONTEXT_TYPE]: "button_session_id",
[FPTI_KEY.EVENT_NAME]: "modal_render",
}),
onClick: () =>
getLogger()
.info("button_message_modal_click")
.track({
[FPTI_KEY.TRANSITION]: "button_message_modal_click",
[FPTI_KEY.STATE]: "BUTTON_MESSAGE",
[FPTI_KEY.BUTTON_SESSION_UID]: buttonSessionID,
[FPTI_KEY.CONTEXT_ID]: buttonSessionID,
[FPTI_KEY.CONTEXT_TYPE]: "button_session_id",
[FPTI_KEY.EVENT_NAME]: "modal_click",
}),
onApply: () =>
getLogger()
.info("button_message_modal_apply")
.track({
[FPTI_KEY.TRANSITION]: "button_message_modal_apply",
[FPTI_KEY.STATE]: "BUTTON_MESSAGE",
[FPTI_KEY.BUTTON_SESSION_UID]: buttonSessionID,
[FPTI_KEY.CONTEXT_ID]: buttonSessionID,
[FPTI_KEY.CONTEXT_TYPE]: "button_session_id",
[FPTI_KEY.EVENT_NAME]: "modal_apply",
}),
buttonSessionId: buttonSessionID,
account: `client-id:${clientID}`,

@@ -403,0 +438,0 @@ merchantId: merchantID?.join(",") || undefined,

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc