fix: core profiler email opt in validation
This commit is contained in:
parent
1f625ca671
commit
5468ce68b8
|
@ -9,6 +9,7 @@ import {
|
|||
Spinner,
|
||||
CheckboxControl,
|
||||
} from '@wordpress/components';
|
||||
import { FormInputValidation } from '@automattic/components';
|
||||
import { SelectControl } from '@woocommerce/components';
|
||||
import { Icon, chevronDown } from '@wordpress/icons';
|
||||
import {
|
||||
|
@ -18,6 +19,8 @@ import {
|
|||
} from '@wordpress/element';
|
||||
import { findCountryOption, getCountry } from '@woocommerce/onboarding';
|
||||
import { decodeEntities } from '@wordpress/html-entities';
|
||||
import { z } from 'zod';
|
||||
import classNames from 'classnames';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -195,6 +198,8 @@ export const BusinessInfo = ( {
|
|||
|
||||
const [ hasSubmitted, setHasSubmitted ] = useState( false );
|
||||
|
||||
const [ isEmailValid, setIsEmailValid ] = useState( true );
|
||||
|
||||
const [ storeEmailAddress, setEmailAddress ] = useState(
|
||||
storeEmailAddressFromOnboardingProfile || currentUserEmail || ''
|
||||
);
|
||||
|
@ -203,6 +208,19 @@ export const BusinessInfo = ( {
|
|||
isOptInMarketingFromOnboardingProfile || false
|
||||
);
|
||||
|
||||
const [ doValidate, setDoValidate ] = useState( false );
|
||||
|
||||
useEffect( () => {
|
||||
if ( isOptInMarketing && doValidate ) {
|
||||
const parseEmail = z
|
||||
.string()
|
||||
.email()
|
||||
.safeParse( storeEmailAddress );
|
||||
setIsEmailValid( parseEmail.success );
|
||||
setDoValidate( false );
|
||||
}
|
||||
}, [ isOptInMarketing, doValidate, storeEmailAddress ] );
|
||||
|
||||
return (
|
||||
<div
|
||||
className="woocommerce-profiler-business-information"
|
||||
|
@ -375,10 +393,19 @@ export const BusinessInfo = ( {
|
|||
{ emailMarketingExperimentAssignment === 'treatment' && (
|
||||
<>
|
||||
<TextControl
|
||||
className="woocommerce-profiler-business-info-email-adddress"
|
||||
className={ classNames(
|
||||
'woocommerce-profiler-business-info-email-adddress',
|
||||
{ 'is-error': ! isEmailValid }
|
||||
) }
|
||||
onChange={ ( value ) => {
|
||||
if ( ! isEmailValid ) {
|
||||
setDoValidate( true ); // trigger validation as we want to feedback to the user as soon as it becomes valid
|
||||
}
|
||||
setEmailAddress( value );
|
||||
} }
|
||||
onBlur={ () => {
|
||||
setDoValidate( true );
|
||||
} }
|
||||
value={ decodeEntities( storeEmailAddress ) }
|
||||
label={
|
||||
<>
|
||||
|
@ -398,6 +425,15 @@ export const BusinessInfo = ( {
|
|||
'woocommerce'
|
||||
) }
|
||||
/>
|
||||
{ ! isEmailValid && (
|
||||
<FormInputValidation
|
||||
isError
|
||||
text={ __(
|
||||
'This email is not valid.',
|
||||
'woocommerce'
|
||||
) }
|
||||
/>
|
||||
) }
|
||||
<CheckboxControl
|
||||
className="core-profiler__checkbox"
|
||||
label={ __(
|
||||
|
@ -405,7 +441,10 @@ export const BusinessInfo = ( {
|
|||
'woocommerce'
|
||||
) }
|
||||
checked={ isOptInMarketing }
|
||||
onChange={ setIsOptInMarketing }
|
||||
onChange={ ( isChecked ) => {
|
||||
setIsOptInMarketing( isChecked );
|
||||
setDoValidate( isChecked );
|
||||
} }
|
||||
/>
|
||||
</>
|
||||
) }
|
||||
|
@ -419,7 +458,7 @@ export const BusinessInfo = ( {
|
|||
( emailMarketingExperimentAssignment ===
|
||||
'treatment' &&
|
||||
isOptInMarketing &&
|
||||
storeEmailAddress.length === 0 )
|
||||
! isEmailValid )
|
||||
}
|
||||
onClick={ () => {
|
||||
sendEvent( {
|
||||
|
|
|
@ -408,5 +408,138 @@ describe( 'BusinessInfo', () => {
|
|||
} );
|
||||
expect( emailInput ).toHaveValue( 'wordpress@automattic.com' );
|
||||
} );
|
||||
|
||||
it( 'should not show an error for invalid email if isOptInMarketing is false', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'invalid email' );
|
||||
expect(
|
||||
screen.queryByText( /This email is not valid./i )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should validate the email field when isOptInMarketing is true', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const checkbox = screen.getByRole( 'checkbox', {
|
||||
name: /Opt-in to receive tips, discounts, and recommendations from the Woo team directly in your inbox./i,
|
||||
} );
|
||||
userEvent.click( checkbox );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'invalid email' );
|
||||
expect(
|
||||
screen.getByText( /This email is not valid./i )
|
||||
).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should not show an error for invalid email if isOptInMarketing is true and email is valid', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const checkbox = screen.getByRole( 'checkbox', {
|
||||
name: /Opt-in to receive tips, discounts, and recommendations from the Woo team directly in your inbox./i,
|
||||
} );
|
||||
userEvent.click( checkbox );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'valid@email.com' );
|
||||
} );
|
||||
|
||||
it( 'should show an error for invalid email if isOptInMarketing is checked after the invalid email has already been filled out', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
expect(
|
||||
screen.queryByText( /This email is not valid./i )
|
||||
).not.toBeInTheDocument();
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'invalid email' );
|
||||
const checkbox = screen.getByRole( 'checkbox', {
|
||||
name: /Opt-in to receive tips, discounts, and recommendations from the Woo team directly in your inbox./i,
|
||||
} );
|
||||
userEvent.click( checkbox );
|
||||
expect(
|
||||
screen.getByText( /This email is not valid./i )
|
||||
).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should hide the error after the invalid email has been corrected', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const checkbox = screen.getByRole( 'checkbox', {
|
||||
name: /Opt-in to receive tips, discounts, and recommendations from the Woo team directly in your inbox./i,
|
||||
} );
|
||||
userEvent.click( checkbox );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'invalid email' );
|
||||
expect(
|
||||
screen.getByText( /This email is not valid./i )
|
||||
).toBeInTheDocument();
|
||||
userEvent.clear( emailInput );
|
||||
userEvent.type( emailInput, 'valid@email.com' );
|
||||
expect(
|
||||
screen.queryByText( /This email is not valid./i )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should not allow the continue button to be pressed if email is invalid and isOptInMarketing is checked', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const checkbox = screen.getByRole( 'checkbox', {
|
||||
name: /Opt-in to receive tips, discounts, and recommendations from the Woo team directly in your inbox./i,
|
||||
} );
|
||||
userEvent.click( checkbox );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'invalid email' );
|
||||
const continueButton = screen.getByRole( 'button', {
|
||||
name: /Continue/i,
|
||||
} );
|
||||
expect( continueButton ).toBeDisabled();
|
||||
} );
|
||||
|
||||
it( 'should allow the continue button to be pressed if email is invalid and isOptInMarketing is unchecked', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
props.context.onboardingProfile.is_store_country_set = true;
|
||||
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
|
||||
userEvent.type( emailInput, 'invalid email' );
|
||||
const continueButton = screen.getByRole( 'button', {
|
||||
name: /Continue/i,
|
||||
} );
|
||||
screen.debug();
|
||||
expect( continueButton ).not.toBeDisabled();
|
||||
} );
|
||||
|
||||
it( 'should allow the continue button to be pressed if email is valid and isOptInMarketing is checked', () => {
|
||||
props.context.businessInfo.location = 'AW';
|
||||
props.context.onboardingProfile.is_store_country_set = true;
|
||||
render( <BusinessInfo { ...props } /> );
|
||||
const checkbox = screen.getByRole( 'checkbox', {
|
||||
name: /Opt-in to receive tips, discounts, and recommendations from the Woo team directly in your inbox./i,
|
||||
} );
|
||||
userEvent.click( checkbox );
|
||||
const emailInput = screen.getByRole( 'textbox', {
|
||||
name: /Your email address/i,
|
||||
} );
|
||||
userEvent.type( emailInput, 'valid@email.com' );
|
||||
const continueButton = screen.getByRole( 'button', {
|
||||
name: /Continue/i,
|
||||
} );
|
||||
expect( continueButton ).not.toBeDisabled();
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
--color-error: #cc1818; // used by some @automattic/components
|
||||
|
||||
@include breakpoint( '<782px' ) {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
@ -395,7 +397,6 @@
|
|||
}
|
||||
|
||||
// Business Info Page
|
||||
|
||||
.woocommerce-profiler-business-information {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -454,6 +455,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
.woocommerce-profiler-business-info-email-adddress.is-error {
|
||||
& .components-text-control__input {
|
||||
box-shadow: 0 0 0 1px var(--color-error);
|
||||
}
|
||||
}
|
||||
|
||||
.form-input-validation.is-error span svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.woocommerce-profiler-select-control__country-spacer + .woocommerce-profiler-business-info-email-adddress {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"@automattic/explat-client": "^0.0.3",
|
||||
"@automattic/explat-client-react-helpers": "^0.0.4",
|
||||
"@automattic/interpolate-components": "^1.2.0",
|
||||
"@automattic/components": "^2.0.1",
|
||||
"@react-spring/web": "^9.4.3",
|
||||
"@types/wordpress__blocks": "^11.0.7",
|
||||
"@woocommerce/api": "^0.2.0",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fix core profiler email opt in validation
|
728
pnpm-lock.yaml
728
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue