Skip to content

Commit

Permalink
Merge pull request #2533 from woocommerce/feature/2500-show-campaign-…
Browse files Browse the repository at this point in the history
…fields

2500: Show paid campaign setup fields during onboarding flow
  • Loading branch information
joemcgill authored Sep 10, 2024
2 parents 057ff88 + 068f4c4 commit 5ac539f
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 160 deletions.
18 changes: 0 additions & 18 deletions js/src/setup-mc/setup-stepper/setup-paid-ads/clientSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,11 @@
* @property {Array<CountryCode>} countryCodes Audience country codes of the paid ads campaign. Example: 'US'.
*/

const KEY_SHOW_PAID_ADS_SETUP = 'gla-onboarding-show-paid-ads-setup';
const KEY_PAID_ADS = 'gla-onboarding-paid-ads';

const { sessionStorage } = window;

const clientSession = {
/**
* @param {boolean} isShowing Whether the paid ads setup is showing.
*/
setShowPaidAdsSetup( isShowing ) {
const showing = Boolean( isShowing ).toString();
sessionStorage.setItem( KEY_SHOW_PAID_ADS_SETUP, showing );
},

/**
* @param {boolean} defaultValue The default value to be returned if stored value is not available.
* @return {boolean} Returns the stored value. It will return `defaultValue` if stored value is not available.
*/
getShowPaidAdsSetup( defaultValue ) {
const showing = sessionStorage.getItem( KEY_SHOW_PAID_ADS_SETUP );
return showing === null ? defaultValue : showing === 'true';
},

/**
* @param {CampaignData} data Campaign data to be stored.
* @param {number|undefined} data.amount Daily average cost of the campaign.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,8 @@ function FeatureList( { hideBudgetContent } ) {
*
* @param {Object} props React props.
* @param {boolean} props.hideBudgetContent Whether to hide the content about the ad budget.
* @param {boolean} props.hideFooterButtons Whether to hide the buttons at the card footer.
* @param {JSX.Element} props.skipButton Button to skip paid ads setup.
* @param {JSX.Element} props.continueButton Button to continue paid ads setup.
*/
export default function PaidAdsFeaturesSection( {
hideBudgetContent,
hideFooterButtons,
skipButton,
continueButton,
} ) {
export default function PaidAdsFeaturesSection( { hideBudgetContent } ) {
return (
<Section
className="gla-paid-ads-features-section"
Expand Down Expand Up @@ -130,10 +122,6 @@ export default function PaidAdsFeaturesSection( {
</FlexItem>
</Flex>
</Section.Card.Body>
<Section.Card.Footer hidden={ hideFooterButtons }>
{ skipButton }
{ continueButton }
</Section.Card.Footer>
</Section.Card>
</Section>
);
Expand Down
59 changes: 9 additions & 50 deletions js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import apiFetch from '@wordpress/api-fetch';
import { select } from '@wordpress/data';
import { useState } from '@wordpress/element';
import { Flex } from '@wordpress/components';
import { noop, merge } from 'lodash';
import { noop } from 'lodash';

/**
* Internal dependencies
Expand All @@ -24,7 +24,6 @@ import PaidAdsFeaturesSection from './paid-ads-features-section';
import PaidAdsSetupSections from './paid-ads-setup-sections';
import SkipPaidAdsConfirmationModal from './skip-paid-ads-confirmation-modal';
import { getProductFeedUrl } from '.~/utils/urls';
import clientSession from './clientSession';
import { API_NAMESPACE, STORE_KEY } from '.~/data/constants';
import { GUIDE_NAMES } from '.~/constants';
import { ACTION_COMPLETE, ACTION_SKIP } from './constants';
Expand All @@ -47,14 +46,12 @@ import { recordGlaEvent } from '.~/utils/tracks';
/**
* Clicking on the skip paid ads button to complete the onboarding flow.
* The 'unknown' value of properties may means:
* - the paid ads setup is not opened
* - the final status has not yet been resolved when recording this event
* - the status is not available, for example, the billing status is unknown if Google Ads account is not yet connected
*
* @event gla_onboarding_complete_button_click
* @property {string} opened_paid_ads_setup Whether the paid ads setup is opened, e.g. 'yes', 'no'
* @property {string} google_ads_account_status The connection status of merchant's Google Ads addcount, e.g. 'connected', 'disconnected', 'incomplete'
* @property {string} billing_method_status aaa, The status of billing method of merchant's Google Ads addcount e.g. 'unknown', 'pending', 'approved', 'cancelled'
* @property {string} billing_method_status The status of billing method of merchant's Google Ads addcount e.g. 'unknown', 'pending', 'approved', 'cancelled'
* @property {string} campaign_form_validation Whether the entered paid campaign form data are valid, e.g. 'unknown', 'valid', 'invalid'
*/

Expand All @@ -71,21 +68,13 @@ export default function SetupPaidAds() {
const { createNotice } = useDispatchCoreNotices();
const { googleAdsAccount, hasGoogleAdsConnection } = useGoogleAdsAccount();
const [ handleSetupComplete ] = useAdsSetupCompleteCallback();
const [ showPaidAdsSetup, setShowPaidAdsSetup ] = useState( () =>
clientSession.getShowPaidAdsSetup( false )
);
const [ paidAds, setPaidAds ] = useState( {} );
const [ completing, setCompleting ] = useState( null );
const [
showSkipPaidAdsConfirmationModal,
setShowSkipPaidAdsConfirmationModal,
] = useState( false );

const handleContinuePaidAdsSetupClick = () => {
setShowPaidAdsSetup( true );
clientSession.setShowPaidAdsSetup( true );
};

const finishOnboardingSetup = async ( event, onBeforeFinish = noop ) => {
setCompleting( event.target.dataset.action );

Expand Down Expand Up @@ -122,27 +111,17 @@ export default function SetupPaidAds() {
};

const handleSkipCreatePaidAds = async ( event ) => {
const selector = select( STORE_KEY );
const billing = selector.getGoogleAdsAccountBillingStatus();

setShowSkipPaidAdsConfirmationModal( false );

const eventProps = {
opened_paid_ads_setup: 'no',
google_ads_account_status: googleAdsAccount?.status,
billing_method_status: 'unknown',
campaign_form_validation: 'unknown',
billing_method_status: billing?.status || 'unknown',
campaign_form_validation: paidAds.isValid ? 'valid' : 'invalid',
};

// TODO: Review once https://github.com/woocommerce/google-listings-and-ads/issues/2500 is merged
if ( showPaidAdsSetup ) {
const selector = select( STORE_KEY );
const billing = selector.getGoogleAdsAccountBillingStatus();

merge( eventProps, {
opened_paid_ads_setup: 'yes',
billing_method_status: billing?.status,
campaign_form_validation: paidAds.isValid ? 'valid' : 'invalid',
} );
}

recordGlaEvent( 'gla_onboarding_complete_button_click', eventProps );

await finishOnboardingSetup( event );
Expand Down Expand Up @@ -189,28 +168,8 @@ export default function SetupPaidAds() {
/>
<PaidAdsFeaturesSection
hideBudgetContent={ ! hasGoogleAdsConnection }
hideFooterButtons={
! hasGoogleAdsConnection || showPaidAdsSetup
}
skipButton={ createSkipButton(
__( 'Skip this step for now', 'google-listings-and-ads' )
) }
continueButton={
<AppButton
isPrimary
text={ __(
'Create campaign',
'google-listings-and-ads'
) }
disabled={ completing === ACTION_SKIP }
onClick={ handleContinuePaidAdsSetupClick }
eventName="gla_onboarding_open_paid_ads_setup_button_click"
/>
}
/>
{ showPaidAdsSetup && (
<PaidAdsSetupSections onStatesReceived={ setPaidAds } />
) }
<PaidAdsSetupSections onStatesReceived={ setPaidAds } />
<FaqsSection />

{ showSkipPaidAdsConfirmationModal && (
Expand All @@ -220,7 +179,7 @@ export default function SetupPaidAds() {
/>
) }

<StepContentFooter hidden={ ! showPaidAdsSetup }>
<StepContentFooter>
<Flex justify="right" gap={ 4 }>
{ createSkipButton(
__(
Expand Down
32 changes: 2 additions & 30 deletions tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,6 @@ test.describe( 'Complete your campaign', () => {

test.describe( 'Set up paid ads', () => {
test.describe( 'Click "Create a paid ad campaign" button', () => {
test.beforeAll( async () => {
await completeCampaign.clickCreatePaidAdButton();
} );

test( 'should not see the "Create a paid ad campaign" button after this section is shown', async () => {
const button = completeCampaign.getCreatePaidAdButton();
await expect( button ).toBeHidden();
} );

test( 'should see "Complete setup" button is disabled', async () => {
const completeSetupButton =
completeCampaign.getCompleteSetupButton();
Expand Down Expand Up @@ -387,7 +378,7 @@ test.describe( 'Complete your campaign', () => {
await page.evaluate( () => window.sessionStorage.clear() );
await setupAdsAccountPage.mockAdsAccountIncomplete();
await completeCampaign.goto();
await completeCampaign.clickSkipStepButton();
await completeCampaign.clickSkipPaidAdsCreationButton();
} );

test( 'should see the modal', async () => {
Expand Down Expand Up @@ -434,7 +425,7 @@ test.describe( 'Complete your campaign', () => {
await page.evaluate( () => window.sessionStorage.clear() );
await setupAdsAccountPage.mockAdsAccountIncomplete();
await completeCampaign.goto();
await completeCampaign.clickSkipStepButton();
await completeCampaign.clickSkipPaidAdsCreationButton();
} );

test( 'should no longer see the confirmation modal', async () => {
Expand All @@ -453,23 +444,4 @@ test.describe( 'Complete your campaign', () => {
} );
}
);

// TODO: Should no longer be needed once https://github.com/woocommerce/google-listings-and-ads/issues/2500 is merged.
test.describe(
'Ask user for confirmation when clicking the "Skip paid ads creation"',
() => {
test.beforeAll( async () => {
await setupAdsAccountPage.mockAdsAccountIncomplete();
await completeCampaign.goto();
await completeCampaign.clickCreatePaidAdButton();
await completeCampaign.clickSkipPaidAdsCreationButon();
} );

test( 'should see the confirmation modal', async () => {
const skipPaidAdsModal =
completeCampaign.getSkipPaidAdsCreationModal();
await expect( skipPaidAdsModal ).toBeVisible();
} );
}
);
} );
52 changes: 3 additions & 49 deletions tests/e2e/utils/pages/setup-mc/step-4-complete-campaign.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,30 +64,6 @@ export default class CompleteCampaign extends MockRequests {
return this.page.locator( '.gla-budget-section' ).nth( 0 );
}

/**
* Get skip this step for now button.
*
* @return {import('@playwright/test').Locator} Get skip this step for now button.
*/
getSkipStepButton() {
return this.page.getByRole( 'button', {
name: 'Skip this step for now',
exact: true,
} );
}

/**
* Get create a paid ad button.
*
* @return {import('@playwright/test').Locator} Get create a paid ad button.
*/
getCreatePaidAdButton() {
return this.page.getByRole( 'button', {
name: 'Create campaign',
exact: true,
} );
}

/**
* Get complete setup button.
*
Expand All @@ -112,39 +88,17 @@ export default class CompleteCampaign extends MockRequests {
} );
}

/**
* Click skip this step for now button.
*
* @return {Promise<void>}
*/
async clickSkipStepButton() {
const button = this.getSkipStepButton();
await button.click();
await this.page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );
}

/**
* Click skip paid ads creation button.
*
* @return {Promise<void>}
*/
async clickSkipPaidAdsCreationButon() {
async clickSkipPaidAdsCreationButton() {
const button = this.getSkipPaidAdsCreationButton();
await button.click();
await this.page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );
}

/**
* Click create a paid ad campaign button.
*
* @return {Promise<void>}
*/
async clickCreatePaidAdButton() {
const button = this.getCreatePaidAdButton();
await button.click();
await this.page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );
}

/**
* Click complete setup button.
*
Expand Down Expand Up @@ -185,7 +139,7 @@ export default class CompleteCampaign extends MockRequests {
*
* @return {import('@playwright/test').Locator} Locator for the "Complete setup without setting up ads" button.
*/
getCompleteSetuModalButton() {
getCompleteSetupModalButton() {
return this.page.getByRole( 'button', {
name: 'Complete setup without setting up ads',
exact: true,
Expand All @@ -198,7 +152,7 @@ export default class CompleteCampaign extends MockRequests {
* @return {Promise<void>} Resolves when the click action is completed and the page has loaded.
*/
async clickCompleteSetupModalButton() {
const button = this.getCompleteSetuModalButton();
const button = this.getCompleteSetupModalButton();
await button.click();
await this.page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );
}
Expand Down

0 comments on commit 5ac539f

Please sign in to comment.