From cf128d70b4def1dfc0310221f6524fb9e6689732 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 9 Jun 2022 13:45:23 -0400 Subject: [PATCH] Apply new ValidationCheckmark component to Registration --- .../__tests__/registration.test.tsx | 17 +++++ .../features/verification/registration.tsx | 71 ++++++++++++++----- app/soapbox/locales/en.json | 3 + 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/app/soapbox/features/verification/__tests__/registration.test.tsx b/app/soapbox/features/verification/__tests__/registration.test.tsx index ff5da7e97..f82c0dab4 100644 --- a/app/soapbox/features/verification/__tests__/registration.test.tsx +++ b/app/soapbox/features/verification/__tests__/registration.test.tsx @@ -64,4 +64,21 @@ describe('', () => { expect(screen.getByTestId('toast')).toHaveTextContent(/failed to register your account/i); }); }); + + describe('validations', () => { + it('should undisable button with valid password', async() => { + render(); + + expect(screen.getByTestId('button')).toBeDisabled(); + fireEvent.change(screen.getByTestId('password-input'), { target: { value: 'Password' } }); + expect(screen.getByTestId('button')).not.toBeDisabled(); + }); + + it('should disable button with invalid password', async() => { + render(); + + fireEvent.change(screen.getByTestId('password-input'), { target: { value: 'Passwor' } }); + expect(screen.getByTestId('button')).toBeDisabled(); + }); + }); }); diff --git a/app/soapbox/features/verification/registration.tsx b/app/soapbox/features/verification/registration.tsx index 68a4805db..567db8b16 100644 --- a/app/soapbox/features/verification/registration.tsx +++ b/app/soapbox/features/verification/registration.tsx @@ -1,5 +1,4 @@ import { AxiosError } from 'axios'; -import classNames from 'classnames'; import * as React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; @@ -10,7 +9,8 @@ import { fetchInstance } from 'soapbox/actions/instance'; import { startOnboarding } from 'soapbox/actions/onboarding'; import snackbar from 'soapbox/actions/snackbar'; import { createAccount, removeStoredVerification } from 'soapbox/actions/verification'; -import { Button, Form, FormGroup, HStack, Icon, Input, Stack, Text } from 'soapbox/components/ui'; +import { Button, Form, FormGroup, Input, Stack } from 'soapbox/components/ui'; +import ValidationCheckmark from 'soapbox/components/validation-checkmark'; import { useAppSelector } from 'soapbox/hooks'; import { getRedirectUrl } from 'soapbox/utils/redirect'; @@ -27,6 +27,18 @@ const messages = defineMessages({ id: 'registrations.error', defaultMessage: 'Failed to register your account.', }, + minimumCharacters: { + id: 'registration.validation.minimum_characters', + defaultMessage: '8 characters', + }, + capitalLetter: { + id: 'registration.validation.capital_letter', + defaultMessage: '1 capital letter', + }, + lowercaseLetter: { + id: 'registration.validation.lowercase_letter', + defaultMessage: '1 lowercase letter', + }, }); const initialState = { @@ -34,6 +46,19 @@ const initialState = { password: '', }; +const hasUppercaseCharacter = (string: string) => { + for (let i = 0; i < string.length; i++) { + if (string.charAt(i) === string.charAt(i).toUpperCase() && string.charAt(i).match(/[a-z]/i)) { + return true; + } + } + return false; +}; + +const hasLowercaseCharacter = (string: string) => { + return string.toUpperCase() !== string; +}; + const Registration = () => { const dispatch = useDispatch(); const intl = useIntl(); @@ -46,11 +71,13 @@ const Registration = () => { const { username, password } = state; const meetsLengthRequirements = React.useMemo(() => password.length >= 8, [password]); + const meetsCapitalLetterRequirements = React.useMemo(() => hasUppercaseCharacter(password), [password]); + const meetsLowercaseLetterRequirements = React.useMemo(() => hasLowercaseCharacter(password), [password]); + const hasValidPassword = meetsLengthRequirements && meetsCapitalLetterRequirements && meetsLowercaseLetterRequirements; const handleSubmit = React.useCallback((event) => { event.preventDefault(); - // TODO: handle validation errors from Pepe dispatch(createAccount(username, password)) .then(() => dispatch(logIn(intl, username, password))) .then(({ access_token }: any) => dispatch(verifyCredentials(access_token))) @@ -121,26 +148,36 @@ const Registration = () => { value={password} onChange={handleInputChange} required + data-testid='password-input' /> - - - - - 8 characters - + + + + + +
- +
diff --git a/app/soapbox/locales/en.json b/app/soapbox/locales/en.json index 9f3894ac5..d6808069a 100644 --- a/app/soapbox/locales/en.json +++ b/app/soapbox/locales/en.json @@ -833,6 +833,9 @@ "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", "registration.username_unavailable": "Username is already taken.", + "registration.validation.minimum_characters": "8 characters", + "registration.validation.capital_letter": "1 capital letter", + "registration.validation.lowercase_letter": "1 lowercase letter", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now",