Skip to content

Commit

Permalink
Disable activation of LPM's requiring additional currencies when MC i…
Browse files Browse the repository at this point in the history
…s disabled (#7211)

Co-authored-by: Jesse Pearson <[email protected]>
  • Loading branch information
tpaksu and jessepearson authored Oct 31, 2023
1 parent 20aaa54 commit b011b37
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 57 deletions.
5 changes: 5 additions & 0 deletions changelog/fix-7154-onboarding-lpms-while-mc-is-disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: add
Comment: Added notice when a LPM is selected that requires additional currencies when MC is disabled


Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ import PaymentMethodCheckboxes from '../../components/payment-methods-checkboxes
import PaymentMethodCheckbox from '../../components/payment-methods-checkboxes/payment-method-checkbox';
import { LoadableBlock } from '../../components/loadable';
import LoadableSettingsSection from '../../settings/loadable-settings-section';
import CurrencyInformationForMethods from '../../components/currency-information-for-methods';
import CurrencyInformationForMethods, {
BuildMissingCurrenciesTooltipMessage,
} from '../../components/currency-information-for-methods';
import { upeCapabilityStatuses, upeMethods } from '../constants';
import paymentMethodsMap from '../../payment-methods-map';
import ConfirmPaymentMethodActivationModal from 'wcpay/payment-methods/activation-modal';
import './add-payment-methods-task.scss';
import PAYMENT_METHOD_IDS from 'wcpay/payment-methods/constants';

const usePaymentMethodsCheckboxState = () => {
// For UPE, the card payment method is required and always active.
Expand Down Expand Up @@ -211,25 +214,47 @@ const AddPaymentMethodsTask = () => {
};

const prepareUpePaymentMethods = ( upeMethodIds ) => {
return upeMethodIds.map(
( key ) =>
availablePaymentMethods.includes( key ) && (
return upeMethodIds.map( ( key ) => {
const { label, currencies } = paymentMethodsMap[ key ];

if ( availablePaymentMethods.includes( key ) ) {
let isSetupRequired = false;
let setupTooltip = '';

if (
! wcpaySettings.isMultiCurrencyEnabled &&
key !== PAYMENT_METHOD_IDS.CARD
) {
const currency = wcpaySettings.storeCurrency;
if ( currencies.indexOf( currency ) < 0 ) {
isSetupRequired = true;
setupTooltip = BuildMissingCurrenciesTooltipMessage(
label,
currencies
);
}
}
return (
<PaymentMethodCheckbox
key={ key }
checked={
paymentMethodsState[ key ] &&
upeCapabilityStatuses.INACTIVE !==
getStatusAndRequirements( key ).status
}
setupTooltip={ setupTooltip }
isSetupRequired={ isSetupRequired }
status={ getStatusAndRequirements( key ).status }
locked={ isPoInProgress }
onChange={ ( name, status ) => {
handleCheckClick( name, status );
} }
name={ key }
/>
)
);
);
}
return '';
} );
};

const availableBuyNowPayLaterUpeMethods = upeMethods.filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
* External dependencies
*/
import React from 'react';
import { act, render, screen, waitFor } from '@testing-library/react';
import {
act,
fireEvent,
render,
screen,
waitFor,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

/**
Expand Down Expand Up @@ -120,6 +126,8 @@ describe( 'AddPaymentMethodsTask', () => {
useManualCapture.mockReturnValue( [ false, jest.fn() ] );
useAccountDomesticCurrency.mockReturnValue( 'usd' );
global.wcpaySettings = {
isMultiCurrencyEnabled: true,
storeCurrency: 'USD',
accountEmail: '[email protected]',
};
} );
Expand Down Expand Up @@ -443,4 +451,54 @@ describe( 'AddPaymentMethodsTask', () => {

jest.useRealTimers();
} );

it( "should render the setup tooltip correctly when multi currency is disabled and store currency doesn't support the LPM", () => {
global.wcpaySettings.isMultiCurrencyEnabled = false;
global.wcpaySettings.storeCurrency = 'USD';
const setCompletedMock = jest.fn();
useEnabledPaymentMethodIds.mockReturnValue( [ [ 'card' ], jest.fn() ] );
useGetAvailablePaymentMethodIds.mockReturnValue( [ 'bancontact' ] );
useGetPaymentMethodStatuses.mockReturnValue( {
bancontact_payments: {
status: upeCapabilityStatuses.ACTIVE,
requirements: [],
},
} );

const { container } = render(
<SettingsContextProvider>
<WizardTaskContext.Provider
value={ { setCompleted: setCompletedMock, isActive: true } }
>
<AddPaymentMethodsTask />
</WizardTaskContext.Provider>
</SettingsContextProvider>
);

expect(
screen.queryByLabelText( 'Bancontact' )
).not.toBeInTheDocument();

const svgIcon = container.querySelectorAll(
'.gridicons-notice-outline'
)[ 0 ];

expect( svgIcon ).toBeInTheDocument();

jest.useFakeTimers();

act( () => {
fireEvent.mouseOver( svgIcon, {
view: window,
bubbles: true,
cancelable: true,
} );
jest.runAllTimers();
} );

expect(
screen.queryByText( /Bancontact requires the EUR currency\./ )
).toBeInTheDocument();
jest.useRealTimers();
} );
} );
27 changes: 27 additions & 0 deletions client/components/currency-information-for-methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,33 @@ const ListToCommaSeparatedSentencePartConverter = ( items ) => {
);
};

export const BuildMissingCurrenciesTooltipMessage = (
paymentMethodLabel,
missingCurrencies
) => {
return sprintf(
__(
'%s requires the %s %s. In order to enable ' +
'the payment method, you must add %s to your store.',
'woocommerce-payments'
),
paymentMethodLabel,
ListToCommaSeparatedSentencePartConverter( missingCurrencies ),
_n(
'currency',
'currencies',
missingCurrencies.length,
'woocommerce-payments'
),
_n(
'this currency',
'these currencies',
missingCurrencies.length,
'woocommerce-payments'
)
);
};

const CurrencyInformationForMethods = ( { selectedMethods } ) => {
const {
isLoading: isLoadingCurrencyInformation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { render, screen } from '@testing-library/react';
* Internal dependencies
*/
import { useCurrencies, useEnabledCurrencies } from '../../../data';
import CurrencyInformationForMethods from '..';
import CurrencyInformationForMethods, {
BuildMissingCurrenciesTooltipMessage,
} from '..';
import WCPaySettingsContext from '../../../settings/wcpay-settings-context';

jest.mock( '../../../data', () => ( {
Expand Down Expand Up @@ -185,4 +187,27 @@ describe( 'CurrencyInformationForMethods', () => {
)
).toBeInTheDocument();
} );

it( 'returns correct string with the given LPM label and currency list', () => {
const output = BuildMissingCurrenciesTooltipMessage( 'x', [ 'EUR' ] );
expect( output ).toBe(
'x requires the EUR currency. In order to enable the payment method, you must add this currency to your store.'
);
const outputMultiple = BuildMissingCurrenciesTooltipMessage( 'x', [
'EUR',
'PLN',
] );
expect( outputMultiple ).toBe(
'x requires the EUR and PLN currencies. In order to enable the payment method, you must add these currencies to your store.'
);
const outputMany = BuildMissingCurrenciesTooltipMessage( 'x', [
'EUR',
'PLN',
'TRY',
] );
expect( outputMany ).toBe(
'x requires the EUR, PLN, and TRY currencies. ' +
'In order to enable the payment method, you must add these currencies to your store.'
);
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ type PaymentMethodCheckboxProps = {
status: string;
required: boolean;
locked: boolean;
isSetupRequired?: boolean;
setupTooltip?: string;
};

const PaymentMethodCheckbox: React.FC< PaymentMethodCheckboxProps > = ( {
Expand All @@ -75,6 +77,8 @@ const PaymentMethodCheckbox: React.FC< PaymentMethodCheckboxProps > = ( {
status,
required,
locked,
isSetupRequired,
setupTooltip,
} ) => {
const {
accountFees,
Expand Down Expand Up @@ -124,6 +128,8 @@ const PaymentMethodCheckbox: React.FC< PaymentMethodCheckboxProps > = ( {
delayMsOnCheck={ 1500 }
delayMsOnUncheck={ 0 }
hideLabel={ true }
isSetupRequired={ isSetupRequired }
setupTooltip={ setupTooltip }
isAllowingManualCapture={ paymentMethod.allows_manual_capture }
/>
<div className={ 'woocommerce-payments__payment-method-icon' }>
Expand Down
115 changes: 67 additions & 48 deletions client/payment-methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import ConfirmPaymentMethodDeleteModal from './delete-modal';
import { getPaymentMethodDescription } from 'wcpay/utils/payment-methods';
import CapabilityRequestNotice from './capability-request';
import InlineNotice from 'wcpay/components/inline-notice';
import { BuildMissingCurrenciesTooltipMessage } from 'wcpay/components/currency-information-for-methods';

const PaymentMethodsDropdownMenu = ( { setOpenModal } ) => {
const { isUpeEnabled, upeType } = useContext( WcPayUpeContext );
Expand Down Expand Up @@ -258,56 +259,74 @@ const PaymentMethods = () => {
allows_manual_capture: isAllowingManualCapture,
setup_required: isSetupRequired,
setup_tooltip: setupTooltip,
} ) => (
<PaymentMethod
id={ id }
key={ id }
label={ label }
description={ getPaymentMethodDescription(
id,
stripeAccountDomesticCurrency
) }
checked={
enabledMethodIds.includes( id ) &&
upeCapabilityStatuses.INACTIVE !==
currencies,
} ) => {
if (
! wcpaySettings.isMultiCurrencyEnabled &&
id !== PAYMENT_METHOD_IDS.CARD
) {
const currency =
wcpaySettings.storeCurrency;
if ( currencies.indexOf( currency ) < 0 ) {
isSetupRequired = true;
setupTooltip = BuildMissingCurrenciesTooltipMessage(
label,
currencies
);
}
}
return (
<PaymentMethod
id={ id }
key={ id }
label={ label }
description={ getPaymentMethodDescription(
id,
stripeAccountDomesticCurrency
) }
checked={
enabledMethodIds.includes( id ) &&
upeCapabilityStatuses.INACTIVE !==
getStatusAndRequirements( id )
.status
}
// The card payment method is required when UPE is active, and it can't be disabled/unchecked.
required={
PAYMENT_METHOD_IDS.CARD === id &&
isUpeEnabled
}
locked={
PAYMENT_METHOD_IDS.CARD === id &&
isCreditCardEnabled &&
isUpeEnabled
}
Icon={ Icon }
status={
getStatusAndRequirements( id )
.status
}
// The card payment method is required when UPE is active, and it can't be disabled/unchecked.
required={
PAYMENT_METHOD_IDS.CARD === id &&
isUpeEnabled
}
locked={
PAYMENT_METHOD_IDS.CARD === id &&
isCreditCardEnabled &&
isUpeEnabled
}
Icon={ Icon }
status={
getStatusAndRequirements( id ).status
}
isSetupRequired={ isSetupRequired }
setupTooltip={ setupTooltip }
isAllowingManualCapture={
isAllowingManualCapture
}
onUncheckClick={ () => {
handleUncheckClick( id );
} }
onCheckClick={ () => {
handleCheckClick( id );
} }
isPoEnabled={
wcpaySettings?.progressiveOnboarding
?.isEnabled
}
isPoComplete={
wcpaySettings?.progressiveOnboarding
?.isComplete
}
/>
)
}
isSetupRequired={ isSetupRequired }
setupTooltip={ setupTooltip }
isAllowingManualCapture={
isAllowingManualCapture
}
onUncheckClick={ () => {
handleUncheckClick( id );
} }
onCheckClick={ () => {
handleCheckClick( id );
} }
isPoEnabled={
wcpaySettings?.progressiveOnboarding
?.isEnabled
}
isPoComplete={
wcpaySettings?.progressiveOnboarding
?.isComplete
}
/>
);
}
) }
</PaymentMethodsList>
</CardBody>
Expand Down
Loading

0 comments on commit b011b37

Please sign in to comment.