From 5c627985745c41f116f226c4b4ea2cf41e96baa8 Mon Sep 17 00:00:00 2001 From: asvinb Date: Fri, 23 Aug 2024 18:38:26 +0400 Subject: [PATCH 01/90] Swap performance cards. --- js/src/dashboard/summary-section/index.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index 813fc1a774..f5c2c71bed 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -111,24 +111,21 @@ export default function SummarySection() { return ( <> - + { adsSetupComplete ? ( + + ) : ( + + ) } - { adsSetupComplete ? ( - - ) : ( - - ) } + ); From a37c974a4ffee67bddc90186953c4879b17d8dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20P=C3=A9rez=20Pellicer?= <5908855+puntope@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:14:21 +0400 Subject: [PATCH 02/90] Tweak WP Proxy Response to force the types of the fields --- src/Integration/WPCOMProxy.php | 9 ++++- tests/Unit/Integration/WPCOMProxyTest.php | 45 +++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index 5109bbd4b7..e20b1088ab 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -132,14 +132,14 @@ protected function register_object_types_filter( string $object_type ): void { add_filter( 'woocommerce_rest_prepare_' . $object_type . '_object', [ $this, 'filter_response_by_syncable_item' ], - 1000, // Run this filter last to override any other response. + PHP_INT_MAX, // Run this filter last to override any other response. 3 ); add_filter( 'woocommerce_rest_prepare_' . $object_type . '_object', [ $this, 'prepare_response' ], - 10, + PHP_INT_MAX - 1, 3 ); @@ -338,6 +338,11 @@ public function prepare_response( WP_REST_Response $response, $item, WP_REST_Req $attr = $this->attribute_manager->get_all_aggregated_values( $item ); // In case of empty array, convert to object to keep the response consistent. $data['gla_attributes'] = (object) $attr; + + // Force types and prevent user type change for fields as Google has strict type requirements. + $data['price'] = strval( $data['price'] ?? null ); + $data['regular_price'] = strval( $data['regular_price'] ?? null ); + $data['sale_price'] = strval( $data['sale_price'] ?? null ); } foreach ( $data['meta_data'] ?? [] as $key => $meta ) { diff --git a/tests/Unit/Integration/WPCOMProxyTest.php b/tests/Unit/Integration/WPCOMProxyTest.php index 8af32bf0c2..403aa18ed5 100644 --- a/tests/Unit/Integration/WPCOMProxyTest.php +++ b/tests/Unit/Integration/WPCOMProxyTest.php @@ -498,4 +498,49 @@ public function test_get_empty_settings_for_shipping_zone_methods_as_object() { $proxy->prepare_data( $data, $request ) ); } + + public function test_product_types() { + add_filter( 'woocommerce_rest_prepare_product_object', [ $this, 'alter_product_price_types' ], 10, 3 ); + + $product = ProductHelper::create_simple_product(); + $product_variable = ProductHelper::create_variation_product(); + $variation = $product_variable->get_available_variations()[0]; + $this->add_metadata( $product->get_id(), $this->get_test_metadata() ); + + $request = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => '1' ] ); + $this->assertEquals( 'string', gettype( $request->get_data()[0]['price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()[0]['regular_price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()[0]['sale_price'] ) ); + + $request = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => '1' ] ); + $this->assertEquals( 'string', gettype( $request->get_data()['price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()['regular_price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()['sale_price'] ) ); + + $request = $this->do_request( '/wc/v3/products/' . $product_variable->get_id() . '/variations', 'GET', [ 'gla_syncable' => '1' ] ); + $this->assertEquals( 'string', gettype( $request->get_data()[0]['price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()[0]['regular_price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()[0]['sale_price'] ) ); + + $request = $this->do_request( '/wc/v3/products/' . $product_variable->get_id() . '/variations/' . $variation['variation_id'], 'GET', [ 'gla_syncable' => '1' ] ); + $this->assertEquals( 'string', gettype( $request->get_data()['price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()['regular_price'] ) ); + $this->assertEquals( 'string', gettype( $request->get_data()['sale_price'] ) ); + + // Doesn't apply if here is not 'gla_syncable' + $request = $this->do_request( '/wc/v3/products' ); + $this->assertEquals( 'integer', gettype( $request->get_data()[0]['price'] ) ); + $this->assertEquals( 'integer', gettype( $request->get_data()[0]['regular_price'] ) ); + $this->assertEquals( 'integer', gettype( $request->get_data()[0]['sale_price'] ) ); + + remove_filter( 'woocommerce_rest_prepare_product_object', [ $this, 'alter_product_price_types' ] ); + } + + public function alter_product_price_types( $response ) { + $response->data['price'] = intval( $response->data['price'] ); + $response->data['regular_price'] = intval( $response->data['regular_price'] ); + $response->data['sale_price'] = intval( $response->data['sale_price'] ); + + return $response; + } } From 7cb753161e8483ba337570e69aad2e7a489b44ba Mon Sep 17 00:00:00 2001 From: Jorge M Date: Wed, 25 Sep 2024 19:39:55 +0200 Subject: [PATCH 03/90] Symlink WC instead of moving the WC folder --- bin/install-wp-tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh index 5883078613..859eda181b 100755 --- a/bin/install-wp-tests.sh +++ b/bin/install-wp-tests.sh @@ -196,14 +196,14 @@ install_wc() { if [ ! -f "$WC_VERSION_FILE" ]; then # set up testing suite rm -rf "$WC_DIR" - mkdir -p "$WC_DIR" echo "Installing WooCommerce ($WC_VERSION)." # Grab the necessary plugins. WC_TMPDIR="${TMPDIR}/woocommerce-${WC_VERSION}" rm -rf "${WC_TMPDIR}" git clone --quiet --depth=1 --branch="${WC_VERSION}" https://github.com/woocommerce/woocommerce.git "${WC_TMPDIR}" - mv "${WC_TMPDIR}"/plugins/woocommerce/* "$WC_DIR" - touch "$WC_VERSION_FILE" + + ln -s "${WC_TMPDIR}"/plugins/woocommerce "$WC_DIR" + touch "$WC_VERSION_FILE" # Install composer for WooCommerce cd "${WC_DIR}" From 2583950f750d5f03e270290bab919c04f9faf542 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Thu, 26 Sep 2024 10:15:48 +0200 Subject: [PATCH 04/90] Fix mixed spacing --- bin/install-wp-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh index 859eda181b..7eb5d01f1a 100755 --- a/bin/install-wp-tests.sh +++ b/bin/install-wp-tests.sh @@ -203,7 +203,7 @@ install_wc() { git clone --quiet --depth=1 --branch="${WC_VERSION}" https://github.com/woocommerce/woocommerce.git "${WC_TMPDIR}" ln -s "${WC_TMPDIR}"/plugins/woocommerce "$WC_DIR" - touch "$WC_VERSION_FILE" + touch "$WC_VERSION_FILE" # Install composer for WooCommerce cd "${WC_DIR}" From 57b4adb25606c764c11e1206e6c2ca7cb83c05b8 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Thu, 10 Oct 2024 04:05:24 +0100 Subject: [PATCH 05/90] intial commit --- .../create-campaign-notice.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 js/src/product-feed/product-statistics/create-campaign-notice.js diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js new file mode 100644 index 0000000000..ad197ec9b4 --- /dev/null +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -0,0 +1,27 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import useMCProductStatistics from '.~/hooks/useMCProductStatistics'; + +const CreateCampaignNotice = () => { + const { hasFinishedResolution, data } = useMCProductStatistics(); + + if ( hasFinishedResolution && ! data ) { + return __( + 'An error occurred while retrieving your product feed. Please try again later.', + 'google-listings-and-ads' + ); + } + const isLoading = ! hasFinishedResolution || data?.loading; + + if ( isLoading ) { + return null; + } +}; + +export default CreateCampaignNotice; From 3922ab1180c66c723e9f1ac89cfcae0778e0e06b Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Sat, 12 Oct 2024 01:59:23 +0100 Subject: [PATCH 06/90] CreateCampaignNotice component --- .../create-campaign-notice.js | 48 +++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index ad197ec9b4..f545433104 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -2,26 +2,56 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; +import { Notice } 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'; const CreateCampaignNotice = () => { - const { hasFinishedResolution, data } = useMCProductStatistics(); + const { hasFinishedResolution: productsResolution, data: products } = + useMCProductStatistics(); + const { loaded: campaignsLoaded, data: campaigns } = useAdsCampaigns(); - if ( hasFinishedResolution && ! data ) { - return __( - 'An error occurred while retrieving your product feed. Please try again later.', - 'google-listings-and-ads' - ); - } - const isLoading = ! hasFinishedResolution || data?.loading; + const isLoading = + ! productsResolution || products?.loading || ! campaignsLoaded; + const inValidData = + ( productsResolution && ! products ) || + ( campaignsLoaded && ! campaigns ); - if ( isLoading ) { + if ( + isLoading || + inValidData || + products?.statistics?.active === 0 || + campaigns?.length > 0 + ) { return null; } + + return ( + +
+

+ { __( + 'You have approved products. Create a Google Ads campaign to reach more customers and drive more sales.', + 'google-listings-and-ads' + ) } +

+ +
+
+ ); }; export default CreateCampaignNotice; From 711160d8985bc545142a178d907d3ebd8b79ea94 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Sat, 12 Oct 2024 01:59:46 +0100 Subject: [PATCH 07/90] Add CreateCampaignNotice to the product-feed page --- js/src/product-feed/product-statistics/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/product-feed/product-statistics/index.js b/js/src/product-feed/product-statistics/index.js index 429313809d..5f73091544 100644 --- a/js/src/product-feed/product-statistics/index.js +++ b/js/src/product-feed/product-statistics/index.js @@ -25,6 +25,7 @@ import SyncStatus from '.~/product-feed/product-statistics/status-box/sync-statu import SyncProductStatistics from '.~/product-feed/product-statistics/status-box/sync-product-statistics'; import FeedStatus from '.~/product-feed/product-statistics/status-box/feed-status'; import AccountStatus from '.~/product-feed/product-statistics/status-box/account-status'; +import CreateCampaignNotice from '.~/product-feed/product-statistics/create-campaign-notice'; import Text from '.~/components/app-text'; import AppSpinner from '.~/components/app-spinner'; import './index.scss'; @@ -133,6 +134,7 @@ const ProductStatistics = () => { ) } + From 656c4a89bcf4d0c2df34cd1d38b0c34c395dc838 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Sat, 12 Oct 2024 02:01:04 +0100 Subject: [PATCH 08/90] check for google ads connection --- js/src/hooks/useAdsCampaigns.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index 5975aec450..235b12a6a7 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -7,7 +7,7 @@ import { useSelect } from '@wordpress/data'; * Internal dependencies */ import { STORE_KEY } from '.~/data'; -import { glaData } from '.~/constants'; +import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; import useIsEqualRefValue from '.~/hooks/useIsEqualRefValue'; const selectorName = 'getAdsCampaigns'; @@ -30,16 +30,12 @@ const selectorName = 'getAdsCampaigns'; */ const useAdsCampaigns = ( ...query ) => { const queryRefValue = useIsEqualRefValue( query ); + const { hasGoogleAdsConnection, hasFinishedResolution } = + useGoogleAdsAccount(); return useSelect( ( select ) => { - // TODO: ideally adsSetupComplete should be retrieved from API endpoint - // and then put into wp-data. - // With that in place, then we don't need to depend on glaData - // which requires force reload using window.location.href. - const { adsSetupComplete } = glaData; - - if ( ! adsSetupComplete ) { + if ( hasFinishedResolution && ! hasGoogleAdsConnection ) { return { loading: false, loaded: true, From 0170b7d9b35a1ba7405fdb77e76b06591fa1d6c6 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 02:44:04 +0100 Subject: [PATCH 09/90] Get Campaign Notice on prodict feed E2E --- .../create-campaign-notice.js | 1 + .../product-feed-campaign-notice.test.js | 222 ++++++++++++++++++ tests/e2e/utils/pages/product-feed.js | 76 ++++++ 3 files changed, 299 insertions(+) create mode 100644 tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js create mode 100644 tests/e2e/utils/pages/product-feed.js diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index f545433104..424769bac0 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -18,6 +18,7 @@ const CreateCampaignNotice = () => { const isLoading = ! productsResolution || products?.loading || ! campaignsLoaded; + const inValidData = ( productsResolution && ! products ) || ( campaignsLoaded && ! campaigns ); diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js new file mode 100644 index 0000000000..32b8e10623 --- /dev/null +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -0,0 +1,222 @@ +/** + * External dependencies + */ +import { expect, test } from '@playwright/test'; +/** + * Internal dependencies + */ +import { clearOnboardedMerchant, setOnboardedMerchant } from '../../utils/api'; +import DashboardPage from '../../utils/pages/dashboard.js'; +import ProductFeedPage from '../../utils/pages/product-feed'; +import SetupAdsAccountsPage from '../../utils/pages/setup-ads/setup-ads-accounts.js'; +import { LOAD_STATE } from '../../utils/constants'; + +test.use( { storageState: process.env.ADMINSTATE } ); + +test.describe.configure( { mode: 'serial' } ); + +/** + * @type {import('../../utils/pages/dashboard.js').default} dashboardPage + */ +let dashboardPage = null; + +/** + * @type {import('../../utils/pages/setup-ads/setup-ads-accounts').default} setupAdsAccounts + */ +let setupAdsAccounts = null; + +/** + * @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(); + dashboardPage = new DashboardPage( page ); + productFeedPage = new ProductFeedPage( page ); + setupAdsAccounts = new SetupAdsAccountsPage( page ); + await setupAdsAccounts.mockAdsAccountsResponse( [] ); + await setOnboardedMerchant(); + await dashboardPage.mockRequests(); + } ); + + test.afterAll( async () => { + await clearOnboardedMerchant(); + await page.close(); + } ); + + test.describe( 'No campaign', () => { + test.beforeAll( async () => { + await setupAdsAccounts.mockAdsAccountsResponse( { + issues: [], + total: 0, + page: 1, + loading: false, + } ); + await productFeedPage.fulfillAdsCampaignsRequest( [] ); + await productFeedPage.goto(); + } ); + + test( 'No active product and no campaign; Do not display campaign notice', async () => { + await expect( + page.getByRole( 'heading', { level: 1, name: 'Product Feed' } ) + ).toBeVisible(); + + await productFeedPage.fulfillProductStatisticsRequest( { + timestamp: 1695011644, + statistics: { + active: 0, + expiring: 0, + pending: 0, + disapproved: 0, + not_synced: 1137, + }, + scheduled_sync: 0, + loading: false, + } ); + + await page.reload(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + + await expect( + page.getByRole( 'heading', { + name: 'Overview', + } ) + ).toBeVisible(); + + await expect( + await productFeedPage.getActiveProductValueElement() + ).toBeVisible(); + + await expect( + ( await productFeedPage.getActiveProductValue() ).trim() + ).toBe( '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 page.reload(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + + await expect( + await productFeedPage.getActiveProductValueElement() + ).toBeVisible(); + + await expect( + ( await productFeedPage.getActiveProductValue() ).trim() + ).toBe( '1' ); + + const noticeSection = + await productFeedPage.getCampaignNoticeSection(); + const createCampaignButton = + await 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(); + + await productFeedPage.goto(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + + await expect( + page.getByRole( 'heading', { level: 1, name: 'Product Feed' } ) + ).toBeVisible(); + } ); + } ); + + test.describe( 'Has campaign', () => { + test.beforeAll( async () => { + await setupAdsAccounts.mockAdsAccountsResponse( { + issues: [], + total: 0, + page: 1, + loading: false, + } ); + await productFeedPage.fulfillAdsCampaignsRequest( [ + { + id: 111111111, + name: 'Test Campaign', + status: 'enabled', + type: 'performance_max', + amount: 1, + country: 'US', + targeted_locations: [ 'US' ], + }, + ] ); + } ); + + test( 'Has active product and a campaign; Do not display campaign notice', async () => { + await productFeedPage.goto(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + + await expect( + await productFeedPage.getActiveProductValueElement() + ).toBeVisible(); + + await expect( + ( await productFeedPage.getActiveProductValue() ).trim() + ).toBe( '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: 1, + } ); + await page.reload(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + + await expect( + await productFeedPage.getActiveProductValueElement() + ).toBeVisible(); + + await expect( + ( await productFeedPage.getActiveProductValue() ).trim() + ).toBe( '0' ); + + await expect( + await productFeedPage.getCampaignNoticeSection() + ).not.toBeVisible(); + } ); + } ); +} ); diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js new file mode 100644 index 0000000000..e3754d131c --- /dev/null +++ b/tests/e2e/utils/pages/product-feed.js @@ -0,0 +1,76 @@ +/** + * Internal dependencies + */ +import { LOAD_STATE } from '../constants'; +import MockRequests from '../mock-requests'; + +/** + * ProductFeed page object class. + */ +export default class ProductFeedPage extends MockRequests { + /** + * @param {import('@playwright/test').Page} page + */ + constructor( page ) { + super( page ); + this.page = page; + } + + /** + * Go to the product feed page. + * + * @return {Promise} + */ + async goto() { + await this.page.goto( + '/wp-admin/admin.php?page=wc-admin&path=%2Fgoogle%2Fproduct-feed', + { waitUntil: LOAD_STATE.DOM_CONTENT_LOADED } + ); + } + + /** + * Get the active product value element. + * + * @return {Promise} The active product value element. + */ + async getActiveProductValueElement() { + return this.page + .locator( '.woocommerce-summary__item-label span >> text=Active' ) + .locator( '../..' ) // Move to parent + .locator( '.woocommerce-summary__item-value span' ); + } + + /** + * Get the active product value. + * + * @return {Promise} The active product value as a string. + */ + async getActiveProductValue() { + return this.page + .locator( '.woocommerce-summary__item-label span >> text=Active' ) + .locator( '../..' ) // Move to parent + .locator( '.woocommerce-summary__item-value span' ) + .innerText(); + } + + /** + * Get the campaign notice section. + * + * @return {Promise} The campaign notice section. + */ + async getCampaignNoticeSection() { + return this.page.locator( '.gla-create-campaign-notice' ); + } + + /** + * Get the create campaign button in the notice section. + * + * @return {Promise} The create campaign button. + */ + async getInNoticeCreateCampaignButton() { + const campaignNoticeSection = await this.getCampaignNoticeSection(); + return campaignNoticeSection.getByRole( 'button', { + name: 'Create Campaign', + } ); + } +} From 7b963a493e6b9a99c33aaa649f2ed85aad16a800 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 03:05:34 +0100 Subject: [PATCH 10/90] fix bug --- js/src/hooks/useAdsCampaigns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index 235b12a6a7..9515b65a80 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -58,7 +58,7 @@ const useAdsCampaigns = ( ...query ) => { data, }; }, - [ queryRefValue ] + [ queryRefValue, hasGoogleAdsConnection, hasFinishedResolution ] ); }; From cefcd7a9d3a3509b1b70e0ee7996c9414e7f6337 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 05:10:06 +0100 Subject: [PATCH 11/90] fix e2e account connection --- .../product-feed-campaign-notice.test.js | 23 +++----- tests/e2e/utils/pages/product-feed.js | 53 +++++++++++++++++++ 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index 32b8e10623..c72d8b0bbe 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -41,9 +41,11 @@ test.describe( 'Product Feed Page', () => { dashboardPage = new DashboardPage( page ); productFeedPage = new ProductFeedPage( page ); setupAdsAccounts = new SetupAdsAccountsPage( page ); - await setupAdsAccounts.mockAdsAccountsResponse( [] ); - await setOnboardedMerchant(); - await dashboardPage.mockRequests(); + await Promise.all( [ + setupAdsAccounts.mockAdsAccountsResponse( [] ), + productFeedPage.mockRequests(), + setOnboardedMerchant(), + ] ); } ); test.afterAll( async () => { @@ -53,12 +55,6 @@ test.describe( 'Product Feed Page', () => { test.describe( 'No campaign', () => { test.beforeAll( async () => { - await setupAdsAccounts.mockAdsAccountsResponse( { - issues: [], - total: 0, - page: 1, - loading: false, - } ); await productFeedPage.fulfillAdsCampaignsRequest( [] ); await productFeedPage.goto(); } ); @@ -155,12 +151,6 @@ test.describe( 'Product Feed Page', () => { test.describe( 'Has campaign', () => { test.beforeAll( async () => { - await setupAdsAccounts.mockAdsAccountsResponse( { - issues: [], - total: 0, - page: 1, - loading: false, - } ); await productFeedPage.fulfillAdsCampaignsRequest( [ { id: 111111111, @@ -201,7 +191,8 @@ test.describe( 'Product Feed Page', () => { disapproved: 0, not_synced: 1137, }, - scheduled_sync: 1, + scheduled_sync: 0, + loading: false, } ); await page.reload(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index e3754d131c..ce5b26791b 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -28,6 +28,59 @@ export default class ProductFeedPage extends MockRequests { ); } + /** + * Mock all requests related to external accounts such as Merchant Center, Google, etc. + * + * @return {Promise} + */ + async mockRequests() { + await Promise.all( [ + this.fulfillMCReview( { + cooldown: 0, + issues: [], + reviewEligibleRegions: [], + status: 'ONBOARDING', + } ), + this.fulfillAccountIssuesRequest( { + issues: [], + page: 1, + total: 0, + loading: false, + } ), + // Mock Reports Programs + this.fulfillMCReportProgram( { + free_listings: null, + products: null, + intervals: null, + totals: { + clicks: 0, + impressions: 0, + }, + next_page: null, + } ), + this.fulfillTargetAudience( { + location: 'selected', + countries: [ 'US' ], + locale: 'en_US', + language: 'English', + } ), + this.fulfillJetPackConnection( { + active: 'yes', + owner: 'yes', + displayName: 'John', + email: 'john@email.com', + } ), + this.mockGoogleConnected(), + this.fulfillAdsConnection( { + id: 1111111, + currency: 'USD', + symbol: '$', + status: 'connected', + step: '', + } ), + ] ); + } + /** * Get the active product value element. * From 25365e5411bcf3955f466bfaa278ae6e39df02a4 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 05:10:53 +0100 Subject: [PATCH 12/90] add more spaces. --- tests/e2e/utils/pages/product-feed.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index ce5b26791b..bf2b2884bc 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -41,12 +41,14 @@ export default class ProductFeedPage extends MockRequests { reviewEligibleRegions: [], status: 'ONBOARDING', } ), + this.fulfillAccountIssuesRequest( { issues: [], page: 1, total: 0, loading: false, } ), + // Mock Reports Programs this.fulfillMCReportProgram( { free_listings: null, @@ -58,19 +60,23 @@ export default class ProductFeedPage extends MockRequests { }, next_page: null, } ), + this.fulfillTargetAudience( { location: 'selected', countries: [ 'US' ], locale: 'en_US', language: 'English', } ), + this.fulfillJetPackConnection( { active: 'yes', owner: 'yes', displayName: 'John', email: 'john@email.com', } ), + this.mockGoogleConnected(), + this.fulfillAdsConnection( { id: 1111111, currency: 'USD', From a3b00cbf54536186d966af392d03e4e831fb87a5 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 05:27:59 +0100 Subject: [PATCH 13/90] remove unused dashboard variable. --- .../product-feed/product-feed-campaign-notice.test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index c72d8b0bbe..9b84fdbc86 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -6,7 +6,6 @@ import { expect, test } from '@playwright/test'; * Internal dependencies */ import { clearOnboardedMerchant, setOnboardedMerchant } from '../../utils/api'; -import DashboardPage from '../../utils/pages/dashboard.js'; import ProductFeedPage from '../../utils/pages/product-feed'; import SetupAdsAccountsPage from '../../utils/pages/setup-ads/setup-ads-accounts.js'; import { LOAD_STATE } from '../../utils/constants'; @@ -15,11 +14,6 @@ test.use( { storageState: process.env.ADMINSTATE } ); test.describe.configure( { mode: 'serial' } ); -/** - * @type {import('../../utils/pages/dashboard.js').default} dashboardPage - */ -let dashboardPage = null; - /** * @type {import('../../utils/pages/setup-ads/setup-ads-accounts').default} setupAdsAccounts */ @@ -38,7 +32,6 @@ let page = null; test.describe( 'Product Feed Page', () => { test.beforeAll( async ( { browser } ) => { page = await browser.newPage(); - dashboardPage = new DashboardPage( page ); productFeedPage = new ProductFeedPage( page ); setupAdsAccounts = new SetupAdsAccountsPage( page ); await Promise.all( [ From df22e4a20f5adb111f20524aae8d0a83b8dd7c5e Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 05:45:55 +0100 Subject: [PATCH 14/90] remove incorrect comment --- tests/e2e/utils/pages/product-feed.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index bf2b2884bc..476e7d9d51 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -95,7 +95,7 @@ export default class ProductFeedPage extends MockRequests { async getActiveProductValueElement() { return this.page .locator( '.woocommerce-summary__item-label span >> text=Active' ) - .locator( '../..' ) // Move to parent + .locator( '../..' ) .locator( '.woocommerce-summary__item-value span' ); } @@ -107,7 +107,7 @@ export default class ProductFeedPage extends MockRequests { async getActiveProductValue() { return this.page .locator( '.woocommerce-summary__item-label span >> text=Active' ) - .locator( '../..' ) // Move to parent + .locator( '../..' ) .locator( '.woocommerce-summary__item-value span' ) .innerText(); } From 15123b099e968d6adda046768db81be99b5283ae Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 14 Oct 2024 06:30:31 +0100 Subject: [PATCH 15/90] remove unused fulfill's --- tests/e2e/utils/pages/product-feed.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index 476e7d9d51..6165df0651 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -49,25 +49,6 @@ export default class ProductFeedPage extends MockRequests { loading: false, } ), - // Mock Reports Programs - this.fulfillMCReportProgram( { - free_listings: null, - products: null, - intervals: null, - totals: { - clicks: 0, - impressions: 0, - }, - next_page: null, - } ), - - this.fulfillTargetAudience( { - location: 'selected', - countries: [ 'US' ], - locale: 'en_US', - language: 'English', - } ), - this.fulfillJetPackConnection( { active: 'yes', owner: 'yes', From 120d5fde7f90bc3d779f2a80ce59497cff47c3b6 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Mon, 14 Oct 2024 21:53:40 -0500 Subject: [PATCH 16/90] Avoid querying campaigns in useAdsCampaigns before connection --- js/src/dashboard/all-programs-table-card/index.js | 5 +++-- js/src/hooks/useAdsCampaigns.js | 15 ++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/js/src/dashboard/all-programs-table-card/index.js b/js/src/dashboard/all-programs-table-card/index.js index 52f1f17eb5..d3046c308b 100644 --- a/js/src/dashboard/all-programs-table-card/index.js +++ b/js/src/dashboard/all-programs-table-card/index.js @@ -78,10 +78,11 @@ const AllProgramsTableCard = ( props ) => { const { formatAmount } = useAdsCurrency(); const { data: finalCountryCodesData } = useTargetAudienceFinalCountryCodes(); - const { data: adsCampaignsData } = useAdsCampaigns(); + const { data: adsCampaignsData, loaded: adsCampaignsLoaded } = + useAdsCampaigns(); const map = useCountryKeyNameMap(); - if ( ! finalCountryCodesData || ! adsCampaignsData ) { + if ( ! finalCountryCodesData || ! adsCampaignsLoaded ) { return ; } diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index 9515b65a80..828456d032 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -30,15 +30,15 @@ const selectorName = 'getAdsCampaigns'; */ const useAdsCampaigns = ( ...query ) => { const queryRefValue = useIsEqualRefValue( query ); - const { hasGoogleAdsConnection, hasFinishedResolution } = + const { hasGoogleAdsConnection, hasFinishedResolution, isResolving } = useGoogleAdsAccount(); return useSelect( ( select ) => { - if ( hasFinishedResolution && ! hasGoogleAdsConnection ) { + if ( ! hasGoogleAdsConnection ) { return { - loading: false, - loaded: true, + loading: isResolving, + loaded: hasFinishedResolution, data: [], }; } @@ -58,7 +58,12 @@ const useAdsCampaigns = ( ...query ) => { data, }; }, - [ queryRefValue, hasGoogleAdsConnection, hasFinishedResolution ] + [ + hasFinishedResolution, + hasGoogleAdsConnection, + isResolving, + queryRefValue, + ] ); }; From 922edb4d14fe5eedfee750f95f0c5aa8e621d8b5 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Mon, 14 Oct 2024 21:53:53 -0500 Subject: [PATCH 17/90] Fix E2E tests --- .../add-paid-campaigns.test.js | 26 +++++++++++++++++++ .../setup-mc/step-4-complete-campaign.test.js | 1 + 2 files changed, 27 insertions(+) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index 805f77e798..c47a378579 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -460,6 +460,18 @@ test.describe( 'Set up Ads account', () => { ) ).toBeVisible(); + await setupBudgetPage.fulfillAdsCampaignsRequest( [ + { + id: 111111111, + name: 'Test Campaign', + status: 'enabled', + type: 'performance_max', + amount: budget, + country: 'US', + targeted_locations: [ 'US' ], + }, + ] ); + //It should redirect to the dashboard page await page.waitForURL( '/wp-admin/admin.php?page=wc-admin&path=%2Fgoogle%2Fdashboard&guide=campaign-creation-success', @@ -499,6 +511,20 @@ test.describe( 'Set up Ads account', () => { } ); test.describe( 'Create Ads with billing data already setup', () => { + test.beforeAll( async () => { + // Reset the campaigns set in the previous tests. + await setupBudgetPage.fulfillAdsCampaignsRequest( [] ); + + // Mock budget recommendations. + await setupBudgetPage.fulfillRequest( + /\/wc\/gla\/ads\/campaigns\/budget-recommendation\b/, + { + currency: 'USD', + recommendations: [ { country: 'US', daily_budget: 15 } ], + } + ); + } ); + test( 'Launch paid campaign should be enabled', async () => { //Click Add paid Campaign await adsConnectionButton.click(); diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index 53b2a4a497..b94eba2d1a 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -412,6 +412,7 @@ test.describe( 'Complete your campaign', () => { await completeCampaign.goto(); await completeCampaign.clickCreatePaidAdButton(); await completeCampaign.clickSkipPaidAdsCreationButon(); + await completeCampaign.fulfillAdsCampaignsRequest( [] ); } ); test( 'should also see the setup success modal', async () => { From c19de7173c5fb5a600e80c4364917aff7f4b828c Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 09:00:22 +0100 Subject: [PATCH 18/90] replace child with text content --- .../product-statistics/create-campaign-notice.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index 424769bac0..b9d25d09ce 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -45,11 +45,9 @@ const CreateCampaignNotice = () => { eventProps={ { context: 'product-feed-overview-promotion', } } - children={ __( - 'Create Campaign', - 'google-listings-and-ads' - ) } - /> + > + { __( 'Create Campaign', 'google-listings-and-ads' ) }{ ' ' } + ); From 1536e4be5abc757b2d9cca4f33be1930b3955cf8 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 09:09:10 +0100 Subject: [PATCH 19/90] simplyfy logic --- .../product-statistics/create-campaign-notice.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index b9d25d09ce..e8be8eb7f7 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -19,13 +19,11 @@ const CreateCampaignNotice = () => { const isLoading = ! productsResolution || products?.loading || ! campaignsLoaded; - const inValidData = - ( productsResolution && ! products ) || - ( campaignsLoaded && ! campaigns ); + const invalidData = ! isLoading && ( ! products || ! campaigns ); if ( isLoading || - inValidData || + invalidData || products?.statistics?.active === 0 || campaigns?.length > 0 ) { From 46319786f6b6d490dfa3854099a62bf50053c6c7 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 09:10:57 +0100 Subject: [PATCH 20/90] simplify logic --- .../product-statistics/create-campaign-notice.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index e8be8eb7f7..3276f099d4 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -19,11 +19,10 @@ const CreateCampaignNotice = () => { const isLoading = ! productsResolution || products?.loading || ! campaignsLoaded; - const invalidData = ! isLoading && ( ! products || ! campaigns ); - if ( isLoading || - invalidData || + ! products || + ! campaigns || products?.statistics?.active === 0 || campaigns?.length > 0 ) { From 6181299006419c90c5d0c00ac21c31b48e057fd6 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 09:18:36 +0100 Subject: [PATCH 21/90] slight rearragment --- .../product-feed/product-statistics/create-campaign-notice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index 3276f099d4..06af03edd4 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -22,8 +22,8 @@ const CreateCampaignNotice = () => { if ( isLoading || ! products || - ! campaigns || products?.statistics?.active === 0 || + ! campaigns || campaigns?.length > 0 ) { return null; From c65f0716c13e27aa491f850ec85657737dffc17e Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 10:53:55 +0100 Subject: [PATCH 22/90] change variable name --- .../product-statistics/create-campaign-notice.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index 06af03edd4..a4ee312515 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -12,12 +12,16 @@ import useMCProductStatistics from '.~/hooks/useMCProductStatistics'; import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; const CreateCampaignNotice = () => { - const { hasFinishedResolution: productsResolution, data: products } = - useMCProductStatistics(); + const { + hasFinishedResolution: hasMCProductStatsFinishedResolution, + data: products, + } = useMCProductStatistics(); const { loaded: campaignsLoaded, data: campaigns } = useAdsCampaigns(); const isLoading = - ! productsResolution || products?.loading || ! campaignsLoaded; + ! hasMCProductStatsFinishedResolution || + products?.loading || + ! campaignsLoaded; if ( isLoading || From 59ac898e0dc46ab8f9bc07704fffaf77f30f943e Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 10:55:06 +0100 Subject: [PATCH 23/90] remove alaising --- .../product-statistics/create-campaign-notice.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index a4ee312515..4c2967235c 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -12,16 +12,11 @@ import useMCProductStatistics from '.~/hooks/useMCProductStatistics'; import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; const CreateCampaignNotice = () => { - const { - hasFinishedResolution: hasMCProductStatsFinishedResolution, - data: products, - } = useMCProductStatistics(); + const { hasFinishedResolution, data: products } = useMCProductStatistics(); const { loaded: campaignsLoaded, data: campaigns } = useAdsCampaigns(); const isLoading = - ! hasMCProductStatsFinishedResolution || - products?.loading || - ! campaignsLoaded; + ! hasFinishedResolution || products?.loading || ! campaignsLoaded; if ( isLoading || From 1b739a6024691aca9013fa0e9ffffc7e5ae4f22c Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 18 Oct 2024 11:16:08 +0100 Subject: [PATCH 24/90] remove class name --- .../product-statistics/create-campaign-notice.js | 2 +- tests/e2e/utils/pages/product-feed.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice.js index 4c2967235c..64345c06f7 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice.js @@ -29,7 +29,7 @@ const CreateCampaignNotice = () => { } return ( - +

{ __( diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index 6165df0651..2463630e18 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -99,7 +99,10 @@ export default class ProductFeedPage extends MockRequests { * @return {Promise} The campaign notice section. */ async getCampaignNoticeSection() { - return this.page.locator( '.gla-create-campaign-notice' ); + return this.page.locator( '.components-notice__content' ).filter( { + hasText: + 'You have approved products. Create a Google Ads campaign to reach more customers and drive more sales.', + } ); } /** From 6d90bb9e3ea577f4f987eab213025240a9b7e22c Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 21 Oct 2024 17:17:21 +0100 Subject: [PATCH 25/90] fix jest error --- js/src/dashboard/all-programs-table-card/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/dashboard/all-programs-table-card/index.test.js b/js/src/dashboard/all-programs-table-card/index.test.js index ac57aed8f8..dec57759a9 100644 --- a/js/src/dashboard/all-programs-table-card/index.test.js +++ b/js/src/dashboard/all-programs-table-card/index.test.js @@ -83,7 +83,7 @@ describe( 'AllProgramsTableCard', () => { let mockedCampaigns = []; useAdsCampaigns.mockImplementation( () => { - return { data: mockedCampaigns }; + return { data: mockedCampaigns, loaded: true }; } ); mockCampaigns = ( ...campaigns ) => { From 199675d6c77e4e41b73a0aaa83713fa2e918ae02 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Mon, 21 Oct 2024 18:33:49 -0500 Subject: [PATCH 26/90] Fix notice styling --- .../index.js} | 4 +++- .../create-campaign-notice/index.scss | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) rename js/src/product-feed/product-statistics/{create-campaign-notice.js => create-campaign-notice/index.js} (91%) create mode 100644 js/src/product-feed/product-statistics/create-campaign-notice/index.scss diff --git a/js/src/product-feed/product-statistics/create-campaign-notice.js b/js/src/product-feed/product-statistics/create-campaign-notice/index.js similarity index 91% rename from js/src/product-feed/product-statistics/create-campaign-notice.js rename to js/src/product-feed/product-statistics/create-campaign-notice/index.js index 64345c06f7..ec0ca21663 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.js @@ -10,6 +10,7 @@ import { Notice } from '@wordpress/components'; 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 { hasFinishedResolution, data: products } = useMCProductStatistics(); @@ -29,7 +30,7 @@ const CreateCampaignNotice = () => { } return ( - +

{ __( @@ -38,6 +39,7 @@ const CreateCampaignNotice = () => { ) }

Date: Mon, 21 Oct 2024 18:48:02 -0500 Subject: [PATCH 27/90] Fix CSS lint issues --- .../product-statistics/create-campaign-notice/index.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss index cc658ae06b..e96e3b4585 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss @@ -1,7 +1,7 @@ -.gla-ads-inline-notice{ +.gla-ads-inline-notice { margin: $grid-unit-20; border-left: none; - padding: .75rem 1rem; + padding: 0.75rem 1rem; &.is-info { background-color: #f0f6fc; From 80016a257809565976253596774e98a5e7e3906d Mon Sep 17 00:00:00 2001 From: asvinb Date: Tue, 22 Oct 2024 12:14:05 +0400 Subject: [PATCH 28/90] Review styles. --- .../product-statistics/create-campaign-notice/index.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss index e96e3b4585..db63c2e539 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss @@ -7,7 +7,7 @@ background-color: #f0f6fc; } - .components-notice__content p:first-child { - margin-top: 2px; + .components-notice__content p { + margin-top: 0; } } From d54475975ad8b7294badfa7e8fd20694133034a6 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 13:12:19 +0100 Subject: [PATCH 29/90] remove free credits --- .../paid-ads/ads-campaign/paid-ads-features-section.js | 6 +----- js/src/setup-ads/ads-stepper/setup-accounts/index.js | 4 +--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/js/src/components/paid-ads/ads-campaign/paid-ads-features-section.js b/js/src/components/paid-ads/ads-campaign/paid-ads-features-section.js index 8abdde4e33..94da88b4da 100644 --- a/js/src/components/paid-ads/ads-campaign/paid-ads-features-section.js +++ b/js/src/components/paid-ads/ads-campaign/paid-ads-features-section.js @@ -14,7 +14,6 @@ import AppDocumentationLink from '.~/components/app-documentation-link'; import CampaignPreview from '.~/components/paid-ads/campaign-preview'; import FreeAdCredit from '.~/components/free-ad-credit'; import VerticalGapLayout from '.~/components/vertical-gap-layout'; -import useFreeAdCredit from '.~/hooks/useFreeAdCredit'; import './paid-ads-features-section.scss'; function FeatureList() { @@ -49,8 +48,6 @@ function FeatureList() { * for the next actions: skip or continue the paid ads setup. */ export default function PaidAdsFeaturesSection() { - const hasFreeAdCredit = useFreeAdCredit(); - return (
- - { hasFreeAdCredit && } + diff --git a/js/src/setup-ads/ads-stepper/setup-accounts/index.js b/js/src/setup-ads/ads-stepper/setup-accounts/index.js index 17ee5995b6..021303dc92 100644 --- a/js/src/setup-ads/ads-stepper/setup-accounts/index.js +++ b/js/src/setup-ads/ads-stepper/setup-accounts/index.js @@ -18,7 +18,6 @@ import FreeAdCredit from '.~/components/free-ad-credit'; import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; import useGoogleAdsAccountStatus from '.~/hooks/useGoogleAdsAccountStatus'; import useGoogleAccount from '.~/hooks/useGoogleAccount'; -import useFreeAdCredit from '.~/hooks/useFreeAdCredit'; import AppSpinner from '.~/components/app-spinner'; import Section from '.~/wcdl/section'; @@ -27,7 +26,6 @@ const SetupAccounts = ( props ) => { const { google } = useGoogleAccount(); const { googleAdsAccount, hasGoogleAdsConnection } = useGoogleAdsAccount(); const { hasAccess, step } = useGoogleAdsAccountStatus(); - const hasFreeAdCredit = useFreeAdCredit(); if ( ! google || ( google.active === 'yes' && ! googleAdsAccount ) ) { return ; @@ -72,7 +70,7 @@ const SetupAccounts = ( props ) => { ) } /> - { hasFreeAdCredit && } +
From 62d124c4392644a6fd2eda86252c2c9c8e62806a Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 13:12:45 +0100 Subject: [PATCH 30/90] add paid-features.js --- .../paid-campaign-promotion-card.js | 34 +----- .../summary-section/paid-features.js | 102 ++++++++++++++++++ 2 files changed, 104 insertions(+), 32 deletions(-) create mode 100644 js/src/dashboard/summary-section/paid-features.js diff --git a/js/src/dashboard/summary-section/paid-campaign-promotion-card.js b/js/src/dashboard/summary-section/paid-campaign-promotion-card.js index 39296f3a36..1c22fc565a 100644 --- a/js/src/dashboard/summary-section/paid-campaign-promotion-card.js +++ b/js/src/dashboard/summary-section/paid-campaign-promotion-card.js @@ -8,44 +8,14 @@ import { Spinner } from '@woocommerce/components'; * Internal dependencies */ import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; -import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button'; -import { GOOGLE_ADS_ACCOUNT_STATUS } from '.~/constants'; - -const PromotionContent = ( { adsAccount } ) => { - const showFreeCredit = - adsAccount.sub_account || - adsAccount.status === GOOGLE_ADS_ACCOUNT_STATUS.DISCONNECTED; - - return ( - <> -

- { showFreeCredit - ? __( - 'Create your first campaign and get $500 in ad credit*', - 'google-listings-and-ads' - ) - : __( - 'Create your first campaign', - 'google-listings-and-ads' - ) } -

- - - ); -}; +import PaidFeatures from './paid-features'; function PaidCampaignPromotionCard() { const { googleAdsAccount } = useGoogleAdsAccount(); return (
- { googleAdsAccount ? ( - - ) : ( - - ) } + { googleAdsAccount ? : }
); } diff --git a/js/src/dashboard/summary-section/paid-features.js b/js/src/dashboard/summary-section/paid-features.js new file mode 100644 index 0000000000..da140ec02b --- /dev/null +++ b/js/src/dashboard/summary-section/paid-features.js @@ -0,0 +1,102 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { createInterpolateElement } from '@wordpress/element'; +import { Flex, FlexBlock, FlexItem, Card } from '@wordpress/components'; +import GridiconCheckmark from 'gridicons/dist/checkmark'; + +/** + * Internal dependencies + */ +import { ContentLink } from '.~/components/guide-page-content'; +import CampaignPreview from '.~/components/paid-ads/campaign-preview'; +import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button'; +import FreeAdCredit from '.~/components/free-ad-credit'; +import VerticalGapLayout from '.~/components/vertical-gap-layout'; + +// import '.~/setup-mc/setup-stepper/setup-paid-ads/paid-ads-features-section.scss'; + +function FeatureList() { + const featuresItems = [ + { + Icon: GridiconCheckmark, + content: __( + 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.', + 'google-listings-and-ads' + ), + }, + { + Icon: GridiconCheckmark, + content: __( + 'Set a daily budget and only pay when people click on your ads.', + 'google-listings-and-ads' + ), + }, + { + Icon: GridiconCheckmark, + content: createInterpolateElement( + __( + "Performance Max uses the best of Google's AI to show the most impactful ads for your products at the right time and place. Learn more about Performance Max technology.", + 'google-listings-and-ads' + ), + { + link: ( + + ), + } + ), + }, + ]; + + return ( +
+ { featuresItems.map( ( { Icon, content }, idx ) => ( + + + { content } + + ) ) } +
+ ); +} + +/** + * Returns a Card with the given content. + * + * @return {Card} Card with title and content. + */ +const PaidFeatures = () => { + return ( + + + + + + + + + + + + { __( 'Create Campaign', 'google-listings-and-ads' ) } + + + ); +}; + +export default PaidFeatures; From 19ef7b1e0a3306984c31ac1659b665a8a3a5814e Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 13:17:32 +0100 Subject: [PATCH 31/90] remove translations --- js/src/dashboard/summary-section/paid-campaign-promotion-card.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/src/dashboard/summary-section/paid-campaign-promotion-card.js b/js/src/dashboard/summary-section/paid-campaign-promotion-card.js index 1c22fc565a..99f2406303 100644 --- a/js/src/dashboard/summary-section/paid-campaign-promotion-card.js +++ b/js/src/dashboard/summary-section/paid-campaign-promotion-card.js @@ -1,7 +1,6 @@ /** * External dependencies */ -import { __ } from '@wordpress/i18n'; import { Spinner } from '@woocommerce/components'; /** From 90ea27ad2c505a4519056cd0ca31ad22a48c553b Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 13:35:03 +0100 Subject: [PATCH 32/90] e2e --- .../add-paid-campaigns.test.js | 4 ++++ tests/e2e/utils/pages/dashboard.js | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index 987a7111ae..3b3037545f 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -85,6 +85,10 @@ test.describe( 'Set up Ads account', () => { dashboardPage.getAdsConnectionAllProgramsButton( 'summary-card' ) ).toBeEnabled(); + await expect( + dashboardPage.getPaidFeaturesContentArea() + ).toBeVisible(); + //Add page campaign in the programs section. adsConnectionButton = dashboardPage.getAdsConnectionAllProgramsButton(); await expect( adsConnectionButton ).toBeEnabled(); diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index 57aba3ed61..481e0a0927 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -142,8 +142,23 @@ export default class DashboardPage extends MockRequests { : '.gla-summary-card' }`, { - hasText: 'Add paid campaign', + hasText: + type === 'programs-table' + ? 'Add paid campaign' + : 'Create Campaign', } ); } + + /** + * Get the Paid Features content area. + * + * @return {import('@playwright/test').Locator} Get the Ads connection button. + */ + getPaidFeaturesContentArea() { + return this.page.locator( 'gla-paid-ads-features-section__content', { + hasText: + 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.', + } ); + } } From 2a7af585a15156f81e80c11f19392850ada71238 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 14:31:32 +0100 Subject: [PATCH 33/90] style fixes and e2e --- .../index.js} | 11 ++++--- .../summary-section/paid-features/index.scss | 30 +++++++++++++++++++ .../add-paid-campaigns.test.js | 10 ++++--- 3 files changed, 41 insertions(+), 10 deletions(-) rename js/src/dashboard/summary-section/{paid-features.js => paid-features/index.js} (90%) create mode 100644 js/src/dashboard/summary-section/paid-features/index.scss diff --git a/js/src/dashboard/summary-section/paid-features.js b/js/src/dashboard/summary-section/paid-features/index.js similarity index 90% rename from js/src/dashboard/summary-section/paid-features.js rename to js/src/dashboard/summary-section/paid-features/index.js index da140ec02b..8d6f01bdb8 100644 --- a/js/src/dashboard/summary-section/paid-features.js +++ b/js/src/dashboard/summary-section/paid-features/index.js @@ -14,8 +14,7 @@ import CampaignPreview from '.~/components/paid-ads/campaign-preview'; import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button'; import FreeAdCredit from '.~/components/free-ad-credit'; import VerticalGapLayout from '.~/components/vertical-gap-layout'; - -// import '.~/setup-mc/setup-stepper/setup-paid-ads/paid-ads-features-section.scss'; +import './index.scss'; function FeatureList() { const featuresItems = [ @@ -53,7 +52,7 @@ function FeatureList() { ]; return ( -
+
{ featuresItems.map( ( { Icon, content }, idx ) => ( @@ -71,11 +70,11 @@ function FeatureList() { */ const PaidFeatures = () => { return ( - + @@ -83,8 +82,8 @@ const PaidFeatures = () => { - + { dashboardPage.getAdsConnectionAllProgramsButton( 'summary-card' ) ).toBeEnabled(); - await expect( - dashboardPage.getPaidFeaturesContentArea() - ).toBeVisible(); - //Add page campaign in the programs section. adsConnectionButton = dashboardPage.getAdsConnectionAllProgramsButton(); await expect( adsConnectionButton ).toBeEnabled(); } ); + test( 'Dashboard page contains Paid Features section', async () => { + await expect( + dashboardPage.getPaidFeaturesContentArea() + ).toBeVisible(); + } ); + test.describe( 'Set up your accounts page', async () => { test.beforeAll( async () => { await setupAdsAccounts.mockAdsAccountsResponse( [] ); From 1ed56b8b8fb33b9c6f3478008f4621caa2177cb6 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 14:55:33 +0100 Subject: [PATCH 34/90] fix e2e button clicking --- .../add-paid-campaigns.test.js | 29 ++++++++++++++----- tests/e2e/utils/pages/dashboard.js | 28 +++++------------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index 6cb12b7fc4..6f8d6408cf 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -80,20 +80,35 @@ test.describe( 'Set up Ads account', () => { } ); test( 'Dashboard page contains Add Paid campaign buttons', async () => { - //Add page campaign in the Performance (Paid Campaigns) section - await expect( - dashboardPage.getAdsConnectionAllProgramsButton( 'summary-card' ) - ).toBeEnabled(); - //Add page campaign in the programs section. adsConnectionButton = dashboardPage.getAdsConnectionAllProgramsButton(); await expect( adsConnectionButton ).toBeEnabled(); } ); - test( 'Dashboard page contains Paid Features section', async () => { + test( 'Dashboard page contains Paid Features section with feature list and Create Campaign button', async () => { + await expect( + page.getByText( + 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.' + ) + ).toBeVisible(); + await expect( - dashboardPage.getPaidFeaturesContentArea() + page.getByText( + 'New to Google Ads? Get $500 in ad credit when you spend $500 within your first 60 days.' + ) ).toBeVisible(); + + await expect( dashboardPage.getCreateCampaignButton() ).toBeEnabled(); + await dashboardPage.getCreateCampaignButton().click(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + await expect( + page.getByRole( 'heading', { + name: 'Set up your accounts', + } ) + ).toBeVisible(); + + await dashboardPage.goto(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); } ); test.describe( 'Set up your accounts page', async () => { diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index 481e0a0927..5a8ae6d867 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -131,34 +131,22 @@ export default class DashboardPage extends MockRequests { /** * Get the Ads connection button. * - * @param {('programs-table'|'summary-card')} [type] The type of button to get. Either 'programs-table' or 'summary-card'. * @return {import('@playwright/test').Locator} Get the Ads connection button. */ - getAdsConnectionAllProgramsButton( type = 'programs-table' ) { - return this.page.locator( - `${ - type === 'programs-table' - ? '.gla-all-programs-table-card button' - : '.gla-summary-card' - }`, - { - hasText: - type === 'programs-table' - ? 'Add paid campaign' - : 'Create Campaign', - } - ); + getAdsConnectionAllProgramsButton() { + return this.page.locator( '.gla-all-programs-table-card button', { + hasText: 'Add paid campaign', + } ); } /** - * Get the Paid Features content area. + * Get the Create Campaign button. * * @return {import('@playwright/test').Locator} Get the Ads connection button. */ - getPaidFeaturesContentArea() { - return this.page.locator( 'gla-paid-ads-features-section__content', { - hasText: - 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.', + getCreateCampaignButton() { + return this.page.locator( '.gla-summary-card button', { + hasText: 'Create Campaign', } ); } } From cd2521c25211f764cb977ede3bce1ff580fe8a07 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 22 Oct 2024 15:48:29 +0100 Subject: [PATCH 35/90] fix old e2e --- .../setup-mc/step-4-complete-campaign.test.js | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index adc31ea614..ed0fb458ad 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -9,6 +9,7 @@ const { test, expect } = require( '@playwright/test' ); import SetupBudgetPage from '../../utils/pages/setup-ads/setup-budget'; import CompleteCampaign from '../../utils/pages/setup-mc/step-4-complete-campaign'; import SetupAdsAccountPage from '../../utils/pages/setup-ads/setup-ads-accounts'; +import DashboardPage from '../../utils/pages/dashboard'; import { checkFAQExpandable, getFAQPanelTitle, @@ -35,6 +36,11 @@ let completeCampaign = null; */ let setupAdsAccountPage = null; +/** + * @type {import('../../utils/pages/dashboard.js').default} dashboardPage + */ +let dashboardPage = null; + /** * @type {import('@playwright/test').Page} page */ @@ -44,6 +50,7 @@ test.describe( 'Complete your campaign', () => { test.beforeAll( async ( { browser } ) => { page = await browser.newPage(); setupBudgetPage = new SetupBudgetPage( page ); + dashboardPage = new DashboardPage( page ); completeCampaign = new CompleteCampaign( page ); setupAdsAccountPage = new SetupAdsAccountPage( page ); await Promise.all( [ @@ -321,16 +328,16 @@ test.describe( 'Complete your campaign', () => { test( 'should see buttons on Dashboard for Google Ads onboarding', async () => { await page.keyboard.press( 'Escape' ); await page.getByRole( 'tab', { name: 'Dashboard' } ).click(); + const addPaidCampaignButton = + await dashboardPage.getAdsConnectionAllProgramsButton(); - const buttons = page.getByRole( 'button', { - name: 'Add paid campaign', - } ); + await expect( addPaidCampaignButton ).toBeVisible(); + await expect( addPaidCampaignButton ).toBeEnabled(); - await expect( buttons ).toHaveCount( 2 ); - for ( const button of await buttons.all() ) { - await expect( button ).toBeVisible(); - await expect( button ).toBeEnabled(); - } + const createCampaignButton = + await dashboardPage.getCreateCampaignButton(); + await expect( createCampaignButton ).toBeVisible(); + await expect( createCampaignButton ).toBeEnabled(); } ); } ); @@ -360,7 +367,7 @@ test.describe( 'Complete your campaign', () => { } ); test.describe( 'Free Ad Credit', () => { - test( 'should not see the Free Ad Credit section if the account is not eligible', async () => { + test( 'should see the Free Ad Credit section always', async () => { await setupAdsAccountPage.mockAdsAccountConnected(); await completeCampaign.goto(); await setupAdsAccountPage.awaitAdsConnectionResponse(); @@ -370,21 +377,6 @@ test.describe( 'Complete your campaign', () => { page.getByText( 'Create a campaign to advertise your products' ) ).toBeVisible(); - await expect( - page.getByText( - 'Spend $500 to get $500 in Google Ads credits!' - ) - ).not.toBeVisible(); - } ); - - test( 'should see the Free Ad Credit section if the account is eligible', async () => { - await setupAdsAccountPage.mockAdsAccountConnected( 12345, { - sub_account: true, - created_timestamp: Math.floor( Date.now() / 1000 ), - } ); - await completeCampaign.goto(); - await setupAdsAccountPage.awaitAdsConnectionResponse(); - await expect( page.getByText( 'Spend $500 to get $500 in Google Ads credits!' From 165543cc1f6e87d45b75660203e1c081476335f0 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Thu, 24 Oct 2024 07:47:48 -0500 Subject: [PATCH 36/90] Convert notice to a Flex component in the CardFooter --- .../create-campaign-notice/index.js | 10 +++++----- .../create-campaign-notice/index.scss | 11 ++++------- js/src/product-feed/product-statistics/index.js | 3 ++- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice/index.js b/js/src/product-feed/product-statistics/create-campaign-notice/index.js index ec0ca21663..8770b3203e 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice/index.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.js @@ -2,7 +2,7 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import { Notice } from '@wordpress/components'; +import { Flex, FlexItem } from '@wordpress/components'; /** * Internal dependencies @@ -30,8 +30,8 @@ const CreateCampaignNotice = () => { } return ( - -
+ +

{ __( 'You have approved products. Create a Google Ads campaign to reach more customers and drive more sales.', @@ -46,8 +46,8 @@ const CreateCampaignNotice = () => { > { __( 'Create Campaign', 'google-listings-and-ads' ) }{ ' ' } -

-
+ +
); }; diff --git a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss index db63c2e539..4ece4cf782 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss @@ -1,13 +1,10 @@ .gla-ads-inline-notice { - margin: $grid-unit-20; + background-color: #f0f6fc; border-left: none; - padding: 0.75rem 1rem; + margin-bottom: $grid-unit-20; + padding: $grid-unit-20 $grid-unit-30; - &.is-info { - background-color: #f0f6fc; - } - - .components-notice__content p { + p { margin-top: 0; } } diff --git a/js/src/product-feed/product-statistics/index.js b/js/src/product-feed/product-statistics/index.js index 5f73091544..e3e0f2cfa4 100644 --- a/js/src/product-feed/product-statistics/index.js +++ b/js/src/product-feed/product-statistics/index.js @@ -134,8 +134,9 @@ const ProductStatistics = () => { ) } - + + From 51dfbca64399c0fd10c6809607deeb42ccf2aef7 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 25 Oct 2024 08:58:42 +0100 Subject: [PATCH 37/90] this could be null so return [] --- js/src/hooks/useAdsCampaigns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index 828456d032..89bdc215a0 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -55,7 +55,7 @@ const useAdsCampaigns = ( ...query ) => { return { loading, loaded, - data, + data: data || [], }; }, [ From 3f824c05fa47744ba758894c8e6dffe736f70419 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 25 Oct 2024 08:59:12 +0100 Subject: [PATCH 38/90] update condition here --- .../create-campaign-notice/index.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice/index.js b/js/src/product-feed/product-statistics/create-campaign-notice/index.js index 8770b3203e..f194505b72 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice/index.js +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.js @@ -13,17 +13,12 @@ import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; import './index.scss'; const CreateCampaignNotice = () => { - const { hasFinishedResolution, data: products } = useMCProductStatistics(); + const { data: products } = useMCProductStatistics(); const { loaded: campaignsLoaded, data: campaigns } = useAdsCampaigns(); - const isLoading = - ! hasFinishedResolution || products?.loading || ! campaignsLoaded; - if ( - isLoading || - ! products || - products?.statistics?.active === 0 || - ! campaigns || + ! products?.statistics?.active || + ! campaignsLoaded || campaigns?.length > 0 ) { return null; @@ -44,7 +39,7 @@ const CreateCampaignNotice = () => { context: 'product-feed-overview-promotion', } } > - { __( 'Create Campaign', 'google-listings-and-ads' ) }{ ' ' } + { __( 'Create Campaign', 'google-listings-and-ads' ) } From 660ad11cfbad1876b641f8ead0aecdc3648d5875 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 25 Oct 2024 10:31:40 +0100 Subject: [PATCH 39/90] only fetch campaigns from fully connected account --- js/src/hooks/useAdsCampaigns.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index 89bdc215a0..a70b7455fe 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -9,6 +9,7 @@ import { useSelect } from '@wordpress/data'; import { STORE_KEY } from '.~/data'; import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; import useIsEqualRefValue from '.~/hooks/useIsEqualRefValue'; +import { GOOGLE_ADS_ACCOUNT_STATUS } from '.~/constants'; const selectorName = 'getAdsCampaigns'; @@ -30,15 +31,22 @@ const selectorName = 'getAdsCampaigns'; */ const useAdsCampaigns = ( ...query ) => { const queryRefValue = useIsEqualRefValue( query ); - const { hasGoogleAdsConnection, hasFinishedResolution, isResolving } = - useGoogleAdsAccount(); + const { + googleAdsAccount, + hasGoogleAdsConnection, + hasFinishedResolution, + isResolving, + } = useGoogleAdsAccount(); return useSelect( ( select ) => { - if ( ! hasGoogleAdsConnection ) { + if ( + ! hasGoogleAdsConnection || + googleAdsAccount?.status !== GOOGLE_ADS_ACCOUNT_STATUS.CONNECTED + ) { return { - loading: isResolving, - loaded: hasFinishedResolution, + loading: false, + loaded: true, data: [], }; } @@ -55,7 +63,7 @@ const useAdsCampaigns = ( ...query ) => { return { loading, loaded, - data: data || [], + data, }; }, [ From 052a386632c0f421a75d78fba90c47d13bef7640 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 25 Oct 2024 10:55:58 +0100 Subject: [PATCH 40/90] match loading attributes with that of google ads account api status --- js/src/hooks/useAdsCampaigns.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index a70b7455fe..e273cbbb47 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -45,8 +45,8 @@ const useAdsCampaigns = ( ...query ) => { googleAdsAccount?.status !== GOOGLE_ADS_ACCOUNT_STATUS.CONNECTED ) { return { - loading: false, - loaded: true, + loading: isResolving, + loaded: hasFinishedResolution, data: [], }; } From 77dd887b511bb1a7ed0f12d1cf7b1df498bf1a2f Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 25 Oct 2024 12:00:52 +0100 Subject: [PATCH 41/90] remove button click --- tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index c44718c41e..2f1ec3b1f3 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -363,8 +363,6 @@ test.describe( 'Complete your campaign', () => { test( 'should not see the Free Ad Credit section if the account is not eligible', async () => { await setupAdsAccountPage.mockAdsAccountConnected(); await completeCampaign.goto(); - await completeCampaign.clickCreatePaidAdButton(); - await completeCampaign.clickSkipPaidAdsCreationButon(); await completeCampaign.fulfillAdsCampaignsRequest( [] ); await setupAdsAccountPage.awaitAdsConnectionResponse(); From 30237f320096ec76c7a3c6c07b787536e2a3b81f Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 28 Oct 2024 07:44:24 +0000 Subject: [PATCH 42/90] revert back changes to useAdsCampaigns --- .../all-programs-table-card/index.js | 5 ++- .../all-programs-table-card/index.test.js | 2 +- js/src/hooks/useAdsCampaigns.js | 31 +++++++------------ .../setup-mc/step-4-complete-campaign.test.js | 1 - 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/js/src/dashboard/all-programs-table-card/index.js b/js/src/dashboard/all-programs-table-card/index.js index d3046c308b..52f1f17eb5 100644 --- a/js/src/dashboard/all-programs-table-card/index.js +++ b/js/src/dashboard/all-programs-table-card/index.js @@ -78,11 +78,10 @@ const AllProgramsTableCard = ( props ) => { const { formatAmount } = useAdsCurrency(); const { data: finalCountryCodesData } = useTargetAudienceFinalCountryCodes(); - const { data: adsCampaignsData, loaded: adsCampaignsLoaded } = - useAdsCampaigns(); + const { data: adsCampaignsData } = useAdsCampaigns(); const map = useCountryKeyNameMap(); - if ( ! finalCountryCodesData || ! adsCampaignsLoaded ) { + if ( ! finalCountryCodesData || ! adsCampaignsData ) { return ; } diff --git a/js/src/dashboard/all-programs-table-card/index.test.js b/js/src/dashboard/all-programs-table-card/index.test.js index dec57759a9..ac57aed8f8 100644 --- a/js/src/dashboard/all-programs-table-card/index.test.js +++ b/js/src/dashboard/all-programs-table-card/index.test.js @@ -83,7 +83,7 @@ describe( 'AllProgramsTableCard', () => { let mockedCampaigns = []; useAdsCampaigns.mockImplementation( () => { - return { data: mockedCampaigns, loaded: true }; + return { data: mockedCampaigns }; } ); mockCampaigns = ( ...campaigns ) => { diff --git a/js/src/hooks/useAdsCampaigns.js b/js/src/hooks/useAdsCampaigns.js index e273cbbb47..5975aec450 100644 --- a/js/src/hooks/useAdsCampaigns.js +++ b/js/src/hooks/useAdsCampaigns.js @@ -7,9 +7,8 @@ import { useSelect } from '@wordpress/data'; * Internal dependencies */ import { STORE_KEY } from '.~/data'; -import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; +import { glaData } from '.~/constants'; import useIsEqualRefValue from '.~/hooks/useIsEqualRefValue'; -import { GOOGLE_ADS_ACCOUNT_STATUS } from '.~/constants'; const selectorName = 'getAdsCampaigns'; @@ -31,22 +30,19 @@ const selectorName = 'getAdsCampaigns'; */ const useAdsCampaigns = ( ...query ) => { const queryRefValue = useIsEqualRefValue( query ); - const { - googleAdsAccount, - hasGoogleAdsConnection, - hasFinishedResolution, - isResolving, - } = useGoogleAdsAccount(); return useSelect( ( select ) => { - if ( - ! hasGoogleAdsConnection || - googleAdsAccount?.status !== GOOGLE_ADS_ACCOUNT_STATUS.CONNECTED - ) { + // TODO: ideally adsSetupComplete should be retrieved from API endpoint + // and then put into wp-data. + // With that in place, then we don't need to depend on glaData + // which requires force reload using window.location.href. + const { adsSetupComplete } = glaData; + + if ( ! adsSetupComplete ) { return { - loading: isResolving, - loaded: hasFinishedResolution, + loading: false, + loaded: true, data: [], }; } @@ -66,12 +62,7 @@ const useAdsCampaigns = ( ...query ) => { data, }; }, - [ - hasFinishedResolution, - hasGoogleAdsConnection, - isResolving, - queryRefValue, - ] + [ queryRefValue ] ); }; diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index 2f1ec3b1f3..adc31ea614 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -363,7 +363,6 @@ test.describe( 'Complete your campaign', () => { test( 'should not see the Free Ad Credit section if the account is not eligible', async () => { await setupAdsAccountPage.mockAdsAccountConnected(); await completeCampaign.goto(); - await completeCampaign.fulfillAdsCampaignsRequest( [] ); await setupAdsAccountPage.awaitAdsConnectionResponse(); // Check we are on the correct page. From 65972acffddb78cefba28ab239ef578b1054b00a Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 28 Oct 2024 11:23:39 +0000 Subject: [PATCH 43/90] fix e2e --- .../product-feed-campaign-notice.test.js | 1 + tests/e2e/utils/pages/product-feed.js | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index 9b84fdbc86..db417331f4 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -144,6 +144,7 @@ test.describe( 'Product Feed Page', () => { test.describe( 'Has campaign', () => { test.beforeAll( async () => { + await productFeedPage.mockAdsSetupComplete(); await productFeedPage.fulfillAdsCampaignsRequest( [ { id: 111111111, diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index 2463630e18..6d07395c45 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -68,6 +68,28 @@ export default class ProductFeedPage extends MockRequests { ] ); } + /** + * Change the value of adsSetupComplete to `true` after it is discovered. + * + * @return {Promise} + */ + async mockAdsSetupComplete() { + this.page.addInitScript( () => { + const targetId = 'google-listings-and-ads-js-before'; + const checkElement = () => { + const targetElement = document.getElementById( targetId ); + if ( targetElement ) { + window.glaData = window.glaData || {}; + window.glaData.adsSetupComplete = true; + } else { + // If not, keep checking until targetElement exists + window.requestAnimationFrame( checkElement ); + } + }; + checkElement(); + } ); + } + /** * Get the active product value element. * @@ -99,7 +121,7 @@ export default class ProductFeedPage extends MockRequests { * @return {Promise} The campaign notice section. */ async getCampaignNoticeSection() { - return this.page.locator( '.components-notice__content' ).filter( { + return this.page.locator( '.gla-ads-inline-notice' ).filter( { hasText: 'You have approved products. Create a Google Ads campaign to reach more customers and drive more sales.', } ); From d8cb4ccaab617a6b3e1b4fe4946d4512688d944d Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 28 Oct 2024 13:23:03 +0000 Subject: [PATCH 44/90] address review feedback. --- js/src/dashboard/index.scss | 1 + .../paid-features/free-ad-credit.js | 38 +++++++++++++++++++ .../summary-section/paid-features/index.js | 2 +- .../summary-section/paid-features/index.scss | 4 ++ js/src/hooks/useFreeAdCredit.js | 37 ------------------ 5 files changed, 44 insertions(+), 38 deletions(-) create mode 100644 js/src/dashboard/summary-section/paid-features/free-ad-credit.js delete mode 100644 js/src/hooks/useFreeAdCredit.js diff --git a/js/src/dashboard/index.scss b/js/src/dashboard/index.scss index c1dfa3b54a..417e5efb82 100644 --- a/js/src/dashboard/index.scss +++ b/js/src/dashboard/index.scss @@ -26,6 +26,7 @@ margin-bottom: var(--main-gap); @include break-medium { + align-items: flex-start; flex-direction: row; } diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js new file mode 100644 index 0000000000..b73c131f47 --- /dev/null +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -0,0 +1,38 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import GridiconGift from 'gridicons/dist/gift'; +import { createInterpolateElement } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import AppDocumentationLink from '.~/components/app-documentation-link'; + +const FreeAdCredit = () => { + return ( +
+ +
+ { createInterpolateElement( + __( + 'Claim $500 in ads credit when you spend your first $500 with Google Ads. Terms and conditions apply.', + 'google-listings-and-ads' + ), + { + termLink: ( + + ), + } + ) } +
+
+ ); +}; + +export default FreeAdCredit; diff --git a/js/src/dashboard/summary-section/paid-features/index.js b/js/src/dashboard/summary-section/paid-features/index.js index 8d6f01bdb8..53a0fb2f39 100644 --- a/js/src/dashboard/summary-section/paid-features/index.js +++ b/js/src/dashboard/summary-section/paid-features/index.js @@ -12,7 +12,7 @@ import GridiconCheckmark from 'gridicons/dist/checkmark'; import { ContentLink } from '.~/components/guide-page-content'; import CampaignPreview from '.~/components/paid-ads/campaign-preview'; import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button'; -import FreeAdCredit from '.~/components/free-ad-credit'; +import FreeAdCredit from './free-ad-credit'; import VerticalGapLayout from '.~/components/vertical-gap-layout'; import './index.scss'; diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index ca80a2ca13..b150ee64d2 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -22,6 +22,10 @@ .gla-free-ad-credit { text-align: left; + background-color: #fff; + .gridicon { + fill: #5ec862; + } } .components-button { diff --git a/js/src/hooks/useFreeAdCredit.js b/js/src/hooks/useFreeAdCredit.js deleted file mode 100644 index 556f7fc919..0000000000 --- a/js/src/hooks/useFreeAdCredit.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * External dependencies - */ -import { getDateDifferenceInDays } from '@woocommerce/date'; - -/** - * Internal dependencies - */ -import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; - -/** - * Returns a Boolean value indicating whether the user is eligible for free ad credit. - * - * This will retrieve the user's Google Ads account. - * - * To be eligible for the free ad credit, the account must be a sub-account - * that is newly created within the last 60 days. - * If users disconnected the account and reconnect again, - * it will not be seen as a newly created sub-account - * and hence won't be eligible for the free ad credit. - * - * @return {boolean} Value indicating whether the user is eligible for free ad credit. - */ -const useFreeAdCredit = () => { - const { googleAdsAccount } = useGoogleAdsAccount(); - - return ( - googleAdsAccount && - googleAdsAccount.sub_account && - getDateDifferenceInDays( - new Date(), - new Date( googleAdsAccount.created_timestamp * 1000 ) - ) < 60 - ); -}; - -export default useFreeAdCredit; From cd58bcacfed2d37a08666e5f5b0408cc15bdfffe Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 28 Oct 2024 15:05:44 +0000 Subject: [PATCH 45/90] doc updated. --- .../summary-section/paid-features/free-ad-credit.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index b73c131f47..9fbc447f36 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -10,6 +10,11 @@ import { createInterpolateElement } from '@wordpress/element'; */ import AppDocumentationLink from '.~/components/app-documentation-link'; +/** + * Render the Free Ads Credit section inside the Paid Features section. + * + * @return {JSX.Element} Free Ads Credit section. + */ const FreeAdCredit = () => { return (
From 2954cf654977be99a10ed424f74353e615f1914b Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 30 Oct 2024 09:43:20 +0000 Subject: [PATCH 46/90] update e2e --- .../product-feed-campaign-notice.test.js | 48 ++++++++++--------- tests/e2e/test-data/test-data.php | 36 ++++++++++++++ tests/e2e/utils/api.js | 14 ++++++ tests/e2e/utils/pages/product-feed.js | 43 ++++------------- 4 files changed, 83 insertions(+), 58 deletions(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index db417331f4..da5b69f3e7 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -5,7 +5,12 @@ import { expect, test } from '@playwright/test'; /** * Internal dependencies */ -import { clearOnboardedMerchant, setOnboardedMerchant } from '../../utils/api'; +import { + clearOnboardedMerchant, + setOnboardedMerchant, + setAdsCompletedAt, + clearAdsCompletedAt, +} from '../../utils/api'; import ProductFeedPage from '../../utils/pages/product-feed'; import SetupAdsAccountsPage from '../../utils/pages/setup-ads/setup-ads-accounts.js'; import { LOAD_STATE } from '../../utils/constants'; @@ -35,7 +40,6 @@ test.describe( 'Product Feed Page', () => { productFeedPage = new ProductFeedPage( page ); setupAdsAccounts = new SetupAdsAccountsPage( page ); await Promise.all( [ - setupAdsAccounts.mockAdsAccountsResponse( [] ), productFeedPage.mockRequests(), setOnboardedMerchant(), ] ); @@ -80,12 +84,12 @@ test.describe( 'Product Feed Page', () => { ).toBeVisible(); await expect( - await productFeedPage.getActiveProductValueElement() + productFeedPage.getActiveProductValueElement() ).toBeVisible(); await expect( - ( await productFeedPage.getActiveProductValue() ).trim() - ).toBe( '0' ); + productFeedPage.getActiveProductValueElement() + ).toHaveText( /^0$/ ); await expect( await productFeedPage.getCampaignNoticeSection() @@ -110,17 +114,17 @@ test.describe( 'Product Feed Page', () => { await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await expect( - await productFeedPage.getActiveProductValueElement() + productFeedPage.getActiveProductValueElement() ).toBeVisible(); await expect( - ( await productFeedPage.getActiveProductValue() ).trim() - ).toBe( '1' ); + productFeedPage.getActiveProductValueElement() + ).toHaveText( /^1$/ ); const noticeSection = await productFeedPage.getCampaignNoticeSection(); const createCampaignButton = - await productFeedPage.getInNoticeCreateCampaignButton(); + productFeedPage.getInNoticeCreateCampaignButton(); await expect( noticeSection ).toBeVisible(); await expect( createCampaignButton ).toBeVisible(); @@ -132,19 +136,12 @@ test.describe( 'Product Feed Page', () => { name: 'Set up your accounts', } ) ).toBeVisible(); - - await productFeedPage.goto(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); - - await expect( - page.getByRole( 'heading', { level: 1, name: 'Product Feed' } ) - ).toBeVisible(); } ); } ); test.describe( 'Has campaign', () => { test.beforeAll( async () => { - await productFeedPage.mockAdsSetupComplete(); + await setAdsCompletedAt(); await productFeedPage.fulfillAdsCampaignsRequest( [ { id: 111111111, @@ -158,17 +155,22 @@ test.describe( 'Product Feed Page', () => { ] ); } ); + test.afterAll( async () => { + await clearAdsCompletedAt(); + await page.close(); + } ); + test( 'Has active product and a campaign; Do not display campaign notice', async () => { await productFeedPage.goto(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await expect( - await productFeedPage.getActiveProductValueElement() + productFeedPage.getActiveProductValueElement() ).toBeVisible(); await expect( - ( await productFeedPage.getActiveProductValue() ).trim() - ).toBe( '1' ); + productFeedPage.getActiveProductValueElement() + ).toHaveText( /^1$/ ); await expect( await productFeedPage.getCampaignNoticeSection() @@ -192,12 +194,12 @@ test.describe( 'Product Feed Page', () => { await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await expect( - await productFeedPage.getActiveProductValueElement() + productFeedPage.getActiveProductValueElement() ).toBeVisible(); await expect( - ( await productFeedPage.getActiveProductValue() ).trim() - ).toBe( '0' ); + productFeedPage.getActiveProductValueElement() + ).toHaveText( /^0$/ ); await expect( await productFeedPage.getCampaignNoticeSection() diff --git a/tests/e2e/test-data/test-data.php b/tests/e2e/test-data/test-data.php index 242a117c73..7bc2ff8fee 100644 --- a/tests/e2e/test-data/test-data.php +++ b/tests/e2e/test-data/test-data.php @@ -51,6 +51,22 @@ function register_routes() { ], ], ); + register_rest_route( + 'wc/v3', + 'gla-test/ads-completed', + [ + [ + 'methods' => 'POST', + 'callback' => __NAMESPACE__ . '\set_ads_completed_at', + 'permission_callback' => __NAMESPACE__ . '\permissions', + ], + [ + 'methods' => 'DELETE', + 'callback' => __NAMESPACE__ . '\clear_ads_completed_at', + 'permission_callback' => __NAMESPACE__ . '\permissions', + ], + ], + ); register_rest_route( 'wc/v3', 'gla-test/notifications-ready', @@ -100,6 +116,26 @@ function clear_onboarded_merchant() { $options->delete( OptionsInterface::GOOGLE_CONNECTED ); } +/** + * Set the ADS_SETUP_COMPLETED_AT option. + */ +function set_ads_completed_at() { + /** @var OptionsInterface $options */ + $options = woogle_get_container()->get( OptionsInterface::class ); + $options->update( + OptionsInterface::ADS_SETUP_COMPLETED_AT, + 1693215209 + ); +} + +/** + * Clear a previously set ADS_SETUP_COMPLETED_AT option. + */ +function clear_ads_completed_at() { + /** @var OptionsInterface $options */ + $options = woogle_get_container()->get( OptionsInterface::class ); + $options->delete( OptionsInterface::ADS_SETUP_COMPLETED_AT ); +} /** * Set the Ads Conversion Action to test values. diff --git a/tests/e2e/utils/api.js b/tests/e2e/utils/api.js index 1dbe0d6fe7..d4d59dddcf 100644 --- a/tests/e2e/utils/api.js +++ b/tests/e2e/utils/api.js @@ -113,6 +113,20 @@ export async function clearOnboardedMerchant() { await api().delete( 'gla-test/onboarded-merchant' ); } +/** + * Set Ads Completed At. + */ +export async function setAdsCompletedAt() { + await api().post( 'gla-test/ads-completed' ); +} + +/** + * Clear Ads Completed At. + */ +export async function clearAdsCompletedAt() { + await api().delete( 'gla-test/ads-completed' ); +} + /** * Set Notifications Ready. */ diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index 6d07395c45..465fa62d92 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -49,22 +49,9 @@ export default class ProductFeedPage extends MockRequests { loading: false, } ), - this.fulfillJetPackConnection( { - active: 'yes', - owner: 'yes', - displayName: 'John', - email: 'john@email.com', - } ), - + this.mockJetpackConnected(), this.mockGoogleConnected(), - - this.fulfillAdsConnection( { - id: 1111111, - currency: 'USD', - symbol: '$', - status: 'connected', - step: '', - } ), + this.mockAdsAccountConnected(), ] ); } @@ -93,32 +80,19 @@ export default class ProductFeedPage extends MockRequests { /** * Get the active product value element. * - * @return {Promise} The active product value element. + * @return {import('@playwright/test').Locator} The active product value element. */ - async getActiveProductValueElement() { + getActiveProductValueElement() { return this.page .locator( '.woocommerce-summary__item-label span >> text=Active' ) .locator( '../..' ) .locator( '.woocommerce-summary__item-value span' ); } - /** - * Get the active product value. - * - * @return {Promise} The active product value as a string. - */ - async getActiveProductValue() { - return this.page - .locator( '.woocommerce-summary__item-label span >> text=Active' ) - .locator( '../..' ) - .locator( '.woocommerce-summary__item-value span' ) - .innerText(); - } - /** * Get the campaign notice section. * - * @return {Promise} The campaign notice section. + * @return {import('@playwright/test').Locator} The campaign notice section. */ async getCampaignNoticeSection() { return this.page.locator( '.gla-ads-inline-notice' ).filter( { @@ -130,11 +104,10 @@ export default class ProductFeedPage extends MockRequests { /** * Get the create campaign button in the notice section. * - * @return {Promise} The create campaign button. + * @return {import('@playwright/test').Locator} The create campaign button. */ - async getInNoticeCreateCampaignButton() { - const campaignNoticeSection = await this.getCampaignNoticeSection(); - return campaignNoticeSection.getByRole( 'button', { + getInNoticeCreateCampaignButton() { + return this.page.getByRole( 'button', { name: 'Create Campaign', } ); } From 09146cfa24a48ceab99edb470954563b71ca4b64 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 30 Oct 2024 09:47:33 +0000 Subject: [PATCH 47/90] add page reload --- .../specs/product-feed/product-feed-campaign-notice.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index da5b69f3e7..cc597f88ec 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -136,6 +136,8 @@ test.describe( 'Product Feed Page', () => { name: 'Set up your accounts', } ) ).toBeVisible(); + await productFeedPage.goto(); + await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); } ); } ); @@ -161,7 +163,7 @@ test.describe( 'Product Feed Page', () => { } ); test( 'Has active product and a campaign; Do not display campaign notice', async () => { - await productFeedPage.goto(); + await page.reload(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await expect( From c1bfc5b0ef272bedaba870ede186bbf6e3bb7f64 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 30 Oct 2024 10:00:10 +0000 Subject: [PATCH 48/90] remove unused variable. --- .../product-feed/product-feed-campaign-notice.test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index cc597f88ec..303fb0f3fb 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -12,18 +12,12 @@ import { clearAdsCompletedAt, } from '../../utils/api'; import ProductFeedPage from '../../utils/pages/product-feed'; -import SetupAdsAccountsPage from '../../utils/pages/setup-ads/setup-ads-accounts.js'; import { LOAD_STATE } from '../../utils/constants'; test.use( { storageState: process.env.ADMINSTATE } ); test.describe.configure( { mode: 'serial' } ); -/** - * @type {import('../../utils/pages/setup-ads/setup-ads-accounts').default} setupAdsAccounts - */ -let setupAdsAccounts = null; - /** * @type {import('../../utils/pages/product-feed').default} productFeedPage */ @@ -38,7 +32,6 @@ test.describe( 'Product Feed Page', () => { test.beforeAll( async ( { browser } ) => { page = await browser.newPage(); productFeedPage = new ProductFeedPage( page ); - setupAdsAccounts = new SetupAdsAccountsPage( page ); await Promise.all( [ productFeedPage.mockRequests(), setOnboardedMerchant(), From 33ebb24d3e0e2ec133b654427266e1ab007ed8b6 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 30 Oct 2024 11:18:41 +0000 Subject: [PATCH 49/90] remove unused css --- .../product-statistics/create-campaign-notice/index.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss index 4ece4cf782..9a71d5d38b 100644 --- a/js/src/product-feed/product-statistics/create-campaign-notice/index.scss +++ b/js/src/product-feed/product-statistics/create-campaign-notice/index.scss @@ -1,6 +1,5 @@ .gla-ads-inline-notice { background-color: #f0f6fc; - border-left: none; margin-bottom: $grid-unit-20; padding: $grid-unit-20 $grid-unit-30; From 616756f17c96ea429a4f8308a8a10c73a413ff9d Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Thu, 31 Oct 2024 09:56:11 +0000 Subject: [PATCH 50/90] remove unused mock. use page.goto instead or reload and rearrage tests --- .../product-feed-campaign-notice.test.js | 30 +++++++------------ tests/e2e/utils/api.js | 4 +-- tests/e2e/utils/pages/product-feed.js | 22 -------------- 3 files changed, 13 insertions(+), 43 deletions(-) diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index 303fb0f3fb..4b57cbd87e 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -8,8 +8,8 @@ import { expect, test } from '@playwright/test'; import { clearOnboardedMerchant, setOnboardedMerchant, - setAdsCompletedAt, - clearAdsCompletedAt, + setCompletedAdsSetup, + clearCompletedAdsSetup, } from '../../utils/api'; import ProductFeedPage from '../../utils/pages/product-feed'; import { LOAD_STATE } from '../../utils/constants'; @@ -46,14 +46,9 @@ test.describe( 'Product Feed Page', () => { test.describe( 'No campaign', () => { test.beforeAll( async () => { await productFeedPage.fulfillAdsCampaignsRequest( [] ); - await productFeedPage.goto(); } ); test( 'No active product and no campaign; Do not display campaign notice', async () => { - await expect( - page.getByRole( 'heading', { level: 1, name: 'Product Feed' } ) - ).toBeVisible(); - await productFeedPage.fulfillProductStatisticsRequest( { timestamp: 1695011644, statistics: { @@ -67,8 +62,10 @@ test.describe( 'Product Feed Page', () => { loading: false, } ); - await page.reload(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + await productFeedPage.goto(); + await expect( + page.getByRole( 'heading', { level: 1, name: 'Product Feed' } ) + ).toBeVisible(); await expect( page.getByRole( 'heading', { @@ -103,8 +100,7 @@ test.describe( 'Product Feed Page', () => { loading: false, } ); - await page.reload(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + await productFeedPage.goto(); await expect( productFeedPage.getActiveProductValueElement() @@ -129,14 +125,12 @@ test.describe( 'Product Feed Page', () => { name: 'Set up your accounts', } ) ).toBeVisible(); - await productFeedPage.goto(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); } ); } ); test.describe( 'Has campaign', () => { test.beforeAll( async () => { - await setAdsCompletedAt(); + await setCompletedAdsSetup(); await productFeedPage.fulfillAdsCampaignsRequest( [ { id: 111111111, @@ -151,13 +145,12 @@ test.describe( 'Product Feed Page', () => { } ); test.afterAll( async () => { - await clearAdsCompletedAt(); + await clearCompletedAdsSetup(); await page.close(); } ); test( 'Has active product and a campaign; Do not display campaign notice', async () => { - await page.reload(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + await productFeedPage.goto(); await expect( productFeedPage.getActiveProductValueElement() @@ -185,8 +178,7 @@ test.describe( 'Product Feed Page', () => { scheduled_sync: 0, loading: false, } ); - await page.reload(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + await productFeedPage.goto(); await expect( productFeedPage.getActiveProductValueElement() diff --git a/tests/e2e/utils/api.js b/tests/e2e/utils/api.js index d4d59dddcf..c7f6eddc4f 100644 --- a/tests/e2e/utils/api.js +++ b/tests/e2e/utils/api.js @@ -116,14 +116,14 @@ export async function clearOnboardedMerchant() { /** * Set Ads Completed At. */ -export async function setAdsCompletedAt() { +export async function setCompletedAdsSetup() { await api().post( 'gla-test/ads-completed' ); } /** * Clear Ads Completed At. */ -export async function clearAdsCompletedAt() { +export async function clearCompletedAdsSetup() { await api().delete( 'gla-test/ads-completed' ); } diff --git a/tests/e2e/utils/pages/product-feed.js b/tests/e2e/utils/pages/product-feed.js index 465fa62d92..ed1f9aa4dc 100644 --- a/tests/e2e/utils/pages/product-feed.js +++ b/tests/e2e/utils/pages/product-feed.js @@ -55,28 +55,6 @@ export default class ProductFeedPage extends MockRequests { ] ); } - /** - * Change the value of adsSetupComplete to `true` after it is discovered. - * - * @return {Promise} - */ - async mockAdsSetupComplete() { - this.page.addInitScript( () => { - const targetId = 'google-listings-and-ads-js-before'; - const checkElement = () => { - const targetElement = document.getElementById( targetId ); - if ( targetElement ) { - window.glaData = window.glaData || {}; - window.glaData.adsSetupComplete = true; - } else { - // If not, keep checking until targetElement exists - window.requestAnimationFrame( checkElement ); - } - }; - checkElement(); - } ); - } - /** * Get the active product value element. * From cfa279ce44a517f08b0d0828b592befb7bf046c2 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil <30643833+kt-12@users.noreply.github.com> Date: Fri, 1 Nov 2024 01:03:22 +0000 Subject: [PATCH 51/90] Update js/src/dashboard/summary-section/paid-features/free-ad-credit.js adding fires info Co-authored-by: Eason --- js/src/dashboard/summary-section/paid-features/free-ad-credit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index 9fbc447f36..eaa6a863f1 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -13,6 +13,7 @@ import AppDocumentationLink from '.~/components/app-documentation-link'; /** * Render the Free Ads Credit section inside the Paid Features section. * + * @fires gla_documentation_link_click with `{ context: 'dashboard', link_id: 'free-ad-credit-terms', href: 'https://www.google.com/ads/coupons/terms/' }` * @return {JSX.Element} Free Ads Credit section. */ const FreeAdCredit = () => { From 96e4162a314267fa7bf03565423d9a3368d5da65 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil <30643833+kt-12@users.noreply.github.com> Date: Fri, 1 Nov 2024 01:03:50 +0000 Subject: [PATCH 52/90] Update js/src/dashboard/summary-section/paid-features/free-ad-credit.js fix context Co-authored-by: Eason --- .../dashboard/summary-section/paid-features/free-ad-credit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index eaa6a863f1..975255ba29 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -29,7 +29,7 @@ const FreeAdCredit = () => { { termLink: ( From d5d1d2f2bf23e8fa8d3936debc5ffe0928575dcc Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 01:24:53 +0000 Subject: [PATCH 53/90] remove usage of sections, fix styling --- .../summary-section/paid-features/free-ad-credit.js | 6 +++--- .../dashboard/summary-section/paid-features/index.js | 12 ++++++------ .../summary-section/paid-features/index.scss | 10 ++++++++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index 9fbc447f36..bf0e34878c 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -11,13 +11,13 @@ import { createInterpolateElement } from '@wordpress/element'; import AppDocumentationLink from '.~/components/app-documentation-link'; /** - * Render the Free Ads Credit section inside the Paid Features section. + * Render the Free Ads Credit div inside the Paid Features div. * - * @return {JSX.Element} Free Ads Credit section. + * @return {JSX.Element} Free Ads Credit div. */ const FreeAdCredit = () => { return ( -
+
{ createInterpolateElement( diff --git a/js/src/dashboard/summary-section/paid-features/index.js b/js/src/dashboard/summary-section/paid-features/index.js index 53a0fb2f39..a60e2175cf 100644 --- a/js/src/dashboard/summary-section/paid-features/index.js +++ b/js/src/dashboard/summary-section/paid-features/index.js @@ -3,7 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { createInterpolateElement } from '@wordpress/element'; -import { Flex, FlexBlock, FlexItem, Card } from '@wordpress/components'; +import { Flex, FlexBlock, FlexItem } from '@wordpress/components'; import GridiconCheckmark from 'gridicons/dist/checkmark'; /** @@ -52,7 +52,7 @@ function FeatureList() { ]; return ( -
+
{ featuresItems.map( ( { Icon, content }, idx ) => ( @@ -64,17 +64,17 @@ function FeatureList() { } /** - * Returns a Card with the given content. + * Returns a div with paid features content. * - * @return {Card} Card with title and content. + * @return {JSX.Element} Paid Features div. */ const PaidFeatures = () => { return ( - + diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index b150ee64d2..a39fff4cc0 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -1,4 +1,4 @@ -.gla-paid-features-section { +.gla-paid-features-div { @media (max-width: $break-small) { &__content { flex-direction: column; @@ -20,9 +20,15 @@ } } - .gla-free-ad-credit { + .gla-free-ad-credit-div { text-align: left; background-color: #fff; + display: flex; + align-items: center; + gap: calc(var(--main-gap) / 3 * 2); + padding: calc(var(--main-gap) / 3 * 2); + color: $black; + .gridicon { fill: #5ec862; } From d043e819c7e214fde8018b04e323bea226aab236 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:10:09 +0000 Subject: [PATCH 54/90] remove margin --- js/src/dashboard/summary-section/paid-features/index.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index a39fff4cc0..187f706695 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -10,7 +10,6 @@ display: flex; flex-direction: column; gap: $grid-unit-20; - margin: $grid-unit-30 0 $grid-unit-20; line-height: $gla-line-height-smaller; color: $gray-800; text-align: left; From b77f18ea38af269a8e2a451660509128925ba435 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:10:37 +0000 Subject: [PATCH 55/90] seperate file for paid-features test --- .../e2e/specs/dashboard/paid-features.test.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/e2e/specs/dashboard/paid-features.test.js diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js new file mode 100644 index 0000000000..18c81151dd --- /dev/null +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -0,0 +1,58 @@ +/** + * External dependencies + */ +import { expect, test } from '@playwright/test'; + +/** + * Internal dependencies + */ +import { clearOnboardedMerchant, setOnboardedMerchant } from '../../utils/api'; +import DashboardPage from '../../utils/pages/dashboard.js'; + +test.use( { storageState: process.env.ADMINSTATE } ); + +test.describe.configure( { mode: 'serial' } ); + +/** + * @type {import('../../utils/pages/dashboard.js').default} dashboardPage + */ +let dashboardPage = null; + +/** + * @type {import('@playwright/test').Page} page + */ +let page = null; + +test.describe( 'Paid Feature Listing', () => { + test.beforeAll( async ( { browser } ) => { + page = await browser.newPage(); + dashboardPage = new DashboardPage( page ); + await setOnboardedMerchant(); + await dashboardPage.mockRequests(); + await dashboardPage.goto(); + } ); + + test.afterAll( async () => { + await clearOnboardedMerchant(); + await page.close(); + } ); + + test( 'Paid Feature Listing is visible if ads campaign setup not complete', async () => { + await expect( dashboardPage.googleAdsSummaryCard ).toContainText( + 'Google Ads' + ); + + await expect( dashboardPage.paidFeaturesDiv ).toContainText( + 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.' + ); + + // FreeAdCredit div content visible. + await expect( dashboardPage.paidFeaturesDiv ).toContainText( + 'Claim $500 in ads credit when you spend your first $500 with Google Ads.' + ); + + await expect( dashboardPage.createCampaignButton ).toBeEnabled(); + + await dashboardPage.createCampaignButton.click(); + } ); +} ); From cd7ec9fbf5836fe86cf782711423ef7c573d301e Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:10:58 +0000 Subject: [PATCH 56/90] fix button name --- .../specs/setup-mc/step-4-complete-campaign.test.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index ed0fb458ad..9a71447dd2 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -334,10 +334,12 @@ test.describe( 'Complete your campaign', () => { await expect( addPaidCampaignButton ).toBeVisible(); await expect( addPaidCampaignButton ).toBeEnabled(); - const createCampaignButton = - await dashboardPage.getCreateCampaignButton(); - await expect( createCampaignButton ).toBeVisible(); - await expect( createCampaignButton ).toBeEnabled(); + await expect( + dashboardPage.createCampaignButton + ).toBeVisible(); + await expect( + dashboardPage.createCampaignButton + ).toBeEnabled(); } ); } ); From 6fe5003e46d675833b16eaebc9fe48b88e256925 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:17:12 +0000 Subject: [PATCH 57/90] update variable names and cleanup --- .../setup-mc/step-4-complete-campaign.test.js | 20 ++++------ tests/e2e/utils/pages/dashboard.js | 37 ++++++++----------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index 9a71447dd2..841776bb05 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -328,18 +328,14 @@ test.describe( 'Complete your campaign', () => { test( 'should see buttons on Dashboard for Google Ads onboarding', async () => { await page.keyboard.press( 'Escape' ); await page.getByRole( 'tab', { name: 'Dashboard' } ).click(); - const addPaidCampaignButton = - await dashboardPage.getAdsConnectionAllProgramsButton(); - - await expect( addPaidCampaignButton ).toBeVisible(); - await expect( addPaidCampaignButton ).toBeEnabled(); - - await expect( - dashboardPage.createCampaignButton - ).toBeVisible(); - await expect( - dashboardPage.createCampaignButton - ).toBeEnabled(); + const { adsConnectionAllProgramsButton, createCampaignButton } = + dashboardPage; + + await expect( adsConnectionAllProgramsButton ).toBeVisible(); + await expect( adsConnectionAllProgramsButton ).toBeEnabled(); + + await expect( createCampaignButton ).toBeVisible(); + await expect( createCampaignButton ).toBeEnabled(); } ); } ); diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index 5a8ae6d867..55864286c7 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -20,6 +20,21 @@ export default class DashboardPage extends MockRequests { this.editFreeListingButton = this.freeListingRow.getByRole( 'button', { name: 'Edit', } ); + this.googleAdsSummaryCard = this.page.locator( + '.gla-dashboard__performance .gla-summary-card:nth-child(1)' + ); + this.paidFeaturesDiv = this.googleAdsSummaryCard.locator( + '.gla-paid-features-div' + ); + this.createCampaignButton = this.paidFeaturesDiv.locator( 'button', { + hasText: 'Create Campaign', + } ); + this.adsConnectionAllProgramsButton = this.page.locator( + '.gla-all-programs-table-card button', + { + hasText: 'Add paid campaign', + } + ); } /** @@ -127,26 +142,4 @@ export default class DashboardPage extends MockRequests { const continueToEditButton = await this.getContinueToEditButton(); await continueToEditButton.click(); } - - /** - * Get the Ads connection button. - * - * @return {import('@playwright/test').Locator} Get the Ads connection button. - */ - getAdsConnectionAllProgramsButton() { - return this.page.locator( '.gla-all-programs-table-card button', { - hasText: 'Add paid campaign', - } ); - } - - /** - * Get the Create Campaign button. - * - * @return {import('@playwright/test').Locator} Get the Ads connection button. - */ - getCreateCampaignButton() { - return this.page.locator( '.gla-summary-card button', { - hasText: 'Create Campaign', - } ); - } } From 51d51871b6354d872bfeba669dbe17a6a8e19118 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:20:00 +0000 Subject: [PATCH 58/90] cleanup --- .../add-paid-campaigns.test.js | 36 ++----------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index 6f8d6408cf..9a9d722990 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -41,11 +41,6 @@ let dashboardPage = null; */ let setupAdsAccounts = null; -/** - * @type {import('@playwright/test').Locator} adsConnectionButton - */ -let adsConnectionButton = null; - /** * @type {import('../../utils/pages/setup-ads/setup-budget.js').default} setupBudgetPage */ @@ -81,40 +76,15 @@ test.describe( 'Set up Ads account', () => { test( 'Dashboard page contains Add Paid campaign buttons', async () => { //Add page campaign in the programs section. - adsConnectionButton = dashboardPage.getAdsConnectionAllProgramsButton(); - await expect( adsConnectionButton ).toBeEnabled(); - } ); - - test( 'Dashboard page contains Paid Features section with feature list and Create Campaign button', async () => { await expect( - page.getByText( - 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.' - ) - ).toBeVisible(); - - await expect( - page.getByText( - 'New to Google Ads? Get $500 in ad credit when you spend $500 within your first 60 days.' - ) - ).toBeVisible(); - - await expect( dashboardPage.getCreateCampaignButton() ).toBeEnabled(); - await dashboardPage.getCreateCampaignButton().click(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); - await expect( - page.getByRole( 'heading', { - name: 'Set up your accounts', - } ) - ).toBeVisible(); - - await dashboardPage.goto(); - await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + dashboardPage.adsConnectionAllProgramsButton + ).toBeEnabled(); } ); test.describe( 'Set up your accounts page', async () => { test.beforeAll( async () => { await setupAdsAccounts.mockAdsAccountsResponse( [] ); - await adsConnectionButton.click(); + await dashboardPage.adsConnectionAllProgramsButton.click(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); } ); From 2d77db85b9bd0995e3ab038d0d4d9949829e800a Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:52:42 +0000 Subject: [PATCH 59/90] check when ads complete is set --- .../e2e/specs/dashboard/paid-features.test.js | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index 18c81151dd..14c41a0134 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -6,7 +6,12 @@ import { expect, test } from '@playwright/test'; /** * Internal dependencies */ -import { clearOnboardedMerchant, setOnboardedMerchant } from '../../utils/api'; +import { + clearOnboardedMerchant, + setOnboardedMerchant, + setCompletedAdsSetup, + clearCompletedAdsSetup, +} from '../../utils/api'; import DashboardPage from '../../utils/pages/dashboard.js'; test.use( { storageState: process.env.ADMINSTATE } ); @@ -37,7 +42,7 @@ test.describe( 'Paid Feature Listing', () => { await page.close(); } ); - test( 'Paid Feature Listing is visible if ads campaign setup not complete', async () => { + test( 'Paid Features Listing is visible if ads campaign setup is not complete', async () => { await expect( dashboardPage.googleAdsSummaryCard ).toContainText( 'Google Ads' ); @@ -54,5 +59,30 @@ test.describe( 'Paid Feature Listing', () => { await expect( dashboardPage.createCampaignButton ).toBeEnabled(); await dashboardPage.createCampaignButton.click(); + await expect( + page.getByRole( 'heading', { + level: 1, + name: 'Set up your accounts', + } ) + ).toBeVisible(); + } ); + + test.describe( 'When ads campaign setup is complete', async () => { + test.beforeAll( async () => { + await setCompletedAdsSetup(); + } ); + + test.afterAll( async () => { + await clearCompletedAdsSetup(); + await page.close(); + } ); + test( 'Paid Features listing is complete', async () => { + await dashboardPage.goto(); + await expect( dashboardPage.googleAdsSummaryCard ).toContainText( + 'Google Ads' + ); + + await expect( dashboardPage.paidFeaturesDiv ).not.toBeVisible(); + } ); } ); } ); From 0fcba0f3c3bcb1f32ec73a91950342d5cee48d3b Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 02:59:01 +0000 Subject: [PATCH 60/90] change variable name --- .../e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js | 6 ++---- tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js | 6 +++--- tests/e2e/utils/pages/dashboard.js | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index 49ab95cfdf..c2600613ac 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -86,15 +86,13 @@ test.describe( 'Set up Ads account', () => { test( 'Dashboard page contains Add Paid campaign buttons', async () => { //Add page campaign in the programs section. - await expect( - dashboardPage.adsConnectionAllProgramsButton - ).toBeEnabled(); + await expect( dashboardPage.addPaidCampaignButton ).toBeEnabled(); } ); test.describe( 'Set up your accounts page', async () => { test.beforeAll( async () => { await setupAdsAccounts.mockAdsAccountsResponse( [] ); - await dashboardPage.adsConnectionAllProgramsButton.click(); + await dashboardPage.addPaidCampaignButton.click(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); } ); diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index 7df0bcebbd..4b381325d3 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -424,11 +424,11 @@ test.describe( 'Complete your campaign', () => { test( 'should see buttons on Dashboard for Google Ads onboarding', async () => { await page.keyboard.press( 'Escape' ); await page.getByRole( 'tab', { name: 'Dashboard' } ).click(); - const { adsConnectionAllProgramsButton, createCampaignButton } = + const { addPaidCampaignButton, createCampaignButton } = dashboardPage; - await expect( adsConnectionAllProgramsButton ).toBeVisible(); - await expect( adsConnectionAllProgramsButton ).toBeEnabled(); + await expect( addPaidCampaignButton ).toBeVisible(); + await expect( addPaidCampaignButton ).toBeEnabled(); await expect( createCampaignButton ).toBeVisible(); await expect( createCampaignButton ).toBeEnabled(); diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index 55864286c7..54a3842542 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -29,7 +29,7 @@ export default class DashboardPage extends MockRequests { this.createCampaignButton = this.paidFeaturesDiv.locator( 'button', { hasText: 'Create Campaign', } ); - this.adsConnectionAllProgramsButton = this.page.locator( + this.addPaidCampaignButton = this.page.locator( '.gla-all-programs-table-card button', { hasText: 'Add paid campaign', From 38318b26e7d8c38917fd9cfd802670801d115fbd Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Fri, 1 Nov 2024 03:48:56 +0000 Subject: [PATCH 61/90] avoide flakyness --- tests/e2e/specs/dashboard/paid-features.test.js | 2 +- .../e2e/specs/product-feed/product-feed-campaign-notice.test.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index 14c41a0134..b6727f17d6 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -57,7 +57,7 @@ test.describe( 'Paid Feature Listing', () => { ); await expect( dashboardPage.createCampaignButton ).toBeEnabled(); - + await dashboardPage.mockAdsAccountsResponse( [] ); await dashboardPage.createCampaignButton.click(); await expect( page.getByRole( 'heading', { diff --git a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js index 4b57cbd87e..24250d9179 100644 --- a/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js +++ b/tests/e2e/specs/product-feed/product-feed-campaign-notice.test.js @@ -119,6 +119,7 @@ test.describe( 'Product Feed Page', () => { await expect( createCampaignButton ).toBeVisible(); await createCampaignButton.click(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); + await productFeedPage.mockAdsAccountsResponse( [] ); await expect( page.getByRole( 'heading', { level: 1, From 22979820e1781bfe77b506e5a2521715adbee687 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 4 Nov 2024 09:42:08 +0000 Subject: [PATCH 62/90] change variable name --- js/src/dashboard/summary-section/index.js | 18 +++++++++++++++--- .../paid-features/free-ad-credit.js | 4 ++-- .../summary-section/paid-features/index.js | 8 ++++---- .../summary-section/paid-features/index.scss | 2 +- .../e2e/specs/dashboard/paid-features.test.js | 6 +++--- tests/e2e/utils/pages/dashboard.js | 7 +++---- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index f5c2c71bed..a8e031018c 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -8,6 +8,7 @@ import { SummaryNumber } from '@woocommerce/components'; * Internal dependencies */ import { glaData, REPORT_SOURCE_PAID, REPORT_SOURCE_FREE } from '.~/constants'; +import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; import useAdsCurrency from '.~/hooks/useAdsCurrency'; import useCurrencyFormat from '.~/hooks/useCurrencyFormat'; import usePerformance from './usePerformance'; @@ -106,17 +107,28 @@ const PaidPerformanceCard = () => { }; export default function SummarySection() { + const { loaded, data: adsCampaignsData } = useAdsCampaigns(); const { adsSetupComplete } = glaData; + let showCampaignPromotionCard = true; + if ( adsSetupComplete ) { + if ( ! loaded ) { + return null; + } + showCampaignPromotionCard = false; + if ( adsCampaignsData.length === 0 ) { + showCampaignPromotionCard = true; + } + } return ( <> - { adsSetupComplete ? ( - - ) : ( + { showCampaignPromotionCard ? ( + ) : ( + ) } { return ( diff --git a/js/src/dashboard/summary-section/paid-features/index.js b/js/src/dashboard/summary-section/paid-features/index.js index a60e2175cf..5988ddca19 100644 --- a/js/src/dashboard/summary-section/paid-features/index.js +++ b/js/src/dashboard/summary-section/paid-features/index.js @@ -52,7 +52,7 @@ function FeatureList() { ]; return ( -
+
{ featuresItems.map( ( { Icon, content }, idx ) => ( @@ -66,15 +66,15 @@ function FeatureList() { /** * Returns a div with paid features content. * - * @return {JSX.Element} Paid Features div. + * @return {JSX.Element} Paid Features component. */ const PaidFeatures = () => { return ( - + diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index 187f706695..10a6055eb7 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -1,4 +1,4 @@ -.gla-paid-features-div { +.gla-paid-features { @media (max-width: $break-small) { &__content { flex-direction: column; diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index b6727f17d6..4467a3a9b6 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -47,12 +47,12 @@ test.describe( 'Paid Feature Listing', () => { 'Google Ads' ); - await expect( dashboardPage.paidFeaturesDiv ).toContainText( + await expect( dashboardPage.paidFeatures ).toContainText( 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.' ); // FreeAdCredit div content visible. - await expect( dashboardPage.paidFeaturesDiv ).toContainText( + await expect( dashboardPage.paidFeatures ).toContainText( 'Claim $500 in ads credit when you spend your first $500 with Google Ads.' ); @@ -82,7 +82,7 @@ test.describe( 'Paid Feature Listing', () => { 'Google Ads' ); - await expect( dashboardPage.paidFeaturesDiv ).not.toBeVisible(); + await expect( dashboardPage.paidFeatures ).not.toBeVisible(); } ); } ); } ); diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index 54a3842542..e7deb3b5e1 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -23,10 +23,9 @@ export default class DashboardPage extends MockRequests { this.googleAdsSummaryCard = this.page.locator( '.gla-dashboard__performance .gla-summary-card:nth-child(1)' ); - this.paidFeaturesDiv = this.googleAdsSummaryCard.locator( - '.gla-paid-features-div' - ); - this.createCampaignButton = this.paidFeaturesDiv.locator( 'button', { + this.paidFeatures = + this.googleAdsSummaryCard.locator( '.gla-paid-features' ); + this.createCampaignButton = this.paidFeatures.locator( 'button', { hasText: 'Create Campaign', } ); this.addPaidCampaignButton = this.page.locator( From f8f9c4a631bf715508954594202cda3dce39c88e Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 4 Nov 2024 09:46:08 +0000 Subject: [PATCH 63/90] remove additional assignement --- js/src/dashboard/summary-section/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index a8e031018c..e2112aa1d9 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -114,9 +114,8 @@ export default function SummarySection() { if ( ! loaded ) { return null; } - showCampaignPromotionCard = false; - if ( adsCampaignsData.length === 0 ) { - showCampaignPromotionCard = true; + if ( adsCampaignsData.length > 0 ) { + showCampaignPromotionCard = false; } } From d7d17adefa7e8b2b037b3504aacfa9aaa9e19f3d Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 4 Nov 2024 20:51:27 +0000 Subject: [PATCH 64/90] style changes --- .../summary-section/paid-features/free-ad-credit.js | 2 +- .../dashboard/summary-section/paid-features/index.scss | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index 56dc0fb4a4..2c4360d6ef 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -18,7 +18,7 @@ import AppDocumentationLink from '.~/components/app-documentation-link'; */ const FreeAdCredit = () => { return ( -
+
{ createInterpolateElement( diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index 10a6055eb7..d218614da7 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -19,14 +19,15 @@ } } - .gla-free-ad-credit-div { + .gla-free-ad-credit-claim { text-align: left; - background-color: #fff; + background-color: $white; display: flex; align-items: center; gap: calc(var(--main-gap) / 3 * 2); - padding: calc(var(--main-gap) / 3 * 2); - color: $black; + padding: 16px 12px; + color: #1e1e1e; + font-size: $gla-font-base; .gridicon { fill: #5ec862; From 311a8502de203d6b2b63135c5bd4b864e83a1aaf Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Mon, 4 Nov 2024 21:41:34 +0000 Subject: [PATCH 65/90] update E2E --- js/src/dashboard/summary-section/index.js | 2 +- .../e2e/specs/dashboard/paid-features.test.js | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index e2112aa1d9..9322c6bc7d 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -114,7 +114,7 @@ export default function SummarySection() { if ( ! loaded ) { return null; } - if ( adsCampaignsData.length > 0 ) { + if ( adsCampaignsData?.length > 0 ) { showCampaignPromotionCard = false; } } diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index 4467a3a9b6..16f61063ec 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -76,7 +76,26 @@ test.describe( 'Paid Feature Listing', () => { await clearCompletedAdsSetup(); await page.close(); } ); - test( 'Paid Features listing is complete', async () => { + test( 'When no campaign present', async () => { + await dashboardPage.goto(); + await expect( dashboardPage.googleAdsSummaryCard ).toContainText( + 'Google Ads' + ); + + await expect( dashboardPage.paidFeatures ).toBeVisible(); + } ); + test( 'When atleast one campaign present', async () => { + await dashboardPage.fulfillAdsCampaignsRequest( [ + { + id: 111111111, + name: 'Test Campaign', + status: 'enabled', + type: 'performance_max', + amount: 1, + country: 'US', + targeted_locations: [ 'US' ], + }, + ] ); await dashboardPage.goto(); await expect( dashboardPage.googleAdsSummaryCard ).toContainText( 'Google Ads' From f899c31a80ab60bd7427e44dff46ebd0c204fb1c Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 5 Nov 2024 11:01:33 +0000 Subject: [PATCH 66/90] jest update --- tests/e2e/specs/dashboard/paid-features.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index 16f61063ec..c92b29bd27 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -84,7 +84,7 @@ test.describe( 'Paid Feature Listing', () => { await expect( dashboardPage.paidFeatures ).toBeVisible(); } ); - test( 'When atleast one campaign present', async () => { + test( 'When at least one campaign present', async () => { await dashboardPage.fulfillAdsCampaignsRequest( [ { id: 111111111, From ff4376eeb8b58c766687464490fc80b197ac8b33 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 5 Nov 2024 11:01:46 +0000 Subject: [PATCH 67/90] fix review changes. --- js/src/dashboard/summary-section/index.js | 12 +++------- .../summary-section/paid-features/index.scss | 4 ++-- .../summary-section/summary-section.test.js | 24 +++++++++++++------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index 9322c6bc7d..057d9fb96f 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -108,16 +108,10 @@ const PaidPerformanceCard = () => { export default function SummarySection() { const { loaded, data: adsCampaignsData } = useAdsCampaigns(); - const { adsSetupComplete } = glaData; - let showCampaignPromotionCard = true; - if ( adsSetupComplete ) { - if ( ! loaded ) { - return null; - } - if ( adsCampaignsData?.length > 0 ) { - showCampaignPromotionCard = false; - } + if ( ! loaded ) { + return null; } + const showCampaignPromotionCard = Boolean( ! adsCampaignsData?.length ); return ( <> diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index d218614da7..6a13f08742 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -25,8 +25,8 @@ display: flex; align-items: center; gap: calc(var(--main-gap) / 3 * 2); - padding: 16px 12px; - color: #1e1e1e; + padding: $grid-unit-20 $grid-unit-15; + color: $gray-900; font-size: $gla-font-base; .gridicon { diff --git a/js/src/dashboard/summary-section/summary-section.test.js b/js/src/dashboard/summary-section/summary-section.test.js index 3b43dbfcdd..14e1cb3116 100644 --- a/js/src/dashboard/summary-section/summary-section.test.js +++ b/js/src/dashboard/summary-section/summary-section.test.js @@ -7,6 +7,7 @@ import { render } from '@testing-library/react'; * Internal dependencies */ import SummarySection from '.~/dashboard/summary-section'; +import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; // Mimic no data loaded. jest.mock( './usePerformance', () => @@ -22,34 +23,43 @@ jest.mock( '.~/hooks/useAdsCurrency', () => } ) ); jest.mock( '.~/hooks/useCurrencyFormat', () => jest.fn() ); +jest.mock( '.~/hooks/useAdsCampaigns', () => + jest.fn().mockName( 'useAdsCampaigns' ) +); describe( 'SummarySection when no data is loaded', () => { + beforeAll( () => { + useAdsCampaigns.mockImplementation( () => { + return { loaded: true, data: [] }; + } ); + } ); + it( 'Shows no data message for Free Campaigns', async () => { - const { queryByText } = render( ); + const { findByText } = render( ); expect( - queryByText( + await findByText( "We're having trouble loading this data. Try again later, or track your performance in Google Merchant Center." ) ).toBeTruthy(); - const link = queryByText( 'Open Google Merchant Center' ); + const link = await findByText( 'Open Google Merchant Center' ); expect( link ).toBeTruthy(); expect( link.href ).toBe( 'https://merchants.google.com/mc/reporting/dashboard' ); } ); - it( 'Shows no data message for Paid Campaigns', () => { - const { queryByText } = render( ); + it( 'Shows no data message for Paid Campaigns', async () => { + const { findByText } = render( ); expect( - queryByText( + await findByText( "We're having trouble loading this data. Try again later, or track your performance in Google Ads." ) ).toBeTruthy(); - const link = queryByText( 'Open Google Ads' ); + const link = await findByText( 'Open Google Ads' ); expect( link ).toBeTruthy(); expect( link.href ).toBe( 'https://ads.google.com/' ); From f46e880cf7d679ccc461306f14de5cb286308068 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 5 Nov 2024 11:10:41 +0000 Subject: [PATCH 68/90] fix jest --- .../summary-section/summary-section.test.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/js/src/dashboard/summary-section/summary-section.test.js b/js/src/dashboard/summary-section/summary-section.test.js index 14e1cb3116..d90c99c074 100644 --- a/js/src/dashboard/summary-section/summary-section.test.js +++ b/js/src/dashboard/summary-section/summary-section.test.js @@ -28,13 +28,22 @@ jest.mock( '.~/hooks/useAdsCampaigns', () => ); describe( 'SummarySection when no data is loaded', () => { + let mockCampaigns; + beforeAll( () => { + let mockedCampaigns = []; + useAdsCampaigns.mockImplementation( () => { - return { loaded: true, data: [] }; + return { loaded: true, data: mockedCampaigns }; } ); + + mockCampaigns = ( ...campaigns ) => { + mockedCampaigns = campaigns; + }; } ); it( 'Shows no data message for Free Campaigns', async () => { + mockCampaigns( [] ); const { findByText } = render( ); expect( @@ -50,7 +59,8 @@ describe( 'SummarySection when no data is loaded', () => { 'https://merchants.google.com/mc/reporting/dashboard' ); } ); - it( 'Shows no data message for Paid Campaigns', async () => { + it.only( 'Shows no data message for Paid Campaigns', async () => { + mockCampaigns( [] ); const { findByText } = render( ); expect( From f0ab0f629bc211f81a265cce98c24630310ae105 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 5 Nov 2024 11:14:13 +0000 Subject: [PATCH 69/90] fix unused variable --- js/src/dashboard/summary-section/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index 057d9fb96f..22f2fd92a0 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -7,7 +7,7 @@ import { SummaryNumber } from '@woocommerce/components'; /** * Internal dependencies */ -import { glaData, REPORT_SOURCE_PAID, REPORT_SOURCE_FREE } from '.~/constants'; +import { REPORT_SOURCE_PAID, REPORT_SOURCE_FREE } from '.~/constants'; import useAdsCampaigns from '.~/hooks/useAdsCampaigns'; import useAdsCurrency from '.~/hooks/useAdsCurrency'; import useCurrencyFormat from '.~/hooks/useCurrencyFormat'; From 9caf01d1c6e63142acc3de96e2e112de2e76442a Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Tue, 5 Nov 2024 11:16:00 +0000 Subject: [PATCH 70/90] remove only --- js/src/dashboard/summary-section/summary-section.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/dashboard/summary-section/summary-section.test.js b/js/src/dashboard/summary-section/summary-section.test.js index d90c99c074..2ced0f1157 100644 --- a/js/src/dashboard/summary-section/summary-section.test.js +++ b/js/src/dashboard/summary-section/summary-section.test.js @@ -59,7 +59,7 @@ describe( 'SummarySection when no data is loaded', () => { 'https://merchants.google.com/mc/reporting/dashboard' ); } ); - it.only( 'Shows no data message for Paid Campaigns', async () => { + it( 'Shows no data message for Paid Campaigns', async () => { mockCampaigns( [] ); const { findByText } = render( ); From 5a27b759251a7dfaaa30097daa2030e77d7043c8 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 6 Nov 2024 08:46:44 +0000 Subject: [PATCH 71/90] fix jest --- .../summary-section/summary-section.test.js | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/js/src/dashboard/summary-section/summary-section.test.js b/js/src/dashboard/summary-section/summary-section.test.js index 2ced0f1157..9a2a3ba607 100644 --- a/js/src/dashboard/summary-section/summary-section.test.js +++ b/js/src/dashboard/summary-section/summary-section.test.js @@ -28,22 +28,26 @@ jest.mock( '.~/hooks/useAdsCampaigns', () => ); describe( 'SummarySection when no data is loaded', () => { - let mockCampaigns; - beforeAll( () => { - let mockedCampaigns = []; - useAdsCampaigns.mockImplementation( () => { - return { loaded: true, data: mockedCampaigns }; + return { + loading: false, + loaded: true, + data: [ + { + id: 10, + name: 'PMax Campaign', + status: 'enabled', + type: 'performance_max', + amount: 20, + displayCountries: [ 'US' ], + }, + ], + }; } ); - - mockCampaigns = ( ...campaigns ) => { - mockedCampaigns = campaigns; - }; } ); it( 'Shows no data message for Free Campaigns', async () => { - mockCampaigns( [] ); const { findByText } = render( ); expect( @@ -60,7 +64,6 @@ describe( 'SummarySection when no data is loaded', () => { ); } ); it( 'Shows no data message for Paid Campaigns', async () => { - mockCampaigns( [] ); const { findByText } = render( ); expect( From f8c333953777f4664cb675c78bc90827e51609dd Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 6 Nov 2024 08:47:48 +0000 Subject: [PATCH 72/90] remove unnecessary typecasting. --- js/src/dashboard/summary-section/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/dashboard/summary-section/index.js b/js/src/dashboard/summary-section/index.js index 22f2fd92a0..a4ffc23da8 100644 --- a/js/src/dashboard/summary-section/index.js +++ b/js/src/dashboard/summary-section/index.js @@ -111,7 +111,7 @@ export default function SummarySection() { if ( ! loaded ) { return null; } - const showCampaignPromotionCard = Boolean( ! adsCampaignsData?.length ); + const showCampaignPromotionCard = ! adsCampaignsData?.length; return ( <> From 0e805698755f56cefc438eef6ecc466546053f51 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 6 Nov 2024 13:48:23 +0000 Subject: [PATCH 73/90] css changes --- js/src/dashboard/summary-section/paid-features/index.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index 6a13f08742..2f252f46af 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -27,10 +27,9 @@ gap: calc(var(--main-gap) / 3 * 2); padding: $grid-unit-20 $grid-unit-15; color: $gray-900; - font-size: $gla-font-base; .gridicon { - fill: #5ec862; + fill: $gla-color-green; } } From 64eaab6bd8a70b27f75d49c3ec29737a9784355c Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Wed, 6 Nov 2024 13:58:44 +0000 Subject: [PATCH 74/90] div -> component --- js/src/dashboard/summary-section/paid-features/index.js | 2 +- tests/e2e/specs/dashboard/paid-features.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/dashboard/summary-section/paid-features/index.js b/js/src/dashboard/summary-section/paid-features/index.js index 5988ddca19..9694c7edb5 100644 --- a/js/src/dashboard/summary-section/paid-features/index.js +++ b/js/src/dashboard/summary-section/paid-features/index.js @@ -64,7 +64,7 @@ function FeatureList() { } /** - * Returns a div with paid features content. + * Returns a component with paid features content. * * @return {JSX.Element} Paid Features component. */ diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index c92b29bd27..b68a99766a 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -51,7 +51,7 @@ test.describe( 'Paid Feature Listing', () => { 'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.' ); - // FreeAdCredit div content visible. + // FreeAdCredit component content visible. await expect( dashboardPage.paidFeatures ).toContainText( 'Claim $500 in ads credit when you spend your first $500 with Google Ads.' ); From b0c712eb7a440adf5065ad0b071a6a9b904d0c27 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Wed, 6 Nov 2024 18:04:57 -0600 Subject: [PATCH 75/90] Style fixes --- js/src/components/free-ad-credit/index.scss | 2 +- .../summary-section/paid-features/free-ad-credit.js | 2 +- .../dashboard/summary-section/paid-features/index.scss | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/js/src/components/free-ad-credit/index.scss b/js/src/components/free-ad-credit/index.scss index f36176c07d..9732c19755 100644 --- a/js/src/components/free-ad-credit/index.scss +++ b/js/src/components/free-ad-credit/index.scss @@ -8,7 +8,7 @@ svg { flex: 0 0 auto; - fill: #007017; + fill: $gla-color-green; } &__title { diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index 2c4360d6ef..de7938e046 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -19,7 +19,7 @@ import AppDocumentationLink from '.~/components/app-documentation-link'; const FreeAdCredit = () => { return (
- +
{ createInterpolateElement( __( diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index 2f252f46af..82b345362c 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -15,7 +15,8 @@ text-align: left; .gridicon { - fill: #5ec862; + fill: $gla-color-green; + flex: 0 0 auto; } } @@ -23,13 +24,15 @@ text-align: left; background-color: $white; display: flex; - align-items: center; - gap: calc(var(--main-gap) / 3 * 2); + align-items: flex-start; + gap: $grid-unit; padding: $grid-unit-20 $grid-unit-15; color: $gray-900; .gridicon { fill: $gla-color-green; + margin: $grid-unit-10 / 2; + flex: 0 0 auto; } } From 64eb3b41365afbf989840267eed8c8564c6d2b8d Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Wed, 6 Nov 2024 18:33:25 -0600 Subject: [PATCH 76/90] More style adjustments --- .../dashboard/summary-section/paid-features/index.scss | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index 82b345362c..8e7025d9e3 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -1,7 +1,11 @@ .gla-paid-features { - @media (max-width: $break-small) { - &__content { - flex-direction: column; + + &__content { + flex-direction: column; + + @media (min-width: $break-small) { + align-items: flex-start; + flex-direction: row; gap: $grid-unit-20; } } From d1fe9eb27c7dbcc3db8baf064ed4feb54eb2cceb Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Thu, 7 Nov 2024 03:24:34 +0000 Subject: [PATCH 77/90] add new Fulfill for ad report. --- tests/e2e/utils/mock-requests.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/e2e/utils/mock-requests.js b/tests/e2e/utils/mock-requests.js index 4230c8c50d..3ebbb81817 100644 --- a/tests/e2e/utils/mock-requests.js +++ b/tests/e2e/utils/mock-requests.js @@ -64,6 +64,19 @@ export default class MockRequests { ); } + /** + * Fulfill the Ads Report Program request. + * + * @param {Object} payload + * @return {Promise} + */ + async fulfillAdsReportProgram( payload ) { + await this.fulfillRequest( + /\/wc\/gla\/ads\/reports\/programs\b/, + payload + ); + } + /** * Fulfill the Target Audience request. * From c7bbc72842671d1451437d82588e3cc1f0bbbd37 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil Date: Thu, 7 Nov 2024 03:32:38 +0000 Subject: [PATCH 78/90] check for text content in Summary+ mock add empty campaign. --- tests/e2e/specs/dashboard/paid-features.test.js | 3 ++- tests/e2e/utils/pages/dashboard.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/e2e/specs/dashboard/paid-features.test.js b/tests/e2e/specs/dashboard/paid-features.test.js index b68a99766a..9eace25aca 100644 --- a/tests/e2e/specs/dashboard/paid-features.test.js +++ b/tests/e2e/specs/dashboard/paid-features.test.js @@ -77,6 +77,7 @@ test.describe( 'Paid Feature Listing', () => { await page.close(); } ); test( 'When no campaign present', async () => { + await dashboardPage.fulfillAdsCampaignsRequest( [] ); await dashboardPage.goto(); await expect( dashboardPage.googleAdsSummaryCard ).toContainText( 'Google Ads' @@ -98,7 +99,7 @@ test.describe( 'Paid Feature Listing', () => { ] ); await dashboardPage.goto(); await expect( dashboardPage.googleAdsSummaryCard ).toContainText( - 'Google Ads' + /Google Ads.*Total Sales.*Total Spend/ ); await expect( dashboardPage.paidFeatures ).not.toBeVisible(); diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index e7deb3b5e1..b53bd867cc 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -63,6 +63,20 @@ export default class DashboardPage extends MockRequests { next_page: null, } ); + await this.fulfillAdsReportProgram( { + products: null, + campaigns: null, + intervals: null, + totals: { + sales: 0, + conversions: 0, + spend: 0, + clicks: 0, + impressions: 0, + }, + next_page: null, + } ); + await this.fulfillTargetAudience( { location: 'selected', countries: [ 'US' ], From 0f809f304a5ab3e17b68f455550f4bc4b54c8157 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil <30643833+kt-12@users.noreply.github.com> Date: Thu, 7 Nov 2024 03:36:20 +0000 Subject: [PATCH 79/90] update variable name. Co-authored-by: Eason --- js/src/dashboard/summary-section/paid-features/index.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index 8e7025d9e3..a33454d922 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -19,8 +19,7 @@ text-align: left; .gridicon { - fill: $gla-color-green; - flex: 0 0 auto; + fill: $alert-green; } } From c7247670218f49d00d632ea79efb9fb99f6254ff Mon Sep 17 00:00:00 2001 From: Karthik Thayyil <30643833+kt-12@users.noreply.github.com> Date: Thu, 7 Nov 2024 03:36:39 +0000 Subject: [PATCH 80/90] remove margin Co-authored-by: Eason --- js/src/dashboard/summary-section/paid-features/index.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/js/src/dashboard/summary-section/paid-features/index.scss b/js/src/dashboard/summary-section/paid-features/index.scss index a33454d922..1902c36b30 100644 --- a/js/src/dashboard/summary-section/paid-features/index.scss +++ b/js/src/dashboard/summary-section/paid-features/index.scss @@ -34,7 +34,6 @@ .gridicon { fill: $gla-color-green; - margin: $grid-unit-10 / 2; flex: 0 0 auto; } } From 1a516c71c57716523e2fbdc286e782e456d13d22 Mon Sep 17 00:00:00 2001 From: Karthik Thayyil <30643833+kt-12@users.noreply.github.com> Date: Thu, 7 Nov 2024 03:36:57 +0000 Subject: [PATCH 81/90] remove size attribute. Co-authored-by: Eason --- .../dashboard/summary-section/paid-features/free-ad-credit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js index de7938e046..2c4360d6ef 100644 --- a/js/src/dashboard/summary-section/paid-features/free-ad-credit.js +++ b/js/src/dashboard/summary-section/paid-features/free-ad-credit.js @@ -19,7 +19,7 @@ import AppDocumentationLink from '.~/components/app-documentation-link'; const FreeAdCredit = () => { return (
- +
{ createInterpolateElement( __( From d38b1ec4391c3a1e3e0a81ad4788e3d611545b66 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Mon, 11 Nov 2024 17:40:35 -0600 Subject: [PATCH 82/90] Remove 'Paid' from ads creation --- .../paid-ads/add-paid-campaign-button.js | 6 ++--- .../paid-ads/ads-campaign/ads-campaign.js | 2 +- .../paid-ads/asset-group/asset-group.js | 5 +---- .../campaign-creation-success-guide/index.js | 2 +- js/src/dashboard/index.test.js | 2 +- .../pages/create-paid-ads-campaign/index.js | 8 +++---- js/src/pages/edit-paid-ads-campaign/index.js | 4 ++-- .../submission-success-guide/index.js | 2 +- js/src/setup-ads/ads-stepper/index.js | 2 +- .../ads-stepper/setup-accounts/index.js | 2 +- .../setup-ads/ads-stepper/setup-paid-ads.js | 4 ++-- js/src/setup-ads/top-bar/index.js | 2 +- src/Tracking/README.md | 4 ++-- .../add-paid-campaigns.test.js | 22 +++++++++---------- tests/e2e/utils/pages/dashboard.js | 2 +- .../e2e/utils/pages/setup-ads/setup-budget.js | 8 +++---- 16 files changed, 37 insertions(+), 40 deletions(-) diff --git a/js/src/components/paid-ads/add-paid-campaign-button.js b/js/src/components/paid-ads/add-paid-campaign-button.js index 7cb591f9a3..6af8534393 100644 --- a/js/src/components/paid-ads/add-paid-campaign-button.js +++ b/js/src/components/paid-ads/add-paid-campaign-button.js @@ -13,7 +13,7 @@ import { getCreateCampaignUrl } from '.~/utils/urls'; import { recordGlaEvent } from '.~/utils/tracks'; /** - * "Add paid campaign" button is clicked. + * "Add campaign" button is clicked. * * @event gla_add_paid_campaign_clicked * @property {string} context Indicate the place where the button is located. @@ -21,7 +21,7 @@ import { recordGlaEvent } from '.~/utils/tracks'; */ /** - * Renders an AppButton with the text "Add Paid Campaign". + * Renders an AppButton with the text "Add campaign". * Clicking on the button will call `recordGlaEvent` and * redirect to Setup MC or Create New Campaign depending on * whether the users have completed ads setup or not. @@ -68,7 +68,7 @@ const AddPaidCampaignButton = ( props ) => { return ( - { children || __( 'Add paid campaign', 'google-listings-and-ads' ) } + { children || __( 'Add campaign', 'google-listings-and-ads' ) } ); }; diff --git a/js/src/components/paid-ads/ads-campaign/ads-campaign.js b/js/src/components/paid-ads/ads-campaign/ads-campaign.js index 34324fd40c..d0c08151b3 100644 --- a/js/src/components/paid-ads/ads-campaign/ads-campaign.js +++ b/js/src/components/paid-ads/ads-campaign/ads-campaign.js @@ -62,7 +62,7 @@ export default function AdsCampaign( { let description = createInterpolateElement( __( - 'Paid Performance Max campaigns are automatically optimized for you by Google. See what your ads will look like.', + 'Performance Max campaigns are automatically optimized for you by Google. See what your ads will look like.', 'google-listings-and-ads' ), { diff --git a/js/src/components/paid-ads/asset-group/asset-group.js b/js/src/components/paid-ads/asset-group/asset-group.js index 205f79cd29..ccc05ea5a1 100644 --- a/js/src/components/paid-ads/asset-group/asset-group.js +++ b/js/src/components/paid-ads/asset-group/asset-group.js @@ -163,10 +163,7 @@ export default function AssetGroup( { campaign } ) { onClick={ handleLaunchClick } > { isCreation - ? __( - 'Launch paid campaign', - 'google-listings-and-ads' - ) + ? __( 'Create campaign', 'google-listings-and-ads' ) : __( 'Save changes', 'google-listings-and-ads' ) } diff --git a/js/src/dashboard/campaign-creation-success-guide/index.js b/js/src/dashboard/campaign-creation-success-guide/index.js index b015b60304..3bd00205c2 100644 --- a/js/src/dashboard/campaign-creation-success-guide/index.js +++ b/js/src/dashboard/campaign-creation-success-guide/index.js @@ -88,7 +88,7 @@ export default function CampaignCreationSuccessGuide( {
diff --git a/js/src/dashboard/index.test.js b/js/src/dashboard/index.test.js index 8c44142042..b07409c6c3 100644 --- a/js/src/dashboard/index.test.js +++ b/js/src/dashboard/index.test.js @@ -46,7 +46,7 @@ jest.mock( '@woocommerce/navigation', () => { jest.mock( '.~/utils/isWCTracksEnabled', () => jest.fn() ); const CAMPAIGN_CREATION_SUCCESS_GUIDE_TEXT = - "You've set up a paid Performance Max Campaign!"; + "You've set up a Performance Max Campaign!"; const CES_PROMPT_TEXT = 'How easy was it to create a Google Ad campaign?'; jest.mock( '.~/components/customer-effort-score-prompt', () => () => ( diff --git a/js/src/pages/create-paid-ads-campaign/index.js b/js/src/pages/create-paid-ads-campaign/index.js index da0656a0d1..cbcb4e3096 100644 --- a/js/src/pages/create-paid-ads-campaign/index.js +++ b/js/src/pages/create-paid-ads-campaign/index.js @@ -104,7 +104,7 @@ const CreatePaidAdsCampaign = () => { createNotice( 'success', __( - 'You’ve successfully created a paid campaign!', + 'You’ve successfully created a campaign!', 'google-listings-and-ads' ) ); @@ -125,7 +125,7 @@ const CreatePaidAdsCampaign = () => { <> } @@ -144,13 +144,13 @@ const CreatePaidAdsCampaign = () => { { key: STEP.CAMPAIGN, label: __( - 'Create paid campaign', + 'Create campaign', 'google-listings-and-ads' ), content: ( { { key: STEP.CAMPAIGN, label: __( - 'Edit paid campaign', + 'Edit campaign', 'google-listings-and-ads' ), content: ( @@ -205,7 +205,7 @@ const EditPaidAdsCampaign = () => { campaign={ campaign } context={ eventContext } headerTitle={ __( - 'Edit your paid campaign', + 'Edit your campaign', 'google-listings-and-ads' ) } continueButton={ ( formContext ) => ( diff --git a/js/src/product-feed/submission-success-guide/index.js b/js/src/product-feed/submission-success-guide/index.js index 968124ecec..041085b822 100644 --- a/js/src/product-feed/submission-success-guide/index.js +++ b/js/src/product-feed/submission-success-guide/index.js @@ -203,7 +203,7 @@ const SubmissionSuccessGuide = () => { action: 'create-paid-campaign', } } > - { __( 'Create paid campaign', 'google-listings-and-ads' ) } + { __( 'Create campaign', 'google-listings-and-ads' ) } ); diff --git a/js/src/setup-ads/ads-stepper/index.js b/js/src/setup-ads/ads-stepper/index.js index 614132033f..f6534f79f9 100644 --- a/js/src/setup-ads/ads-stepper/index.js +++ b/js/src/setup-ads/ads-stepper/index.js @@ -96,7 +96,7 @@ const AdsStepper = () => { }, { key: '2', - label: __( 'Create your paid campaign', 'google-listings-and-ads' ), + label: __( 'Create your campaign', 'google-listings-and-ads' ), content: , onClick: handleStepClick, }, diff --git a/js/src/setup-ads/ads-stepper/setup-accounts/index.js b/js/src/setup-ads/ads-stepper/setup-accounts/index.js index 021303dc92..3564cb72a4 100644 --- a/js/src/setup-ads/ads-stepper/setup-accounts/index.js +++ b/js/src/setup-ads/ads-stepper/setup-accounts/index.js @@ -49,7 +49,7 @@ const SetupAccounts = ( props ) => { 'google-listings-and-ads' ) } description={ __( - 'Connect your Google account and your Google Ads account to set up a paid Performance Max campaign.', + 'Connect your Google account and your Google Ads account to set up a Performance Max campaign.', 'google-listings-and-ads' ) } /> diff --git a/js/src/setup-ads/ads-stepper/setup-paid-ads.js b/js/src/setup-ads/ads-stepper/setup-paid-ads.js index c19d4ef139..18f219e9eb 100644 --- a/js/src/setup-ads/ads-stepper/setup-paid-ads.js +++ b/js/src/setup-ads/ads-stepper/setup-paid-ads.js @@ -94,7 +94,7 @@ const SetupPaidAds = () => { > { { return ( } backHref={ getNewPath( {}, '/google/dashboard' ) } onBackButtonClick={ handleBackButtonClick } diff --git a/src/Tracking/README.md b/src/Tracking/README.md index 126bd02c16..2d25e128cd 100644 --- a/src/Tracking/README.md +++ b/src/Tracking/README.md @@ -136,7 +136,7 @@ Do not edit it manually! --> ### [`gla_add_paid_campaign_clicked`](../../js/src/components/paid-ads/add-paid-campaign-button.js#L15) -"Add paid campaign" button is clicked. +"Add campaign" button is clicked. #### Properties | name | type | description | | ---- | ---- | ----------- | @@ -546,7 +546,7 @@ Clicking on the "Scan for assets" button. - [`exports`](../../js/src/components/paid-ads/asset-group/assets-loader.js#L96) ### [`gla_launch_paid_campaign_button_click`](../../js/src/utils/tracks.js#L167) -Triggered when the "Launch paid campaign" button is clicked to add a new paid campaign in the Google Ads setup flow. +Triggered when the "Create campaign" button is clicked to add a new paid campaign in the Google Ads setup flow. #### Properties | name | type | description | | ---- | ---- | ----------- | diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index c2600613ac..fb48e58a72 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -84,7 +84,7 @@ test.describe( 'Set up Ads account', () => { await page.close(); } ); - test( 'Dashboard page contains Add Paid campaign buttons', async () => { + test( 'Dashboard page contains Add campaign buttons', async () => { //Add page campaign in the programs section. await expect( dashboardPage.addPaidCampaignButton ).toBeEnabled(); } ); @@ -102,7 +102,7 @@ test.describe( 'Set up Ads account', () => { ).toBeVisible(); await expect( page.getByText( - 'Connect your Google account and your Google Ads account to set up a paid Performance Max campaign.' + 'Connect your Google account and your Google Ads account to set up a Performance Max campaign.' ) ).toBeVisible(); } ); @@ -120,7 +120,7 @@ test.describe( 'Set up Ads account', () => { } ); } ); - test.describe( 'Add paid campaigns with no Ads account', async () => { + test.describe( 'Add campaigns with no Ads account', async () => { test( 'Create an account should be visible', async () => { const createAccountButton = page.getByRole( 'button', { name: 'Create account', @@ -230,7 +230,7 @@ test.describe( 'Set up Ads account', () => { } ); } ); - test.describe( 'Add paid campaigns with existing Ads accounts', () => { + test.describe( 'Add campaigns with existing Ads accounts', () => { test.beforeAll( async () => { await setupAdsAccounts.mockAdsAccountsResponse( ADS_ACCOUNTS ); //Disconnect the account from the previous test @@ -280,13 +280,13 @@ test.describe( 'Set up Ads account', () => { } ); } ); - test.describe( 'Create your paid campaign', () => { + test.describe( 'Create your campaign', () => { test( 'Continue to create paid ad campaign', async () => { await setupAdsAccounts.clickContinue(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await expect( page.getByRole( 'heading', { - name: 'Create your paid campaign', + name: 'Create your campaign', } ) ).toBeVisible(); @@ -351,7 +351,7 @@ test.describe( 'Set up Ads account', () => { await setupBudgetPage.fillBudget( budget ); await expect( - setupBudgetPage.getLaunchPaidCampaignButton() + setupBudgetPage.getCreateCampaignButton() ).toBeDisabled(); } ); @@ -360,7 +360,7 @@ test.describe( 'Set up Ads account', () => { await setupBudgetPage.fillBudget( budget ); await expect( - setupBudgetPage.getLaunchPaidCampaignButton() + setupBudgetPage.getCreateCampaignButton() ).toBeDisabled(); } ); @@ -381,7 +381,7 @@ test.describe( 'Set up Ads account', () => { await setupBudgetPage.fillBudget( budget ); await expect( - setupBudgetPage.getLaunchPaidCampaignButton() + setupBudgetPage.getCreateCampaignButton() ).toBeEnabled(); } ); @@ -400,7 +400,7 @@ test.describe( 'Set up Ads account', () => { [ 'US' ] ); - await setupBudgetPage.getLaunchPaidCampaignButton().click(); + await setupBudgetPage.getCreateCampaignButton().click(); await campaignCreation; @@ -415,7 +415,7 @@ test.describe( 'Set up Ads account', () => { await expect( page.getByRole( 'heading', { - name: "You've set up a paid Performance Max Campaign!", + name: "You've set up a Performance Max Campaign!", } ) ).toBeVisible(); diff --git a/tests/e2e/utils/pages/dashboard.js b/tests/e2e/utils/pages/dashboard.js index b53bd867cc..d671fbaed9 100644 --- a/tests/e2e/utils/pages/dashboard.js +++ b/tests/e2e/utils/pages/dashboard.js @@ -31,7 +31,7 @@ export default class DashboardPage extends MockRequests { this.addPaidCampaignButton = this.page.locator( '.gla-all-programs-table-card button', { - hasText: 'Add paid campaign', + hasText: 'Add campaign', } ); } diff --git a/tests/e2e/utils/pages/setup-ads/setup-budget.js b/tests/e2e/utils/pages/setup-ads/setup-budget.js index 86eeab1af5..4246be6b3e 100644 --- a/tests/e2e/utils/pages/setup-ads/setup-budget.js +++ b/tests/e2e/utils/pages/setup-ads/setup-budget.js @@ -96,13 +96,13 @@ export default class SetupBudget extends MockRequests { } /** - * Get the Launch paid campaign button. + * Get the Create campaign button. * - * @return {import('@playwright/test').Locator} Launch paid campaign button. + * @return {import('@playwright/test').Locator} Create campaign button. */ - getLaunchPaidCampaignButton() { + getCreateCampaignButton() { return this.page.getByRole( 'button', { - name: 'Launch paid campaign', + name: 'Create campaign', exact: true, } ); } From 4ac7c89d8f116341f00a98067e14bd330ca2db47 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Tue, 12 Nov 2024 11:42:33 -0600 Subject: [PATCH 83/90] Update E2E test description --- tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index fb48e58a72..78871193bd 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -281,7 +281,7 @@ test.describe( 'Set up Ads account', () => { } ); test.describe( 'Create your campaign', () => { - test( 'Continue to create paid ad campaign', async () => { + test( 'Continue to create your campaign', async () => { await setupAdsAccounts.clickContinue(); await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await expect( From 3a36464fde5fdc403eab3c9333e75f6f29b19499 Mon Sep 17 00:00:00 2001 From: Joe McGill <801097+joemcgill@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:43:29 -0600 Subject: [PATCH 84/90] Update src/Tracking/README.md Co-authored-by: Mik --- src/Tracking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tracking/README.md b/src/Tracking/README.md index 2d25e128cd..c7667f19c5 100644 --- a/src/Tracking/README.md +++ b/src/Tracking/README.md @@ -546,7 +546,7 @@ Clicking on the "Scan for assets" button. - [`exports`](../../js/src/components/paid-ads/asset-group/assets-loader.js#L96) ### [`gla_launch_paid_campaign_button_click`](../../js/src/utils/tracks.js#L167) -Triggered when the "Create campaign" button is clicked to add a new paid campaign in the Google Ads setup flow. +Triggered when the "Create campaign" button is clicked to add a new campaign in the Google Ads setup flow. #### Properties | name | type | description | | ---- | ---- | ----------- | From fa1f5ed6b18ea5a87207664a2a6e33dcd72bad5b Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Thu, 14 Nov 2024 12:49:39 -0600 Subject: [PATCH 85/90] Remove additional instances of the word 'paid' with Ads --- .../edit-program-button/edit-program-prompt-modal/index.js | 2 +- .../program-toggle/pause-program-modal/index.js | 4 ++-- .../remove-program-button/remove-program-modal/index.js | 2 +- js/src/get-started-page/faqs/index.js | 2 +- js/src/get-started-page/features-card/index.js | 2 +- js/src/pages/edit-paid-ads-campaign/index.js | 2 +- js/src/reports/index.js | 2 +- js/src/reports/metric-number.js | 2 +- js/src/reports/products/filter-config.js | 2 +- js/src/settings/disconnect-modal/confirm-modal.js | 4 ++-- src/Notes/CompleteSetup.php | 2 +- src/Notes/SetupCampaignTwoWeeks.php | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js b/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js index dd3bb6ecc4..76f3517444 100644 --- a/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js +++ b/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js @@ -68,7 +68,7 @@ const EditProgramPromptModal = ( { programId, onRequestClose } ) => { >

{ __( - 'Results typically improve with time with Google’s Free Listing and paid ad campaigns.', + 'Results typically improve with time with Google’s Free Listing and Google Ads campaigns.', 'google-listings-and-ads' ) }

diff --git a/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js b/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js index e5d15231c3..46ab6ad3c8 100644 --- a/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js +++ b/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js @@ -52,13 +52,13 @@ const PauseProgramModal = ( props ) => { >

{ __( - 'Results typically improve with time with Google’s paid ad campaigns. If you pause, your products won’t be shown to people looking for what you offer.', + 'Results typically improve with time with Google Ads campaigns. If you pause, your products won’t be shown to people looking for what you offer.', 'google-listings-and-ads' ) }

{ __( - 'Pausing a paid ad campaign will result in the loss of any optimisations learned from those campaigns.', + 'Pausing a campaign will result in the loss of any optimisations learned from those campaigns.', 'google-listings-and-ads' ) }

diff --git a/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js b/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js index 0f6a5c227d..cdda3d71e4 100644 --- a/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js +++ b/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js @@ -67,7 +67,7 @@ const RemoveProgramModal = ( props ) => { >

{ __( - 'Results typically improve with time with Google’s paid ad campaigns. Removing a paid ad campaign will result in the loss of any optimisations learned from those campaigns.', + 'Results typically improve with time with Google Ads campaigns. Removing a campaign will result in the loss of any optimisations learned from those campaigns.', 'google-listings-and-ads' ) }

diff --git a/js/src/get-started-page/faqs/index.js b/js/src/get-started-page/faqs/index.js index dd4a41cbb6..03774ac981 100644 --- a/js/src/get-started-page/faqs/index.js +++ b/js/src/get-started-page/faqs/index.js @@ -231,7 +231,7 @@ const faqItems = [

{ createInterpolateElement( __( - 'Yes, you can run both at the same time, and we recommend you do! Once you sync your store it’s automatically listed on Google, so you can choose to run a paid Performance Max campaign as soon as you’d like. In the US, advertisers who sync their products to Google and run Google Ads Performance Max campaigns have seen an average of over 50% increase in clicks and over 100% increase in impressions in both their product listings and their ads on the Shopping tab. ', + 'Yes, you can run both at the same time, and we recommend you do! Once you sync your store it’s automatically listed on Google, so you can choose to run a Performance Max campaign as soon as you’d like. In the US, advertisers who sync their products to Google and run Google Ads Performance Max campaigns have seen an average of over 50% increase in clicks and over 100% increase in impressions in both their product listings and their ads on the Shopping tab. ', 'google-listings-and-ads' ), { diff --git a/js/src/get-started-page/features-card/index.js b/js/src/get-started-page/features-card/index.js index 003f457c05..532c7e10f2 100644 --- a/js/src/get-started-page/features-card/index.js +++ b/js/src/get-started-page/features-card/index.js @@ -114,7 +114,7 @@ const FeaturesCard = () => { variant="label" > { __( - 'Promote products and drive more sales with paid ads', + 'Promote products and drive more sales with ads', 'google-listings-and-ads' ) } diff --git a/js/src/pages/edit-paid-ads-campaign/index.js b/js/src/pages/edit-paid-ads-campaign/index.js index eb043af9c7..c3ec3e746c 100644 --- a/js/src/pages/edit-paid-ads-campaign/index.js +++ b/js/src/pages/edit-paid-ads-campaign/index.js @@ -113,7 +113,7 @@ const EditPaidAdsCampaign = () => { />

{ __( - 'Error in loading your paid ads campaign. Please try again later.', + 'Error in loading your ads campaign. Please try again later.', 'google-listings-and-ads' ) }
diff --git a/js/src/reports/index.js b/js/src/reports/index.js index 9b8f924395..c7f39be9f7 100644 --- a/js/src/reports/index.js +++ b/js/src/reports/index.js @@ -39,7 +39,7 @@ export { default as ProductsReport } from './products'; /** * @typedef {Object} ProgramsReportData * @property {Array} freeListings Free listings data - * @property {Array} campaigns Paid campaigns data. + * @property {Array} campaigns Ad campaigns data. * @property {Array | null} intervals Intervals data. * @property {PerformanceData} totals Performance data. */ diff --git a/js/src/reports/metric-number.js b/js/src/reports/metric-number.js index 5589627c03..82701c5fba 100644 --- a/js/src/reports/metric-number.js +++ b/js/src/reports/metric-number.js @@ -61,7 +61,7 @@ const MetricNumber = ( { // And Free Listings API may not respond with data. if ( missingFreeListingsData !== MISSING_FREE_LISTINGS_DATA.NONE ) { const text = __( - 'This data is currently available for paid campaigns only.', + 'This data is currently available for Google Ads campaigns only.', 'google-listings-and-ads' ); infos.push( text ); diff --git a/js/src/reports/products/filter-config.js b/js/src/reports/products/filter-config.js index 105f7667c8..a719522124 100644 --- a/js/src/reports/products/filter-config.js +++ b/js/src/reports/products/filter-config.js @@ -191,7 +191,7 @@ const reportSourceConfig = { filters: [ { value: REPORT_SOURCE_PAID, - label: __( 'Paid campaigns', 'google-listings-and-ads' ), + label: __( 'Ad campaigns', 'google-listings-and-ads' ), }, { value: REPORT_SOURCE_FREE, diff --git a/js/src/settings/disconnect-modal/confirm-modal.js b/js/src/settings/disconnect-modal/confirm-modal.js index 2f64511db3..18685ecdfd 100644 --- a/js/src/settings/disconnect-modal/confirm-modal.js +++ b/js/src/settings/disconnect-modal/confirm-modal.js @@ -35,7 +35,7 @@ const textDict = { 'google-listings-and-ads' ), __( - 'Any ongoing paid campaigns will continue to run. They can be managed, edited, or deleted manually from Google Ads (ads.google.com).', + 'Any ongoing campaigns will continue to run. They can be managed, edited, or deleted manually from Google Ads (ads.google.com).', 'google-listings-and-ads' ), ], @@ -57,7 +57,7 @@ const textDict = { 'google-listings-and-ads' ), __( - 'Any ongoing paid campaigns will continue to run. They can be managed, edited, or deleted manually from Google Ads (ads.google.com).', + 'Any ongoing campaigns will continue to run. They can be managed, edited, or deleted manually from Google Ads (ads.google.com).', 'google-listings-and-ads' ), __( diff --git a/src/Notes/CompleteSetup.php b/src/Notes/CompleteSetup.php index 2579ec04b9..4838044b55 100644 --- a/src/Notes/CompleteSetup.php +++ b/src/Notes/CompleteSetup.php @@ -38,7 +38,7 @@ public function get_name(): string { public function get_entry(): NoteEntry { $note = new NoteEntry(); $note->set_title( __( 'Reach more shoppers with free listings on Google', 'google-listings-and-ads' ) ); - $note->set_content( __( 'Finish setting up Google for WooCommerce to list your products on Google for free and promote them with paid ads.', 'google-listings-and-ads' ) ); + $note->set_content( __( 'Finish setting up Google for WooCommerce to list your products on Google for free and promote them with ads.', 'google-listings-and-ads' ) ); $note->set_content_data( new stdClass() ); $note->set_type( NoteEntry::E_WC_ADMIN_NOTE_INFORMATIONAL ); $note->set_layout( 'plain' ); diff --git a/src/Notes/SetupCampaignTwoWeeks.php b/src/Notes/SetupCampaignTwoWeeks.php index 860e2697ac..6e17836db3 100644 --- a/src/Notes/SetupCampaignTwoWeeks.php +++ b/src/Notes/SetupCampaignTwoWeeks.php @@ -48,7 +48,7 @@ protected function set_title_and_content( NoteEntry $note ): void { $note->set_title( __( 'Reach more shoppers with paid listings on Google', 'google-listings-and-ads' ) ); $note->set_content( __( - 'Your products are ready for Google Ads! Connect with the right shoppers at the right moment when they’re searching for products like yours. Connect your Google Ads account to create your first paid ad campaign.', + 'Your products are ready for Google Ads! Connect with the right shoppers at the right moment when they’re searching for products like yours. Connect your Google Ads account to create your first campaign.', 'google-listings-and-ads' ) ); From cef1b839d7dc55f3cd52f63835cb789d6e937ae6 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Thu, 14 Nov 2024 12:55:58 -0600 Subject: [PATCH 86/90] Copy tweak --- js/src/get-started-page/features-card/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/get-started-page/features-card/index.js b/js/src/get-started-page/features-card/index.js index 532c7e10f2..c79e3d0e90 100644 --- a/js/src/get-started-page/features-card/index.js +++ b/js/src/get-started-page/features-card/index.js @@ -114,7 +114,7 @@ const FeaturesCard = () => { variant="label" > { __( - 'Promote products and drive more sales with ads', + 'Promote products and drive more sales with Google Ads', 'google-listings-and-ads' ) } From 9b71ea6f9b31e88d43cff892a686e369162c304e Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Sun, 17 Nov 2024 15:36:32 -0600 Subject: [PATCH 87/90] Results typically improve with time --- .../edit-program-button/edit-program-prompt-modal/index.js | 2 +- .../program-toggle/pause-program-modal/index.js | 2 +- .../remove-program-button/remove-program-modal/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js b/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js index 76f3517444..9c237818ad 100644 --- a/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js +++ b/js/src/dashboard/all-programs-table-card/edit-program-button/edit-program-prompt-modal/index.js @@ -68,7 +68,7 @@ const EditProgramPromptModal = ( { programId, onRequestClose } ) => { >

{ __( - 'Results typically improve with time with Google’s Free Listing and Google Ads campaigns.', + 'Results typically improve with time.', 'google-listings-and-ads' ) }

diff --git a/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js b/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js index 46ab6ad3c8..143c88676c 100644 --- a/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js +++ b/js/src/dashboard/all-programs-table-card/program-toggle/pause-program-modal/index.js @@ -52,7 +52,7 @@ const PauseProgramModal = ( props ) => { >

{ __( - 'Results typically improve with time with Google Ads campaigns. If you pause, your products won’t be shown to people looking for what you offer.', + 'Results typically improve with time. If you pause, your products won’t be shown to people looking for what you offer.', 'google-listings-and-ads' ) }

diff --git a/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js b/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js index cdda3d71e4..3bec6d37ca 100644 --- a/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js +++ b/js/src/dashboard/all-programs-table-card/remove-program-button/remove-program-modal/index.js @@ -67,7 +67,7 @@ const RemoveProgramModal = ( props ) => { >

{ __( - 'Results typically improve with time with Google Ads campaigns. Removing a campaign will result in the loss of any optimisations learned from those campaigns.', + 'Results typically improve with time. Removing a campaign will result in the loss of any optimisations learned from those campaigns.', 'google-listings-and-ads' ) }

From 933e5b417ab3f15939f9320c103f7a6deed50a0a Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Sun, 17 Nov 2024 15:38:06 -0600 Subject: [PATCH 88/90] Skip ads creation --- js/src/setup-mc/setup-stepper/skip-button.js | 5 +---- tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js | 4 ++-- tests/e2e/utils/pages/setup-mc/step-4-complete-campaign.js | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/js/src/setup-mc/setup-stepper/skip-button.js b/js/src/setup-mc/setup-stepper/skip-button.js index c5a62f2d54..89f8440b66 100644 --- a/js/src/setup-mc/setup-stepper/skip-button.js +++ b/js/src/setup-mc/setup-stepper/skip-button.js @@ -64,10 +64,7 @@ export default function SkipButton( { <> { await expect( completeSetupButton ).toBeDisabled(); } ); - test( 'should see "Skip paid ads creation" button is enabled', async () => { + test( 'should see "Skip ads creation" button is enabled', async () => { const skipPaidAdsCreationButton = completeCampaign.getSkipPaidAdsCreationButton(); await expect( skipPaidAdsCreationButton ).toBeVisible(); @@ -199,7 +199,7 @@ test.describe( 'Complete your campaign', () => { await expect( budgetSection ).toBeVisible(); } ); - test( 'should see "Skip paid ads creation" is enabled and "Complete setup" button is disabled', async () => { + test( 'should see "Skip ads creation" is enabled and "Complete setup" button is disabled', async () => { const completeButton = completeCampaign.getCompleteSetupButton(); await expect( completeButton ).toBeVisible(); diff --git a/tests/e2e/utils/pages/setup-mc/step-4-complete-campaign.js b/tests/e2e/utils/pages/setup-mc/step-4-complete-campaign.js index 909f1ea8cd..d494586dba 100644 --- a/tests/e2e/utils/pages/setup-mc/step-4-complete-campaign.js +++ b/tests/e2e/utils/pages/setup-mc/step-4-complete-campaign.js @@ -74,7 +74,7 @@ export default class CompleteCampaign extends MockRequests { */ getSkipPaidAdsCreationButton() { return this.page.getByRole( 'button', { - name: 'Skip paid ads creation', + name: 'Skip ads creation', exact: true, } ); } From a70da30caa0a0578961d1d1742b8e67b1a73315c Mon Sep 17 00:00:00 2001 From: Eason Su Date: Mon, 11 Nov 2024 16:39:36 +0800 Subject: [PATCH 89/90] Fix the issue that E2E test can't log in to wp-admin. --- tests/e2e/global-setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/global-setup.js b/tests/e2e/global-setup.js index 26870e5aaa..6cf36e5a4a 100644 --- a/tests/e2e/global-setup.js +++ b/tests/e2e/global-setup.js @@ -55,7 +55,7 @@ module.exports = async ( config ) => { await adminPage .locator( 'input[name="pwd"]' ) .fill( admin.password ); - await adminPage.locator( 'text=Log In' ).click(); + await adminPage.getByRole( 'button', { name: 'Log In' } ).click(); await adminPage.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); await adminPage.goto( `/wp-admin` ); await adminPage.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); From 10dc1c944909f4b42e2e7e0a3fa3818710ebddd0 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Sun, 17 Nov 2024 16:13:59 -0600 Subject: [PATCH 90/90] Reach more shoppers with Google Ads --- src/Notes/SetupCampaignTwoWeeks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Notes/SetupCampaignTwoWeeks.php b/src/Notes/SetupCampaignTwoWeeks.php index 6e17836db3..6b22d9c7e8 100644 --- a/src/Notes/SetupCampaignTwoWeeks.php +++ b/src/Notes/SetupCampaignTwoWeeks.php @@ -45,7 +45,7 @@ protected function get_gla_setup_days(): int { */ protected function set_title_and_content( NoteEntry $note ): void { if ( ! $this->ads_service->is_setup_started() ) { - $note->set_title( __( 'Reach more shoppers with paid listings on Google', 'google-listings-and-ads' ) ); + $note->set_title( __( 'Reach more shoppers with Google Ads', 'google-listings-and-ads' ) ); $note->set_content( __( 'Your products are ready for Google Ads! Connect with the right shoppers at the right moment when they’re searching for products like yours. Connect your Google Ads account to create your first campaign.',