Skip to content

Commit

Permalink
feat(sign-up): update password-requirements tests, lint issues
Browse files Browse the repository at this point in the history
  • Loading branch information
jgdev committed Feb 7, 2024
1 parent 684382b commit ca171a6
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 100 deletions.
4 changes: 2 additions & 2 deletions ios/MindloggerMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
4E9EC54929BA279C002F69A5 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4E9EC54629BA279C002F69A5 /* MaterialIcons.ttf */; };
4E9EC54A29BA279C002F69A5 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4E9EC54629BA279C002F69A5 /* MaterialIcons.ttf */; };
4EBCD5B22971514E00D3C04C /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4EBCD5B12971514E00D3C04C /* Foundation.ttf */; };
51A6E1C8BEDF3FA779731DCF /* (null) in Frameworks */ = {isa = PBXBuildFile; };
51A6E1C8BEDF3FA779731DCF /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
877235D0EBDAE5907B848DAB /* libPods-MindloggerMobileCommonPods-MindloggerMobileDev.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C9F67E64152DFD9983278 /* libPods-MindloggerMobileCommonPods-MindloggerMobileDev.a */; };
90CA1E95A0B7D5AEBD875DF2 /* libPods-MindloggerMobileCommonPods-MindloggerMobileStaging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 372995A11045EA25FEF29C24 /* libPods-MindloggerMobileCommonPods-MindloggerMobileStaging.a */; };
Expand Down Expand Up @@ -318,7 +318,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
51A6E1C8BEDF3FA779731DCF /* (null) in Frameworks */,
51A6E1C8BEDF3FA779731DCF /* BuildFile in Frameworks */,
90CA1E95A0B7D5AEBD875DF2 /* libPods-MindloggerMobileCommonPods-MindloggerMobileStaging.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -951,4 +951,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 3fd9f605d2ca061c942789de32928fa0ba430aa8

COCOAPODS: 1.11.3
COCOAPODS: 1.15.0
14 changes: 8 additions & 6 deletions src/features/sign-up/ui/SignUpForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Provider } from 'react-redux';
import renderer from 'react-test-renderer';
import renderer, { act } from 'react-test-renderer';

import ReactQueryProvider from '@app/app/ui/AppProvider/ReactQueryProvider';
import { reduxStore } from '@app/app/ui/AppProvider/ReduxProvider';
Expand Down Expand Up @@ -45,7 +45,7 @@ const FormTestWrapper = ({ children }: { children: React.ReactNode }) => {
);
};

const createTest = ({}: any = {}) => {
const createTest = () => {
const tree = renderer.create(
<FormTestWrapper>
<SignUpForm onLoginSuccess={() => {}} />
Expand All @@ -57,10 +57,12 @@ const createTest = ({}: any = {}) => {

describe('SignUp Form', () => {
it('should render properly', () => {
const { getRequirements } = createTest();
const [minCharacters, noBlankSpaces] = getRequirements();
expect(minCharacters.props.isValid).toBe(false);
expect(noBlankSpaces.props.isValid).toBe(false);
const { tree, instance } = createTest();
act(() => {
/* display password requirements */
instance.findByProps({ name: 'password' }).props.onFocus();
});
expect(tree.toJSON()).toMatchSnapshot();
});

it.todo('should validate password requirements');
Expand Down
90 changes: 48 additions & 42 deletions src/features/sign-up/ui/SignUpForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
/* eslint-disable react-native/no-inline-styles */
import { FC, useCallback, useState } from 'react';
import { FC, useMemo, useState } from 'react';
import { TouchableWithoutFeedback } from 'react-native';

import { FormProvider } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { isTablet } from 'react-native-device-info';

