-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Connect MC Account within combo card #2639
base: feature/2509-consolidate-google-account-cards
Are you sure you want to change the base?
Connect MC Account within combo card #2639
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## feature/2509-consolidate-google-account-cards #2639 +/- ##
===============================================================================
- Coverage 62.7% 62.7% -0.0%
===============================================================================
Files 325 325
Lines 5162 5161 -1
Branches 1265 1265
===============================================================================
- Hits 3239 3238 -1
Misses 1746 1746
Partials 177 177
Flags with carried forward coverage won't be shown. Click here to find out more.
|
…ate/2597-connect-mc-account
…te/2597-connect-mc-account
…te/2597-connect-mc-account
…te/2597-connect-mc-account
@joemcgill Can you review PR please? The failing unit tests are from the parent branch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @asvinb This is looking pretty good, but I've got a few questions/suggestions inline.
js/src/components/google-combo-account-card/connect-mc/connect-mc.js
Outdated
Show resolved
Hide resolved
js/src/components/google-combo-account-card/connect-mc/connect-mc.js
Outdated
Show resolved
Hide resolved
if ( ! isConnected && resultConnectMC.response?.status === 409 ) { | ||
return ( | ||
<SwitchUrlCard | ||
id={ resultConnectMC.error.id } | ||
message={ resultConnectMC.error.message } | ||
claimedUrl={ resultConnectMC.error.claimed_url } | ||
newUrl={ resultConnectMC.error.new_url } | ||
onSelectAnotherAccount={ resultConnectMC.reset } | ||
/> | ||
); | ||
} | ||
|
||
if ( | ||
! isConnected && | ||
( resultConnectMC.response?.status === 403 || | ||
resultCreateAccount.response?.status === 403 ) | ||
) { | ||
return ( | ||
<ReclaimUrlCard | ||
id={ | ||
resultConnectMC.error?.id || resultCreateAccount.error?.id | ||
} | ||
websiteUrl={ | ||
resultConnectMC.error?.website_url || | ||
resultCreateAccount.error?.website_url | ||
} | ||
onSwitchAccount={ () => { | ||
resultConnectMC.reset(); | ||
resultCreateAccount.reset(); | ||
} } | ||
/> | ||
); | ||
} | ||
|
||
if ( | ||
! isConnected && | ||
( resultCreateAccount.loading || | ||
resultCreateAccount.response?.status === 503 ) | ||
) { | ||
return ( | ||
<CreatingCard | ||
retryAfter={ resultCreateAccount.error?.retry_after } | ||
onRetry={ handleCreateAccount } | ||
/> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This duplicates a lot of logic directly from js/src/components/google-mc-account-card/connect-mc/index.js
. Curious if we could abstract some of this into a shared component and avoid the redundant isConnected
check in the process?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill I've introduced a new AccountConnectionStatus
where we have this logic.
https://github.com/woocommerce/google-listings-and-ads/pull/2639/files#diff-398198aee87feb6f89983540431ac7e76d24a4d36793dd440d8758a287e190bbR1
However am not sure if there's an easier way to have the conditions to render that component:
https://github.com/woocommerce/google-listings-and-ads/pull/2639/files#diff-adf83b7ae2454ff433c2f50eb0f115c58b3a97776516764ef0ec88707353d177R45-R51
indicator={ getIndicator() } | ||
/> | ||
|
||
<ConnectMC /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than making this a sibling component of the AccountCard
above, I would have expected ConnectMC
to return a Section.Card.Body
component that is passed as a child of the AccountCard
above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill We synced in Slack about that. We'll have a group of cars, so it'll be siblings.
…te/2597-connect-mc-account
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few questions, but no blockers. Marking this as approved and ready for QA/WooCR
{ ! isConnected && ! isConnecting && ( | ||
<AppButton | ||
isSecondary | ||
disabled={ ! value } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what circumstance would this be visible and disabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill This will be visible only when we need to connect a new account. I removed the disabled
prop since we will always have a value set.
useEffect( () => { | ||
if ( isGoogleMCReady ) { | ||
setAccountID( googleMCAccount.id ); | ||
} | ||
}, [ googleMCAccount, isGoogleMCReady ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand why we need to save the MC account separately as component state here rather than using googleMcaccount.id
directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill We need to save the value set from the select in case the user needs to connect to a different acccount.
( existingAccount ) => existingAccount.id === googleMCAccount.id | ||
); | ||
|
||
if ( ! accountIdExists && isConnected ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a clever workaround. I assume this is for a newly created account that has not yet shown up in the API response for existing accounts? If so, adding that context to the inline doc would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill I added it at the start of the component where we explain why we have this intermediary component:
https://github.com/woocommerce/google-listings-and-ads/pull/2639/files#diff-38d86396eccec4e8e7e5b37e8de9cf25e28fb0a2536261feb312adfe9c6689aeR15-R24
resultCreateAccount, | ||
onRetry, | ||
} ) => { | ||
if ( resultConnectMC.response?.status === 409 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker, but I think using raw response status codes like this is not very readable. Curious if we could create a utility to map these to more human friendly, or at least add inline comments that makes it easy to understand what a 409 indicates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some inline comments, just describing what are the error statuses. More details can be found in the utils function: https://github.com/woocommerce/google-listings-and-ads/pull/2639/files#diff-289f2d84147885af5105af45f5b616e4057a4490f0fe42b5cf487ca942fdfcefR6-R7
…ate/2597-connect-mc-account
QA Report- ✅Testing Environment -
Test Results: Tested multiple scenarios related to MC account creation and connection with the store, including cases where Google accounts have multiple MC accounts, a single MC account, connection when the URL is already claimed, connection when the URL doesn’t need to be claimed, and creating a new MC account from the options. All cases were found to be working. Functional Demo / ScreencastConnection when Google account has only single MC account: when.account.has.only.One.MC.account.avaaible.mp4Creating New account when Google Account has single MC account: creeatung.new.account.mp4Creating account when Google Accounts has multiple MC accounts: Creating.new.account.when.user.has.already.multiple.MC.accounts.mp4Connection with existing MC account when Google has multiple MC accounts: Connecting.when.multiple.MC.accounts.availble.mp4 |
…ctor 2597: Refactor ConnectMC with updated AccountCard
…ate/2597-connect-mc-account
@@ -39,7 +56,7 @@ const ConnectedGoogleComboAccountCard = () => { | |||
<AccountCard | |||
appearance={ APPEARANCE.GOOGLE } | |||
alignIcon="top" | |||
className="gla-google-combo-account-card--connected" | |||
className="gla-google-combo-account-card gla-google-combo-account-card--connected" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the gla-google-combo-account-card
to be consistent with the other cards.
const MerchantCenterSelect = ( { isConnected, ...rest } ) => { | ||
const { data: existingAccounts } = useExistingGoogleMCAccounts(); | ||
const { googleMCAccount } = useGoogleMCAccount(); | ||
const domain = new URL( getSetting( 'homeUrl' ) ).host; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about moving this variable into the below if
block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing! Updated @eason9487
js/src/data/resolvers.js
Outdated
getExistingGoogleMCAccounts.shouldInvalidate = ( action ) => { | ||
return action.type === TYPES.RECEIVE_ACCOUNTS_GOOGLE_MC; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this invalidation is trying to refetch the existing accounts so that it can have the newly created account. If so, after the following findings, maybe this could be removed since it usually won't work.
Lines 20 to 22 in 8fba3e4
* we found that when a URL is reclaimed for Merchant Center (MC), the Google API does not | |
* return the newly reclaimed account immediately in the list provided by the useExistingGoogleMCAccounts hook, | |
* even though the data in the store is invalidated. In that case, thus we end up having an account ID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
await setUpAccountsPage.mockMCConnected(); | ||
await setUpAccountsPage.mockAdsAccountConnected(); | ||
|
||
await setUpAccountsPage.mockMCHasAccounts(); | ||
await setUpAccountsPage.mockMCConnected(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicated await setUpAccountsPage.mockMCConnected();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Removed.
const createAccountButton = | ||
setUpAccountsPage.getMCCreateAccountButtonFromPage(); | ||
await createAccountButton.click(); | ||
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it needs to wait for load state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out we don't need it. Removed.
await page.waitForLoadState( | ||
LOAD_STATE.DOM_CONTENT_LOADED | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it needs to wait for load state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed and removed unnecessary wait for load state.
// Mock Jetpack as connected. | ||
setUpAccountsPage.mockJetpackConnected(), | ||
|
||
// Mock google as connected. | ||
setUpAccountsPage.mockGoogleConnected( | ||
'[email protected]' | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These mocks seem to be redundant as the upper test.beforeAll
block has set the same mocks and they won't invalidated when entering here.
google-listings-and-ads/tests/e2e/specs/setup-mc/step-1-accounts.test.js
Lines 297 to 304 in 8fba3e4
test.describe( 'Connect Merchant Center account', () => { | |
test.beforeAll( async () => { | |
await Promise.all( [ | |
// Mock Jetpack as connected. | |
setUpAccountsPage.mockJetpackConnected(), | |
// Mock google as connected. | |
setUpAccountsPage.mockGoogleConnected( '[email protected]' ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
return this.getMCAccountCard().locator( | ||
'select[id*="inspector-select-control"]' | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return this.getMCAccountCard().locator( | |
'select[id*="inspector-select-control"]' | |
); | |
return this.getMCAccountCard().getByRole( 'combobox' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// Mock Jetpack as connected. | ||
setUpAccountsPage.mockJetpackConnected(), | ||
|
||
// Mock google as connected. | ||
setUpAccountsPage.mockGoogleConnected( | ||
'[email protected]' | ||
), | ||
|
||
// Mock Google Ads as connected. | ||
setUpAccountsPage.mockAdsAccountConnected(), | ||
setUpAccountsPage.mockAdsStatusClaimed(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These mocks seem to be redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Removed.
test( 'should see see a modal to ensure the intention of creating a new account', async () => { | ||
// Click 'Or, create a new Merchant Center account' | ||
const mcFooterButton = | ||
setUpAccountsPage.getMCCardFooterButton(); | ||
await mcFooterButton.click(); | ||
await page.waitForLoadState( | ||
LOAD_STATE.DOM_CONTENT_LOADED | ||
); | ||
|
||
const modalHeader = setUpAccountsPage.getModalHeader(); | ||
await expect( modalHeader ).toContainText( | ||
'Create Google Merchant Center Account' | ||
); | ||
|
||
const modalCheckbox = setUpAccountsPage.getModalCheckbox(); | ||
await expect( modalCheckbox ).toBeEnabled(); | ||
|
||
const modalPrimaryButton = | ||
setUpAccountsPage.getModalPrimaryButton(); | ||
await expect( modalPrimaryButton ).toContainText( | ||
'Create account' | ||
); | ||
await expect( modalPrimaryButton ).toBeDisabled(); | ||
|
||
// Select the checkbox, the button should be enabled. | ||
await modalCheckbox.click(); | ||
await expect( modalPrimaryButton ).toBeEnabled(); | ||
} ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the same test is already in place.
google-listings-and-ads/tests/e2e/specs/setup-mc/step-1-accounts.test.js
Lines 342 to 364 in 8fba3e4
test( 'click "Create account" button should see the modal of confirmation of creating account', async () => { | |
// Click the create account button | |
const createAccountButton = | |
setUpAccountsPage.getMCCreateAccountButtonFromPage(); | |
await createAccountButton.click(); | |
await page.waitForLoadState( LOAD_STATE.DOM_CONTENT_LOADED ); | |
const modalHeader = setUpAccountsPage.getModalHeader(); | |
await expect( modalHeader ).toContainText( | |
'Create Google Merchant Center Account' | |
); | |
const modalCheckbox = setUpAccountsPage.getModalCheckbox(); | |
await expect( modalCheckbox ).toBeEnabled(); | |
const createAccountButtonFromModal = | |
setUpAccountsPage.getMCCreateAccountButtonFromModal(); | |
await expect( createAccountButtonFromModal ).toBeDisabled(); | |
// Click the checkbox of accepting ToS, the create account button will be enabled. | |
await modalCheckbox.click(); | |
await expect( createAccountButtonFromModal ).toBeEnabled(); | |
} ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test removed @eason9487
return this.page | ||
.locator( '.components-card-body', { | ||
has: this.page.locator( '.gla-account-card__title', { | ||
hasText: 'Google', | ||
} ), | ||
} ) | ||
.first(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May add a CSS class for this as well like the getMCAccountCard
method below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the original components under the js/src/components/google-mc-account-card
directory are only used for the Onboarding accounts step, except for ConnectedGoogleMCAccountCard
which is shared by the Setting page. Given this, extracting some code into shared components or functions and creating another ConnectedMC
component would make for unnecessary redundant code and reduce maintainability.
This PR should be able to be done based on the original existing code and minimize code changes to optimally leverage codes that have been run for 2-3 years.
Suggest exploring possibilities in this direction:
- Adjust the
google-mc-account-card/connect-mc/index.js
to fulfill the new UI and functionality rather than creatinggoogle-combo-account-card/connect-mc/connect-mc.js
- Revert the extraction of
AccountConnectionStatus
andhasAccountConnectionIssue
ConnectedGoogleMCAccountCard
will only be used on the Settings page and itshideAccountSwitch
prop will no longer be needed- Remove code related to
hideAccountSwitch
- Rename to specify that this component is dedicated to the Settings page
- Remove code related to
Changes proposed in this Pull Request:
Closes #2597 .
Replace this with a good description of your changes & reasoning.
Detailed test instructions:
Additional details:
Changelog entry