Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Introduce a test drive mode into the onboarding process #9109

Merged
merged 74 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
2b0d340
Add a test drive mode button on connect page
mordeth Jul 17, 2024
57547a7
Merge branch 'develop' into add/test-drive-mode
mordeth Jul 17, 2024
08fe035
Add overviewUrl to wcPaySettings
mordeth Jul 17, 2024
b67bd92
Onboard test drive accounts async
mordeth Jul 17, 2024
387440e
Remove obsolete text string
mordeth Jul 18, 2024
f1e138d
Redirect to connect page after Jetpack connection
mordeth Jul 18, 2024
2cb4c68
Test drive redirect to Jetpack connect screen
mordeth Jul 18, 2024
8269574
Merge branch 'develop' into add/test-drive-mode
mordeth Jul 20, 2024
5e8b5f9
Check account status only if account is onboarded
mordeth Jul 20, 2024
d98fc5c
Merge branch 'add/test-drive-mode' of github.com:Automattic/woocommer…
mordeth Jul 20, 2024
2c3fee0
Merge branch 'develop' into add/test-drive-mode
mordeth Jul 24, 2024
c489d99
Install @woocommerce/onboarding
mordeth Jul 24, 2024
c503f62
Add loader for test drive onboarding
mordeth Jul 24, 2024
1953e1d
Show error if the sandbox account creation failed
mordeth Jul 24, 2024
5faf107
Show a success message on the overview page
mordeth Jul 24, 2024
b98d260
Fake test onboarding progress bar
mordeth Jul 24, 2024
d658133
Fix onboarding loader on tablet and mobile screens
mordeth Jul 25, 2024
9f734ec
Force refresh account cache after onboarding
mordeth Jul 25, 2024
d361ffb
Merge branch 'develop' into add/test-drive-mode
mordeth Jul 25, 2024
69cc111
Add changelog
mordeth Jul 26, 2024
3504b3e
Update test drive loader styling
mordeth Jul 29, 2024
215c82b
Merge branch 'develop' into add/test-drive-mode
mordeth Jul 29, 2024
63a625e
Fallback in case Stripe never provide complete account
mordeth Jul 29, 2024
cc9478b
Restart loader progress in case of error
mordeth Jul 29, 2024
0d9044a
Merge branch 'develop' into add/test-drive-mode
mordeth Jul 29, 2024
a924d18
Merge branch 'develop' into add/test-drive-mode
mordeth Aug 1, 2024
9a2e2c6
Merge branch 'develop' into add/test-drive-mode
mordeth Aug 5, 2024
f80fea1
Update changelog and block comment
mordeth Aug 5, 2024
3a84f96
Update sandbox mode copy
mordeth Aug 5, 2024
bf80405
Merge branch 'develop' into add/test-drive-mode
mordeth Aug 6, 2024
deaf1af
Merge branch 'develop' into add/test-drive-mode
vladolaru Aug 9, 2024
a21c718
Add array_filter_recursive util
vladolaru Aug 9, 2024
0d48264
test: Add unit tests for array utils
vladolaru Aug 9, 2024
35078f1
Better filter onboarding data
vladolaru Aug 9, 2024
7f4dc19
Add array_merge_recursive_distinct util
vladolaru Aug 9, 2024
cb2c16b
test: Add unit tests for array_merge_recursive_distinct
vladolaru Aug 9, 2024
058c592
Test-drive accounts don't have access to the Stripe dashboard
vladolaru Aug 9, 2024
0bd7eb8
Add required props
vladolaru Aug 9, 2024
7a989fb
Minor refactoring on Overview page
vladolaru Aug 9, 2024
a56bad4
Carry over sandbox params
vladolaru Aug 9, 2024
f94fcb3
Ensure proper cache and state handling
vladolaru Aug 9, 2024
ded3690
Refactor init_stripe_onboarding around three setup modes
vladolaru Aug 9, 2024
d8d0e05
Look for pending-like status to determine test-drive completion
vladolaru Aug 9, 2024
10ab2ee
Show test-drive error on Connect
vladolaru Aug 9, 2024
164ea6c
Improvements to the test-drive FE logic
vladolaru Aug 9, 2024
a97f96b
test: Fix unit tests
vladolaru Aug 9, 2024
0309f3c
Merge branch 'develop' into add/test-drive-mode
vladolaru Aug 9, 2024
9618aa2
Use a bigger icon size
vladolaru Aug 9, 2024
c34320d
Include login error class with notice
vladolaru Aug 9, 2024
1d61c0c
test: Fix login error test
vladolaru Aug 9, 2024
45eff84
test: Fix Account Status tests
vladolaru Aug 9, 2024
064d10e
Fix test drive onboarding without an existing Jetpack connection
vladolaru Aug 9, 2024
a3dd2a6
Merge branch 'develop' into add/test-drive-mode
mordeth Aug 15, 2024
85cdfd6
Fallback to express accounts for Singapore and UAE
mordeth Aug 15, 2024
5bb8f08
Do not redirect to onboarding wizard for builder accounts
mordeth Aug 15, 2024
49d4f60
Skip MOX for sandbox accounts already in progress
mordeth Aug 15, 2024
1ea0e0a
Merge branch 'develop' into add/test-drive-mode
mordeth Aug 15, 2024
3392118
Prevent JS error
vladolaru Aug 15, 2024
668fa62
Merge branch 'develop' into add/test-drive-mode
vladolaru Aug 16, 2024
7d47f18
Revert "Fallback to express accounts for Singapore and UAE"
vladolaru Aug 16, 2024
9bd946d
Revert "Do not redirect to onboarding wizard for builder accounts"
vladolaru Aug 16, 2024
8434523
Revert "Skip MOX for sandbox accounts already in progress"
vladolaru Aug 16, 2024
9a893d5
Add cache control headers
vladolaru Aug 16, 2024
19da916
Handle test-driven mode fallback to regular test accounts
vladolaru Aug 16, 2024
97b13ca
Ensure more consistent data submitted on onboarding
vladolaru Aug 16, 2024
515bef4
Fix undefined error
mordeth Aug 16, 2024
2c09ae8
Refactor JS test-drive logic to work with just JSON
vladolaru Aug 16, 2024
4cbd41a
Pass through the sandbox success param
vladolaru Aug 16, 2024
b9b77ee
Fix error when account data is false
vladolaru Aug 16, 2024
9afe041
Merge branch 'develop' into add/test-drive-mode
vladolaru Aug 16, 2024
b2af679
Don't show test drive success notice when account is not complete or …
vladolaru Aug 16, 2024
81121b5
Skip InlineNotices on deposits when the account link is not present
mordeth Aug 16, 2024
7d37c45
test: fix unit test
vladolaru Aug 16, 2024
fbe7b82
Merge branch 'develop' into add/test-drive-mode
mordeth Aug 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/add-test-drive-mode
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Enhance Sandbox mode onboarding by skipping KYC and making it fully automated for all supported countries.
208 changes: 178 additions & 30 deletions client/connect-account-page/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* External dependencies
*/
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import { render } from '@wordpress/element';
import {
Button,
Expand All @@ -15,6 +15,7 @@ import {
} from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import { Loader } from '@woocommerce/onboarding';

/**
* Internal dependencies
Expand All @@ -30,13 +31,41 @@ import strings from './strings';
import './style.scss';
import InlineNotice from 'components/inline-notice';
import { WooPaymentMethodsLogos } from 'components/payment-method-logos';
import WooPaymentsLogo from 'assets/images/logo.svg?asset';
import { __ } from '@wordpress/i18n';

interface AccountData {
status: string;
}

const SandboxModeNotice = () => (
<BannerNotice icon status="warning" isDismissible={ false }>
{ strings.sandboxModeNotice }
</BannerNotice>
);

const TestDriveLoader: React.FunctionComponent< {
progress: number;
} > = ( { progress } ) => (
<Loader className="connect-account-page__preloader">
<img src={ WooPaymentsLogo } alt="" />
<Loader.Layout>
<Loader.Title>
{ __(
'Creating your sandbox account',
mordeth marked this conversation as resolved.
Show resolved Hide resolved
'woocommerce-payments'
) }
</Loader.Title>
<Loader.ProgressBar progress={ progress ?? 0 } />
<Loader.Sequence interval={ 0 }>
{ __(
'In just a few moments, you will be ready to test payments on your store.'
) }
</Loader.Sequence>
</Loader.Layout>
</Loader>
);

const ConnectAccountPage: React.FC = () => {
const firstName = wcSettings.admin?.currentUserData?.first_name;
const incentive = wcpaySettings.connectIncentive;
Expand All @@ -47,9 +76,23 @@ const ConnectAccountPage: React.FC = () => {
wcpaySettings.errorMessage
);
const [ isSubmitted, setSubmitted ] = useState( false );
const [ isSandboxModeClicked, setSandboxModeClicked ] = useState( false );
const [ isTestDriveModeSubmitted, setTestDriveModeSubmitted ] = useState(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous name isSandboxModeClicked is a better choice here. But given it'll go away soon, WDYT about isTestDriveModeRequested?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest we keep this variable the same isSandboxModeClicked or isSandboxModeRequested for now.

false
);
const [ isTestDriveModeModalShown, setTestDriveModeModalShown ] = useState(
false
);
const [ testDriveLoaderProgress, setTestDriveLoaderProgress ] = useState(
5
);

// Create a reference object.
const loaderProgressRef = useRef( testDriveLoaderProgress );
loaderProgressRef.current = testDriveLoaderProgress;

const {
connectUrl,
overviewUrl,
connect: { availableCountries, country },
devMode,
} = wcpaySettings;
Expand All @@ -74,6 +117,131 @@ const ConnectAccountPage: React.FC = () => {
return source;
};

const updateLoaderProgress = ( maxPercent: number, step: number ) => {
if ( loaderProgressRef.current < maxPercent ) {
const newProgress = loaderProgressRef.current + step;
setTestDriveLoaderProgress( newProgress );
}
};

const checkAccountStatus = () => {
// Fetch account status from the cache.
apiFetch( {
path: `/wc/v3/payments/accounts`,
method: 'GET',
} ).then( ( account ) => {
// Simulate the update of the loader progress bar by 4% per check.
// Limit to a maximum of 15 checks or 30 seconds.
updateLoaderProgress( 100, 4 );

// If the account status is complete or progress percentage is above 95, redirect to the overview page.
// Otherwise, schedule another check after 2 seconds.
if (
( account as AccountData ).status === 'complete' ||
loaderProgressRef.current > 95
) {
setTestDriveLoaderProgress( 100 );
const redirectUrl = addQueryArgs( overviewUrl, {
'sandbox-onboarded': true,
} );
window.location.href = redirectUrl;
} else {
setTimeout( checkAccountStatus, 2000 );
}
} );
};

const trackConnectAccountClicked = ( sandboxMode: boolean ) => {
recordEvent( 'wcpay_connect_account_clicked', {
anu-rock marked this conversation as resolved.
Show resolved Hide resolved
wpcom_connection: wcpaySettings.isJetpackConnected ? 'Yes' : 'No',
is_new_onboarding_flow: isNewFlowEnabled,
...( incentive && {
incentive_id: incentive.id,
} ),
sandbox_mode: sandboxMode,
path: 'payments_connect_v2',
source: determineTrackingSource(),
} );
};

const handleSetupTestDriveMode = async () => {
setTestDriveLoaderProgress( 5 );
anu-rock marked this conversation as resolved.
Show resolved Hide resolved
setTestDriveModeSubmitted( true );
trackConnectAccountClicked( true );

// Scroll the page to the top to ensure the logo is visible.
window.scrollTo( {
top: 0,
} );

const url = addQueryArgs( connectUrl, {
test_mode: true,
test_drive: true,
} );

const updateProgress = setInterval( updateLoaderProgress, 2500, 40, 5 );

// If Jetpack is connected, we should proceed with AJAX onboarding.
// Otherwise, redirect to the Jetpack connect screen.
if ( wcpaySettings.isJetpackConnected ) {
setTestDriveModeModalShown( true );
fetch( url, {
method: 'GET',
redirect: 'follow',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
} ).then( ( response ) => {
clearInterval( updateProgress );
setTestDriveLoaderProgress( 40 );

// Check the response url for the `wcpay-connection-success` parameter,
// indicating a successful connection.
const urlParams = new URLSearchParams( response.url );
const connected =
urlParams.get( 'wcpay-connection-success' ) || '';

// The account has been successfully onboarded.
// Start checking the account status every 2 seconds.
// Once the status is complete, redirect to the Overview page.
if ( connected === '1' ) {
checkAccountStatus();
} else {
// Set the error message.
setErrorMessage(
__(
'An error occurred while creating a sandbox account. Please try again!',
'woocommerce-payments'
)
);

// Scroll window to the top
window.scrollTo( {
top: 0,
} );

// Hide loader.
setTestDriveModeModalShown( false );
setTestDriveModeSubmitted( false );
}
} );
} else {
window.location.href = url;
}
};

const forceOnboardTestDrive = () => {
const urlParams = new URLSearchParams( window.location.search );
const forceOnboard = urlParams.get( 'force-test-onboard' ) || false;

// If the force test onboard is present and Jetpack is connected
// we should start onboarding Test Drive account automatically.
if ( forceOnboard && wcpaySettings.isJetpackConnected ) {
handleSetupTestDriveMode();
}
};

useEffect( () => {
recordEvent( 'page_view', {
path: 'payments_connect_v2',
Expand All @@ -82,6 +250,8 @@ const ConnectAccountPage: React.FC = () => {
} ),
source: determineTrackingSource(),
} );

forceOnboardTestDrive();
// We only want to run this once.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
Expand Down Expand Up @@ -116,19 +286,6 @@ const ConnectAccountPage: React.FC = () => {
document.body.appendChild( container );
};

const trackConnectAccountClicked = ( sandboxMode: boolean ) => {
recordEvent( 'wcpay_connect_account_clicked', {
wpcom_connection: wcpaySettings.isJetpackConnected ? 'Yes' : 'No',
is_new_onboarding_flow: isNewFlowEnabled,
...( incentive && {
incentive_id: incentive.id,
} ),
sandbox_mode: sandboxMode,
path: 'payments_connect_v2',
source: determineTrackingSource(),
} );
};

const handleSetup = async () => {
setSubmitted( true );

Expand Down Expand Up @@ -158,18 +315,6 @@ const ConnectAccountPage: React.FC = () => {
window.location.href = connectUrl;
};

const handleEnableSandboxMode = async () => {
setSandboxModeClicked( true );

trackConnectAccountClicked( true );

const url = addQueryArgs( connectUrl, {
test_mode: true,
create_builder_account: true,
} );
window.location.href = url;
};

return (
<Page isNarrow className="connect-account-page">
{ errorMessage && (
Expand Down Expand Up @@ -272,16 +417,19 @@ const ConnectAccountPage: React.FC = () => {
</InlineNotice>
<Button
variant="secondary"
isBusy={ isSandboxModeClicked }
disabled={ isSandboxModeClicked }
onClick={ handleEnableSandboxMode }
isBusy={ isTestDriveModeSubmitted }
disabled={ isTestDriveModeSubmitted }
onClick={ handleSetupTestDriveMode }
>
{ strings.button.sandbox }
</Button>
</PanelBody>
</Panel>
</>
) }
{ isTestDriveModeModalShown && (
<TestDriveLoader progress={ testDriveLoaderProgress } />
) }
</Page>
);
};
Expand Down
19 changes: 19 additions & 0 deletions client/connect-account-page/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,23 @@
}
}
}

&__preloader {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fff;
z-index: 999999;
text-align: center;

img {
position: absolute;
height: 44px;
width: 167px;
top: 18px;
left: calc( 50% - 84px );
}
}
}
1 change: 1 addition & 0 deletions client/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare global {
const wcpaySettings: {
version: string;
connectUrl: string;
overviewUrl: string;
isSubscriptionsActive: boolean;
featureFlags: {
customSearch: boolean;
Expand Down
23 changes: 22 additions & 1 deletion client/overview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, { useState } from 'react';
import { Button, Card, Notice } from '@wordpress/components';
import { getQuery } from '@woocommerce/navigation';
import { __, sprintf } from '@wordpress/i18n';
import { useDispatch } from '@wordpress/data';

/**
* Internal dependencies.
Expand Down Expand Up @@ -66,7 +67,7 @@ const OverviewSandboxModeNotice = ( { ctaAction = () => {} } ) => {
/* translators: %1$s: WooPayments */
__(
// eslint-disable-next-line max-len
'{{strong}}%1$s is in sandbox mode.{{/strong}} To accept real transactions, {{switchToLiveLink}}set up a live %1$s account.{{/switchToLiveLink}} {{learnMoreIcon/}}',
'{{strong}}%1$s is in sandbox mode.{{/strong}} To accept real payments, {{switchToLiveLink}}set up a live %1$s account.{{/switchToLiveLink}} {{learnMoreIcon/}}',
'woocommerce-payments'
),
'WooPayments'
Expand Down Expand Up @@ -138,11 +139,17 @@ const OverviewPage = () => {
wpcomReconnectUrl,
} = wcpaySettings;

const { createSuccessNotice } = useDispatch( 'core/notices' );

const isDevMode = wcpaySettings.devMode;
const { isLoading: settingsIsLoading } = useSettings();
const [ livePaymentsModalVisible, setLivePaymentsModalVisible ] = useState(
false
);
const [
isTestDriveSuccessDisplayed,
setTestDriveSuccessDisplayed,
] = useState( false );
const settings = useGetSettings();

const { disputes: activeDisputes } = useDisputes( {
Expand All @@ -166,6 +173,8 @@ const OverviewPage = () => {

const showConnectionSuccess =
queryParams[ 'wcpay-connection-success' ] === '1';
const isSandboxOnboardedSuccessful =
queryParams[ 'sandbox-onboarded' ] === 'true';

const showLoanOfferError = queryParams[ 'wcpay-loan-offer-error' ] === '1';
const showServerLinkError =
Expand Down Expand Up @@ -197,6 +206,18 @@ const OverviewPage = () => {
} )
.filter( ( e ) => e && e.fee !== undefined );

if ( ! isTestDriveSuccessDisplayed && isSandboxOnboardedSuccessful ) {
createSuccessNotice(
__(
'Success! You can start using WooPayments in sandbox mode.',
'woocommerce-payments'
)
);

// Ensure the success message is displayed only once.
setTestDriveSuccessDisplayed( true );
}

return (
<Page isNarrow className="wcpay-overview">
<OverviewPageError />
Expand Down
Loading
Loading