Skip to content

Commit

Permalink
feat(payment): PAYPAL-2725 added an ability to switch braintree sdk v…
Browse files Browse the repository at this point in the history
…ersion (core part) (#2065)
  • Loading branch information
serhii-tkachenko authored Jul 20, 2023
1 parent 94a4ce3 commit 29d5451
Show file tree
Hide file tree
Showing 31 changed files with 266 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ describe('BraintreePaypalButtonStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
});

Expand All @@ -283,6 +284,7 @@ describe('BraintreePaypalButtonStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
expect(braintreeSDKCreator.getPaypalCheckout).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,16 @@ export default class BraintreePaypalButtonStrategy implements CheckoutButtonStra
currencyCode = state.cart.getCartOrThrow().currency.code;
}

if (!paymentMethod.clientToken) {
const { clientToken, initializationData } = paymentMethod;

if (!clientToken || !initializationData) {
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
}

const paypalCheckoutOptions: Partial<BraintreePaypalSdkCreatorConfig> = {
currency: currencyCode,
intent: paymentMethod.initializationData?.intent,
isCreditEnabled: paymentMethod.initializationData?.isCreditEnabled,
intent: initializationData.intent,
isCreditEnabled: initializationData.isCreditEnabled,
};

const paypalCheckoutSuccessCallback = (
Expand All @@ -111,7 +113,7 @@ export default class BraintreePaypalButtonStrategy implements CheckoutButtonStra
const paypalCheckoutErrorCallback = (error: BraintreeError) =>
this._handleError(error, containerId, messagingContainerId, onError);

this._braintreeSDKCreator.initialize(paymentMethod.clientToken);
this._braintreeSDKCreator.initialize(clientToken, initializationData);
await this._braintreeSDKCreator.getPaypalCheckout(
paypalCheckoutOptions,
paypalCheckoutSuccessCallback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ describe('BraintreePaypalCreditButtonStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
});

Expand All @@ -297,6 +298,7 @@ describe('BraintreePaypalCreditButtonStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
expect(braintreeSDKCreator.getPaypalCheckout).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,16 @@ export default class BraintreePaypalCreditButtonStrategy implements CheckoutButt
currencyCode = state.cart.getCartOrThrow().currency.code;
}

if (!paymentMethod.clientToken) {
const { clientToken, initializationData } = paymentMethod;

if (!clientToken || !initializationData) {
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
}

const paypalCheckoutOptions: Partial<BraintreePaypalSdkCreatorConfig> = {
currency: currencyCode,
intent: paymentMethod.initializationData?.intent,
isCreditEnabled: paymentMethod.initializationData?.isCreditEnabled,
intent: initializationData.intent,
isCreditEnabled: initializationData.isCreditEnabled,
};

const paypalCheckoutCallback = (braintreePaypalCheckout: BraintreePaypalCheckout) =>
Expand All @@ -111,7 +113,7 @@ export default class BraintreePaypalCreditButtonStrategy implements CheckoutButt
const paypalCheckoutErrorCallback = (error: BraintreeError) =>
this._handleError(error, containerId, braintreepaypalcredit.onError);

this._braintreeSDKCreator.initialize(paymentMethod.clientToken);
this._braintreeSDKCreator.initialize(clientToken, initializationData);
await this._braintreeSDKCreator.getPaypalCheckout(
paypalCheckoutOptions,
paypalCheckoutCallback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ describe('BraintreeVenmoButtonStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
});

Expand All @@ -224,6 +225,7 @@ describe('BraintreeVenmoButtonStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
expect(braintreeSDKCreator.getVenmoCheckout).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ export default class BraintreeVenmoButtonStrategy implements CheckoutButtonStrat
this._paymentMethodActionCreator.loadPaymentMethod(methodId),
);
const paymentMethod = state.paymentMethods.getPaymentMethodOrThrow(methodId);
const { clientToken, initializationData } = paymentMethod;

if (!paymentMethod.clientToken) {
if (!clientToken || !initializationData) {
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
}

Expand All @@ -84,7 +85,7 @@ export default class BraintreeVenmoButtonStrategy implements CheckoutButtonStrat

this._onError = braintreevenmo?.onError || this._handleError;

this._braintreeSDKCreator.initialize(paymentMethod.clientToken);
this._braintreeSDKCreator.initialize(clientToken, initializationData);
await this._braintreeSDKCreator.getVenmoCheckout(
(braintreeVenmoCheckout) =>
this._handleInitializationVenmoSuccess(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ describe('BraintreePaypalCreditCustomerStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
});

Expand All @@ -296,6 +297,7 @@ describe('BraintreePaypalCreditCustomerStrategy', () => {

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
);
expect(braintreeSDKCreator.getPaypalCheckout).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,17 @@ export default class BraintreePaypalCreditCustomerStrategy implements CustomerSt
this._paymentMethodActionCreator.loadPaymentMethod(methodId),
);
const paymentMethod = state.paymentMethods.getPaymentMethodOrThrow(methodId);
const { clientToken, initializationData } = paymentMethod;

if (!paymentMethod.clientToken) {
if (!clientToken || !initializationData) {
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
}

const currencyCode = state.cart.getCartOrThrow().currency.code;
const paypalCheckoutOptions: Partial<BraintreePaypalSdkCreatorConfig> = {
currency: currencyCode,
intent: paymentMethod.initializationData?.intent,
isCreditEnabled: paymentMethod.initializationData?.isCreditEnabled,
intent: initializationData.intent,
isCreditEnabled: initializationData.isCreditEnabled,
};

const paypalCheckoutCallback = (braintreePaypalCheckout: BraintreePaypalCheckout) =>
Expand All @@ -94,7 +95,7 @@ export default class BraintreePaypalCreditCustomerStrategy implements CustomerSt
const paypalCheckoutErrorCallback = (error: BraintreeError) =>
this._handleError(error, braintreepaypalcredit);

this._braintreeSDKCreator.initialize(paymentMethod.clientToken);
this._braintreeSDKCreator.initialize(clientToken, initializationData);
await this._braintreeSDKCreator.getPaypalCheckout(
paypalCheckoutOptions,
paypalCheckoutCallback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import { CustomerInitializeOptions } from '../../customer-request-options';
import CustomerStrategyActionCreator from '../../customer-strategy-action-creator';
import { CustomerStrategyActionType } from '../../customer-strategy-actions';
import { getRemoteCustomer } from '../../internal-customers.mock';
import CustomerStrategy from '../customer-strategy';

import BraintreeVisaCheckoutCustomerStrategy from './braintree-visacheckout-customer-strategy';

Expand All @@ -49,7 +48,7 @@ describe('BraintreeVisaCheckoutCustomerStrategy', () => {
let paymentMethodMock: PaymentMethod;
let remoteCheckoutActionCreator: RemoteCheckoutActionCreator;
let store: CheckoutStore;
let strategy: CustomerStrategy;
let strategy: BraintreeVisaCheckoutCustomerStrategy;
let visaCheckoutScriptLoader: VisaCheckoutScriptLoader;
let visaCheckoutSDK: VisaCheckoutSDK;
let formPoster: FormPoster;
Expand All @@ -65,12 +64,12 @@ describe('BraintreeVisaCheckoutCustomerStrategy', () => {
braintreeVisaCheckoutPaymentProcessor.initialize = jest.fn(() => Promise.resolve());
braintreeVisaCheckoutPaymentProcessor.handleSuccess = jest.fn(() => Promise.resolve());

paymentMethodMock = { ...getBraintreeVisaCheckout(), clientToken: 'clientToken' };
paymentMethodMock = getBraintreeVisaCheckout();

store = createCheckoutStore(getCheckoutStoreState());

jest.spyOn(store, 'dispatch').mockReturnValue(Promise.resolve(store.getState()));
jest.spyOn(store.getState().paymentMethods, 'getPaymentMethod').mockReturnValue(
jest.spyOn(store.getState().paymentMethods, 'getPaymentMethodOrThrow').mockReturnValue(
paymentMethodMock,
);

Expand Down Expand Up @@ -181,6 +180,7 @@ describe('BraintreeVisaCheckoutCustomerStrategy', () => {

expect(braintreeVisaCheckoutPaymentProcessor.initialize).toHaveBeenCalledWith(
'clientToken',
{},
{
collectShipping: true,
currencyCode: 'USD',
Expand Down Expand Up @@ -292,7 +292,7 @@ describe('BraintreeVisaCheckoutCustomerStrategy', () => {
});

it('throws error if trying to sign in programmatically', () => {
expect(() => strategy.signIn({ email: 'foo@bar.com', password: 'foobar' })).toThrow();
expect(() => strategy.signIn()).toThrow();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export default class BraintreeVisaCheckoutCustomerStrategy implements CustomerSt
return this._store
.dispatch(this._paymentMethodActionCreator.loadPaymentMethod(methodId))
.then((state) => {
this._paymentMethod = state.paymentMethods.getPaymentMethod(methodId);
this._paymentMethod = state.paymentMethods.getPaymentMethodOrThrow(methodId);
const { clientToken, initializationData } = this._paymentMethod;

const checkout = state.checkout.getCheckout();
const storeConfig = state.config.getStoreConfig();
Expand All @@ -62,7 +63,7 @@ export default class BraintreeVisaCheckoutCustomerStrategy implements CustomerSt
throw new MissingDataError(MissingDataErrorType.MissingCheckoutConfig);
}

if (!this._paymentMethod || !this._paymentMethod.clientToken) {
if (!clientToken || !initializationData) {
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
}

Expand All @@ -78,7 +79,8 @@ export default class BraintreeVisaCheckoutCustomerStrategy implements CustomerSt
return Promise.all([
this._visaCheckoutScriptLoader.load(this._paymentMethod.config.testMode),
this._braintreeVisaCheckoutPaymentProcessor.initialize(
this._paymentMethod.clientToken,
clientToken,
initializationData,
initOptions,
),
])
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/payment/payment-methods.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PaymentMethodState from './payment-method-state';
export function getBraintree(): PaymentMethod {
return {
id: 'braintree',
clientToken: 'clientToken',
logoUrl:
'https://cdn.bcapp.dev/rHEAD/modules/checkout/braintree/images/paypal_powered_braintree_horizontal.png',
method: 'credit-card',
Expand All @@ -17,6 +18,10 @@ export function getBraintree(): PaymentMethod {
isVisaCheckoutEnabled: false,
},
type: 'PAYMENT_TYPE_API',
initializationData: {
isAcceleratedCheckoutEnabled: false,
merchantAccountId: '100000',
},
};
}

Expand Down Expand Up @@ -74,13 +79,15 @@ export function getBraintreePaypalCredit(): PaymentMethod {
export function getBraintreeVisaCheckout(): PaymentMethod {
return {
id: 'braintreevisacheckout',
clientToken: 'clientToken',
logoUrl: '',
method: 'paypal',
supportedCards: [],
config: {
testMode: false,
isVisaCheckoutEnabled: true,
},
initializationData: {},
type: 'PAYMENT_TYPE_API',
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,7 @@ describe('BraintreeCreditCardPaymentStrategy', () => {
Promise.resolve('my_session_id'),
);

paymentMethodMock = {
...getBraintree(),
clientToken: 'myToken',
initializationData: {
merchantAccountId: '100000',
},
};
paymentMethodMock = getBraintree();

store = createCheckoutStore(getCheckoutStoreState());

Expand Down Expand Up @@ -132,6 +126,10 @@ describe('BraintreeCreditCardPaymentStrategy', () => {
loadPaymentMethodAction,
);

jest.spyOn(store.getState().paymentMethods, 'getPaymentMethodOrThrow').mockReturnValue(
paymentMethodMock,
);

braintreeCreditCardPaymentStrategy = new BraintreeCreditCardPaymentStrategy(
store,
orderActionCreator,
Expand Down Expand Up @@ -169,6 +167,7 @@ describe('BraintreeCreditCardPaymentStrategy', () => {

expect(braintreePaymentProcessorMock.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
options.braintree,
);
expect(braintreePaymentProcessorMock.initializeHostedForm).not.toHaveBeenCalled();
Expand Down Expand Up @@ -196,6 +195,7 @@ describe('BraintreeCreditCardPaymentStrategy', () => {

expect(braintreePaymentProcessorMock.initialize).toHaveBeenCalledWith(
paymentMethodMock.clientToken,
paymentMethodMock.initializationData,
options.braintree,
);
expect(braintreePaymentProcessorMock.initializeHostedForm).toHaveBeenCalledWith(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ export default class BraintreeCreditCardPaymentStrategy implements PaymentStrate
this._paymentMethodActionCreator.loadPaymentMethod(options.methodId),
);

this._paymentMethod = state.paymentMethods.getPaymentMethod(options.methodId);
this._paymentMethod = state.paymentMethods.getPaymentMethodOrThrow(options.methodId);

if (!this._paymentMethod?.clientToken) {
const { clientToken, initializationData } = this._paymentMethod;

if (!clientToken || !initializationData) {
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
}

try {
this._braintreePaymentProcessor.initialize(
this._paymentMethod.clientToken,
clientToken,
initializationData,
options.braintree,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ describe('BraintreePaymentProcessor', () => {
let braintreeHostedForm: BraintreeHostedForm;
let overlay: Overlay;

const clientToken = 'clientToken';
const initializationData = {
isAcceleratedCheckoutEnabled: false,
};

beforeEach(() => {
braintreeSDKCreator = {} as BraintreeSDKCreator;
braintreeHostedForm = {} as BraintreeHostedForm;
Expand All @@ -58,9 +63,12 @@ describe('BraintreePaymentProcessor', () => {
overlay,
);

braintreePaymentProcessor.initialize('clientToken');
braintreePaymentProcessor.initialize(clientToken, initializationData);

expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith('clientToken');
expect(braintreeSDKCreator.initialize).toHaveBeenCalledWith(
clientToken,
initializationData,
);
});
});

Expand Down Expand Up @@ -537,7 +545,7 @@ describe('BraintreePaymentProcessor', () => {
overlay,
);

braintreePaymentProcessor.initialize('clientToken', {
braintreePaymentProcessor.initialize(clientToken, initializationData, {
threeDSecure: {
...getThreeDSecureOptionsMock(),
addFrame: (_error, _iframe, cancel) => {
Expand Down
Loading

0 comments on commit 29d5451

Please sign in to comment.