Skip to content

Commit

Permalink
loaders and tests for profile
Browse files Browse the repository at this point in the history
  • Loading branch information
KamogeloMoeketse committed Jul 5, 2024
1 parent 6a74e24 commit 1166bda
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 33 deletions.
25 changes: 13 additions & 12 deletions frontend/occupi-mobile4/components/GradientButton.tsx
Original file line number Diff line number Diff line change
@@ -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';

Check warning on line 3 in frontend/occupi-mobile4/components/GradientButton.tsx

View workflow job for this annotation

GitHub Actions / lint

'TouchableOpacity' is defined but never used
import { Heading } from '@gluestack-ui/themed';
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';

const GradientButton = ({ onPress, text }) => {
return (
<LinearGradient
colors={['#614DC8', '#86EBCC', '#B2FC3A', '#EEF060']}
locations={[0.02, 0.31, 0.67, 0.97]}
start={[0, 1]}
end={[1, 0]}
style={styles.buttonContainer}
>
<Heading style={styles.buttonText} onPress={onPress}>
{text}
</Heading>
</LinearGradient>
<LinearGradient
testID="gradient-button"
colors={['#614DC8', '#86EBCC', '#B2FC3A', '#EEF060']}
locations={[0.02, 0.31, 0.67, 0.97]}
start={[0, 1]}
end={[1, 0]}
style={styles.buttonContainer}
>
<Heading style={styles.buttonText} onPress={onPress}>
{text}
</Heading>
</LinearGradient>
)
};

Expand Down
29 changes: 29 additions & 0 deletions frontend/occupi-mobile4/components/LoadingGradientButton.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<LinearGradient
testID="gradient-loading-button"
colors={['#614DC8', '#86EBCC', '#B2FC3A', '#EEF060']}
locations={[0.02, 0.31, 0.67, 0.97]}
start={[0, 1]}
end={[1, 0]}
style={{
paddingVertical: 15,
alignItems: 'center',
borderRadius: 15,
marginTop: hp('2%'),
width: wp('90%'),
height: hp('6%'),
alignSelf: 'center',
}}
>
<ActivityIndicator testID="loading-indicator" size="small" color="#000" />
</LinearGradient>
);
};

export default LoadingGradientButton;
Original file line number Diff line number Diff line change
@@ -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(<GradientButton text="Click Me" />);
const buttonText = getByText('Click Me');
expect(buttonText).toBeTruthy();
});

it('calls the onPress function when pressed', () => {
const onPressMock = jest.fn();
const { getByText } = render(<GradientButton text="Click Me" onPress={onPressMock} />);
const buttonText = getByText('Click Me');
fireEvent.press(buttonText);
expect(onPressMock).toHaveBeenCalledTimes(1);
});

it('has the correct gradient colors', () => {
const { getByTestId } = render(<GradientButton text="Click Me" />);
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]);
});
});
Original file line number Diff line number Diff line change
@@ -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(<LoadingGradientButton />);
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(<LoadingGradientButton />);
const activityIndicator = getByTestId('loading-indicator');

expect(activityIndicator).toBeTruthy();
expect(activityIndicator.props.size).toBe('small');
expect(activityIndicator.props.color).toBe('#000');
});
});

6 changes: 6 additions & 0 deletions frontend/occupi-mobile4/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/occupi-mobile4/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ exports[`Onboarding1 component renders correctly and matches snapshot 1`] = `
"width": 675,
}
}
testID="gradient-button"
>
<Text
accessibilityRole="header"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ exports[`Onboarding2 component renders correctly and matches snapshot 1`] = `
"width": 675,
}
}
testID="gradient-button"
>
<Text
accessibilityRole="header"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ exports[`Onboarding3 component renders correctly and matches snapshot 1`] = `
"width": 675,
}
}
testID="gradient-button"
>
<Text
accessibilityRole="header"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ exports[`Welcome component renders correctly and matches snapshot 1`] = `
"width": 675,
}
}
testID="gradient-button"
>
<Text
accessibilityRole="header"
Expand Down
54 changes: 33 additions & 21 deletions frontend/occupi-mobile4/screens/Settings/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { router } from 'expo-router';
import { useColorScheme } from 'react-native';
import { heightPercentageToDP as hp } from 'react-native-responsive-screen';
import GradientButton from '@/components/GradientButton';
import LoadingGradientButton from '@/components/LoadingGradientButton';

const COLORS = {
white: '#FFFFFF',
Expand Down Expand Up @@ -53,6 +54,7 @@ const Profile = () => {
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();

Expand All @@ -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
Expand Down Expand Up @@ -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',
Expand All @@ -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');
}
Expand Down Expand Up @@ -159,7 +166,7 @@ const Profile = () => {
<View style={styles.header}>
<Icon
as={Feather}
name="chevron-left"
name={"chevron-left"}
size="xl"
color={colorScheme === 'dark' ? 'white' : 'black'}
onPress={() => router.replace('/settings')}
Expand Down Expand Up @@ -201,8 +208,8 @@ const Profile = () => {
/>

<Text style={colorScheme === 'dark' ? styles.labeldark : styles.labellight}>Gender</Text>
<RadioGroup mb="$4" onChange={(index) => setSelectedGenderIndex(index)}>
<VStack flexDirection="row" justifyContent="space-between" space="$2">
{/* <RadioGroup mb="$4" onChange={(index) => setSelectedGenderIndex(index)}>
<VStack flexDirection="row" justifyContent="space-between" space="sm">
<Radio
backgroundColor={colorScheme === 'dark' ? '#5A5A5A' : '#f2f2f2'}
borderRadius="$xl"
Expand Down Expand Up @@ -240,7 +247,7 @@ const Profile = () => {
</RadioIndicator>
</Radio>
</VStack>
</RadioGroup>
</RadioGroup> */}

<Text style={colorScheme === 'dark' ? styles.labeldark : styles.labellight}>Email Address</Text>
<TextInput
Expand Down Expand Up @@ -275,11 +282,16 @@ const Profile = () => {
placeholderTextColor={COLORS.gray}
onChangeText={setPronouns}
/>
{isLoading ? (
<LoadingGradientButton />
) : (
<GradientButton
onPress={onSave}
text="Save"
/>
)
}

<GradientButton
onPress={onSave}
text="Save"
/>
</ScrollView>
</SafeAreaView>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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: '[email protected]',
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(<Profile />);

// 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('[email protected]')).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
});

0 comments on commit 1166bda

Please sign in to comment.