-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2641 from woocommerce/feature/2539-show-promo
Show promo for setting up Google Ads on the product feed tabs #2539
- Loading branch information
Showing
7 changed files
with
399 additions
and
0 deletions.
There are no files selected for viewing
49 changes: 49 additions & 0 deletions
49
js/src/product-feed/product-statistics/create-campaign-notice/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { __ } from '@wordpress/i18n'; | ||
import { Flex, FlexItem } from '@wordpress/components'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button'; | ||
import useMCProductStatistics from '.~/hooks/useMCProductStatistics'; | ||
import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; | ||
import './index.scss'; | ||
|
||
const CreateCampaignNotice = () => { | ||
const { data: products } = useMCProductStatistics(); | ||
const { loaded: campaignsLoaded, data: campaigns } = useAdsCampaigns(); | ||
|
||
if ( | ||
! products?.statistics?.active || | ||
! campaignsLoaded || | ||
campaigns?.length > 0 | ||
) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Flex className="gla-ads-inline-notice"> | ||
<FlexItem> | ||
<p> | ||
{ __( | ||
'You have approved products. Create a Google Ads campaign to reach more customers and drive more sales.', | ||
'google-listings-and-ads' | ||
) } | ||
</p> | ||
<AddPaidCampaignButton | ||
isSmall={ false } | ||
eventProps={ { | ||
context: 'product-feed-overview-promotion', | ||
} } | ||
> | ||
{ __( 'Create Campaign', 'google-listings-and-ads' ) } | ||
</AddPaidCampaignButton> | ||
</FlexItem> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default CreateCampaignNotice; |
9 changes: 9 additions & 0 deletions
9
js/src/product-feed/product-statistics/create-campaign-notice/index.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.gla-ads-inline-notice { | ||
background-color: #f0f6fc; | ||
margin-bottom: $grid-unit-20; | ||
padding: $grid-unit-20 $grid-unit-30; | ||
|
||
p { | ||
margin-top: 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
196 changes: 196 additions & 0 deletions
196
tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { expect, test } from '@playwright/test'; | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { | ||
clearOnboardedMerchant, | ||
setOnboardedMerchant, | ||
setCompletedAdsSetup, | ||
clearCompletedAdsSetup, | ||
} from '../../utils/api'; | ||
import ProductFeedPage from '../../utils/pages/product-feed'; | ||
import { LOAD_STATE } from '../../utils/constants'; | ||
|
||
test.use( { storageState: process.env.ADMINSTATE } ); | ||
|
||
test.describe.configure( { mode: 'serial' } ); | ||
|
||
/** | ||
* @type {import('../../utils/pages/product-feed').default} productFeedPage | ||
*/ | ||
let productFeedPage = null; | ||
|
||
/** | ||
* @type {import('@playwright/test').Page} page | ||
*/ | ||
let page = null; | ||
|
||
test.describe( 'Product Feed Page', () => { | ||
test.beforeAll( async ( { browser } ) => { | ||
page = await browser.newPage(); | ||
productFeedPage = new ProductFeedPage( page ); | ||
await Promise.all( [ | ||
productFeedPage.mockRequests(), | ||
setOnboardedMerchant(), | ||
] ); | ||
} ); | ||
|
||
test.afterAll( async () => { | ||
await clearOnboardedMerchant(); | ||
await page.close(); | ||
} ); | ||
|
||
test.describe( 'No campaign', () => { | ||
test.beforeAll( async () => { | ||
await productFeedPage.fulfillAdsCampaignsRequest( [] ); | ||
} ); | ||
|
||
test( 'No active product and no campaign; Do not display campaign notice', async () => { | ||
await productFeedPage.fulfillProductStatisticsRequest( { | ||
timestamp: 1695011644, | ||
statistics: { | ||
active: 0, | ||
expiring: 0, | ||
pending: 0, | ||
disapproved: 0, | ||
not_synced: 1137, | ||
}, | ||
scheduled_sync: 0, | ||
loading: false, | ||
} ); | ||
|
||
await productFeedPage.goto(); | ||
await expect( | ||
page.getByRole( 'heading', { level: 1, name: 'Product Feed' } ) | ||
).toBeVisible(); | ||
|
||
await expect( | ||
page.getByRole( 'heading', { | ||
name: 'Overview', | ||
} ) | ||
).toBeVisible(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toBeVisible(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toHaveText( /^0$/ ); | ||
|
||
await expect( | ||
await productFeedPage.getCampaignNoticeSection() | ||
).not.toBeVisible(); | ||
} ); | ||
|
||
test( 'Has active product but no campaign; Display campaign notice', async () => { | ||
await productFeedPage.fulfillProductStatisticsRequest( { | ||
timestamp: 1695011644, | ||
statistics: { | ||
active: 1, | ||
expiring: 0, | ||
pending: 0, | ||
disapproved: 0, | ||
not_synced: 1137, | ||
}, | ||
scheduled_sync: 0, | ||
loading: false, | ||
} ); | ||
|
||
await productFeedPage.goto(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toBeVisible(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toHaveText( /^1$/ ); | ||
|
||
const noticeSection = | ||
await productFeedPage.getCampaignNoticeSection(); | ||
const createCampaignButton = | ||
productFeedPage.getInNoticeCreateCampaignButton(); | ||
|
||
await expect( noticeSection ).toBeVisible(); | ||
await expect( createCampaignButton ).toBeVisible(); | ||
await createCampaignButton.click(); | ||
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); | ||
await expect( | ||
page.getByRole( 'heading', { | ||
level: 1, | ||
name: 'Set up your accounts', | ||
} ) | ||
).toBeVisible(); | ||
} ); | ||
} ); | ||
|
||
test.describe( 'Has campaign', () => { | ||
test.beforeAll( async () => { | ||
await setCompletedAdsSetup(); | ||
await productFeedPage.fulfillAdsCampaignsRequest( [ | ||
{ | ||
id: 111111111, | ||
name: 'Test Campaign', | ||
status: 'enabled', | ||
type: 'performance_max', | ||
amount: 1, | ||
country: 'US', | ||
targeted_locations: [ 'US' ], | ||
}, | ||
] ); | ||
} ); | ||
|
||
test.afterAll( async () => { | ||
await clearCompletedAdsSetup(); | ||
await page.close(); | ||
} ); | ||
|
||
test( 'Has active product and a campaign; Do not display campaign notice', async () => { | ||
await productFeedPage.goto(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toBeVisible(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toHaveText( /^1$/ ); | ||
|
||
await expect( | ||
await productFeedPage.getCampaignNoticeSection() | ||
).not.toBeVisible(); | ||
} ); | ||
|
||
test( 'Has campaign but no active product; Do not display campaign notice', async () => { | ||
await productFeedPage.fulfillProductStatisticsRequest( { | ||
timestamp: 1695011644, | ||
statistics: { | ||
active: 0, | ||
expiring: 0, | ||
pending: 0, | ||
disapproved: 0, | ||
not_synced: 1137, | ||
}, | ||
scheduled_sync: 0, | ||
loading: false, | ||
} ); | ||
await productFeedPage.goto(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toBeVisible(); | ||
|
||
await expect( | ||
productFeedPage.getActiveProductValueElement() | ||
).toHaveText( /^0$/ ); | ||
|
||
await expect( | ||
await productFeedPage.getCampaignNoticeSection() | ||
).not.toBeVisible(); | ||
} ); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.