Deploy payments banner in settings page (#34326)
* Deploy payments banner in settings page, updated tests * Add track on banner CTA click * Add test for track * Changelog * Fix unit tests
This commit is contained in:
parent
68985e3222
commit
cd5ffed61b
|
@ -9,13 +9,18 @@ import {
|
||||||
WCPayBannerBody,
|
WCPayBannerBody,
|
||||||
WCPayBannerFooter,
|
WCPayBannerFooter,
|
||||||
} from '@woocommerce/onboarding';
|
} from '@woocommerce/onboarding';
|
||||||
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import './payment-recommendations.scss';
|
import './payment-recommendations.scss';
|
||||||
import { getAdminSetting } from '~/utils/admin-settings';
|
import { getAdminSetting } from '~/utils/admin-settings';
|
||||||
import { usePaymentExperiment } from './use-payments-experiment';
|
import { usePaymentsBanner } from './use-payments-banner';
|
||||||
|
|
||||||
|
const recordTrack = () => {
|
||||||
|
recordEvent( 'settings_payments_banner_connect_click' );
|
||||||
|
};
|
||||||
|
|
||||||
const WCPaySettingBanner = () => {
|
const WCPaySettingBanner = () => {
|
||||||
const WC_PAY_SETUP_URL = getAdminLink(
|
const WC_PAY_SETUP_URL = getAdminLink(
|
||||||
|
@ -28,7 +33,11 @@ const WCPaySettingBanner = () => {
|
||||||
<WCPayBannerBody
|
<WCPayBannerBody
|
||||||
textPosition="right"
|
textPosition="right"
|
||||||
actionButton={
|
actionButton={
|
||||||
<Button href={ WC_PAY_SETUP_URL } isPrimary>
|
<Button
|
||||||
|
href={ WC_PAY_SETUP_URL }
|
||||||
|
isPrimary
|
||||||
|
onClick={ recordTrack }
|
||||||
|
>
|
||||||
{ __( 'Get started', 'woocommerce' ) }
|
{ __( 'Get started', 'woocommerce' ) }
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
|
@ -53,13 +62,9 @@ const DefaultPaymentMethodsHeaderText = () => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PaymentsBannerWrapper = () => {
|
export const PaymentsBannerWrapper = () => {
|
||||||
const { isLoadingExperiment, experimentAssignment } =
|
const { hasFinishedResolution, shouldShowBanner } = usePaymentsBanner();
|
||||||
usePaymentExperiment();
|
|
||||||
|
|
||||||
if (
|
if ( hasFinishedResolution && shouldShowBanner ) {
|
||||||
! isLoadingExperiment &&
|
|
||||||
experimentAssignment?.variationName === 'treatment'
|
|
||||||
) {
|
|
||||||
return <WCPaySettingBanner />;
|
return <WCPaySettingBanner />;
|
||||||
}
|
}
|
||||||
return <DefaultPaymentMethodsHeaderText />;
|
return <DefaultPaymentMethodsHeaderText />;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { waitFor, render } from '@testing-library/react';
|
import { waitFor, render, fireEvent } from '@testing-library/react';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
import { loadExperimentAssignment } from '@woocommerce/explat';
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -15,13 +15,7 @@ jest.mock( '@wordpress/data', () => ( {
|
||||||
useSelect: jest.fn(),
|
useSelect: jest.fn(),
|
||||||
} ) );
|
} ) );
|
||||||
jest.mock( '@woocommerce/explat' );
|
jest.mock( '@woocommerce/explat' );
|
||||||
|
jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
|
||||||
const whenExperimentAssigned = (
|
|
||||||
experimentVariation: 'treatment' | 'control'
|
|
||||||
) =>
|
|
||||||
( loadExperimentAssignment as jest.Mock ).mockImplementation( () => {
|
|
||||||
return Promise.resolve( { variationName: experimentVariation } );
|
|
||||||
} );
|
|
||||||
|
|
||||||
const paymentsBannerShouldBe = async ( status: 'hidden' | 'visible' ) => {
|
const paymentsBannerShouldBe = async ( status: 'hidden' | 'visible' ) => {
|
||||||
const { container } = render( <PaymentsBannerWrapper /> );
|
const { container } = render( <PaymentsBannerWrapper /> );
|
||||||
|
@ -65,28 +59,14 @@ describe( 'Payment Settings Banner', () => {
|
||||||
|
|
||||||
whenWcPay( { supported: true, activated: false, installed: true } );
|
whenWcPay( { supported: true, activated: false, installed: true } );
|
||||||
|
|
||||||
whenExperimentAssigned( 'treatment' );
|
|
||||||
|
|
||||||
await paymentsBannerShouldBe( 'visible' );
|
await paymentsBannerShouldBe( 'visible' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'should not render the banner if treatment is control', async () => {
|
|
||||||
expect.assertions( 1 );
|
|
||||||
|
|
||||||
whenWcPay( { supported: true, activated: false, installed: true } );
|
|
||||||
|
|
||||||
whenExperimentAssigned( 'control' );
|
|
||||||
|
|
||||||
await paymentsBannerShouldBe( 'hidden' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
it( 'should not render anything if woocommerce payments is not supported', async () => {
|
it( 'should not render anything if woocommerce payments is not supported', async () => {
|
||||||
expect.assertions( 1 );
|
expect.assertions( 1 );
|
||||||
|
|
||||||
whenWcPay( { supported: false, activated: false, installed: false } );
|
whenWcPay( { supported: false, activated: false, installed: false } );
|
||||||
|
|
||||||
whenExperimentAssigned( 'treatment' );
|
|
||||||
|
|
||||||
await paymentsBannerShouldBe( 'hidden' );
|
await paymentsBannerShouldBe( 'hidden' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -95,8 +75,17 @@ describe( 'Payment Settings Banner', () => {
|
||||||
|
|
||||||
whenWcPay( { supported: true, activated: true, installed: true } );
|
whenWcPay( { supported: true, activated: true, installed: true } );
|
||||||
|
|
||||||
whenExperimentAssigned( 'treatment' );
|
|
||||||
|
|
||||||
await paymentsBannerShouldBe( 'hidden' );
|
await paymentsBannerShouldBe( 'hidden' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
it( 'should record track when clicking the action button', async () => {
|
||||||
|
whenWcPay( { supported: true, activated: false, installed: true } );
|
||||||
|
|
||||||
|
const { getByText } = render( <PaymentsBannerWrapper /> );
|
||||||
|
fireEvent.click( getByText( 'Get started' ) );
|
||||||
|
|
||||||
|
expect( recordEvent ).toHaveBeenCalledWith(
|
||||||
|
'settings_payments_banner_connect_click'
|
||||||
|
);
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { useSelect } from '@wordpress/data';
|
||||||
|
import {
|
||||||
|
ONBOARDING_STORE_NAME,
|
||||||
|
PAYMENT_GATEWAYS_STORE_NAME,
|
||||||
|
PaymentGateway,
|
||||||
|
WCDataSelector,
|
||||||
|
} from '@woocommerce/data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { isWcPaySupported } from './utils';
|
||||||
|
|
||||||
|
export const usePaymentsBanner = () => {
|
||||||
|
const {
|
||||||
|
installedPaymentGateways,
|
||||||
|
paymentGatewaySuggestions,
|
||||||
|
hasFinishedResolution,
|
||||||
|
} = useSelect( ( select: WCDataSelector ) => {
|
||||||
|
return {
|
||||||
|
installedPaymentGateways: select(
|
||||||
|
PAYMENT_GATEWAYS_STORE_NAME
|
||||||
|
).getPaymentGateways(),
|
||||||
|
paymentGatewaySuggestions: select(
|
||||||
|
ONBOARDING_STORE_NAME
|
||||||
|
).getPaymentGatewaySuggestions(),
|
||||||
|
hasFinishedResolution:
|
||||||
|
select( ONBOARDING_STORE_NAME ).hasFinishedResolution(
|
||||||
|
'getPaymentGatewaySuggestions'
|
||||||
|
) &&
|
||||||
|
select( PAYMENT_GATEWAYS_STORE_NAME ).hasFinishedResolution(
|
||||||
|
'getPaymentGateways'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
} );
|
||||||
|
|
||||||
|
const isWcPayInstalled = installedPaymentGateways.some(
|
||||||
|
( gateway: PaymentGateway ) => {
|
||||||
|
return gateway.id === 'woocommerce_payments';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const isWcPayDisabled = installedPaymentGateways.find(
|
||||||
|
( gateway: PaymentGateway ) => {
|
||||||
|
return (
|
||||||
|
gateway.id === 'woocommerce_payments' &&
|
||||||
|
gateway.enabled === false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const shouldShowBanner =
|
||||||
|
isWcPaySupported( paymentGatewaySuggestions ) &&
|
||||||
|
isWcPayInstalled &&
|
||||||
|
isWcPayDisabled;
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasFinishedResolution,
|
||||||
|
shouldShowBanner,
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,101 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import { useState, useEffect } from '@wordpress/element';
|
|
||||||
import { loadExperimentAssignment } from '@woocommerce/explat';
|
|
||||||
import { ExperimentAssignment } from '@automattic/explat-client';
|
|
||||||
import { useSelect } from '@wordpress/data';
|
|
||||||
import {
|
|
||||||
ONBOARDING_STORE_NAME,
|
|
||||||
PAYMENT_GATEWAYS_STORE_NAME,
|
|
||||||
PaymentGateway,
|
|
||||||
WCDataSelector,
|
|
||||||
} from '@woocommerce/data';
|
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import { isWcPaySupported } from './utils';
|
|
||||||
|
|
||||||
export const usePaymentExperiment = () => {
|
|
||||||
const [ isLoadingExperiment, setIsLoadingExperiment ] =
|
|
||||||
useState< boolean >( true );
|
|
||||||
const [ experimentAssignment, setExperimentAssignment ] =
|
|
||||||
useState< null | ExperimentAssignment >( null );
|
|
||||||
|
|
||||||
const {
|
|
||||||
installedPaymentGateways,
|
|
||||||
paymentGatewaySuggestions,
|
|
||||||
hasFinishedResolution,
|
|
||||||
} = useSelect( ( select: WCDataSelector ) => {
|
|
||||||
return {
|
|
||||||
installedPaymentGateways: select(
|
|
||||||
PAYMENT_GATEWAYS_STORE_NAME
|
|
||||||
).getPaymentGateways(),
|
|
||||||
paymentGatewaySuggestions: select(
|
|
||||||
ONBOARDING_STORE_NAME
|
|
||||||
).getPaymentGatewaySuggestions(),
|
|
||||||
hasFinishedResolution:
|
|
||||||
select( ONBOARDING_STORE_NAME ).hasFinishedResolution(
|
|
||||||
'getPaymentGatewaySuggestions'
|
|
||||||
) &&
|
|
||||||
select( PAYMENT_GATEWAYS_STORE_NAME ).hasFinishedResolution(
|
|
||||||
'getPaymentGateways'
|
|
||||||
),
|
|
||||||
};
|
|
||||||
} );
|
|
||||||
|
|
||||||
const isWcPayInstalled = installedPaymentGateways.some(
|
|
||||||
( gateway: PaymentGateway ) => {
|
|
||||||
return gateway.id === 'woocommerce_payments';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const isWcPayDisabled = installedPaymentGateways.find(
|
|
||||||
( gateway: PaymentGateway ) => {
|
|
||||||
return (
|
|
||||||
gateway.id === 'woocommerce_payments' &&
|
|
||||||
gateway.enabled === false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
if (
|
|
||||||
experimentAssignment === null &&
|
|
||||||
hasFinishedResolution &&
|
|
||||||
isWcPaySupported( paymentGatewaySuggestions ) &&
|
|
||||||
isWcPayInstalled &&
|
|
||||||
isWcPayDisabled
|
|
||||||
) {
|
|
||||||
const momentDate = moment().utc();
|
|
||||||
const year = momentDate.format( 'YYYY' );
|
|
||||||
const month = momentDate.format( 'MM' );
|
|
||||||
setIsLoadingExperiment( true );
|
|
||||||
loadExperimentAssignment(
|
|
||||||
`woocommerce_payments_settings_banner_${ year }_${ month }`
|
|
||||||
)
|
|
||||||
.then( ( assignment ) => {
|
|
||||||
setExperimentAssignment( assignment );
|
|
||||||
setIsLoadingExperiment( false );
|
|
||||||
} )
|
|
||||||
.catch( () => {
|
|
||||||
setIsLoadingExperiment( false );
|
|
||||||
} );
|
|
||||||
} else if ( hasFinishedResolution ) {
|
|
||||||
setIsLoadingExperiment( false );
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
experimentAssignment,
|
|
||||||
hasFinishedResolution,
|
|
||||||
isWcPayDisabled,
|
|
||||||
isWcPayInstalled,
|
|
||||||
paymentGatewaySuggestions,
|
|
||||||
] );
|
|
||||||
|
|
||||||
return {
|
|
||||||
isLoadingExperiment,
|
|
||||||
experimentAssignment,
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: update
|
||||||
|
|
||||||
|
Deploy payments settings banner and add tracks
|
Loading…
Reference in New Issue