import { executeIfOnline, useAppForm, useFormChanges } from '@app/shared/lib';
import {
executeIfOnline,
useAppForm,
useFormChanges,
colors,
} from '@app/shared/lib';
import { Box, BoxProps, YStack, SubmitButton } from '@shared/ui';
import {
InputField,
Expand All @@ -16,7 +22,6 @@ import { EyeIcon, EyeSlashIcon } from '@shared/ui/icons';

import { SignUpModel } from '../';
import { SignUpFormSchema } from '../validation';
import { TouchableWithoutFeedback } from 'react-native';

type Props = BoxProps & {
onLoginSuccess: () => void;
Expand All @@ -25,6 +30,8 @@ type Props = BoxProps & {
const SignUpForm: FC<Props> = props => {
const { t } = useTranslation();
const [isPasswordHidden, setPasswordHidden] = useState(true);
const [displayPasswordRequirements, setDisplayPasswordRequirements] =
useState(false);

const {
isLoading,
Expand Down Expand Up @@ -52,25 +59,20 @@ const SignUpForm: FC<Props> = props => {
},
});

const passwordRequirements = useCallback(() => {
const passwordHasLength = !!form.getValues().password.length;
const passwordRequirements = useMemo(() => {
const errors = Object.values(
form.formState.errors?.password?.types || {},
).flat();

return [
{
label: 'password_requirements:at_least_characters',
isValid:
form.getValues().password.length > 0 &&
!errors.includes('password_requirements:at_least_characters'),
},
{
label: 'password_requirements:no_blank_spaces',
isValid:
form.getValues().password.length > 0 &&
!errors.includes('password_requirements:no_blank_spaces'),
},
];
}, [form.formState.errors?.password?.types]);
'password_requirements:at_least_characters',
'password_requirements:no_blank_spaces',
].map(key => ({
label: key,
isValid: passwordHasLength && !errors.includes(key),
}));
}, [passwordHasLength, form.formState.errors?.password?.types]);

const ShowPasswordIcon = isPasswordHidden ? EyeSlashIcon : EyeIcon;

Expand Down Expand Up @@ -105,10 +107,12 @@ const SignUpForm: FC<Props> = props => {
<TouchableWithoutFeedback
onPress={() => setPasswordHidden(!isPasswordHidden)}
>
<ShowPasswordIcon size={24} color="#FFFFFF" />
<ShowPasswordIcon size={24} color={colors.white} />
</TouchableWithoutFeedback>
}
hideError
hideError={displayPasswordRequirements || passwordHasLength}
onFocus={() => setDisplayPasswordRequirements(true)}
onBlur={() => setDisplayPasswordRequirements(false)}
/>

{error && (
Expand All @@ -119,29 +123,31 @@ const SignUpForm: FC<Props> = props => {
error={{ message: error?.evaluatedMessage! }}
/>
)}
</YStack>

<PasswordRequirements requirements={passwordRequirements()} />

<SubmitButton
isLoading={isLoading}
onPress={submit}
accessibilityLabel="sign_up-button"
borderRadius={30}
width="100%"
bg="$lighterGrey4"
mt={isTablet() ? 110 : 50}
textProps={{
fontSize: 14,
color: 'black',
}}
buttonStyle={{
alignSelf: 'center',
paddingVertical: isTablet() ? 13 : 16,
}}
>
{t('sign_up_form:sign_up')}
</SubmitButton>
{(displayPasswordRequirements || passwordHasLength) && (
<PasswordRequirements requirements={passwordRequirements} />
)}

<SubmitButton
isLoading={isLoading}
onPress={submit}
accessibilityLabel="sign_up-button"
borderRadius={30}
width="100%"
bg="$lighterGrey4"
mt={isTablet() ? 110 : 50}
textProps={{
fontSize: 14,
color: 'black',
}}
buttonStyle={{
alignSelf: 'center',
paddingVertical: isTablet() ? 13 : 16,
}}
>
{t('sign_up_form:sign_up')}
</SubmitButton>
</YStack>
</FormProvider>
</Box>
);
Expand Down
Loading

0 comments on commit ca171a6

Please sign in to comment.