diff --git a/src/braintree/apple/braintreeOnShippingContactSelectedApple.ts b/src/braintree/apple/braintreeOnShippingContactSelectedApple.ts index 73718b0..44d1829 100644 --- a/src/braintree/apple/braintreeOnShippingContactSelectedApple.ts +++ b/src/braintree/apple/braintreeOnShippingContactSelectedApple.ts @@ -9,7 +9,11 @@ import { getValueByCurrency, } from 'src'; import { + changeShippingLine, + estimateShippingLines, + estimateTaxes, getCurrency, + getOrderInitialData, getShipping, getShippingLines, setTaxes @@ -20,6 +24,8 @@ export async function braintreeOnShippingContactSelectedApple(event: ApplePayShi const applePaySession = getBraintreeApplePaySessionChecked(); const shippingAddress = event.shippingContact; const address = formatApplePayContactToCheckoutAddress(shippingAddress, true); + const {general_settings} = getOrderInitialData(); + const rsaEnabled = general_settings.checkout_process.rsa_enabled; const fail = () => { const {totalAmountDue} = getTotals(); @@ -29,37 +35,53 @@ export async function braintreeOnShippingContactSelectedApple(event: ApplePayShi }); }; - const response = await callShippingAddressEndpoint(address, false); - - if(response.success){ - const shippingLinesResponse = await getShippingLines(API_RETRY); - const taxResponse = await setTaxes(API_RETRY); - - if(shippingLinesResponse.success && taxResponse.success){ - const {totalAmountDue} = getTotals(); - const displayItems = getPaymentRequestDisplayItems().map( - ({label, amount}) => ({ - label, - amount: getValueByCurrency(amount, currencyCode), - })); - const {available_shipping_lines: shippingLines} = getShipping(); + let responseSuccess = false; + if (rsaEnabled) { + const estimateShippingResponse = await estimateShippingLines(address, API_RETRY); + if (estimateShippingResponse.success) { + const {selected_shipping: selectedShipping, available_shipping_lines: shippingLines} = getShipping(); + if (!selectedShipping && shippingLines.length > 0) { + await changeShippingLine(shippingLines[0].id, API_RETRY); + } + await getShippingLines(API_RETRY); + } + const estimateTaxResponse = await estimateTaxes(address, API_RETRY); + if (estimateShippingResponse.success && estimateTaxResponse.success) { + responseSuccess = true; + } + } else { + const shippingResponse = await callShippingAddressEndpoint(address, false); + if (shippingResponse.success) { + const shippingLinesResponse = await getShippingLines(API_RETRY); + const taxResponse = await setTaxes(API_RETRY); + if (shippingLinesResponse.success && taxResponse.success) { + responseSuccess = true; + } + } + } - const shippingOptions = shippingLines.map(p => ({ - label: p.description, - detail: '', - amount: getValueByCurrency(p.amount, currencyCode), - identifier: p.id + if (responseSuccess) { + const {totalAmountDue} = getTotals(); + const displayItems = getPaymentRequestDisplayItems().map( + ({label, amount}) => ({ + label, + amount: getValueByCurrency(amount, currencyCode), })); + const {available_shipping_lines: shippingLines} = getShipping(); - applePaySession.completeShippingContactSelection({ - newLineItems: displayItems, - newShippingMethods: shippingOptions, - newTotal: {label: 'Total', amount: getValueByCurrency(totalAmountDue, currencyCode)}, - }); + const shippingOptions = shippingLines.map(p => ({ + label: p.description, + detail: '', + amount: getValueByCurrency(p.amount, currencyCode), + identifier: p.id + })); + + applePaySession.completeShippingContactSelection({ + newLineItems: displayItems, + newShippingMethods: shippingOptions, + newTotal: {label: 'Total', amount: getValueByCurrency(totalAmountDue, currencyCode)}, + }); - } else { - fail(); - } } else { fail(); } diff --git a/src/braintree/apple/braintreeOnShippingMethodSelectedApple.ts b/src/braintree/apple/braintreeOnShippingMethodSelectedApple.ts index 9fcc952..3cd73de 100644 --- a/src/braintree/apple/braintreeOnShippingMethodSelectedApple.ts +++ b/src/braintree/apple/braintreeOnShippingMethodSelectedApple.ts @@ -8,9 +8,12 @@ import { import { changeShippingLine, getCurrency, + getOrderInitialData, getShipping, getShippingLines, - setTaxes + setTaxes, + getShippingAddress, + estimateTaxes } from '@boldcommerce/checkout-frontend-library'; import ApplePayLineItem = ApplePayJS.ApplePayLineItem; import ApplePayShippingMethodSelectedEvent = ApplePayJS.ApplePayShippingMethodSelectedEvent; @@ -21,13 +24,21 @@ export async function braintreeOnShippingMethodSelectedApple(event: ApplePayShip const {available_shipping_lines: shippingLines} = getShipping(); const selectedShippingMethod = event.shippingMethod; const option = shippingLines.find(line => line.id === selectedShippingMethod.identifier); + const {general_settings} = getOrderInitialData(); + const rsaEnabled = general_settings.checkout_process.rsa_enabled; + const address = getShippingAddress(); if (option) { const response = await changeShippingLine(option.id, API_RETRY); if (response.success) { const shippingLinesResponse = await getShippingLines(API_RETRY); - const taxResponse = await setTaxes(API_RETRY); + let taxResponse; + if (rsaEnabled) { + taxResponse = await estimateTaxes(address, API_RETRY); + } else { + taxResponse = await setTaxes(API_RETRY); + } if (shippingLinesResponse.success && taxResponse.success) { const {totalAmountDue} = getTotals(); diff --git a/src/braintree/google/braintreeOnPaymentDataChangeGoogle.ts b/src/braintree/google/braintreeOnPaymentDataChangeGoogle.ts index 7a2a597..e18b0c9 100644 --- a/src/braintree/google/braintreeOnPaymentDataChangeGoogle.ts +++ b/src/braintree/google/braintreeOnPaymentDataChangeGoogle.ts @@ -6,11 +6,14 @@ import {callShippingAddressEndpoint, getTotals, getValueByCurrency} from 'src/ut import { changeShippingLine, getCurrency, + getOrderInitialData, getShipping, getShippingLines, - setTaxes + setTaxes, + estimateShippingLines, + estimateTaxes, } from '@boldcommerce/checkout-frontend-library'; -import {API_RETRY} from 'src/types'; +import {API_RETRY, BRAINTREE_GOOGLE_EMPTY_SHIPPING_OPTION} from 'src/types'; import CallbackIntent = google.payments.api.CallbackIntent; import {braintreeConstants} from 'src/variables'; @@ -18,13 +21,18 @@ export async function braintreeOnPaymentDataChangeGoogle(intermediatePaymentData const {callbackTrigger, shippingAddress, shippingOptionData} = intermediatePaymentData; const paymentDataRequestUpdate: PaymentDataRequestUpdate = {}; const intent = callbackTrigger === braintreeConstants.GOOGLEPAY_TRIGGER_INITIALIZE ? braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_ADDRESS : callbackTrigger as CallbackIntent; + const {general_settings} = getOrderInitialData(); + const rsaEnabled = general_settings.checkout_process.rsa_enabled; switch (callbackTrigger) { case braintreeConstants.GOOGLEPAY_TRIGGER_INITIALIZE: case braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_OPTION: case braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_ADDRESS: { - if (shippingAddress) { - const address = formatBraintreeShippingAddressGoogle(shippingAddress, true); + let shippingLinesResponse; + const address = formatBraintreeShippingAddressGoogle(shippingAddress, true); + if (rsaEnabled) { + shippingLinesResponse = await estimateShippingLines(address, API_RETRY); + } else { const shippingAddressResponse = await callShippingAddressEndpoint(address, false); if (!shippingAddressResponse.success) { paymentDataRequestUpdate.error = { @@ -34,11 +42,12 @@ export async function braintreeOnPaymentDataChangeGoogle(intermediatePaymentData }; return paymentDataRequestUpdate; } + shippingLinesResponse = await getShippingLines(API_RETRY); } - const shippingLinesResponse = await getShippingLines(API_RETRY); + const {selected_shipping: selectedShipping, available_shipping_lines: shippingLines} = getShipping(); if (shippingLinesResponse.success) { - if (shippingOptionData) { + if (shippingOptionData && shippingOptionData.id !== BRAINTREE_GOOGLE_EMPTY_SHIPPING_OPTION) { const option = shippingLines.find(line => line.id === shippingOptionData.id); option && await changeShippingLine(option.id, API_RETRY); } else if (!selectedShipping && shippingLines.length > 0) { @@ -47,7 +56,11 @@ export async function braintreeOnPaymentDataChangeGoogle(intermediatePaymentData await getShippingLines(API_RETRY); } - await setTaxes(API_RETRY); + if (rsaEnabled) { + await estimateTaxes(address, API_RETRY); + } else { + await setTaxes(API_RETRY); + } const {iso_code: currencyCode} = getCurrency(); const {totalAmountDue} = getTotals(); diff --git a/src/paypal/paypalOnShippingChange.ts b/src/paypal/paypalOnShippingChange.ts index 8ff0c7c..cd1f594 100644 --- a/src/paypal/paypalOnShippingChange.ts +++ b/src/paypal/paypalOnShippingChange.ts @@ -10,6 +10,9 @@ import { } from 'src'; import { changeShippingLine, + estimateShippingLines, + estimateTaxes, + getOrderInitialData, getShipping, getShippingLines, setTaxes, @@ -20,31 +23,48 @@ export async function paypalOnShippingChange(data: OnShippingChangeData, actions const {shipping_address: address, selected_shipping_option: selectedOption} = data; const {reject, order: {patch: patch}} = actions; const {MAX_STRING_LENGTH: maxStringSize} = paypalConstants; + const {general_settings} = getOrderInitialData(); + const rsaEnabled = general_settings.checkout_process.rsa_enabled; if (address) { const formattedAddress = formatPaypalToApiAddress(address, undefined, undefined , getPhoneNumber()); - const success = true; - - const shippingAddressResponse = await callShippingAddressEndpoint(formattedAddress, false); - if (!shippingAddressResponse.success) { - return reject(); + let success = false; + if (rsaEnabled) { + const shippingLinesResponse = await estimateShippingLines(formattedAddress, API_RETRY); + if (shippingLinesResponse.success) { + success = true; + } + } else { + const shippingAddressResponse = await callShippingAddressEndpoint(formattedAddress, false); + if (!shippingAddressResponse.success) { + return reject(); + } + const shippingLinesResponse = await getShippingLines(API_RETRY); + if (shippingLinesResponse.success) { + success = true; + } } - if(success) { - const shippingLinesResponse = await getShippingLines(API_RETRY); + + if (success) { const {selected_shipping: selectedShipping, available_shipping_lines: shippingLines} = getShipping(); - if (shippingLinesResponse.success) { - if (selectedOption) { - const option = shippingLines.find(line => isSimilarStrings(line.description.substring(0, maxStringSize), selectedOption.label)); - option && await changeShippingLine(option.id, API_RETRY); - } else if (!selectedShipping && shippingLines.length > 0) { - await changeShippingLine(shippingLines[0].id, API_RETRY); - } - await getShippingLines(API_RETRY); + if (selectedOption) { + const option = shippingLines.find(line => isSimilarStrings(line.description.substring(0, maxStringSize), selectedOption.label)); + option && await changeShippingLine(option.id, API_RETRY); + } else if (!selectedShipping && shippingLines.length > 0) { + await changeShippingLine(shippingLines[0].id, API_RETRY); } + await getShippingLines(API_RETRY); } } - const taxResponse = await setTaxes(API_RETRY); + + let taxResponse; + if (rsaEnabled && address) { + const formattedAddress = formatPaypalToApiAddress(address, undefined, undefined , getPhoneNumber()); + taxResponse = await estimateTaxes(formattedAddress, API_RETRY); + } else { + taxResponse = await setTaxes(API_RETRY); + } if (taxResponse.success) { const patchOperations = getPaypalPatchOperations(!!selectedOption); diff --git a/src/stripe/addStripePayment.ts b/src/stripe/addStripePayment.ts index afc98a7..999732a 100644 --- a/src/stripe/addStripePayment.ts +++ b/src/stripe/addStripePayment.ts @@ -4,7 +4,7 @@ import { getOrderInitialData, IAddPaymentRequest, setBillingAddress, - updateShippingAddress + setTaxes, } from '@boldcommerce/checkout-frontend-library'; import { formatStripeBillingAddress, @@ -12,7 +12,8 @@ import { getFirstAndLastName, orderProcessing, formatStripeShippingAddress, - getTotals + getTotals, + callShippingAddressEndpoint } from 'src'; export async function addStripePayment(event: IStripePaymentEvent, stripeGatewayId: string): Promise { @@ -32,22 +33,26 @@ export async function addStripePayment(event: IStripePaymentEvent, stripeGateway shippingPhoneNumber = event.payerPhone; } const address = formatStripeShippingAddress(shippingAddress, shippingPhoneNumber); - await updateShippingAddress(address, API_RETRY).then(async (shippingResult) => { + await callShippingAddressEndpoint(address, true).then(async (shippingResult) => { if (shippingResult.success) { const billingAddress = formatStripeBillingAddress(card, event.payerName, event.payerPhone); await setBillingAddress(billingAddress, API_RETRY).then(async (billingResult) => { if (billingResult.success) { - const walletPayType = window.ApplePaySession && ApplePaySession.canMakePayments() ? 'applepay' : 'paywithgoogle'; - const payment: IAddPaymentRequest = { - token: token.id, - gateway_public_id: stripeGatewayId, - currency: card.currency, - amount: totalAmountDue, - wallet_pay_type: walletPayType, - }; - await addPayment(payment, API_RETRY).then(async (paymentResult) => { - if (paymentResult.success) { - success = true; + await setTaxes(API_RETRY).then(async (taxResult) => { + if (taxResult.success) { + const walletPayType = window.ApplePaySession && ApplePaySession.canMakePayments() ? 'applepay' : 'paywithgoogle'; + const payment: IAddPaymentRequest = { + token: token.id, + gateway_public_id: stripeGatewayId, + currency: card.currency, + amount: totalAmountDue, + wallet_pay_type: walletPayType, + }; + await addPayment(payment, API_RETRY).then(async (paymentResult) => { + if (paymentResult.success) { + success = true; + } + }); } }); } diff --git a/src/stripe/changeStripeShippingLines.ts b/src/stripe/changeStripeShippingLines.ts index 1725715..015c198 100644 --- a/src/stripe/changeStripeShippingLines.ts +++ b/src/stripe/changeStripeShippingLines.ts @@ -1,23 +1,47 @@ -import {changeShippingLine} from '@boldcommerce/checkout-frontend-library'; +import { + changeShippingLine, + estimateTaxes, + getOrderInitialData, + getShippingAddress, + getShippingLines, + setTaxes +} from '@boldcommerce/checkout-frontend-library'; import {API_RETRY, IStripeEvent, IStripeShippingOptions, getPaymentRequestDisplayItems, getTotals} from 'src'; export async function changeStripeShippingLines(event: IStripeEvent): Promise { const shippingOption = event.shippingOption as IStripeShippingOptions; const response = await changeShippingLine(shippingOption.id, API_RETRY); const displayItems = getPaymentRequestDisplayItems(); + const {general_settings} = getOrderInitialData(); + const rsaEnabled = general_settings.checkout_process.rsa_enabled; + const address = getShippingAddress(); - if(response.success){ - const {totalAmountDue} = getTotals(); - const total = { - label: 'Total', - amount: totalAmountDue - }; + if (response.success) { + const shippingLinesResponse = await getShippingLines(API_RETRY); + let taxResponse; + if (rsaEnabled) { + taxResponse = await estimateTaxes(address, API_RETRY); + } else { + taxResponse = await setTaxes(API_RETRY); + } - event.updateWith({ - total: total, - status: 'success', - displayItems: displayItems - }); + if (shippingLinesResponse.success && taxResponse.success) { + const {totalAmountDue} = getTotals(); + const total = { + label: 'Total', + amount: totalAmountDue + }; + + event.updateWith({ + total: total, + status: 'success', + displayItems: displayItems + }); + } else { + event.updateWith({ + status:'fail' + }); + } } else { event.updateWith({ status:'fail' diff --git a/src/stripe/checkStripeAddress.ts b/src/stripe/checkStripeAddress.ts index a7728eb..23df6fc 100644 --- a/src/stripe/checkStripeAddress.ts +++ b/src/stripe/checkStripeAddress.ts @@ -9,6 +9,10 @@ import { getTotals } from 'src'; import { + changeShippingLine, + estimateShippingLines, + estimateTaxes, + getOrderInitialData, getShipping, getShippingLines, setShippingAddress, @@ -19,33 +23,62 @@ export async function checkStripeAddress(event: IStripeEvent): Promise { let error = false; const shippingAddress = event.shippingAddress as IStripeAddress; const address = formatStripeShippingAddress(shippingAddress, getPhoneNumber(shippingAddress.phone)); - const response = await setShippingAddress(address, API_RETRY); - - if(response.success){ - const shippingLinesResponse = await getShippingLines(API_RETRY); - const taxResponse = await setTaxes(API_RETRY); - - if(shippingLinesResponse.success && taxResponse.success){ - - const {totalAmountDue} = getTotals(); - const displayItems = getPaymentRequestDisplayItems(); - const {available_shipping_lines: shippingLines} = getShipping(); - if(shippingLines.length > 0) { - const shippingOptions = shippingLines.map(p => ({id: p.id, label: p.description, amount: p.amount})); - const total: IStripePaymentItem = { - label: 'Total', - amount: totalAmountDue - }; - - event.updateWith({ - total: total, - status: 'success', - shippingOptions: shippingOptions, - displayItems: displayItems - }); - } else { - error = true; + const {general_settings} = getOrderInitialData(); + const rsaEnabled = general_settings.checkout_process.rsa_enabled; + + let shippingLinesResponse; + let successResponse = false; + if (rsaEnabled) { + shippingLinesResponse = await estimateShippingLines(address, API_RETRY); + } else { + const response = await setShippingAddress(address, API_RETRY); + if (response.success) { + shippingLinesResponse = await getShippingLines(API_RETRY); + } + } + + if (shippingLinesResponse && shippingLinesResponse.success) { + const {selected_shipping: selectedShipping, available_shipping_lines: shippingLines} = getShipping(); + if (!selectedShipping && shippingLines.length > 0) { + await changeShippingLine(shippingLines[0].id, API_RETRY); + } + await getShippingLines(API_RETRY); + } + + if (rsaEnabled) { + if (shippingLinesResponse && shippingLinesResponse.success) { + const taxResponse = await estimateTaxes(address, API_RETRY); + if (taxResponse.success) { + successResponse = true; } + } + } else { + if (shippingLinesResponse && shippingLinesResponse.success) { + const taxResponse = await setTaxes(API_RETRY); + if (taxResponse.success) { + successResponse = true; + } + } + } + + + if (successResponse) { + const {totalAmountDue} = getTotals(); + const displayItems = getPaymentRequestDisplayItems(); + const {available_shipping_lines: shippingLines} = getShipping(); + if(shippingLines.length > 0) { + const shippingOptions = shippingLines.map(p => ({id: p.id, label: p.description, amount: p.amount})); + const total: IStripePaymentItem = { + label: 'Total', + amount: totalAmountDue + }; + + event.updateWith({ + total: total, + status: 'success', + shippingOptions: shippingOptions, + displayItems: displayItems + }); } else { error = true; } diff --git a/src/types/constant.ts b/src/types/constant.ts index dbf5ea6..3d9cc7a 100644 --- a/src/types/constant.ts +++ b/src/types/constant.ts @@ -1 +1,2 @@ export const API_RETRY = 1; +export const BRAINTREE_GOOGLE_EMPTY_SHIPPING_OPTION = 'shipping_option_unselected'; diff --git a/tests/braintree/apple/braintreeOnShippingContactSelectedApple.test.ts b/tests/braintree/apple/braintreeOnShippingContactSelectedApple.test.ts index 2941c72..95d7d37 100644 --- a/tests/braintree/apple/braintreeOnShippingContactSelectedApple.test.ts +++ b/tests/braintree/apple/braintreeOnShippingContactSelectedApple.test.ts @@ -9,16 +9,21 @@ import { } from 'src'; import { baseReturnObject, + estimateShippingLines, + estimateTaxes, getApplicationState, getCurrency, + getOrderInitialData, getShipping, getShippingLines, + IOrderInitialData, setTaxes } from '@boldcommerce/checkout-frontend-library'; import { addressesMock, applicationStateMock, currencyMock, + orderInitialDataMock, shippingMock } from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; import ApplePayShippingContactSelectedEvent = ApplePayJS.ApplePayShippingContactSelectedEvent; @@ -33,6 +38,9 @@ jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getShipping'); jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getApplicationState'); jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/getShippingLines'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getOrderInitialData'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/estimateTaxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/estimateShippingLines'); const getBraintreeApplePaySessionCheckedMock = mocked(getBraintreeApplePaySessionChecked, true); const formatApplePayContactToCheckoutAddressMock = mocked(formatApplePayContactToCheckoutAddress, true); const getPaymentRequestDisplayItemsMock = mocked(getPaymentRequestDisplayItems, true); @@ -42,6 +50,9 @@ const getShippingMock = mocked(getShipping, true); const getApplicationStateMock = mocked(getApplicationState, true); const setTaxesMock = mocked(setTaxes, true); const getShippingLinesMock = mocked(getShippingLines, true); +const getOrderInitialDataMock = mocked(getOrderInitialData, true); +const estimateShippingLinesMock = mocked(estimateShippingLines, true); +const estimateTaxesMock = mocked(estimateTaxes, true); describe('testing braintreeOnShippingContactSelectedApple function',() => { const successReturn = {...baseReturnObject, success: true}; @@ -69,6 +80,7 @@ describe('testing braintreeOnShippingContactSelectedApple function',() => { beforeEach(() => { jest.resetAllMocks(); + getBraintreeApplePaySessionCheckedMock.mockReturnValue(applePaySessionObj); getCurrencyMock.mockReturnValue(currencyMock); getShippingMock.mockReturnValue(shippingMock); @@ -78,9 +90,12 @@ describe('testing braintreeOnShippingContactSelectedApple function',() => { getShippingLinesMock.mockReturnValue(Promise.resolve(successReturn)); setTaxesMock.mockReturnValue(Promise.resolve(successReturn)); getPaymentRequestDisplayItemsMock.mockReturnValueOnce(displayItemMock); + getOrderInitialDataMock.mockReturnValue(orderInitialDataMock); + estimateShippingLinesMock.mockReturnValue(Promise.resolve(successReturn)); + estimateTaxesMock.mockReturnValue(Promise.resolve(successReturn)); }); - test('call successfully',async () => { + test('call successfully without rsa',async () => { const expectedCompleteParam = { newLineItems: displayItemMappedMock, newShippingMethods: shippingMethodsMock, @@ -106,30 +121,104 @@ describe('testing braintreeOnShippingContactSelectedApple function',() => { }); }); + test('call successfully with rsa',async () => { + const expectedCompleteParam = { + newLineItems: displayItemMappedMock, + newShippingMethods: shippingMethodsMock, + newTotal: {amount: '100.00', label: 'Total'} + }; + + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + getOrderInitialDataMock.mockReturnValue(initialData); + + await braintreeOnShippingContactSelectedApple(eventMock).then(() => { + expect(getCurrencyMock).toBeCalledTimes(1); + expect(getBraintreeApplePaySessionCheckedMock).toBeCalledTimes(1); + expect(formatApplePayContactToCheckoutAddressMock).toBeCalledTimes(1); + expect(formatApplePayContactToCheckoutAddressMock).toBeCalledWith(addressContact, true); + expect(callShippingAddressEndpointMock).toBeCalledTimes(0); + expect(estimateShippingLinesMock).toBeCalledTimes(1); + expect(estimateTaxesMock).toBeCalledTimes(1); + expect(getApplicationStateMock).toBeCalledTimes(1); + expect(getPaymentRequestDisplayItemsMock).toBeCalledTimes(1); + expect(getShippingMock).toBeCalledTimes(2); + expect(applePaySessionCompleteShippingContactSelection).toBeCalledTimes(1); + expect(applePaySessionCompleteShippingContactSelection).toBeCalledWith(expectedCompleteParam); + }); + }); + const failureResponse = {...baseReturnObject, success: false}; const failureData = [ { - name: 'Shipping Address', + name: 'Shipping Address without RSA', shippingAddressResp: failureResponse, shippingLinesResp: successReturn, setTaxesResp: successReturn, + estimateShippingResp: successReturn, + estimateTaxResp: successReturn, shippingLineTimes: 0, - setTaxesTimes: 0 + setTaxesTimes: 0, + estimateShippingTimes: 0, + estimateTaxTimes: 0, + rsaEnabled: false, + getShippingTimes: 0, }, { - name: 'Shipping Lines', + name: 'Shipping Lines without RSA', shippingAddressResp: successReturn, shippingLinesResp: failureResponse, setTaxesResp: successReturn, + estimateShippingResp: successReturn, + estimateTaxResp: successReturn, shippingLineTimes: 1, - setTaxesTimes: 1 + setTaxesTimes: 1, + estimateShippingTimes: 0, + estimateTaxTimes: 0, + rsaEnabled: false, + getShippingTimes: 0, }, { - name: 'Set Taxes', + name: 'Set Taxes without RSA', shippingAddressResp: successReturn, shippingLinesResp: successReturn, setTaxesResp: failureResponse, + estimateShippingResp: successReturn, + estimateTaxResp: successReturn, shippingLineTimes: 1, - setTaxesTimes: 1 + setTaxesTimes: 1, + estimateShippingTimes: 0, + estimateTaxTimes: 0, + rsaEnabled: false, + getShippingTimes: 0, }, + { + name: 'Estimate Shipping with RSA', + shippingAddressResp: successReturn, + shippingLinesResp: successReturn, + setTaxesResp: successReturn, + estimateShippingResp: failureResponse, + estimateTaxResp: successReturn, + shippingLineTimes: 0, + setTaxesTimes: 0, + estimateShippingTimes: 1, + estimateTaxTimes: 1, + rsaEnabled: true, + getShippingTimes: 0, + }, { + name: 'Estimate tax with RSA', + shippingAddressResp: successReturn, + shippingLinesResp: successReturn, + setTaxesResp: successReturn, + estimateShippingResp: successReturn, + estimateTaxResp: failureResponse, + shippingLineTimes: 1, + setTaxesTimes: 0, + estimateShippingTimes: 1, + estimateTaxTimes: 1, + rsaEnabled: true, + getShippingTimes: 1, + } ]; test.each(failureData)('call failure in $name response',async ( @@ -137,31 +226,51 @@ describe('testing braintreeOnShippingContactSelectedApple function',() => { shippingAddressResp, shippingLinesResp, setTaxesResp, + estimateShippingResp, + estimateTaxResp, shippingLineTimes, - setTaxesTimes + setTaxesTimes, + estimateShippingTimes, + estimateTaxTimes, + rsaEnabled, + getShippingTimes } ) => { global.window.ApplePayError = Error; callShippingAddressEndpointMock.mockReturnValueOnce(Promise.resolve(shippingAddressResp)); getShippingLinesMock.mockReturnValueOnce(Promise.resolve(shippingLinesResp)); setTaxesMock.mockReturnValueOnce(Promise.resolve(setTaxesResp)); + estimateShippingLinesMock.mockReturnValue(Promise.resolve(estimateShippingResp)); + estimateTaxesMock.mockReturnValue(Promise.resolve(estimateTaxResp)); const expectedCompleteParam = { errors: [new Error('shippingContactInvalid')], newTotal: {amount: '100.00', label: 'Total'} }; + if (rsaEnabled) { + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + getOrderInitialDataMock.mockReturnValue(initialData); + } + await braintreeOnShippingContactSelectedApple(eventMock).then(() => { expect(getCurrencyMock).toBeCalledTimes(1); expect(getBraintreeApplePaySessionCheckedMock).toBeCalledTimes(1); expect(formatApplePayContactToCheckoutAddressMock).toBeCalledTimes(1); expect(formatApplePayContactToCheckoutAddressMock).toBeCalledWith(addressContact, true); - expect(callShippingAddressEndpointMock).toBeCalledTimes(1); - expect(callShippingAddressEndpointMock).toBeCalledWith(addressesMock.shipping, false); + if (!rsaEnabled) { + expect(callShippingAddressEndpointMock).toBeCalledTimes(1); + expect(callShippingAddressEndpointMock).toBeCalledWith(addressesMock.shipping, false); + } expect(getShippingLinesMock).toBeCalledTimes(shippingLineTimes); expect(setTaxesMock).toBeCalledTimes(setTaxesTimes); + expect(estimateShippingLinesMock).toBeCalledTimes(estimateShippingTimes); + expect(estimateTaxesMock).toBeCalledTimes(estimateTaxTimes); expect(getApplicationStateMock).toBeCalledTimes(1); expect(getPaymentRequestDisplayItemsMock).toBeCalledTimes(0); - expect(getShippingMock).toBeCalledTimes(0); + expect(getShippingMock).toBeCalledTimes(getShippingTimes); expect(applePaySessionCompleteShippingContactSelection).toBeCalledTimes(1); expect(applePaySessionCompleteShippingContactSelection).toBeCalledWith(expectedCompleteParam); }); diff --git a/tests/braintree/apple/braintreeOnShippingMethodSelectedApple.test.ts b/tests/braintree/apple/braintreeOnShippingMethodSelectedApple.test.ts index b52195f..4208906 100644 --- a/tests/braintree/apple/braintreeOnShippingMethodSelectedApple.test.ts +++ b/tests/braintree/apple/braintreeOnShippingMethodSelectedApple.test.ts @@ -8,14 +8,21 @@ import { import { baseReturnObject, changeShippingLine, + estimateTaxes, getApplicationState, getCurrency, + getOrderInitialData, getShipping, - getShippingLines, + getShippingLines, IOrderInitialData, setTaxes } from '@boldcommerce/checkout-frontend-library'; import ApplePayShippingMethodSelectedEvent = ApplePayJS.ApplePayShippingMethodSelectedEvent; -import {applicationStateMock, currencyMock, shippingMock} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; +import { + applicationStateMock, + currencyMock, + orderInitialDataMock, + shippingMock +} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; jest.mock('src/braintree/manageBraintreeState'); jest.mock('src/utils/getPaymentRequestDisplayItems'); @@ -25,6 +32,8 @@ jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getApplicationState jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/getShippingLines'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/changeShippingLine'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/estimateTaxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getOrderInitialData'); const getBraintreeApplePaySessionCheckedMock = mocked(getBraintreeApplePaySessionChecked, true); const getPaymentRequestDisplayItemsMock = mocked(getPaymentRequestDisplayItems, true); const changeShippingLineMock = mocked(changeShippingLine, true); @@ -33,6 +42,8 @@ const getShippingMock = mocked(getShipping, true); const getApplicationStateMock = mocked(getApplicationState, true); const setTaxesMock = mocked(setTaxes, true); const getShippingLinesMock = mocked(getShippingLines, true); +const getOrderInitialDataMock = mocked(getOrderInitialData, true); +const estimateTaxesMock = mocked(estimateTaxes, true); describe('testing braintreeOnShippingMethodSelectedApple function',() => { const successReturn = {...baseReturnObject, success: true}; @@ -61,6 +72,8 @@ describe('testing braintreeOnShippingMethodSelectedApple function',() => { getShippingLinesMock.mockReturnValue(Promise.resolve(successReturn)); setTaxesMock.mockReturnValue(Promise.resolve(successReturn)); getPaymentRequestDisplayItemsMock.mockReturnValueOnce(displayItemMock); + getOrderInitialDataMock.mockReturnValue(orderInitialDataMock); + estimateTaxesMock.mockReturnValue(Promise.resolve(successReturn)); }); test('call successfully',async () => { @@ -86,4 +99,34 @@ describe('testing braintreeOnShippingMethodSelectedApple function',() => { }); }); + + test('call successfully with rsa',async () => { + const expectedCompleteParam = { + newLineItems: displayItemMappedMock, + newTotal: {amount: '100.00', label: 'Total'} + }; + + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + getOrderInitialDataMock.mockReturnValue(initialData); + + await braintreeOnShippingMethodSelectedApple(eventMock).then(() => { + expect(getCurrencyMock).toBeCalledTimes(1); + expect(getBraintreeApplePaySessionCheckedMock).toBeCalledTimes(1); + expect(getShippingMock).toBeCalledTimes(1); + expect(changeShippingLineMock).toBeCalledTimes(1); + expect(changeShippingLineMock).toBeCalledWith('test_select_shipping_line_id', API_RETRY); + expect(getShippingLinesMock).toBeCalledTimes(1); + expect(getShippingLinesMock).toBeCalledWith(API_RETRY); + expect(setTaxesMock).toBeCalledTimes(0); + expect(estimateTaxesMock).toBeCalledTimes(1); + expect(getApplicationStateMock).toBeCalledTimes(1); + expect(getPaymentRequestDisplayItemsMock).toBeCalledTimes(1); + expect(applePaySessionCompleteShippingMethodSelection).toBeCalledTimes(1); + expect(applePaySessionCompleteShippingMethodSelection).toBeCalledWith(expectedCompleteParam); + + }); + }); }); diff --git a/tests/braintree/google/braintreeOnPaymentDataChangeGoogle.test.ts b/tests/braintree/google/braintreeOnPaymentDataChangeGoogle.test.ts index 202ce0e..f19137c 100644 --- a/tests/braintree/google/braintreeOnPaymentDataChangeGoogle.test.ts +++ b/tests/braintree/google/braintreeOnPaymentDataChangeGoogle.test.ts @@ -16,12 +16,16 @@ import { getShippingLines, setTaxes, IApiReturnObject, - IShipping + IShipping, + getOrderInitialData, + estimateShippingLines, + estimateTaxes, + IOrderInitialData } from '@boldcommerce/checkout-frontend-library'; import { addressesMock, applicationStateMock, - currencyMock, + currencyMock, orderInitialDataMock, shippingMock } from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; import IntermediatePaymentData = google.payments.api.IntermediatePaymentData; @@ -37,6 +41,9 @@ jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getApplicationState jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/getShippingLines'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/changeShippingLine'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getOrderInitialData'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/estimateTaxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/estimateShippingLines'); const getBraintreeShippingOptionsGoogleMock = mocked(getBraintreeShippingOptionsGoogle, true); const formatBraintreeShippingAddressGoogleMock = mocked(formatBraintreeShippingAddressGoogle, true); const callShippingAddressEndpointMock = mocked(callShippingAddressEndpoint, true); @@ -46,6 +53,9 @@ const getApplicationStateMock = mocked(getApplicationState, true); const setTaxesMock = mocked(setTaxes, true); const getShippingLinesMock = mocked(getShippingLines, true); const changeShippingLineMock = mocked(changeShippingLine, true); +const getOrderInitialDataMock = mocked(getOrderInitialData, true); +const estimateShippingLinesMock = mocked(estimateShippingLines, true); +const estimateTaxesMock = mocked(estimateTaxes, true); describe('testing braintreeOnPaymentDataChangeGoogle function',() => { const successReturn = {...baseReturnObject, success: true}; @@ -74,6 +84,9 @@ describe('testing braintreeOnPaymentDataChangeGoogle function',() => { getShippingLinesMock.mockReturnValue(Promise.resolve(successReturn)); setTaxesMock.mockReturnValue(Promise.resolve(successReturn)); getBraintreeShippingOptionsGoogleMock.mockReturnValueOnce(shippingOptionsGoogleMock); + getOrderInitialDataMock.mockReturnValue(orderInitialDataMock); + estimateShippingLinesMock.mockReturnValue(Promise.resolve(successReturn)); + estimateTaxesMock.mockReturnValue(Promise.resolve(successReturn)); }); test('call successfully default trigger',async () => { @@ -98,25 +111,54 @@ describe('testing braintreeOnPaymentDataChangeGoogle function',() => { case: 'GOOGLEPAY_TRIGGER_INITIALIZE', callbackTrigger: braintreeConstants.GOOGLEPAY_TRIGGER_INITIALIZE, selected: shippingMock.selected_shipping, - option: shippingOptionData + option: shippingOptionData, + rsaEnabled: false, }, { case: 'GOOGLEPAY_INTENT_SHIPPING_OPTION', callbackTrigger: braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_OPTION, selected: shippingMock.selected_shipping, - option: shippingOptionData + option: shippingOptionData, + rsaEnabled: false, }, { case: 'GOOGLEPAY_INTENT_SHIPPING_ADDRESS', callbackTrigger: braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_ADDRESS, selected: shippingMock.selected_shipping, - option: shippingOptionData + option: shippingOptionData, + rsaEnabled: false, }, { case: 'No option, no selected option and GOOGLEPAY_INTENT_SHIPPING_ADDRESS', callbackTrigger: braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_ADDRESS, selected: null, - option: null + option: null, + rsaEnabled: false, + }, + { + case: 'GOOGLEPAY_TRIGGER_INITIALIZE and rsa', + callbackTrigger: braintreeConstants.GOOGLEPAY_TRIGGER_INITIALIZE, + selected: shippingMock.selected_shipping, + option: shippingOptionData, + rsaEnabled: true, + }, { + case: 'GOOGLEPAY_INTENT_SHIPPING_OPTION and rsa', + callbackTrigger: braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_OPTION, + selected: shippingMock.selected_shipping, + option: shippingOptionData, + rsaEnabled: true, + }, { + case: 'GOOGLEPAY_INTENT_SHIPPING_ADDRESS and rsa', + callbackTrigger: braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_ADDRESS, + selected: shippingMock.selected_shipping, + option: shippingOptionData, + rsaEnabled: true, + }, { + case: 'No option, no selected option and GOOGLEPAY_INTENT_SHIPPING_ADDRESS and rsa', + callbackTrigger: braintreeConstants.GOOGLEPAY_INTENT_SHIPPING_ADDRESS, + selected: null, + option: null, + rsaEnabled: true, }, ]; - test.each(triggerData)('call successfully $case trigger',async ({callbackTrigger,selected, option}) => { + test.each(triggerData)('call successfully $case trigger',async ({callbackTrigger,selected, option, rsaEnabled}) => { const newShippingMock = {...shippingMock, selected_shipping: selected} as IShipping; getShippingMock.mockReturnValueOnce(newShippingMock); const param = {...intermediatePaymentData, shippingOptionData: option, callbackTrigger: callbackTrigger} as unknown as IntermediatePaymentData; @@ -125,20 +167,34 @@ describe('testing braintreeOnPaymentDataChangeGoogle function',() => { newTransactionInfo: {currencyCode: 'USD', totalPrice: '100.00', totalPriceStatus: 'ESTIMATED'} }; + if (rsaEnabled) { + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + getOrderInitialDataMock.mockReturnValue(initialData); + } + const result = await braintreeOnPaymentDataChangeGoogle(param); expect(result).toStrictEqual(expectedResult); expect(formatBraintreeShippingAddressGoogleMock).toBeCalledTimes(1); expect(formatBraintreeShippingAddressGoogleMock).toBeCalledWith(addressContact, true); - expect(callShippingAddressEndpointMock).toBeCalledTimes(1); - expect(callShippingAddressEndpointMock).toBeCalledWith(addressesMock.shipping, false); - expect(getShippingLinesMock).toBeCalledTimes(2); + if (!rsaEnabled) { + expect(callShippingAddressEndpointMock).toBeCalledTimes(1); + expect(callShippingAddressEndpointMock).toBeCalledWith(addressesMock.shipping, false); + expect(getShippingLinesMock).toBeCalledTimes(2); + expect(setTaxesMock).toBeCalledTimes(1); + expect(setTaxesMock).toBeCalledWith(API_RETRY); + } else { + expect(estimateShippingLinesMock).toBeCalledTimes(1); + expect(estimateTaxesMock).toBeCalledTimes(1); + expect(getShippingLinesMock).toBeCalledTimes(1); + } expect(getShippingLinesMock).toBeCalledWith(API_RETRY); expect(getShippingMock).toBeCalledTimes(1); expect(changeShippingLineMock).toBeCalledTimes(1); expect(changeShippingLineMock).toBeCalledWith('test_select_shipping_line_id', API_RETRY); - expect(setTaxesMock).toBeCalledTimes(1); - expect(setTaxesMock).toBeCalledWith(API_RETRY); expect(getCurrencyMock).toBeCalledTimes(1); expect(getApplicationStateMock).toBeCalledTimes(1); expect(getBraintreeShippingOptionsGoogleMock).toBeCalledTimes(1); diff --git a/tests/paypal/paypalOnShippingChange.test.ts b/tests/paypal/paypalOnShippingChange.test.ts index b75d489..e165835 100644 --- a/tests/paypal/paypalOnShippingChange.test.ts +++ b/tests/paypal/paypalOnShippingChange.test.ts @@ -11,13 +11,17 @@ import {mocked} from 'jest-mock'; import { baseReturnObject, changeShippingLine, + estimateShippingLines, + estimateTaxes, + getOrderInitialData, getShipping, getShippingLines, + IOrderInitialData, ISetShippingAddressRequest, IShipping } from '@boldcommerce/checkout-frontend-library'; import {setTaxes} from '@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'; -import {shippingMock} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; +import {orderInitialDataMock, shippingMock} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; import {AmountWithBreakdown, ShippingInfoOption} from '@paypal/paypal-js/types/apis/orders'; jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getShipping'); @@ -26,6 +30,9 @@ jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/changeShippingLi jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'); jest.mock('@boldcommerce/checkout-frontend-library/lib/address/setShippingAddress'); jest.mock('@boldcommerce/checkout-frontend-library/lib/address/updateShippingAddress'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getOrderInitialData'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/estimateTaxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/estimateShippingLines'); jest.mock('src/paypal/formatPaypalToApiAddress'); jest.mock('src/paypal/getPaypalPatchOperations'); jest.mock('src/utils/callShippingAddressEndpoint'); @@ -36,6 +43,9 @@ const getShippingLinesMock = mocked(getShippingLines, true); const changeShippingLineMock = mocked(changeShippingLine, true); const setTaxesMock = mocked(setTaxes, true); const callShippingAddressEndpointMock = mocked(callShippingAddressEndpoint, true); +const getOrderInitialDataMock = mocked(getOrderInitialData, true); +const estimateShippingLinesMock = mocked(estimateShippingLines, true); +const estimateTaxesMock = mocked(estimateTaxes, true); describe('testing paypalOnShippingChange function', () => { const onShippingChangeActionsMock: OnShippingChangeActions = { @@ -108,6 +118,9 @@ describe('testing paypalOnShippingChange function', () => { changeShippingLineMock.mockReturnValue(Promise.resolve(successfulReturnObject)); setTaxesMock.mockReturnValue(Promise.resolve(successfulReturnObject)); callShippingAddressEndpointMock.mockReturnValue(Promise.resolve(successfulReturnObject)); + getOrderInitialDataMock.mockReturnValue(orderInitialDataMock); + estimateShippingLinesMock.mockReturnValue(Promise.resolve(successfulReturnObject)); + estimateTaxesMock.mockReturnValue(Promise.resolve(successfulReturnObject)); }); test('new addr, old addr empty, all data in and success API calls', async () => { @@ -129,6 +142,34 @@ describe('testing paypalOnShippingChange function', () => { expect(onShippingChangeActionsMock.order.patch).toHaveBeenCalledTimes(1); }); + test('new addr, old addr empty, all data in and success API calls with rsa', async () => { + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + getOrderInitialDataMock.mockReturnValue(initialData); + + const result = await paypalOnShippingChange(dataMock, onShippingChangeActionsMock); + + expect(result).toStrictEqual({id: '123'}); + expect(formatPaypalToApiAddressMock).toHaveBeenCalledTimes(2); + expect(formatPaypalToApiAddressMock).toHaveBeenCalledWith(dataMock.shipping_address, undefined, undefined , ''); + expect(callShippingAddressEndpointMock).toHaveBeenCalledTimes(0); + expect(estimateShippingLinesMock).toHaveBeenCalledTimes(1); + expect(estimateShippingLinesMock).toHaveBeenCalledWith(formattedAddress, API_RETRY); + expect(getShippingLinesMock).toHaveBeenCalledTimes(1); + expect(getShippingLinesMock).toHaveBeenCalledWith(API_RETRY); + expect(getShippingMock).toHaveBeenCalledTimes(1); + expect(changeShippingLineMock).toHaveBeenCalledTimes(0); + expect(setTaxesMock).toHaveBeenCalledTimes(0); + expect(estimateTaxesMock).toHaveBeenCalledTimes(1); + expect(estimateTaxesMock).toHaveBeenCalledWith(formattedAddress, API_RETRY); + expect(getPaypalPatchOperationsMock).toHaveBeenCalledTimes(1); + expect(getPaypalPatchOperationsMock).toHaveBeenCalledWith(true); + expect(onShippingChangeActionsMock.reject).toHaveBeenCalledTimes(0); + expect(onShippingChangeActionsMock.order.patch).toHaveBeenCalledTimes(1); + }); + test('no addr, no selected option and success API calls', async () => { const data = {...dataMock, shipping_address: undefined, selected_shipping_option: undefined}; diff --git a/tests/stripe/addStripePayment.test.ts b/tests/stripe/addStripePayment.test.ts index 926ed78..db2f096 100644 --- a/tests/stripe/addStripePayment.test.ts +++ b/tests/stripe/addStripePayment.test.ts @@ -5,7 +5,7 @@ import { getOrderInitialData, processOrder, setBillingAddress, - updateShippingAddress + setTaxes, } from '@boldcommerce/checkout-frontend-library'; import { formatStripeBillingAddress, @@ -15,7 +15,8 @@ import { IStripePaymentEvent, callGuestCustomerEndpoint, getTotals, - ITotals + ITotals, + callShippingAddressEndpoint } from 'src'; import {mocked} from 'jest-mock'; @@ -27,18 +28,20 @@ jest.mock('@boldcommerce/checkout-frontend-library/lib/state'); jest.mock('@boldcommerce/checkout-frontend-library/lib/customer'); jest.mock('@boldcommerce/checkout-frontend-library/lib/payment'); jest.mock('@boldcommerce/checkout-frontend-library/lib/order'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'); jest.mock('src/utils/callGuestCustomerEndpoint'); jest.mock('src/utils/getTotals'); - +jest.mock('src/utils/callShippingAddressEndpoint'); const formatStripeShippingAddressMock = mocked(formatStripeShippingAddress, true); const formatStripeBillingAddressMock = mocked(formatStripeBillingAddress, true); -const updateShippingAddressMock = mocked(updateShippingAddress, true); +const callShippingAddressEndpointMock = mocked(callShippingAddressEndpoint, true); const setBillingAddressMock = mocked(setBillingAddress, true); const addPaymentMock = mocked(addPayment, true); const processOrderMock = mocked(processOrder, true); const getTotalsMock = mocked(getTotals, true); const getOrderInitialDataMock = mocked(getOrderInitialData, true); const callGuestCustomerEndpointMock = mocked(callGuestCustomerEndpoint, true); +const setTaxesMock = mocked(setTaxes, true); const canMakePaymentsMock = jest.fn(); const applePaySession = {canMakePayments: canMakePaymentsMock}; @@ -53,11 +56,12 @@ describe('testing stripe payment function', () => { orderInitialData.general_settings.checkout_process.phone_number_required = true; const data = [ - {name: 'success on all endpoints', guestCustomer: successApi, updateShipping: successApi, setBilling: successApi, addPayment: successApi, processOrder: successApi, expected: 'success' }, - {name: 'failed guest customer', guestCustomer: failApi, updateShipping: successApi, setBilling: successApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, - {name: 'failed update shipping', guestCustomer: successApi, updateShipping: failApi, setBilling: successApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, - {name: 'failed update billing', guestCustomer: successApi, updateShipping: successApi, setBilling: failApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, - {name: 'failed add payment', guestCustomer: successApi, updateShipping: successApi, setBilling: successApi, addPayment: failApi, processOrder: successApi, expected: 'fail' }, + {name: 'success on all endpoints', guestCustomer: successApi, callShipping: successApi, setBilling: successApi, setTaxes: successApi, addPayment: successApi, processOrder: successApi, expected: 'success' }, + {name: 'failed guest customer', guestCustomer: failApi, callShipping: successApi, setBilling: successApi, setTaxes: successApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, + {name: 'failed update shipping', guestCustomer: successApi, callShipping: failApi, setBilling: successApi, setTaxes: successApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, + {name: 'failed update billing', guestCustomer: successApi, callShipping: successApi, setBilling: failApi, setTaxes: successApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, + {name: 'failed add payment', guestCustomer: successApi, callShipping: successApi, setBilling: successApi, setTaxes: successApi, addPayment: failApi, processOrder: successApi, expected: 'fail' }, + {name: 'failed on set taxes', guestCustomer: successApi, callShipping: successApi, setBilling: successApi, setTaxes: failApi, addPayment: successApi, processOrder: successApi, expected: 'fail' }, ]; const cardMock: IStripeCard = { @@ -123,10 +127,11 @@ describe('testing stripe payment function', () => { }); - test.each(data)('$name', async ({guestCustomer, updateShipping, setBilling, addPayment, processOrder, expected}) => { + test.each(data)('$name', async ({guestCustomer, callShipping, setBilling, setTaxes, addPayment, processOrder, expected}) => { callGuestCustomerEndpointMock.mockReturnValueOnce(Promise.resolve(guestCustomer)); - updateShippingAddressMock.mockReturnValueOnce(Promise.resolve(updateShipping)); + callShippingAddressEndpointMock.mockReturnValueOnce(Promise.resolve(callShipping)); setBillingAddressMock.mockReturnValueOnce(Promise.resolve(setBilling)); + setTaxesMock.mockReturnValueOnce(Promise.resolve(setTaxes)); addPaymentMock.mockReturnValueOnce(Promise.resolve(addPayment)); processOrderMock.mockReturnValueOnce(Promise.resolve(processOrder)); canMakePaymentsMock.mockReturnValueOnce(false); @@ -141,8 +146,9 @@ describe('testing stripe payment function', () => { localEventMock.payerName = 'John steve'; localEventMock.payerEmail = 'abc@gmail.com'; callGuestCustomerEndpointMock.mockReturnValueOnce(Promise.resolve(successApi)); - updateShippingAddressMock.mockReturnValueOnce(Promise.resolve(successApi)); + callShippingAddressEndpointMock.mockReturnValueOnce(Promise.resolve(successApi)); setBillingAddressMock.mockReturnValueOnce(Promise.resolve(successApi)); + setTaxesMock.mockReturnValueOnce(Promise.resolve(successApi)); addPaymentMock.mockReturnValueOnce(Promise.resolve(successApi)); processOrderMock.mockReturnValueOnce(Promise.resolve(successApi)); canMakePaymentsMock.mockReturnValueOnce(true); diff --git a/tests/stripe/changeStripeShippingLines.test.ts b/tests/stripe/changeStripeShippingLines.test.ts index a1e9185..8d011c7 100644 --- a/tests/stripe/changeStripeShippingLines.test.ts +++ b/tests/stripe/changeStripeShippingLines.test.ts @@ -9,16 +9,29 @@ import { import {mocked} from 'jest-mock'; import { baseReturnObject, - changeShippingLine + changeShippingLine, + estimateTaxes, + getOrderInitialData, + getShippingLines, + IOrderInitialData, + setTaxes } from '@boldcommerce/checkout-frontend-library'; - +import {orderInitialDataMock} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; jest.mock('@boldcommerce/checkout-frontend-library/lib/state'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/getShippingLines'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getOrderInitialData'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/estimateTaxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/setTaxes'); jest.mock('src/utils/getPaymentRequestDisplayItems'); jest.mock('src/utils/getTotals'); const getTotalsMock = mocked(getTotals, true); const changeShippingLineMock = mocked(changeShippingLine, true); const getPaymentRequestDisplayItemMock = mocked(getPaymentRequestDisplayItems, true); +const getShippingLinesMock = mocked(getShippingLines, true); +const getOrderInitialDataMock = mocked(getOrderInitialData, true); +const estimateTaxesMock = mocked(estimateTaxes, true); +const setTaxesMock = mocked(setTaxes, true); describe('testing change shipping lines function', () => { const orderTotal = 200; @@ -45,16 +58,49 @@ describe('testing change shipping lines function', () => { jest.clearAllMocks(); getTotalsMock.mockReturnValue(totals); getPaymentRequestDisplayItemMock.mockReturnValueOnce(displayItemMock); + getOrderInitialDataMock.mockReturnValue(orderInitialDataMock); + }); + + test('testing the function with success without rsa', async () => { + returnObject.success = true; + changeShippingLineMock.mockReturnValueOnce(Promise.resolve(returnObject)); + getShippingLinesMock.mockReturnValueOnce(Promise.resolve(returnObject)); + setTaxesMock.mockReturnValue(Promise.resolve(returnObject)); + await changeStripeShippingLines({shippingOption: shippingOptionMock, updateWith: updateWithMock}); + + expect(getTotalsMock).toHaveBeenCalledTimes(1); + expect(changeShippingLineMock).toHaveBeenCalledTimes(1); + expect(changeShippingLineMock).toHaveBeenCalledWith(shippingOptionMock.id, API_RETRY); + expect(setTaxesMock).toHaveBeenCalledWith(API_RETRY); + expect(updateWithMock).toHaveBeenCalledTimes(1); + expect(updateWithMock).toBeCalledWith({ + total: { + label: 'Total', + amount: orderTotal, + }, + status: 'success', + displayItems: displayItemMock + }); }); - test('testing the function with success', async () => { + test('testing the function with success with rsa', async () => { + + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + + getOrderInitialDataMock.mockReturnValue(initialData); returnObject.success = true; changeShippingLineMock.mockReturnValueOnce(Promise.resolve(returnObject)); + getShippingLinesMock.mockReturnValueOnce(Promise.resolve(returnObject)); + estimateTaxesMock.mockReturnValue(Promise.resolve(returnObject)); await changeStripeShippingLines({shippingOption: shippingOptionMock, updateWith: updateWithMock}); expect(getTotalsMock).toHaveBeenCalledTimes(1); expect(changeShippingLineMock).toHaveBeenCalledTimes(1); expect(changeShippingLineMock).toHaveBeenCalledWith(shippingOptionMock.id, API_RETRY); + expect(estimateTaxesMock).toHaveBeenCalledTimes(1); expect(updateWithMock).toHaveBeenCalledTimes(1); expect(updateWithMock).toBeCalledWith({ total: { @@ -66,18 +112,70 @@ describe('testing change shipping lines function', () => { }); }); - test('testing the function with failure', async () => { + test('testing the function failure without rsa', async () => { + returnObject.success = false; + changeShippingLineMock.mockReturnValueOnce(Promise.resolve(returnObject)); + getShippingLinesMock.mockReturnValueOnce(Promise.resolve(returnObject)); + setTaxesMock.mockReturnValue(Promise.resolve(returnObject)); + await changeStripeShippingLines({shippingOption: shippingOptionMock, updateWith: updateWithMock}); + + expect(getTotalsMock).toHaveBeenCalledTimes(0); + expect(changeShippingLineMock).toHaveBeenCalledTimes(1); + expect(changeShippingLineMock).toHaveBeenCalledWith(shippingOptionMock.id, API_RETRY); + expect(setTaxesMock).toHaveBeenCalledTimes(0); + expect(updateWithMock).toHaveBeenCalledTimes(1); + expect(updateWithMock).toBeCalledWith({ + status: 'fail' + }); + }); + + test('testing the function with failure with rsa', async () => { + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + + getOrderInitialDataMock.mockReturnValue(initialData); returnObject.success = false; changeShippingLineMock.mockReturnValueOnce(Promise.resolve(returnObject)); + getShippingLinesMock.mockReturnValueOnce(Promise.resolve(returnObject)); + estimateTaxesMock.mockReturnValue(Promise.resolve(returnObject)); + await changeStripeShippingLines({shippingOption: shippingOptionMock, updateWith: updateWithMock}); + + expect(getTotalsMock).toHaveBeenCalledTimes(0); + expect(changeShippingLineMock).toHaveBeenCalledTimes(1); + expect(changeShippingLineMock).toHaveBeenCalledWith(shippingOptionMock.id, API_RETRY); + expect(estimateTaxesMock).toHaveBeenCalledTimes(0); + expect(updateWithMock).toHaveBeenCalledTimes(1); + expect(updateWithMock).toBeCalledWith({ + status: 'fail' + }); + }); + + test('testing the tax with failure with rsa', async () => { + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + + getOrderInitialDataMock.mockReturnValue(initialData); + const successReturnObject = {...baseReturnObject, success: true}; + const failureReturnObject = {...baseReturnObject}; + changeShippingLineMock.mockReturnValueOnce(Promise.resolve(successReturnObject)); + getShippingLinesMock.mockReturnValueOnce(Promise.resolve(successReturnObject)); + estimateTaxesMock.mockReturnValue(Promise.resolve(failureReturnObject)); await changeStripeShippingLines({shippingOption: shippingOptionMock, updateWith: updateWithMock}); expect(getTotalsMock).toHaveBeenCalledTimes(0); expect(changeShippingLineMock).toHaveBeenCalledTimes(1); expect(changeShippingLineMock).toHaveBeenCalledWith(shippingOptionMock.id, API_RETRY); + expect(getShippingLinesMock).toHaveBeenCalledTimes(1); + expect(estimateTaxesMock).toHaveBeenCalledTimes(1); expect(updateWithMock).toHaveBeenCalledTimes(1); expect(updateWithMock).toBeCalledWith({ status: 'fail' }); }); + }); diff --git a/tests/stripe/checkStripeAddress.test.ts b/tests/stripe/checkStripeAddress.test.ts index 270ed51..c5304f9 100644 --- a/tests/stripe/checkStripeAddress.test.ts +++ b/tests/stripe/checkStripeAddress.test.ts @@ -2,15 +2,21 @@ import { checkStripeAddress, formatStripeShippingAddress, getPaymentRequestDisplayItems, - getPhoneNumber, getTotals, - IStripeAddress, ITotals + getPhoneNumber, + getTotals, + IStripeAddress, + ITotals } from 'src'; import {mocked} from 'jest-mock'; -import {applicationStateMock} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; +import {applicationStateMock, orderInitialDataMock} from '@boldcommerce/checkout-frontend-library/lib/variables/mocks'; import { baseReturnObject, + estimateShippingLines, + estimateTaxes, + getOrderInitialData, getShipping, getShippingLines, + IOrderInitialData, IShipping, setShippingAddress, setTaxes @@ -21,6 +27,9 @@ jest.mock('@boldcommerce/checkout-frontend-library/lib/address'); jest.mock('@boldcommerce/checkout-frontend-library/lib/state'); jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping'); jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/state/getOrderInitialData'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/taxes/estimateTaxes'); +jest.mock('@boldcommerce/checkout-frontend-library/lib/shipping/estimateShippingLines'); jest.mock('src/utils/getPaymentRequestDisplayItems'); jest.mock('src/utils/getPhoneNumber'); jest.mock('src/utils/getTotals'); @@ -32,6 +41,9 @@ const getShippingLinesMock = mocked(getShippingLines, true); const setTaxesMock = mocked(setTaxes, true); const getPaymentRequestDisplayItemMock = mocked(getPaymentRequestDisplayItems, true); const getPhoneNumberMock = mocked(getPhoneNumber, true); +const getOrderInitialDataMock = mocked(getOrderInitialData, true); +const estimateShippingLinesMock = mocked(estimateShippingLines, true); +const estimateTaxesMock = mocked(estimateTaxes, true); describe('testing check address function', () => { const successReturnObject = {...baseReturnObject, success: true}; @@ -55,7 +67,7 @@ describe('testing check address function', () => { totalAdditionalFees: 0 }; - const data = [ + const dataWithoutRSA = [ {name: 'success', setShipping: successReturnObject, getShippingLines: successReturnObject, setTaxes: successReturnObject, getShipping: shippingLine, expected: {total: {label: 'Total', amount: orderTotal}, status: 'success', shippingOptions: [{amount: 100, id: 'test_select_shipping_line_id', label: 'Test Description',}], displayItems: displayItemMock}}, {name: 'success with empty shipping lines', setShipping: successReturnObject, getShippingLines: successReturnObject, setTaxes: successReturnObject, getShipping:[], expected:{status:'invalid_shipping_address'}}, {name: 'success with failed taxes call', setShipping: successReturnObject, getShippingLines: successReturnObject, setTaxes: failureReturnObject, getShipping: shippingLine, expected:{status:'invalid_shipping_address'}}, @@ -63,6 +75,13 @@ describe('testing check address function', () => { {name: 'failure', setShipping: failureReturnObject, getShippingLines: failureReturnObject, setTaxes: successReturnObject, getShipping: shippingLine, expected:{status:'invalid_shipping_address'}} ]; + const dataWithRSA = [ + {name: 'success with rsa', estimateShippingLines: successReturnObject, getShipping: shippingLine, getShippingLines: successReturnObject, estimateTaxes: successReturnObject, expected: {total: {label: 'Total', amount: orderTotal}, status: 'success', shippingOptions: [{amount: 100, id: 'test_select_shipping_line_id', label: 'Test Description',}], displayItems: displayItemMock}}, + {name: 'success with empty shipping lines with rsa', estimateShippingLines: successReturnObject, getShipping: [], getShippingLines: successReturnObject, estimateTaxes:successReturnObject, expected:{status:'invalid_shipping_address'}}, + {name: 'success with failed estimates taxes call with rsa', estimateShippingLines: successReturnObject, getShipping: shippingLine, getShippingLines: successReturnObject, estimateTaxes: failureReturnObject, expected:{status:'invalid_shipping_address'}}, + {name: 'success with failed estimates shipping lines call with rsa', estimateShippingLines: failureReturnObject, getShipping: shippingLine, getShippingLines: successReturnObject, estimateTaxes: successReturnObject, expected:{status:'invalid_shipping_address'}}, + ]; + beforeEach(() => { jest.clearAllMocks(); @@ -70,10 +89,11 @@ describe('testing check address function', () => { getTotalsMock.mockReturnValue(totals); getPaymentRequestDisplayItemMock.mockReturnValueOnce(displayItemMock); getPhoneNumberMock.mockReturnValue(''); + getOrderInitialDataMock.mockReturnValue(orderInitialDataMock); }); - test.each(data)('$name', async ({setShipping, getShippingLines, setTaxes, getShipping, expected}) => { - getShippingMock.mockReturnValueOnce({available_shipping_lines: getShipping} as IShipping); + test.each(dataWithoutRSA)('$name', async ({setShipping, getShippingLines, setTaxes, getShipping, expected}) => { + getShippingMock.mockReturnValue({available_shipping_lines: getShipping} as IShipping); setShippingAddressMock.mockReturnValueOnce(Promise.resolve(setShipping)); getShippingLinesMock.mockReturnValueOnce(Promise.resolve(getShippingLines)); setTaxesMock.mockReturnValueOnce(Promise.resolve(setTaxes)); @@ -84,4 +104,22 @@ describe('testing check address function', () => { expect(updateWithMock).toBeCalledWith(expected); }); + test.each(dataWithRSA)('$name', async ({estimateShippingLines, getShipping, getShippingLines, estimateTaxes, expected}) => { + + const {general_settings: generalSettings} = orderInitialDataMock; + const {checkout_process: checkoutProcess} = generalSettings; + const newGeneralSettings = {...generalSettings, checkout_process: {...checkoutProcess, rsa_enabled: true}}; + const initialData: IOrderInitialData = {...orderInitialDataMock, general_settings: newGeneralSettings}; + getOrderInitialDataMock.mockReturnValue(initialData); + estimateShippingLinesMock.mockReturnValue(Promise.resolve(estimateShippingLines)); + getShippingLinesMock.mockReturnValueOnce(Promise.resolve(getShippingLines)); + getShippingMock.mockReturnValue({available_shipping_lines: getShipping} as IShipping); + estimateTaxesMock.mockReturnValueOnce(Promise.resolve(estimateTaxes)); + + await checkStripeAddress({shippingAddress: {} as IStripeAddress, updateWith: updateWithMock}); + + expect(updateWithMock).toHaveBeenCalledTimes(1); + expect(updateWithMock).toBeCalledWith(expected); + }); + });