Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline campaign setup: Temporarily remove the billing setup step from the Ads-onboarding #2577

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
40ea4eb
remove ads campaign steps
kt-12 Sep 4, 2024
8a9a10a
cs fixes
kt-12 Sep 4, 2024
94c8208
e2e support
kt-12 Sep 4, 2024
39a2090
cs fixes
kt-12 Sep 4, 2024
09871a5
cs fixes
kt-12 Sep 4, 2024
5b14c07
fix cs issue
kt-12 Sep 4, 2024
9728b03
address review comments and also add submitbuttontext
kt-12 Sep 7, 2024
f06b5d2
fix doc block
kt-12 Sep 7, 2024
3409919
cs fixes
kt-12 Sep 7, 2024
0c74f98
cs fixes
kt-12 Sep 9, 2024
779eac3
sert default submitButtonText
kt-12 Sep 11, 2024
ef31827
update doc block and remove unused files
kt-12 Sep 13, 2024
e7afe1e
Update tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js
kt-12 Sep 13, 2024
daa483a
fix e2e
kt-12 Sep 13, 2024
71c81ec
Merge branch 'feature/2536-remove-billing' of https://github.com/wooc…
kt-12 Sep 13, 2024
b5a2467
Update js/src/components/paid-ads/ads-campaign.js
kt-12 Sep 13, 2024
0ca45f1
clear jest files
kt-12 Sep 17, 2024
98cd72d
Update js/src/components/paid-ads/ads-campaign.js
kt-12 Sep 17, 2024
52ca19d
conditional enabling continue button
kt-12 Sep 19, 2024
b8178b4
remove file
kt-12 Sep 19, 2024
c5be7e0
update disabled button logic
kt-12 Sep 19, 2024
1833363
only to check in setup-ads context
kt-12 Sep 19, 2024
d053b77
fix billing e2e
kt-12 Sep 26, 2024
c8ee77f
ads campaign request
kt-12 Sep 26, 2024
1b31ca9
change mock
kt-12 Sep 27, 2024
e7da33a
move billing page to bottom
kt-12 Sep 27, 2024
a6d79a0
create a new mock for campaign creation.
kt-12 Sep 27, 2024
7edeb3b
Merge branch 'feature/2536-remove-billing' of https://github.com/wooc…
kt-12 Sep 27, 2024
4ff5165
move budget to top.
kt-12 Sep 27, 2024
b90f77c
e2e cr fixes
kt-12 Sep 30, 2024
0c6d250
remove title button component
kt-12 Sep 30, 2024
fdd3aae
Merge branch 'feature/2459-campaign-creation-flow' into feature/2536-…
joemcgill Sep 30, 2024
104b368
remove accidently functions
kt-12 Oct 1, 2024
2c84851
remove newly introduced function
kt-12 Oct 2, 2024
fe7bab6
Add ContinueButton component.
asvinb Oct 2, 2024
659f560
seperate continue button
kt-12 Oct 8, 2024
836d1a6
continue button component
kt-12 Oct 8, 2024
fdfedba
fix continue button logic on edit and create page
kt-12 Oct 8, 2024
88ba4e8
fix continue button
kt-12 Oct 8, 2024
c82396b
change text
kt-12 Oct 8, 2024
ed886d8
Omit the billing status check for now
joemcgill Oct 8, 2024
cfd7879
Add inline note about the need to update for billing
joemcgill Oct 8, 2024
2564a42
fix review feedback
kt-12 Oct 10, 2024
dc716ec
change prop name
kt-12 Oct 10, 2024
6b85d4d
handleContinueClick to onClick and return type
kt-12 Oct 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions js/src/components/paid-ads/ads-campaign.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,21 @@ import FaqsSection from './faqs-section';
/**
* Renders the container of the form content for campaign management.
*
* Please note that this component relies on an CampaignAssetsForm's context and custom adapter,
* so it expects a `CampaignAssetsForm` to existing in its parents.
* Please note that this component relies on a CampaignAssetsForm's context and custom adapter,
* so it expects a `CampaignAssetsForm` to exist in its parents.
*
* @fires gla_documentation_link_click with `{ context: 'create-ads' | 'edit-ads' | 'setup-ads', link_id: 'see-what-ads-look-like', href: 'https://support.google.com/google-ads/answer/6275294' }`
*
* @param {Object} props React props.
* @param {Campaign} [props.campaign] Campaign data to be edited. If not provided, this component will show campaign creation UI.
* @param {() => void} props.onContinue Callback called once continue button is clicked.
* @param {Object} props.formProps Form props forwarded from `Form` component.
* @param {Function} props.formProps.isSubmitting Callback to display loading till Ads campaign is created.
* @param {Function} props.formProps.handleSubmit Callback to handle campaign creation.
* @param {'create-ads'|'edit-ads'|'setup-ads'} props.trackingContext A context indicating which page this component is used on. This will be the value of `context` in the track event properties.
*/
export default function AdsCampaign( {
campaign,
onContinue,
formProps: { isSubmitting, handleSubmit },
kt-12 marked this conversation as resolved.
Show resolved Hide resolved
trackingContext,
} ) {
const isCreation = ! campaign;
Expand Down Expand Up @@ -102,9 +104,10 @@ export default function AdsCampaign( {
<AppButton
isPrimary
disabled={ ! isValidForm }
onClick={ onContinue }
loading={ isSubmitting }
onClick={ handleSubmit }
>
{ __( 'Continue', 'google-listings-and-ads' ) }
{ __( 'Launch paid campaign', 'google-listings-and-ads' ) }
</AppButton>
</StepContentFooter>
</StepContent>
Expand Down
13 changes: 1 addition & 12 deletions js/src/setup-ads/ads-stepper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useState } from '@wordpress/element';
*/
import SetupAccounts from './setup-accounts';
import AdsCampaign from '.~/components/paid-ads/ads-campaign';
import SetupBilling from './setup-billing';
asvinb marked this conversation as resolved.
Show resolved Hide resolved
import useEventPropertiesFilter from '.~/hooks/useEventPropertiesFilter';
import {
recordStepperChangeEvent,
Expand Down Expand Up @@ -58,10 +57,6 @@ const AdsStepper = ( { formProps } ) => {
continueStep( '2' );
};

const handleCreateCampaignContinue = () => {
continueStep( '3' );
};

return (
// This Stepper with this class name
// should be refactored into separate shared component.
Expand Down Expand Up @@ -92,17 +87,11 @@ const AdsStepper = ( { formProps } ) => {
content: (
<AdsCampaign
trackingContext="setup-ads"
onContinue={ handleCreateCampaignContinue }
formProps={ formProps }
kt-12 marked this conversation as resolved.
Show resolved Hide resolved
/>
),
onClick: handleStepClick,
},
{
key: '3',
label: __( 'Set up billing', 'google-listings-and-ads' ),
content: <SetupBilling formProps={ formProps } />,
onClick: handleStepClick,
},
] }
/>
);
Expand Down
179 changes: 34 additions & 145 deletions tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
getFAQPanelTitle,
getFAQPanelRow,
checkFAQExpandable,
checkBillingAdsPopup,
} from '../../utils/page';

