From 1166bdaec4b7852d7570ed4a43277dcd38d8e2c0 Mon Sep 17 00:00:00 2001 From: Kamogelo Moeketse Date: Sat, 6 Jul 2024 00:49:57 +0200 Subject: [PATCH] loaders and tests for profile --- .../components/GradientButton.tsx | 25 ++++---- .../components/LoadingGradientButton.tsx | 29 +++++++++ .../__tests__/GradientButton-test.tsx | 30 ++++++++++ .../__tests__/LoadingGradient-test.tsx | 26 ++++++++ frontend/occupi-mobile4/package-lock.json | 6 ++ frontend/occupi-mobile4/package.json | 1 + .../__snapshots__/Onboarding1-test.tsx.snap | 1 + .../__snapshots__/Onboarding2-test.tsx.snap | 1 + .../__snapshots__/Onboarding3-test.tsx.snap | 1 + .../__snapshots__/Welcome-test.tsx.snap | 1 + .../screens/Settings/Profile.tsx | 54 ++++++++++------- .../Settings/__tests__/Profile-test.tsx | 59 +++++++++++++++++++ 12 files changed, 201 insertions(+), 33 deletions(-) create mode 100644 frontend/occupi-mobile4/components/LoadingGradientButton.tsx create mode 100644 frontend/occupi-mobile4/components/__tests__/GradientButton-test.tsx create mode 100644 frontend/occupi-mobile4/components/__tests__/LoadingGradient-test.tsx create mode 100644 frontend/occupi-mobile4/screens/Settings/__tests__/Profile-test.tsx diff --git a/frontend/occupi-mobile4/components/GradientButton.tsx b/frontend/occupi-mobile4/components/GradientButton.tsx index adb1f72b..65ece5cb 100644 --- a/frontend/occupi-mobile4/components/GradientButton.tsx +++ b/frontend/occupi-mobile4/components/GradientButton.tsx @@ -1,22 +1,23 @@ import React from 'react' import { LinearGradient } from 'expo-linear-gradient'; -import { StyleSheet } from 'react-native'; +import { StyleSheet, TouchableOpacity } from 'react-native'; import { Heading } from '@gluestack-ui/themed'; import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen'; const GradientButton = ({ onPress, text }) => { return ( - - - {text} - - + + + {text} + + ) }; diff --git a/frontend/occupi-mobile4/components/LoadingGradientButton.tsx b/frontend/occupi-mobile4/components/LoadingGradientButton.tsx new file mode 100644 index 00000000..356d7b8b --- /dev/null +++ b/frontend/occupi-mobile4/components/LoadingGradientButton.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { LinearGradient } from 'expo-linear-gradient'; +import { ActivityIndicator } from 'react-native'; +import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen'; + +const LoadingGradientButton = () => { + return ( + + + + ); +}; + +export default LoadingGradientButton; diff --git a/frontend/occupi-mobile4/components/__tests__/GradientButton-test.tsx b/frontend/occupi-mobile4/components/__tests__/GradientButton-test.tsx new file mode 100644 index 00000000..8f44a99e --- /dev/null +++ b/frontend/occupi-mobile4/components/__tests__/GradientButton-test.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { render, fireEvent } from '@testing-library/react-native'; +import GradientButton from '../GradientButton'; + +describe('GradientButton', () => { + it('renders correctly with the given text', () => { + const { getByText } = render(); + const buttonText = getByText('Click Me'); + expect(buttonText).toBeTruthy(); + }); + + it('calls the onPress function when pressed', () => { + const onPressMock = jest.fn(); + const { getByText } = render(); + const buttonText = getByText('Click Me'); + fireEvent.press(buttonText); + expect(onPressMock).toHaveBeenCalledTimes(1); + }); + + it('has the correct gradient colors', () => { + const { getByTestId } = render(); + const linearGradient = getByTestId('gradient-button').props; + + // Numeric color values + const expectedColors = [4284566984, 4287032268, 4289920058, 4293849184]; + + expect(linearGradient.colors).toEqual(expectedColors); + expect(linearGradient.locations).toEqual([0.02, 0.31, 0.67, 0.97]); + }); +}); diff --git a/frontend/occupi-mobile4/components/__tests__/LoadingGradient-test.tsx b/frontend/occupi-mobile4/components/__tests__/LoadingGradient-test.tsx new file mode 100644 index 00000000..f4527697 --- /dev/null +++ b/frontend/occupi-mobile4/components/__tests__/LoadingGradient-test.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import LoadingGradientButton from '../LoadingGradientButton'; + +describe('LoadingGradientButton', () => { + it('renders the gradient with the correct colors and locations', () => { + const { getByTestId } = render(); + const linearGradient = getByTestId('gradient-loading-button').props; + + // Numeric color values + const expectedColors = [4284566984, 4287032268, 4289920058, 4293849184]; + + expect(linearGradient.colors).toEqual(expectedColors); + expect(linearGradient.locations).toEqual([0.02, 0.31, 0.67, 0.97]); + }); + + it('renders an ActivityIndicator with the correct properties', () => { + const { getByTestId } = render(); + const activityIndicator = getByTestId('loading-indicator'); + + expect(activityIndicator).toBeTruthy(); + expect(activityIndicator.props.size).toBe('small'); + expect(activityIndicator.props.color).toBe('#000'); + }); +}); + \ No newline at end of file diff --git a/frontend/occupi-mobile4/package-lock.json b/frontend/occupi-mobile4/package-lock.json index ec3f7cea..a77eb560 100644 --- a/frontend/occupi-mobile4/package-lock.json +++ b/frontend/occupi-mobile4/package-lock.json @@ -62,6 +62,7 @@ "react-native-skeleton-content": "^1.0.13", "react-native-svg": "^15.3.0", "react-native-web": "~0.19.10", + "tinycolor2": "^1.6.0", "zod": "^3.23.8" }, "devDependencies": { @@ -21713,6 +21714,11 @@ "xtend": "~4.0.1" } }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/frontend/occupi-mobile4/package.json b/frontend/occupi-mobile4/package.json index fcb0249c..523c4813 100644 --- a/frontend/occupi-mobile4/package.json +++ b/frontend/occupi-mobile4/package.json @@ -72,6 +72,7 @@ "react-native-skeleton-content": "^1.0.13", "react-native-svg": "^15.3.0", "react-native-web": "~0.19.10", + "tinycolor2": "^1.6.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/frontend/occupi-mobile4/screens/Login/__tests__/__snapshots__/Onboarding1-test.tsx.snap b/frontend/occupi-mobile4/screens/Login/__tests__/__snapshots__/Onboarding1-test.tsx.snap index 5f8512fa..63f1dfd5 100644 --- a/frontend/occupi-mobile4/screens/Login/__tests__/__snapshots__/Onboarding1-test.tsx.snap +++ b/frontend/occupi-mobile4/screens/Login/__tests__/__snapshots__/Onboarding1-test.tsx.snap @@ -134,6 +134,7 @@ exports[`Onboarding1 component renders correctly and matches snapshot 1`] = ` "width": 675, } } + testID="gradient-button" > { const [phoneNumber, setPhoneNumber] = useState(''); const [pronouns, setPronouns] = useState(''); const [date, setDate] = useState(''); + const [isLoading, setIsLoading] = useState(false); const [isDatePickerVisible, setDatePickerVisibility] = useState(false); let colorScheme = useColorScheme(); @@ -61,14 +63,14 @@ const Profile = () => { let result = await SecureStore.getItemAsync('UserData'); console.log(result); // setUserDetails(JSON.parse(result).data); - let jsonresult = JSON.parse(result); + let jsonresult = JSON.parse(result | "{}"); // console.log(jsonresult.data.details.name); - setName(String(jsonresult.data.details.name)); - setEmail(String(jsonresult.data.email)); - setEmployeeId(String(jsonresult.data.occupiId)); - setPhoneNumber(String(jsonresult.data.details.contactNo)); - setPronouns(String(jsonresult.data.details.pronouns)); - const dateString = jsonresult.data.details.dob; + setName(String(jsonresult?.data?.details?.name)); + setEmail(String(jsonresult?.data?.email)); + setEmployeeId(String(jsonresult?.data?.occupiId)); + setPhoneNumber(String(jsonresult?.data?.details?.contactNo)); + setPronouns(String(jsonresult?.data?.details?.pronouns)); + const dateString = jsonresult?.data?.details?.dob; const date = new Date(dateString); // Get the day, month, and year @@ -102,15 +104,16 @@ const Profile = () => { const onSave = async () => { const body = { - "email" : email, + "email": email, "details": { - "contactNo": phoneNumber, - "gender": "Male", - "name": name, - "pronouns": pronouns + "contactNo": phoneNumber, + "gender": "Male", + "name": name, + "pronouns": pronouns } }; - console.log(JSON.stringify(body)); + // console.log(JSON.stringify(body)); + setIsLoading(true); try { const response = await fetch('https://dev.occupi.tech/api/update-user', { method: 'PUT', @@ -125,10 +128,14 @@ const Profile = () => { console.log(data); if (response.ok) { console.log(response); + setIsLoading(false); + alert('Details updated successfully'); } else { console.log(data); + setIsLoading(false); } } catch (error) { + setIsLoading(false); console.error('Error:', error); // setResponse('An error occurred'); } @@ -159,7 +166,7 @@ const Profile = () => { router.replace('/settings')} @@ -201,8 +208,8 @@ const Profile = () => { /> Gender - setSelectedGenderIndex(index)}> - + {/* setSelectedGenderIndex(index)}> + { - + */} Email Address { placeholderTextColor={COLORS.gray} onChangeText={setPronouns} /> + {isLoading ? ( + + ) : ( + + ) + } - ); diff --git a/frontend/occupi-mobile4/screens/Settings/__tests__/Profile-test.tsx b/frontend/occupi-mobile4/screens/Settings/__tests__/Profile-test.tsx new file mode 100644 index 00000000..eb0033f8 --- /dev/null +++ b/frontend/occupi-mobile4/screens/Settings/__tests__/Profile-test.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import Profile from '../Profile'; // Adjust the import based on your file structure + +// Mocking SecureStore and router +jest.mock('expo-secure-store', () => ({ + getItemAsync: jest.fn(), + setItemAsync: jest.fn(), +})); + +jest.mock('expo-router', () => ({ + router: () => ({ replace: jest.fn() }), +})); + +describe('Profile Component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the Profile component with initial state', async () => { + // Mock data that would typically come from SecureStore + const mockedData = { + data: { + details: { + name: 'John Doe', + contactNo: '1234567890', + pronouns: 'He/Him', + dob: '1990-01-01T00:00:00Z', // Make sure the format matches your component's expectations + }, + email: 'johndoe@example.com', + occupiId: 'EMP12345', + }, + }; + + // Mock SecureStore getItemAsync to resolve with the mocked data + require('expo-secure-store').getItemAsync.mockResolvedValueOnce(JSON.stringify(mockedData)); + + // Render the component + const { getByText } = render(); + + // Assertions for initial render + expect(getByText('My account')).toBeTruthy(); + expect(getByText('Full name')).toBeTruthy(); + // expect(getByPlaceholderText('Kamogelo Moeket')).toBeTruthy(); // Example: Change to actual initial value + expect(getByText('Date of birth')).toBeTruthy(); + expect(getByText('Gender')).toBeTruthy(); + expect(getByText('Email Address')).toBeTruthy(); + // expect(getByPlaceholderText('johndoe@example.com')).toBeTruthy(); // Example: Change to actual initial value + expect(getByText('Occupi ID')).toBeTruthy(); + // expect(getByPlaceholderText('EMP12345')).toBeTruthy(); // Example: Change to actual initial value + expect(getByText('Cell No')).toBeTruthy(); + expect(getByText('Pronouns (optional)')).toBeTruthy(); + // expect(getByPlaceholderText('He/Him')).toBeTruthy(); // Example: Change to actual initial value + expect(getByText('Save')).toBeTruthy(); // Assuming there's a "Save" button + }); + + // Add more tests as needed for specific UI components +}); +