Skip to content

Commit

Permalink
feat(payment): PAYPAL-5097 created BraintreeMessages class and added …
Browse files Browse the repository at this point in the history
…Braintree BNPL Styles implementation
  • Loading branch information
serhii-tkachenko committed Feb 14, 2025
1 parent 7364957 commit b680b8c
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export default interface BraintreePaypalCreditButtonInitializeOptions {
*/
currencyCode?: string;

/**
* The ID of a container which the messaging should be inserted.
*/
messagingContainerId?: string;

/**
* @internal
* This is an internal property and therefore subject to change. DO NOT USE.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
BraintreeError,
BraintreeHostWindow,
BraintreeIntegrationService,
BraintreeMessages,
BraintreePaypalCheckout,
BraintreePaypalCheckoutCreator,
BraintreeScriptLoader,
Expand Down Expand Up @@ -50,6 +51,7 @@ describe('BraintreePaypalCreditButtonStrategy', () => {
let dataCollector: BraintreeDataCollector;
let eventEmitter: EventEmitter;
let braintreeIntegrationService: BraintreeIntegrationService;
let braintreeMessages: BraintreeMessages;
let braintreePaypalCheckoutMock: BraintreePaypalCheckout;
let braintreePaypalCheckoutCreatorMock: BraintreePaypalCheckoutCreator;
let braintreeScriptLoader: BraintreeScriptLoader;
Expand Down Expand Up @@ -160,11 +162,13 @@ describe('BraintreePaypalCreditButtonStrategy', () => {
braintreeScriptLoader,
window,
);
braintreeMessages = new BraintreeMessages(paymentIntegrationService);

strategy = new BraintreePaypalCreditButtonStrategy(
paymentIntegrationService,
formPoster,
braintreeIntegrationService,
braintreeMessages,
window,
);

Expand All @@ -186,6 +190,7 @@ describe('BraintreePaypalCreditButtonStrategy', () => {
dataCollector,
);
jest.spyOn(braintreeIntegrationService, 'removeElement').mockImplementation(jest.fn());
jest.spyOn(braintreeMessages, 'render').mockImplementation(jest.fn());
jest.spyOn(braintreeScriptLoader, 'loadPaypalCheckout').mockResolvedValue(
braintreePaypalCheckoutCreatorMock,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
BraintreeHostWindow,
BraintreeInitializationData,
BraintreeIntegrationService,
BraintreeMessages,
BraintreePaypalCheckout,
BraintreePaypalSdkCreatorConfig,
BraintreeTokenizePayload,
Expand Down Expand Up @@ -39,6 +40,7 @@ export default class BraintreePaypalCreditButtonStrategy implements CheckoutButt
private paymentIntegrationService: PaymentIntegrationService,
private formPoster: FormPoster,
private braintreeIntegrationService: BraintreeIntegrationService,
private braintreeMessages: BraintreeMessages,
private braintreeHostWindow: BraintreeHostWindow,
) {}

Expand Down Expand Up @@ -99,6 +101,14 @@ export default class BraintreePaypalCreditButtonStrategy implements CheckoutButt
const paypalCheckoutSuccessCallback = (
braintreePaypalCheckout: BraintreePaypalCheckout,
) => {
if (braintreepaypalcredit.messagingContainerId) {
this.braintreeMessages.render(
methodId,
braintreepaypalcredit.messagingContainerId,
'cart',
);
}

this.renderPayPalButton(
braintreePaypalCheckout,
braintreepaypalcredit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getScriptLoader } from '@bigcommerce/script-loader';
import {
BraintreeHostWindow,
BraintreeIntegrationService,
BraintreeMessages,
BraintreeScriptLoader,
} from '@bigcommerce/checkout-sdk/braintree-utils';
import {
Expand All @@ -21,11 +22,13 @@ const createBraintreePaypalCreditButtonStrategy: CheckoutButtonStrategyFactory<
new BraintreeScriptLoader(getScriptLoader(), braintreeHostWindow),
braintreeHostWindow,
);
const braintreeMessages = new BraintreeMessages(paymentIntegrationService);

return new BraintreePaypalCreditButtonStrategy(
paymentIntegrationService,
createFormPoster(),
braintreeIntegrationService,
braintreeMessages,
braintreeHostWindow,
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ export default interface BraintreePaypalButtonInitializeOptions {
*/
currencyCode?: string;

/**
* The ID of a container which the messaging should be inserted.
*/
messagingContainerId?: string;

/**
* @internal
* This is an internal property and therefore subject to change. DO NOT USE.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,12 @@ describe('BraintreePaypalButtonStrategy', () => {
let paymentIntegrationService: PaymentIntegrationService;
let paymentMethod: PaymentMethod;
let paypalButtonElement: HTMLDivElement;
let paypalMessageElement: HTMLDivElement;
let paypalSdkMock: PaypalSDK;
let strategy: BraintreePaypalButtonStrategy;

const defaultButtonContainerId = 'braintree-paypal-button-mock-id';
const defaultMessageContainerId = 'braintree-paypal-message-mock-id';

const braintreePaypalOptions: BraintreePaypalButtonInitializeOptions = {
messagingContainerId: defaultMessageContainerId, // only available on cart page
shouldProcessPayment: false,
style: { height: 45 },
onAuthorizeError: jest.fn(),
Expand Down Expand Up @@ -157,10 +154,6 @@ describe('BraintreePaypalButtonStrategy', () => {
paypalButtonElement.id = defaultButtonContainerId;
document.body.appendChild(paypalButtonElement);

paypalMessageElement = document.createElement('div');
paypalMessageElement.id = defaultMessageContainerId;
document.body.appendChild(paypalMessageElement);

formPoster = createFormPoster();
paymentIntegrationService = new PaymentIntegrationServiceMock();
braintreeScriptLoader = new BraintreeScriptLoader(getScriptLoader(), window);
Expand Down Expand Up @@ -222,10 +215,6 @@ describe('BraintreePaypalButtonStrategy', () => {
render: jest.fn(),
};
});

jest.spyOn(paypalSdkMock, 'Messages').mockImplementation(() => ({
render: jest.fn(),
}));
});

afterEach(() => {
Expand All @@ -236,10 +225,6 @@ describe('BraintreePaypalButtonStrategy', () => {
if (document.getElementById(defaultButtonContainerId)) {
document.body.removeChild(paypalButtonElement);
}

if (document.getElementById(defaultMessageContainerId)) {
document.body.removeChild(paypalMessageElement);
}
});

it('creates an instance of the braintree paypal button button strategy', () => {
Expand Down Expand Up @@ -436,15 +421,6 @@ describe('BraintreePaypalButtonStrategy', () => {
);
});

it('renders Braintree PayPal message', async () => {
await strategy.initialize(initializationOptions);

expect(paypalSdkMock.Messages).toHaveBeenCalledWith({
amount: cart.cartAmount,
placement: 'cart',
});
});

it('renders Braintree PayPal button', async () => {
await strategy.initialize(initializationOptions);

Expand All @@ -460,14 +436,11 @@ describe('BraintreePaypalButtonStrategy', () => {
});
});

it('removes Braintree PayPal button and message containers when paypal is not available in window', async () => {
it('removes Braintree PayPal button when paypal is not available in window', async () => {
delete (window as BraintreeHostWindow).paypal;

await strategy.initialize(initializationOptions);

expect(braintreeIntegrationService.removeElement).toHaveBeenCalledWith(
defaultMessageContainerId,
);
expect(braintreeIntegrationService.removeElement).toHaveBeenCalledWith(
defaultButtonContainerId,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ export default class BraintreePaypalButtonStrategy implements CheckoutButtonStra
const paypalCheckoutSuccessCallback = (
braintreePaypalCheckout: BraintreePaypalCheckout,
) => {
this.renderPayPalMessages(braintreepaypal.messagingContainerId);
this.renderPayPalButton(
braintreePaypalCheckout,
braintreepaypal,
Expand All @@ -122,26 +121,6 @@ export default class BraintreePaypalButtonStrategy implements CheckoutButtonStra
await this.braintreeIntegrationService.teardown();
}

private renderPayPalMessages(messagingContainerId?: string): void {
const isMessageContainerAvailable =
messagingContainerId && Boolean(document.getElementById(messagingContainerId));
const { paypal } = this.braintreeHostWindow;

if (isMessageContainerAvailable && paypal) {
const state = this.paymentIntegrationService.getState();
const amount = state.getCartOrThrow().cartAmount;

const paypalMessagesRender = paypal.Messages({
amount,
placement: 'cart',
});

paypalMessagesRender.render(`#${messagingContainerId}`);
} else {
this.braintreeIntegrationService.removeElement(messagingContainerId);
}
}

private renderPayPalButton(
braintreePaypalCheckout: BraintreePaypalCheckout,
braintreepaypal: BraintreePaypalButtonInitializeOptions,
Expand Down
Loading

0 comments on commit b680b8c

Please sign in to comment.