Skip to content

Commit

Permalink
Merge pull request #2426 from woocommerce/release/2.7.2
Browse files Browse the repository at this point in the history
Release 2.7.2
  • Loading branch information
mikkamp authored Jun 10, 2024
2 parents 1b7b1d5 + 62cc942 commit 174c15e
Show file tree
Hide file tree
Showing 91 changed files with 3,322 additions and 1,281 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ module.exports = {
additionalHooks: 'useSelect',
},
],
'jest/expect-expect': [
'warn',
{ assertFunctionNames: [ 'expect', 'expect[A-Z]\\w*' ] },
],
},
overrides: [
{
Expand Down
9 changes: 9 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
*** WooCommerce Google Listings and Ads Changelog ***

= 2.7.2 - 2024-06-10 =
* Add - Google Ads account invitation acceptance step to the connection process.
* Fix - Show tracking snapshots in WPCLI.
* Tweak - Adjust click event tracking when connecting, disconnecting, and opening billing setup for Google Ads account.
* Tweak - Adjust event tracking for the creating and claim buttons of Google Ads account.
* Tweak - WC 9.0 compatibility.
* Update - Enable users to seamlessly set up conversion tracking, without having to set up merchant center first or requiring campaign creation.
* Update - Move the Google Ads account connection process from step 4 to step 1 of the onboarding flow.

= 2.7.1 - 2024-05-29 =
* Dev - Add info about Legacy Google Ads API Client Library in Readme.
* Fix - Prevent PHP Warning when Statistics is null.
Expand Down
6 changes: 3 additions & 3 deletions google-listings-and-ads.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: Google Listings and Ads
* Plugin URL: https://wordpress.org/plugins/google-listings-and-ads/
* Description: Native integration with Google that allows merchants to easily display their products across Google’s network.
* Version: 2.7.1
* Version: 2.7.2
* Author: WooCommerce
* Author URI: https://woo.com/
* Text Domain: google-listings-and-ads
Expand All @@ -13,7 +13,7 @@
* Requires PHP Architecture: 64 bits
* Requires Plugins: woocommerce
* WC requires at least: 6.9
* WC tested up to: 8.9
* WC tested up to: 9.0
* Woo:
*
* @package WooCommerce\Admin
Expand All @@ -30,7 +30,7 @@

defined( 'ABSPATH' ) || exit;

define( 'WC_GLA_VERSION', '2.7.1' ); // WRCS: DEFINED_VERSION.
define( 'WC_GLA_VERSION', '2.7.2' ); // WRCS: DEFINED_VERSION.
define( 'WC_GLA_MIN_PHP_VER', '7.4' );
define( 'WC_GLA_MIN_WC_VER', '6.9' );

Expand Down
13 changes: 0 additions & 13 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,6 @@ module.exports = {
wcAdminFeatures: {
navigation: false,
},
glaData: {
slug: 'gla',
mcSetupComplete: true,
mcSupportedCountry: true,
mcSupportedLanguage: true,
adsSetupComplete: true,
enableReports: true,
dateFormat: 'F j, Y',
timeFormat: 'g:i a',
initialWpData: {
version: '1.2.3',
},
},
},
timers: 'fake',
};
4 changes: 2 additions & 2 deletions js/src/components/account-card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ const appearanceDict = {
icon: googleMCLogo,
title: __( 'Google Merchant Center', 'google-listings-and-ads' ),
description: __(
'Required to sync products and list on Google',
'Required to sync products and list on Google.',
'google-listings-and-ads'
),
},
[ APPEARANCE.GOOGLE_ADS ]: {
icon: googleAdsLogo,
title: __( 'Google Ads', 'google-listings-and-ads' ),
description: __(
'Connect with millions of shoppers who are searching for products like yours and drive sales with Google.',
'Required to set up conversion measurement and create campaigns.',
'google-listings-and-ads'
),
},
Expand Down
8 changes: 8 additions & 0 deletions js/src/components/account-card/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@
background-color: #f8ebea;
}

.components-notice.is-success {
background-color: #edfaef;
border: 0;
font-size: $helptext-font-size;
margin: 0 var(--large-gap) var(--main-gap);
padding: $grid-unit-20;
}

