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

Paypal 4698 test #2661

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ export interface BraintreePaypalButtonInitializeOptions {
*/
onError?(error: BraintreeError | StandardError): void;

/**
*
* A callback that gets called when Braintree SDK restricts to render PayPal component.
*
*/
onEligibilityFailure?(): void;

/**
* The option that used to initialize a PayPal script with provided currency code.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('BraintreePaypalButtonStrategy', () => {
onAuthorizeError: jest.fn(),
onPaymentError: jest.fn(),
onError: jest.fn(),
onEligibilityFailure: jest.fn(),
};

const initializationOptions: CheckoutButtonInitializeOptions = {
Expand Down Expand Up @@ -427,6 +428,33 @@ describe('BraintreePaypalButtonStrategy', () => {
});
});

it('does not render PayPal checkout button and calls onEligibilityFailure callback', async () => {
const renderMock = jest.fn();

jest.spyOn(paypalSdkMock, 'Buttons').mockImplementationOnce(() => {
return {
isEligible: jest.fn(() => false),
render: renderMock,
};
});

await strategy.initialize(initializationOptions);

expect(paypalSdkMock.Buttons).toHaveBeenCalledWith({
createOrder: expect.any(Function),
env: 'sandbox',
fundingSource: paypalSdkMock.FUNDING.PAYPAL,
onApprove: expect.any(Function),
style: {
shape: 'rect',
height: 45,
},
});

expect(braintreePaypalOptions.onEligibilityFailure).toHaveBeenCalled();
expect(renderMock).not.toHaveBeenCalled();
});

it('renders PayPal checkout button in production environment if payment method is in test mode', async () => {
paymentMethodMock.config.testMode = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ export default class BraintreePaypalButtonStrategy implements CheckoutButtonStra
methodId: string,
testMode: boolean,
): void {
const { style, shouldProcessPayment, onAuthorizeError } = braintreepaypal;
const { style, shouldProcessPayment, onAuthorizeError, onEligibilityFailure } =
braintreepaypal;

const { paypal } = this._window;
const fundingSource = paypal?.FUNDING.PAYPAL;
Expand All @@ -179,6 +180,8 @@ export default class BraintreePaypalButtonStrategy implements CheckoutButtonStra

if (paypalButtonRender.isEligible()) {
paypalButtonRender.render(`#${containerId}`);
} else if (onEligibilityFailure && typeof onEligibilityFailure === 'function') {
onEligibilityFailure();
}
} else {
this._removeElement(containerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ export interface BraintreePaypalCreditButtonInitializeOptions {
*/
onError?(error: BraintreeError | StandardError): void;

/**
*
* A callback that gets called when Braintree SDK restricts to render PayPal component.
*
*/
onEligibilityFailure?(): void;

/**
* The option that used to initialize a PayPal script with provided currency code.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('BraintreePaypalCreditButtonStrategy', () => {
onAuthorizeError: jest.fn(),
onPaymentError: jest.fn(),
onError: jest.fn(),
onEligibilityFailure: jest.fn(),
};

const initializationOptions: CheckoutButtonInitializeOptions = {
Expand Down Expand Up @@ -418,12 +419,10 @@ describe('BraintreePaypalCreditButtonStrategy', () => {
});

it('renders braintree credit button if paylater is not eligible', async () => {
// TODO: remove ts-ignore and update test with related type (PAYPAL-4383)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
jest.spyOn(paypalSdkMock, 'Buttons').mockImplementationOnce(() => {
return {
isEligible: jest.fn(() => false),
render: jest.fn(),
};
});

Expand Down Expand Up @@ -455,6 +454,45 @@ describe('BraintreePaypalCreditButtonStrategy', () => {
});
});

it('does not render PayPal checkout button and calls onEligibilityFailure callback', async () => {
const renderMock = jest.fn();

jest.spyOn(paypalSdkMock, 'Buttons').mockImplementation(() => {
return {
isEligible: jest.fn(() => false),
render: renderMock,
};
});

await strategy.initialize(initializationOptions);

expect(paypalSdkMock.Buttons).toHaveBeenCalledWith({
createOrder: expect.any(Function),
env: 'sandbox',
fundingSource: paypalSdkMock.FUNDING.PAYLATER,
onApprove: expect.any(Function),
style: {
shape: 'rect',
height: 45,
},
});

expect(paypalSdkMock.Buttons).toHaveBeenCalledWith({
createOrder: expect.any(Function),
env: 'sandbox',
fundingSource: paypalSdkMock.FUNDING.CREDIT,
onApprove: expect.any(Function),
style: {
shape: 'rect',
height: 45,
label: 'credit',
},
});

expect(braintreePaypalCreditOptions.onEligibilityFailure).toHaveBeenCalled();
expect(renderMock).not.toHaveBeenCalled();
});

it('renders braintree checkout button in production environment if payment method is in test mode', async () => {
paymentMethodMock.config.testMode = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ export default class BraintreePaypalCreditButtonStrategy implements CheckoutButt
methodId: string,
testMode: boolean,
): void {
const { style, shouldProcessPayment, onAuthorizeError } = braintreepaypalcredit;
const { style, shouldProcessPayment, onAuthorizeError, onEligibilityFailure } =
braintreepaypalcredit;
const { paypal } = this._window;

let hasRenderedSmartButton = false;
Expand Down Expand Up @@ -173,6 +174,15 @@ export default class BraintreePaypalCreditButtonStrategy implements CheckoutButt
if (paypalButtonRender.isEligible()) {
paypalButtonRender.render(`#${containerId}`);
hasRenderedSmartButton = true;
} else if (
paypal.FUNDING.CREDIT &&
onEligibilityFailure &&
typeof onEligibilityFailure === 'function'
) {
// the condition is related to paypal.FUNDING.CREDIT because when paypal.FUNDING.PAYLATER is not eligible then
// CREDIT button should be configured and triggered to render with eligibility check
// and if it is not eligible, then onEligibilityFailure callback should be called
onEligibilityFailure();
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ export default interface PayPalCommerceAlternativeMethodsButtonOptions {
* A set of styling options for the checkout button.
*/
style?: PayPalButtonStyleOptions;

/**
*
* A callback that gets called when PayPal SDK restricts to render PayPal component.
*
*/
onEligibilityFailure?(): void;
}

