Skip to content

Commit

Permalink
Plans (State): Update post-share component to utilise Plans data store (
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskmnds authored Aug 9, 2024
1 parent 026e91b commit c29160e
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 43 deletions.
4 changes: 2 additions & 2 deletions client/blocks/post-share/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ class PostShare extends Component {
}

renderPrimarySection() {
const { hasFetchedConnections, hasRepublicizeFeature, siteSlug } = this.props;
const { hasFetchedConnections, hasRepublicizeFeature, siteSlug, siteId } = this.props;

if ( ! hasFetchedConnections ) {
return null;
Expand All @@ -515,7 +515,7 @@ class PostShare extends Component {
if ( ! hasRepublicizeFeature ) {
return (
<div>
<UpgradeToPremiumNudge { ...this.props } />
<UpgradeToPremiumNudge siteId={ siteId } />
<ActionsList { ...this.props } />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,44 @@ import {
TYPE_PREMIUM,
PLAN_PREMIUM,
getPlan,
PlanSlug,
} from '@automattic/calypso-products';
import { Plans } from '@automattic/data-stores';
import formatCurrency from '@automattic/format-currency';
import { useHasEnTranslation } from '@automattic/i18n-utils';
import { connect } from 'react-redux';
import { useTranslate } from 'i18n-calypso';
import UpsellNudge from 'calypso/blocks/upsell-nudge';
import useCheckPlanAvailabilityForPurchase from 'calypso/my-sites/plans-features-main/hooks/use-check-plan-availability-for-purchase';
import { useSelector } from 'calypso/state';
import { canCurrentUser } from 'calypso/state/selectors/can-current-user';
import {
getSitePlanRawPrice,
getPlanDiscountedRawPrice,
} from 'calypso/state/sites/plans/selectors';
import { getSitePlan } from 'calypso/state/sites/selectors';
import { getSelectedSiteId } from 'calypso/state/ui/selectors';

export const UpgradeToPremiumNudgePure = ( props ) => {
const { price, planSlug, translate, userCurrency, canUserUpgrade } = props;
interface Props {
siteId?: number | null;
}

const hasEnTranslation = useHasEnTranslation();
export const UpgradeToPremiumNudge = ( { siteId }: Props ) => {
const translate = useTranslate();
const currentPlan = Plans.useCurrentPlan( { siteId } );
const canUserUpgrade = useSelector( ( state ) =>
canCurrentUser( state, siteId, 'manage_options' )
);

const proposedPlanSlug =
currentPlan?.planSlug &&
findFirstSimilarPlanKey( currentPlan?.planSlug, { type: TYPE_PREMIUM } );

const pricing = Plans.usePricingMetaForGridPlans( {
siteId,
planSlugs: [ proposedPlanSlug as PlanSlug ],
storageAddOns: null,
coupon: undefined,
useCheckPlanAvailabilityForPurchase,
withProratedDiscounts: true,
} )?.[ proposedPlanSlug as PlanSlug ];

const price = pricing?.discountedPrice.monthly ?? pricing?.originalPrice.monthly;

const hasEnTranslation = useHasEnTranslation();
const featureList = [
translate( 'Share posts that have already been published.' ),
translate( 'Schedule your social messages in advance.' ),
Expand All @@ -31,20 +51,22 @@ export const UpgradeToPremiumNudgePure = ( props ) => {
translate( 'Easy monetization options' ),
];

if ( ! canUserUpgrade ) {
if ( ! canUserUpgrade || typeof price !== 'number' || ! pricing?.currencyCode ) {
return null;
}

return (
<UpsellNudge
className="post-share__actions-list-upgrade-nudge"
callToAction={ translate( 'Upgrade for %s', {
args: formatCurrency( price, userCurrency ),
args: formatCurrency( price, pricing?.currencyCode, {
isSmallestUnit: true,
} ),
comment: '%s will be replaced by a formatted price, i.e $9.99',
} ) }
forceDisplay
list={ featureList }
plan={ planSlug }
plan={ proposedPlanSlug }
showIcon
title={
/* translators: %(planName)s is the short-hand version of the Personal plan name */
Expand All @@ -56,19 +78,3 @@ export const UpgradeToPremiumNudgePure = ( props ) => {
/>
);
};

const getDiscountedOrRegularPrice = ( state, siteId, plan ) =>
getPlanDiscountedRawPrice( state, siteId, plan, { returnMonthly: true } ) ||
getSitePlanRawPrice( state, siteId, plan, { returnMonthly: true } );

export const UpgradeToPremiumNudge = connect( ( state, ownProps ) => {
const { siteId } = ownProps;
const currentPlanSlug = ( getSitePlan( state, getSelectedSiteId( state ) ) || {} ).product_slug;
const proposedPlan = findFirstSimilarPlanKey( currentPlanSlug, { type: TYPE_PREMIUM } );

return {
planSlug: proposedPlan,
price: getDiscountedOrRegularPrice( state, siteId, proposedPlan ),
canUserUpgrade: canCurrentUser( state, siteId, 'manage_options' ),
};
} )( UpgradeToPremiumNudgePure );
87 changes: 75 additions & 12 deletions client/blocks/post-share/test/nudges.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ jest.mock( 'calypso/blocks/upsell-nudge', () => ( {
__esModule: true,
default: ( { plan } ) => <div data-testid="upsell-nudge-plan">{ plan }</div>,
} ) );
jest.mock( 'calypso/state/selectors/can-current-user', () => ( {
canCurrentUser: jest.fn(),
} ) );
jest.mock( '@automattic/data-stores', () => ( {
...jest.requireActual( '@automattic/data-stores' ),
Plans: {
...jest.requireActual( '@automattic/data-stores' ).Plans,
usePlans: jest.fn(),
useCurrentPlan: jest.fn(),
usePricingMetaForGridPlans: jest.fn(),
},
} ) );
jest.mock( '@automattic/calypso-products', () => ( {
...jest.requireActual( '@automattic/calypso-products' ),
findFirstSimilarPlanKey: jest.fn(),
} ) );

import {
PLAN_FREE,
Expand All @@ -29,32 +45,66 @@ import {
PLAN_JETPACK_BUSINESS_MONTHLY,
PLAN_ECOMMERCE,
PLAN_ECOMMERCE_2_YEARS,
findFirstSimilarPlanKey,
} from '@automattic/calypso-products';
import { Plans } from '@automattic/data-stores';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, screen } from '@testing-library/react';
import { UpgradeToPremiumNudgePure } from '../nudges';
import { useMemo } from 'react';
import { Provider as ReduxProvider } from 'react-redux';
import { createReduxStore } from 'calypso/state';
import { canCurrentUser } from 'calypso/state/selectors/can-current-user';
import { UpgradeToPremiumNudge } from '../nudges';

const props = {
translate: ( x ) => x,
canUserUpgrade: true,
siteId: undefined,
};

const Wrapper = ( { children } ) => {
const queryClient = useMemo( () => new QueryClient(), [] );
const store = createReduxStore();

return (
<ReduxProvider store={ store }>
<QueryClientProvider client={ queryClient }>{ children }</QueryClientProvider>
</ReduxProvider>
);
};

describe( 'UpgradeToPremiumNudgePure basic tests', () => {
describe( 'UpgradeToPremiumNudge basic tests', () => {
beforeEach( () => {
jest.clearAllMocks();
findFirstSimilarPlanKey.mockImplementation( () => PLAN_PREMIUM );
Plans.useCurrentPlan.mockImplementation( () => ( { planSlug: PLAN_PERSONAL } ) );
Plans.usePricingMetaForGridPlans.mockImplementation( () => ( {
[ PLAN_PREMIUM ]: {
originalPrice: { full: 24000, monthly: 2000 },
discountedPrice: { full: 12000, monthly: 1000 },
currencyCode: 'USD',
},
} ) );
} );

test( 'should not blow up', () => {
render( <UpgradeToPremiumNudgePure { ...props } /> );
canCurrentUser.mockReturnValue( true );
render( <UpgradeToPremiumNudge { ...props } />, { wrapper: Wrapper } );
expect( screen.getByTestId( 'upsell-nudge-plan' ) ).toBeVisible();
} );

test( 'hide when user cannot upgrade', () => {
const localProps = {
translate: ( x ) => x,
canUserUpgrade: false,
};
render( <UpgradeToPremiumNudgePure { ...localProps } /> );
canCurrentUser.mockReturnValue( false );
render( <UpgradeToPremiumNudge { ...props } />, { wrapper: Wrapper } );
expect( screen.queryByTestId( 'upsell-nudge-plan' ) ).not.toBeInTheDocument();
} );
} );

describe( 'UpgradeToPremiumNudgePure.render()', () => {
describe( 'UpgradeToPremiumNudge - upsell-nudge', () => {
beforeEach( () => {
jest.clearAllMocks();
Plans.useCurrentPlan.mockImplementation( () => ( { planSlug: PLAN_PERSONAL } ) );
canCurrentUser.mockReturnValue( true );
} );

[
PLAN_JETPACK_FREE,
PLAN_JETPACK_PERSONAL,
Expand All @@ -77,7 +127,20 @@ describe( 'UpgradeToPremiumNudgePure.render()', () => {
PLAN_ECOMMERCE_2_YEARS,
].forEach( ( plan ) => {
test( `Should pass 2-years wp.com premium plan for 2-years plans ${ plan }`, () => {
render( <UpgradeToPremiumNudgePure { ...props } planSlug={ plan } /> );
/**
* These act as sending directly the plan to the upsell component,
* bypassing findFirstSimilarPlanKey logic (which is an imported utility)
*/
findFirstSimilarPlanKey.mockImplementation( () => plan );
Plans.usePricingMetaForGridPlans.mockImplementation( () => ( {
[ plan ]: {
originalPrice: { full: 24000, monthly: 2000 },
discountedPrice: { full: 12000, monthly: 1000 },
currencyCode: 'USD',
},
} ) );

render( <UpgradeToPremiumNudge { ...props } />, { wrapper: Wrapper } );
expect( screen.getByTestId( 'upsell-nudge-plan' ) ).toHaveTextContent( plan );
} );
} );
Expand Down

0 comments on commit c29160e

Please sign in to comment.