const ADS_ACCOUNTS = [
Expand Down Expand Up @@ -280,11 +279,15 @@ test.describe( 'Set up Ads account', () => {
} );

test.describe( 'Create your paid campaign', () => {
const launchPaidCampaignButton = page.getByRole( 'button', {
asvinb marked this conversation as resolved.
Show resolved Hide resolved
name: 'Launch paid campaign',
} );

test.beforeAll( async () => {
setupBudgetPage = new SetupBudgetPage( page );
} );

test( 'Continue to create paid campaign', async () => {
test( 'Continue to create paid campaign and create ads', async () => {
kt-12 marked this conversation as resolved.
Show resolved Hide resolved
await setupAdsAccounts.clickContinue();
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );

Expand All @@ -302,9 +305,7 @@ test.describe( 'Set up Ads account', () => {
page.getByRole( 'heading', { name: 'Set your budget' } )
).toBeVisible();

await expect(
page.getByRole( 'button', { name: 'Continue' } )
).toBeDisabled();
await expect( launchPaidCampaignButton ).toBeDisabled();

await expect(
page.getByRole( 'link', {
Expand Down Expand Up @@ -370,169 +371,57 @@ test.describe( 'Set up Ads account', () => {
budget = '0';
await setupBudgetPage.fillBudget( budget );

await expect(
page.getByRole( 'button', { name: 'Continue' } )
).toBeDisabled();
await expect( launchPaidCampaignButton ).toBeDisabled();

budget = '1';
await setupBudgetPage.fillBudget( budget );

await expect(
page.getByRole( 'button', { name: 'Continue' } )
).toBeEnabled();
await expect( launchPaidCampaignButton ).toBeEnabled();
} );

test( 'Budget Recommendation', async () => {
await expect(
page.getByText( 'set a daily budget of 15 USD' )
).toBeVisible();
} );
} );

test.describe( 'Set up billing', () => {
test.describe( 'Billing status is not approved', () => {
test.beforeAll( async () => {
await setupBudgetPage.fulfillBillingStatusRequest( {
status: 'pending',
} );
} );
test( 'It should say that the billing is not setup', async () => {
await page.getByRole( 'button', { name: 'Continue' } ).click();
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );

await expect(
page.getByRole( 'button', {
name: 'Set up billing',
exact: true,
} )
).toBeEnabled();

await expect(
page.getByText(
'In order to launch your paid campaign, your billing information is required. You will be billed directly by Google and only pay when someone clicks on your ad.'
)
).toBeVisible();

await expect(
page.getByRole( 'link', {
name: 'click here instead',
} )
).toBeVisible();
} );

// eslint-disable-next-line jest/expect-expect
test( 'should open a popup when clicking set up billing button', async () => {
await checkBillingAdsPopup( page );
} );
} );

test.describe( 'Billing status is approved', async () => {
test.beforeAll( async () => {
await setupBudgetPage.fulfillBillingStatusRequest( {
status: 'approved',
} );

await setupAdsAccounts.mockAdsAccountsResponse( {
id: ADS_ACCOUNTS[ 1 ],
billing_url: null,
} );

// Simulate a bit of delay when creating the Ads campaign so we have enough time to test the content in the page before the redirect.
await page.route(
/\/wc\/gla\/ads\/campaigns\b/,
async ( route ) => {
await new Promise( ( f ) => setTimeout( f, 500 ) );
await route.continue();
}
);
} );
test( 'It should say that the billing is setup', async () => {
//Every 30s the page will check if the billing status is approved and it will trigger the campaign creation.
await setupBudgetPage.awaitForBillingStatusRequest();
await setupBudgetPage.mockCampaignCreationAndAdsSetupCompletion(
budget,
[ 'US' ]
);

await expect(
page.getByText(
'Great! You already have billing information saved for this'
)
).toBeVisible();

//It should redirect to the dashboard page
await page.waitForURL(
'/wp-admin/admin.php?page=wc-admin&path=%2Fgoogle%2Fdashboard&guide=campaign-creation-success',
{
timeout: 30000,
waitUntil: LOAD_STATE.DOM_CONTENT_LOADED,
}
);
} );

test( 'It should show the campaign creation success message', async () => {
await expect(
page.getByRole( 'heading', {
name: "You've set up a paid Performance Max Campaign!",
} )
).toBeVisible();

await expect(
page.getByRole( 'button', {
name: 'Create another campaign',
} )
).toBeEnabled();
test( 'Paid Campaign can be created', async () => {
asvinb marked this conversation as resolved.
Show resolved Hide resolved
launchPaidCampaignButton.click();

await expect(
page.getByRole( 'button', {
name: 'Got It',
} )
).toBeEnabled();

await page
.getByRole( 'button', {
name: 'Got It',
} )
.click();
} );
//It should redirect to the dashboard page
await page.waitForURL(
'/wp-admin/admin.php?page=wc-admin&path=%2Fgoogle%2Fdashboard&guide=campaign-creation-success',
{
timeout: 30000,
waitUntil: LOAD_STATE.DOM_CONTENT_LOADED,
}
);
} );
} );

test.describe( 'Create Ads with billing data already setup', () => {
test( 'Launch paid campaign should be enabled', async () => {
//Click Add paid Campaign
await adsConnectionButton.click();
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );

//Step 1 - Accounts are already set up.
await setupAdsAccounts.clickContinue();
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );

//Step 2 - Fill the budget
await setupBudgetPage.fillBudget( '1' );
await page.getByRole( 'button', { name: 'Continue' } ).click();
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED );

//Step 3 - Billing is already setup
test( 'It should show the campaign creation success message', async () => {
await expect(
page.getByText(
'Great! You already have billing information saved for this'
)
page.getByRole( 'heading', {
name: "You've set up a paid Performance Max Campaign!",
} )
).toBeVisible();

await expect(
page.getByRole( 'button', { name: 'Launch paid campaign' } )
page.getByRole( 'button', {
name: 'Create another campaign',
} )
).toBeEnabled();

await expect(
page.getByRole( 'button', {
name: 'Got It',
} )
).toBeEnabled();

const campaignCreation =
setupBudgetPage.mockCampaignCreationAndAdsSetupCompletion(
'1',
[ 'US' ]
);
await page
.getByRole( 'button', { name: 'Launch paid campaign' } )
.getByRole( 'button', {
name: 'Got It',
} )
.click();
await campaignCreation;
} );
} );
} );
Loading