Skip to content

fix: supports empty message object #2369

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

Merged
merged 6 commits into from
Apr 3, 2024
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
18 changes: 6 additions & 12 deletions src/ui/buttons/buttons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { TagLine } from "./tagline";
import { Script } from "./script";
import { PoweredByPayPal } from "./poweredBy";
import { Message } from "./message";
import { calculateMessagePosition } from "./util";
import { calculateShowPoweredBy } from "./util";

type GetWalletInstrumentOptions = {|
wallet: ?Wallet,
Expand Down Expand Up @@ -247,14 +247,8 @@ export function Buttons(props: ButtonsProps): ElementNode {
layout === BUTTON_LAYOUT.HORIZONTAL &&
!fundingSource &&
!message;
const showPoweredBy =
layout === BUTTON_LAYOUT.VERTICAL && fundingSources.includes(FUNDING.CARD);

const calculatedMessagePosition = calculateMessagePosition({
message,
showPoweredBy,
layout,
});
const showPoweredBy = calculateShowPoweredBy(layout, fundingSources);

return (
<div
Expand All @@ -275,8 +269,8 @@ export function Buttons(props: ButtonsProps): ElementNode {
fundingEligibility={fundingEligibility}
/>

{message && calculatedMessagePosition === MESSAGE_POSITION.TOP ? (
<Message markup={messageMarkup} position={calculatedMessagePosition} />
{message && message.position === MESSAGE_POSITION.TOP ? (
<Message markup={messageMarkup} position={message.position} />
) : null}

{fundingSources.map((source, i) => (
Expand Down Expand Up @@ -332,8 +326,8 @@ export function Buttons(props: ButtonsProps): ElementNode {

{showPoweredBy ? <PoweredByPayPal locale={locale} nonce={nonce} /> : null}

{message && calculatedMessagePosition === MESSAGE_POSITION.BOTTOM ? (
<Message markup={messageMarkup} position={calculatedMessagePosition} />
{message && message.position === MESSAGE_POSITION.BOTTOM ? (
<Message markup={messageMarkup} position={message.position} />
) : null}

<Script nonce={nonce} />
Expand Down
32 changes: 23 additions & 9 deletions src/ui/buttons/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
import { getFundingConfig, isFundingEligible } from "../../funding";

import { BUTTON_SIZE_STYLE } from "./config";
import { isBorderRadiusNumber } from "./util";
import { isBorderRadiusNumber, calculateMessagePosition } from "./util";

export type CreateOrderData = {||} | {||};

Expand Down Expand Up @@ -431,9 +431,9 @@ export type ApplePaySessionConfigRequest = (
export type ButtonMessage = {|
amount?: number,
offer?: $ReadOnlyArray<$Values<typeof MESSAGE_OFFER>>,
color?: $Values<typeof MESSAGE_COLOR>,
position?: $Values<typeof MESSAGE_POSITION>,
align?: $Values<typeof MESSAGE_ALIGN>,
color: $Values<typeof MESSAGE_COLOR>,
position: $Values<typeof MESSAGE_POSITION>,
align: $Values<typeof MESSAGE_ALIGN>,
|};

export type ButtonMessageInputs = {|
Expand Down Expand Up @@ -585,6 +585,7 @@ export type ButtonPropsInputs = {
displayOnly: $ReadOnlyArray<$Values<typeof DISPLAY_ONLY_VALUES>>,
message?: ButtonMessageInputs | void,
messageMarkup?: string | void,
renderedButtons: $ReadOnlyArray<$Values<typeof FUNDING>>,
};

export const DEFAULT_STYLE = {
Expand Down Expand Up @@ -734,10 +735,17 @@ export function normalizeButtonStyle(
}

export function normalizeButtonMessage(
props: ?ButtonPropsInputs,
message: ButtonMessageInputs
message: ButtonMessageInputs,
layout: $Values<typeof BUTTON_LAYOUT>,
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>
): ButtonMessage {
const { amount, offer, color, position, align } = message;
const {
amount,
offer,
color = MESSAGE_COLOR.BLACK,
position,
align = MESSAGE_ALIGN.CENTER,
} = message;

if (typeof amount !== "undefined") {
if (typeof amount !== "number") {
Expand Down Expand Up @@ -787,7 +795,7 @@ export function normalizeButtonMessage(
amount,
offer,
color,
position,
position: calculateMessagePosition(fundingSources, layout, position),
align,
};
}
Expand Down Expand Up @@ -848,6 +856,7 @@ export function normalizeButtonProps(
displayOnly = [],
message,
messageMarkup,
renderedButtons,
} = props;

const { country, lang } = locale;
Expand Down Expand Up @@ -906,6 +915,11 @@ export function normalizeButtonProps(
}

style = normalizeButtonStyle(props, style);
const { layout } = style;

message = message
? normalizeButtonMessage(message, layout, renderedButtons)
: undefined;

return {
clientID,
Expand Down Expand Up @@ -939,7 +953,7 @@ export function normalizeButtonProps(
supportedNativeBrowser,
showPayLabel,
displayOnly,
message: message ? normalizeButtonMessage(props, message) : undefined,
message,
messageMarkup,
};
}
32 changes: 16 additions & 16 deletions src/ui/buttons/util.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
/* @flow */
import { FUNDING } from "@paypal/sdk-constants/src";

import { BUTTON_LAYOUT, MESSAGE_POSITION } from "../../constants";
import { ValidationError } from "../../lib";

import type { ButtonMessage } from "./props";

export function isBorderRadiusNumber(borderRadius?: number): boolean {
return typeof borderRadius === "number";
}

type calculateMessagePositionProps = {|
message: ButtonMessage | void,
showPoweredBy: boolean,
layout: string,
|};
export function calculateShowPoweredBy(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

layout: $Values<typeof BUTTON_LAYOUT>,
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>
): boolean {
return (
layout === BUTTON_LAYOUT.VERTICAL && fundingSources.includes(FUNDING.CARD)
);
}

export function calculateMessagePosition({
message,
showPoweredBy,
layout,
}: calculateMessagePositionProps): string {
if (!message) {
return "none";
}
const { position } = message;
export function calculateMessagePosition(
fundingSources: $ReadOnlyArray<$Values<typeof FUNDING>>,
layout: $Values<typeof BUTTON_LAYOUT>,
position?: $Values<typeof MESSAGE_POSITION>
): $Values<typeof MESSAGE_POSITION> {
const showPoweredBy = calculateShowPoweredBy(layout, fundingSources);

if (showPoweredBy && position === MESSAGE_POSITION.BOTTOM) {
throw new ValidationError(
Expand Down
28 changes: 18 additions & 10 deletions src/zoid/buttons/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,24 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
value: getMerchantRequestedPopupsDisabled,
},

message: {
type: "object",
queryParam: true,
required: false,
decorate: ({ props, value }) => {
const {
style: { layout },
renderedButtons: fundingSources,
} = props;
return normalizeButtonMessage(
// $FlowFixMe
value,
layout,
fundingSources
);
},
},

nonce: {
type: "string",
default: getCSPNonce,
Expand Down Expand Up @@ -987,16 +1005,6 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
required: false,
default: () => window.__TEST_WALLET__,
},

message: {
type: "object",
queryParam: true,
required: false,
decorate: ({ props, value }) => {
// $FlowFixMe
return normalizeButtonMessage(props, value);
},
},
},
});
});
107 changes: 89 additions & 18 deletions test/integration/tests/button/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,95 @@ describe(`paypal button message`, () => {
destroyTestContainer();
});

describe("sets computed default values for undefined message properties", () => {
it("should populate message color when it is undefined", () => {
return wrapPromise(({ expect }) => {
window.paypal
.Buttons({
message: {},
test: {
onRender: expect("onRender", ({ xprops }) => {
const {
message: { color },
} = xprops;
if (!color) {
throw new Error(
`Expected message color property to be populated: ${JSON.stringify(
xprops.message
)}`
);
}
}),
},
})
.render("#testContainer");
});
});
it("should populate message align(ment) when it is undefined", () => {
return wrapPromise(({ expect }) => {
window.paypal
.Buttons({
message: {},
test: {
onRender: expect("onRender", ({ xprops }) => {
const {
message: { align },
} = xprops;
if (!align) {
throw new Error(
`Expected message align property to be populated: ${JSON.stringify(
xprops.message
)}`
);
}
}),
},
})
.render("#testContainer");
});
});
it("should populate position with bottom when layout is horizontal", () => {
return wrapPromise(({ expect }) => {
window.paypal
.Buttons({
style: {
layout: "horizontal",
},
message: {},
test: {
onRender: expect("onRender", ({ xprops }) => {
const {
message: { position },
} = xprops;
assert.equal(position, "bottom");
}),
},
})
.render("#testContainer");
});
});
it("should populate position with top when layout is vertical", () => {
return wrapPromise(({ expect }) => {
window.paypal
.Buttons({
style: {
layout: "vertical",
},
message: {},
test: {
onRender: expect("onRender", ({ xprops }) => {
const {
message: { position },
} = xprops;
assert.equal(position, "top");
}),
},
})
.render("#testContainer");
});
});
});

describe("reserves space for message", () => {
it("should reserve space for a message when messageMarkup is undefined", (done) => {
window.paypal
Expand Down Expand Up @@ -121,24 +210,6 @@ describe(`paypal button message`, () => {
});
});

describe("error handling", () => {
it("should throw error when position is bottom and credit/debit is a funding source", () => {
return wrapPromise(({ expect }) => {
window.paypal
.Buttons({
style: {
layout: "vertical",
},
message: {
position: "bottom",
},
onError: expect("onError"),
})
.render("#testContainer");
});
});
});

describe(`prop considerations`, () => {
it("message should take precedence over tagline when both are truthy", (done) => {
window.paypal
Expand Down
11 changes: 11 additions & 0 deletions test/integration/tests/button/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,17 @@ const buttonConfigs = [
valid: false,
},

{
message: {
amount: 100,
offer: ["pay_later_long_term"],
color: "black",
position: "bottom", // Message position must be 'top' when Debit and/or Credit Card button is present
align: "left",
},
valid: false,
},

{
message: {},
valid: true,
Expand Down
Loading