@media (max-width: $break-small) {
.components-card__body > .components-flex {
flex-direction: column;
Expand Down
55 changes: 55 additions & 0 deletions js/src/components/google-ads-account-card/claim-account-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* External dependencies
*/
import { noop } from 'lodash';

/**
* Internal dependencies
*/
import AppButton from '.~/components/app-button';
import getWindowFeatures from '.~/utils/getWindowFeatures';
import { FILTER_ONBOARDING } from '.~/utils/tracks';
import useGoogleAdsAccountStatus from '.~/hooks/useGoogleAdsAccountStatus';
import useEventPropertiesFilter from '.~/hooks/useEventPropertiesFilter';

/**
* Clicking on the button to open the invitation page for claiming the newly created Google Ads account.
*
* @event gla_open_ads_account_claim_invitation_button_click
* @property {string} [context] Indicates the place where the button is located.
* @property {string} [step] Indicates the step in the onboarding process.
*/

/**
* Renders a button for opening a pop-up window to claim the newly created Google Ads account.
*
* @fires gla_open_ads_account_claim_invitation_button_click When the user clicks on the button to claim the account.
*
* @param {Object} props React props.
* @param {Function} [props.onClick] Function called back when the button is clicked.
* @param {Object} props.restProps Props to be forwarded to AppButton.
*/
const ClaimAccountButton = ( { onClick = noop, ...restProps } ) => {
const { inviteLink } = useGoogleAdsAccountStatus();
const getEventProps = useEventPropertiesFilter( FILTER_ONBOARDING );

const handleClaimAccountClick = ( event ) => {
const { defaultView } = event.target.ownerDocument;
const features = getWindowFeatures( defaultView, 600, 800 );

defaultView.open( inviteLink, '_blank', features );

onClick( event );
};

return (
<AppButton
{ ...restProps }
eventName="gla_open_ads_account_claim_invitation_button_click"
eventProps={ getEventProps() }
onClick={ handleClaimAccountClick }
/>
);
};

export default ClaimAccountButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* External dependencies
*/
import '@testing-library/jest-dom';
import { screen, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { recordEvent } from '@woocommerce/tracks';

/**
* Internal dependencies
*/
import ClaimAccountButton from './claim-account-button';
import useGoogleAdsAccountStatus from '.~/hooks/useGoogleAdsAccountStatus';
import { FILTER_ONBOARDING } from '.~/utils/tracks';
import expectComponentToRecordEventWithFilteredProperties from '.~/tests/expectComponentToRecordEventWithFilteredProperties';

jest.mock( '.~/hooks/useGoogleAdsAccountStatus', () =>
jest.fn().mockName( 'useGoogleAdsAccountStatus' )
);

jest.mock( '@woocommerce/tracks', () => {
return {
recordEvent: jest.fn().mockName( 'recordEvent' ),
};
} );

describe( 'ClaimAccountButton', () => {
let windowOpen;

beforeEach( () => {
windowOpen = jest.spyOn( global, 'open' );

useGoogleAdsAccountStatus.mockReturnValue( {
inviteLink: 'https://example.com',
} );
} );

afterEach( () => {
windowOpen.mockReset();
recordEvent.mockClear();
} );

it( 'should render the specified text in the button', () => {
render(
<ClaimAccountButton>
Claim account in example.com
</ClaimAccountButton>
);

expect( screen.getByRole( 'button' ) ).toHaveTextContent(
'Claim account in example.com'
);
} );

it( 'should forward onClick callback', async () => {
const onClick = jest.fn();
render( <ClaimAccountButton onClick={ onClick } /> );

expect( onClick ).toHaveBeenCalledTimes( 0 );

await userEvent.click( screen.getByRole( 'button' ) );

expect( onClick ).toHaveBeenCalledTimes( 1 );
} );

it( 'should open the invitation link in a pop-up window', async () => {
render( <ClaimAccountButton /> );

expect( windowOpen ).toHaveBeenCalledTimes( 0 );

await userEvent.click( screen.getByRole( 'button' ) );

expect( windowOpen ).toHaveBeenCalledTimes( 1 );
expect( windowOpen ).toHaveBeenCalledWith(
'https://example.com',
'_blank',
// Ignore the value of the window features.
expect.any( String )
);
} );

it( 'should record click events and be aware of extra event properties from filters', async () => {
await expectComponentToRecordEventWithFilteredProperties(
ClaimAccountButton,
FILTER_ONBOARDING,
async () => await userEvent.click( screen.getByRole( 'button' ) ),
'gla_open_ads_account_claim_invitation_button_click',
[
{ context: 'setup-mc', step: '1' },
{ context: 'setup-ads', step: '2' },
]
);
} );
} );
68 changes: 68 additions & 0 deletions js/src/components/google-ads-account-card/claim-account-modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { useEffect } from '@wordpress/element';

/**
* Internal dependencies
*/
import useGoogleAdsAccountStatus from '.~/hooks/useGoogleAdsAccountStatus';
import AppModal from '.~/components/app-modal';
import ClaimAccountButton from './claim-account-button';

/**
* Renders a modal for opening a pop-up window to claim the newly created Google Ads account.
* The modal is displayed when the user has successfully created a Google Ads account and needs to claim it.
*
* @param {Object} props React props.
* @param {Function} props.onRequestClose Function called back when the modal is requested to be closed.
*/
const ClaimAccountModal = ( { onRequestClose } ) => {
const { hasAccess } = useGoogleAdsAccountStatus();

Check warning on line 22 in js/src/components/google-ads-account-card/claim-account-modal.js

View check run for this annotation

Codecov / codecov/patch

js/src/components/google-ads-account-card/claim-account-modal.js#L22

Added line #L22 was not covered by tests

useEffect( () => {

Check warning on line 24 in js/src/components/google-ads-account-card/claim-account-modal.js

View check run for this annotation

Codecov / codecov/patch

js/src/components/google-ads-account-card/claim-account-modal.js#L24

Added line #L24 was not covered by tests
// Close the modal if access has been granted.
if ( hasAccess ) {
onRequestClose();

Check warning on line 27 in js/src/components/google-ads-account-card/claim-account-modal.js

View check run for this annotation

Codecov / codecov/patch

js/src/components/google-ads-account-card/claim-account-modal.js#L27

Added line #L27 was not covered by tests
}
}, [ onRequestClose, hasAccess ] );

return (

Check warning on line 31 in js/src/components/google-ads-account-card/claim-account-modal.js

View check run for this annotation

Codecov / codecov/patch

js/src/components/google-ads-account-card/claim-account-modal.js#L31

Added line #L31 was not covered by tests
<AppModal
className="gla-ads-invite-modal"
title={ __(
'Claim your Google Ads account',
'google-listings-and-ads'
) }
buttons={ [
<ClaimAccountButton
key="1"
isPrimary
onClick={ onRequestClose }
>
{ __(
'Claim account in Google Ads',
'google-listings-and-ads'
) }
</ClaimAccountButton>,
] }
onRequestClose={ onRequestClose }
>
<p>
{ __(
'Claiming your account lets you access Google Ads and sets up conversion measurement. You must claim your account in the next 20 days.',
'google-listings-and-ads'
) }
</p>
<p>
{ __(
'When you claim your account, you’ll be asked to set up billing. This step is optional and you only need to complete it if you want to create Google Ads campaigns. If you don’t want to set up billing, close the window after you’ve clicked ‘Continue’ on the next page.',
'google-listings-and-ads'
) }
</p>
</AppModal>
);
};

export default ClaimAccountModal;
36 changes: 36 additions & 0 deletions js/src/components/google-ads-account-card/claim-account/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { Fragment } from '@wordpress/element';

/**
* Internal dependencies
*/
import { useAppDispatch } from '.~/data';
import Section from '.~/wcdl/section';
import useWindowFocusCallbackIntervalEffect from '.~/hooks/useWindowFocusCallbackIntervalEffect';
import DisconnectAccount from '../disconnect-account';
import './index.scss';

const ClaimAccount = () => {
const { fetchGoogleAdsAccountStatus } = useAppDispatch();
useWindowFocusCallbackIntervalEffect( fetchGoogleAdsAccountStatus, 30 );

return (
<Fragment>
<p className="gla-ads-claim-account-notice">
{ __(
'Claim your new Google Ads account to complete this setup.',
'google-listings-and-ads'
) }
</p>

<Section.Card.Footer>
<DisconnectAccount />
</Section.Card.Footer>
</Fragment>
);
};

export default ClaimAccount;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.gla-ads-claim-account-notice {
background-color: #ffeec1;
font-size: $helptext-font-size;
margin: 0 var(--large-gap) var(--large-gap);
padding: $grid-unit-20;
}
Loading

0 comments on commit 174c15e

Please sign in to comment.