export interface WithPayPalCommerceAlternativeMethodsButtonInitializeOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ describe('PayPalCommerceAlternativeMethodsButtonStrategy', () => {
style: {
height: 45,
},
onEligibilityFailure: jest.fn(),
};

const initializationOptions: CheckoutButtonInitializeOptions = {
Expand Down Expand Up @@ -104,14 +105,16 @@ describe('PayPalCommerceAlternativeMethodsButtonStrategy', () => {
paymentMethod,
);

jest.spyOn(paypalCommerceIntegrationService, 'loadPayPalSdk').mockReturnValue(paypalSdk);
jest.spyOn(paypalCommerceIntegrationService, 'loadPayPalSdk').mockReturnValue(
Promise.resolve(paypalSdk),
);
jest.spyOn(paypalCommerceIntegrationService, 'getPayPalSdkOrThrow').mockReturnValue(
paypalSdk,
);
jest.spyOn(paypalCommerceIntegrationService, 'createBuyNowCartOrThrow').mockReturnValue(
buyNowCart,
Promise.resolve(buyNowCart),
);
jest.spyOn(paypalCommerceIntegrationService, 'createOrder').mockReturnValue(undefined);
jest.spyOn(paypalCommerceIntegrationService, 'createOrder');
jest.spyOn(paypalCommerceIntegrationService, 'tokenizePayment').mockImplementation(
jest.fn(),
);
Expand Down Expand Up @@ -179,6 +182,7 @@ describe('PayPalCommerceAlternativeMethodsButtonStrategy', () => {
return {
isEligible: jest.fn(() => true),
render: jest.fn(),
close: jest.fn(),
};
},
);
Expand Down Expand Up @@ -372,40 +376,28 @@ describe('PayPalCommerceAlternativeMethodsButtonStrategy', () => {
jest.spyOn(paypalSdk, 'Buttons').mockImplementation(() => ({
isEligible: jest.fn(() => true),
render: paypalCommerceSdkRenderMock,
close: jest.fn(),
}));

await strategy.initialize(initializationOptions);

expect(paypalCommerceSdkRenderMock).toHaveBeenCalled();
});

it('does not render PayPal APM button if it is not eligible', async () => {
it('calls onEligibilityFailure callback when PayPal APM button is not eligible', async () => {
const paypalCommerceSdkRenderMock = jest.fn();

jest.spyOn(paypalSdk, 'Buttons').mockImplementation(() => ({
isEligible: jest.fn(() => false),
render: paypalCommerceSdkRenderMock,
close: jest.fn(),
}));

await strategy.initialize(initializationOptions);

expect(paypalCommerceAlternativeMethodsOptions.onEligibilityFailure).toHaveBeenCalled();
expect(paypalCommerceSdkRenderMock).not.toHaveBeenCalled();
});

it('removes PayPal APM button container if the button has not rendered', async () => {
const paypalCommerceSdkRenderMock = jest.fn();

jest.spyOn(paypalSdk, 'Buttons').mockImplementation(() => ({
isEligible: jest.fn(() => false),
render: paypalCommerceSdkRenderMock,
}));

await strategy.initialize(initializationOptions);

expect(paypalCommerceIntegrationService.removeElement).toHaveBeenCalledWith(
defaultButtonContainerId,
);
});
});

describe('#createOrder', () => {
Expand All @@ -424,8 +416,10 @@ describe('PayPalCommerceAlternativeMethodsButtonStrategy', () => {

describe('#handleClick', () => {
beforeEach(() => {
jest.spyOn(paymentIntegrationService, 'createBuyNowCart').mockReturnValue(buyNowCart);
jest.spyOn(paymentIntegrationService, 'loadCheckout').mockReturnValue(true);
jest.spyOn(paymentIntegrationService, 'createBuyNowCart').mockReturnValue(
Promise.resolve(buyNowCart),
);
jest.spyOn(paymentIntegrationService, 'loadCheckout');
});

it('creates buy now cart on button click', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ export default class PayPalCommerceAlternativeMethodsButtonStrategy
methodId: string,
paypalcommercealternativemethods: PayPalCommerceAlternativeMethodsButtonOptions,
): void {
const { apm, buyNowInitializeOptions, style } = paypalcommercealternativemethods;
const { apm, buyNowInitializeOptions, style, onEligibilityFailure } =
paypalcommercealternativemethods;

const paypalSdk = this.paypalCommerceIntegrationService.getPayPalSdkOrThrow();
const isAvailableFundingSource = Object.values(paypalSdk.FUNDING).includes(apm);
Expand Down Expand Up @@ -139,8 +140,8 @@ export default class PayPalCommerceAlternativeMethodsButtonStrategy

if (paypalButtonRender.isEligible()) {
paypalButtonRender.render(`#${containerId}`);
} else {
this.paypalCommerceIntegrationService.removeElement(containerId);
} else if (onEligibilityFailure && typeof onEligibilityFailure === 'function') {
onEligibilityFailure();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export default interface PayPalCommerceCreditButtonInitializeOptions {
* A callback that gets called when payment complete on paypal side.
*/
onComplete?(): void;

/**
*
* A callback that gets called when PayPal SDK restricts to render PayPal component.
*
*/
onEligibilityFailure?(): void;
}

export interface WithPayPalCommerceCreditButtonInitializeOptions {
Expand Down
Loading