@@ -25,6 +25,9 @@ import {
2525 FORM_SUBMISSION_ERROR ,
2626} from './data/constants' ;
2727import { registrationErrorSelector , validationsSelector } from './data/selectors' ;
28+ import {
29+ emailRegex , getSuggestionForInvalidEmail , urlRegex , validateCountryField , validateEmailAddress ,
30+ } from './data/utils' ;
2831import messages from './messages' ;
2932import RegistrationFailure from './RegistrationFailure' ;
3033import { EmailField , UsernameField } from './registrationFields' ;
@@ -36,7 +39,7 @@ import {
3639 fieldDescriptionSelector ,
3740} from '../common-components/data/selectors' ;
3841import {
39- DEFAULT_STATE , REDIRECT ,
42+ DEFAULT_STATE , LETTER_REGEX , NUMBER_REGEX , REDIRECT , USERNAME_REGEX ,
4043} from '../data/constants' ;
4144import {
4245 getAllPossibleQueryParams , setCookie ,
@@ -173,16 +176,76 @@ const EmbeddableRegistrationPage = (props) => {
173176 }
174177 } , [ registrationResult , host ] ) ;
175178
176- const validateInput = ( fieldName , value , payload , shouldValidateFromBackend ) => {
179+ const validateInput = ( fieldName , value , payload , shouldValidateFromBackend , shouldSetErrors = true ) => {
180+ let fieldError = '' ;
181+
177182 switch ( fieldName ) {
178- case 'name' :
179- if ( value && ! payload . username . trim ( ) && shouldValidateFromBackend ) {
180- validateFromBackend ( payload ) ;
183+ case 'name' :
184+ if ( value && value . match ( urlRegex ) ) {
185+ fieldError = formatMessage ( messages [ 'name.validation.message' ] ) ;
186+ } else if ( value && ! payload . username . trim ( ) && shouldValidateFromBackend ) {
187+ validateFromBackend ( payload ) ;
188+ }
189+ break ;
190+ case 'email' :
191+ if ( value . length <= 2 ) {
192+ fieldError = formatMessage ( messages [ 'email.invalid.format.error' ] ) ;
193+ } else {
194+ const [ username , domainName ] = value . split ( '@' ) ;
195+ // Check if email address is invalid. If we have a suggestion for invalid email
196+ // provide that along with the error message.
197+ if ( ! emailRegex . test ( value ) ) {
198+ fieldError = formatMessage ( messages [ 'email.invalid.format.error' ] ) ;
199+ setEmailSuggestion ( {
200+ suggestion : getSuggestionForInvalidEmail ( domainName , username ) ,
201+ type : 'error' ,
202+ } ) ;
203+ } else {
204+ const response = validateEmailAddress ( value , username , domainName ) ;
205+ if ( response . hasError ) {
206+ fieldError = formatMessage ( messages [ 'email.invalid.format.error' ] ) ;
207+ delete response . hasError ;
208+ }
209+ setEmailSuggestion ( { ...response } ) ;
181210 }
182- break ;
183- default :
184- break ;
211+ }
212+ break ;
213+ case 'username' :
214+ if ( ! value . match ( USERNAME_REGEX ) ) {
215+ fieldError = formatMessage ( messages [ 'username.format.validation.message' ] ) ;
216+ }
217+ break ;
218+ case 'password' :
219+ if ( ! value || ! LETTER_REGEX . test ( value ) || ! NUMBER_REGEX . test ( value ) || value . length < 8 ) {
220+ fieldError = formatMessage ( messages [ 'password.validation.message' ] ) ;
221+ }
222+ break ;
223+ case 'country' :
224+ if ( flags . showConfigurableEdxFields || flags . showConfigurableRegistrationFields ) {
225+ const {
226+ countryCode, displayValue, error,
227+ } = validateCountryField ( value . trim ( ) , countryList , formatMessage ( messages [ 'empty.country.field.error' ] ) ) ;
228+ fieldError = error ;
229+ setConfigurableFormFields ( prevState => ( { ...prevState , country : { countryCode, displayValue } } ) ) ;
230+ }
231+ break ;
232+ default :
233+ if ( flags . showConfigurableRegistrationFields ) {
234+ if ( ! value && fieldDescriptions [ fieldName ] ?. error_message ) {
235+ fieldError = fieldDescriptions [ fieldName ] . error_message ;
236+ } else if ( fieldName === 'confirm_email' && formFields . email && value !== formFields . email ) {
237+ fieldError = formatMessage ( messages [ 'email.do.not.match' ] ) ;
238+ }
239+ }
240+ break ;
185241 }
242+ if ( shouldSetErrors && fieldError ) {
243+ setErrors ( prevErrors => ( {
244+ ...prevErrors ,
245+ [ fieldName ] : fieldError ,
246+ } ) ) ;
247+ }
248+ return fieldError ;
186249 } ;
187250
188251 const isFormValid = ( payload ) => {
@@ -226,6 +289,10 @@ const EmbeddableRegistrationPage = (props) => {
226289 event . preventDefault ( ) ;
227290 setErrors ( prevErrors => ( { ...prevErrors , [ fieldName ] : '' } ) ) ;
228291 switch ( fieldName ) {
292+ case 'email' :
293+ setFormFields ( prevState => ( { ...prevState , email : emailSuggestion . suggestion } ) ) ;
294+ setEmailSuggestion ( { suggestion : '' , type : '' } ) ;
295+ break ;
229296 case 'username' :
230297 setFormFields ( prevState => ( { ...prevState , username : suggestion } ) ) ;
231298 props . resetUsernameSuggestions ( ) ;
@@ -267,8 +334,12 @@ const EmbeddableRegistrationPage = (props) => {
267334 value ,
268335 { name : formFields . name , username : formFields . username , form_field_key : name } ,
269336 ! validationApiRateLimited ,
337+ false ,
270338 ) ;
271339 }
340+ if ( name === 'email' ) {
341+ validateInput ( name , value , null , ! validationApiRateLimited , false ) ;
342+ }
272343 } ;
273344
274345 const handleOnFocus = ( event ) => {
@@ -294,7 +365,6 @@ const EmbeddableRegistrationPage = (props) => {
294365 e . preventDefault ( ) ;
295366 const totalRegistrationTime = ( Date . now ( ) - formStartTime ) / 1000 ;
296367 let payload = { ...formFields } ;
297-
298368 if ( ! isFormValid ( payload ) ) {
299369 setErrorCode ( prevState => ( { type : FORM_SUBMISSION_ERROR , count : prevState . count + 1 } ) ) ;
300370 return ;
@@ -307,12 +377,20 @@ const EmbeddableRegistrationPage = (props) => {
307377 payload [ fieldName ] = configurableFormFields [ fieldName ] ;
308378 }
309379 } ) ;
310-
311380 // Don't send the marketing email opt-in value if the flag is turned off
312381 if ( ! flags . showMarketingEmailOptInCheckbox ) {
313382 delete payload . marketingEmailsOptIn ;
314383 }
315-
384+ let isValid = true ;
385+ Object . entries ( payload ) . forEach ( ( [ key , value ] ) => {
386+ if ( validateInput ( key , value , payload , false , true ) !== '' ) {
387+ isValid = false ;
388+ }
389+ } ) ;
390+ if ( ! isValid ) {
391+ setErrorCode ( prevState => ( { type : FORM_SUBMISSION_ERROR , count : prevState . count + 1 } ) ) ;
392+ return ;
393+ }
316394 payload = snakeCaseObject ( payload ) ;
317395 payload . totalRegistrationTime = totalRegistrationTime ;
318396
@@ -350,6 +428,7 @@ const EmbeddableRegistrationPage = (props) => {
350428 handleChange = { handleOnChange }
351429 handleBlur = { handleOnBlur }
352430 handleFocus = { handleOnFocus }
431+ handleSuggestionClick = { ( e ) => handleSuggestionClick ( e , 'email' ) }
353432 handleOnClose = { handleEmailSuggestionClosed }
354433 emailSuggestion = { emailSuggestion }
355434 errorMessage = { errors . email }
0 commit comments