Skip to content

Commit

Permalink
refactor: refine my profile screen (#114)
Browse files Browse the repository at this point in the history
* refactor: used profileStyles when possible

* refactor: put navigation as property and set up the SectionTab

* test: modified tests to reflect changes

* feat: added React import

* fix: addressed sonar cloud issue
  • Loading branch information
GaelCondeLosada authored Apr 25, 2024
1 parent 3cf38e3 commit 965420d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 103 deletions.
51 changes: 29 additions & 22 deletions __test__/screens/Profile/MyProfileScreen/MyProfileScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
import React from "react"
import { render, fireEvent } from "@testing-library/react-native"
import { MyProfileScreen } from "../../../../screens/Profile/MyProfileScreen/MyProfileScreen"
import { useNavigation } from "@react-navigation/native"

jest.mock("@react-navigation/native", () => ({
useNavigation: jest.fn(),
}))
import { NavigationProp, ParamListBase } from "@react-navigation/native"

const mockNavigation = {
navigate: jest.fn(),
goBack: jest.fn(),
addListener: jest.fn(),
removeListener: jest.fn(),
reset: jest.fn(),
setParams: jest.fn(),
dispatch: jest.fn(),
isFocused: jest.fn(),
canGoBack: jest.fn(),
dangerouslyGetParent: jest.fn(),
dangerouslyGetState: jest.fn()
} as unknown as NavigationProp<ParamListBase>

jest.mock('@react-navigation/native', () => {
return {
...jest.requireActual('@react-navigation/native'),
useNavigation: () => ({
navigate: mockNavigation,
}),
}
})

jest.mock("../../../../components/GeneralProfile/GeneralProfile", () => "GeneralProfile")
jest.mock("../../../../components/ExpandableDescription/ExpandableDescription", () => "ExpandableDescription")
Expand All @@ -17,39 +36,27 @@ global.alert = jest.fn()


describe("MyProfileScreen", () => {
const navigateMock = jest.fn()

beforeEach(() => {
// Setup navigation mock
(useNavigation as jest.Mock).mockReturnValue({
navigate: navigateMock,
})
})

afterEach(() => {
jest.clearAllMocks()
})

it("renders correctly", () => {
const { getByText } = render(<MyProfileScreen />)
const { getByText } = render(<MyProfileScreen navigation={mockNavigation}/>)

expect(getByText("Update")).toBeTruthy()
expect(getByText("QR")).toBeTruthy()
})

it("navigates to update profile when update button is pressed", () => {
const { getByText } = render(<MyProfileScreen />)
const { getByText } = render(<MyProfileScreen navigation={mockNavigation}/>)
const updateButton = getByText("Update")

fireEvent.press(updateButton)
expect(navigateMock).toHaveBeenCalledWith("UpdateProfile")
expect(mockNavigation.navigate).toHaveBeenCalledWith("UpdateProfile")
})

it("navigates to my QR code when QR button is pressed", () => {
const { getByText } = render(<MyProfileScreen />)
const { getByText } = render(<MyProfileScreen navigation={mockNavigation}/>)
const qrButton = getByText("QR")

fireEvent.press(qrButton)
expect(navigateMock).toHaveBeenCalledWith("MyQR")
expect(mockNavigation.navigate).toHaveBeenCalledWith("MyQR")
})
})
62 changes: 32 additions & 30 deletions screens/Profile/MyProfileScreen/MyProfileScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React, { useState } from "react"
import { Text, View, TouchableOpacity } from "react-native"
import { Ionicons } from "@expo/vector-icons"
import ExpandableDescription from "../../../components/ExpandableDescription/ExpandableDescription"
import GeneralProfile from "../../../components/GeneralProfile/GeneralProfile"
import { styles } from "./styles"
import { black } from "../../../assets/colors/colors"
import InputField from "../../../components/InputField/InputField"
import { useState } from "react"
import { useNavigation } from "@react-navigation/native"
import { NavigationProp, ParamListBase } from "@react-navigation/native"
import { profileStyles } from "../profileStyles"
import { styles } from "./styles"
import { globalStyles } from "../../../assets/global/globalStyles"
import SectionTabs from "../../../components/SectionTabs/SectionTabs"
import { ProfileEvents } from "../ProfileEvents/ProfileEvents"
import { ProfileInterests } from "../ProfileInterests/ProfileInterests"

type Contact = {
uid: string
Expand All @@ -31,35 +34,38 @@ const dummyProfile: Contact = {
location: "EPFL Ecublens"
}

export const MyProfileScreen = () => {
const [search, setSearch] = useState("")
const useNav = useNavigation()
interface MyProfileScreenProps{
navigation: NavigationProp<ParamListBase>
}

export const MyProfileScreen = ({navigation} : MyProfileScreenProps) => {
const [selectedTab, setSelectedTab] = useState("Events")

return (
<View style={styles.container}>
<View style={styles.topBackground} />
<View style={styles.profileContainer}>
<View style={profileStyles.topBackground} />
<View style={profileStyles.profileContainer}>

<View style={styles.topProfileContainer}>
<View style={profileStyles.topProfileContainer}>

<GeneralProfile
name={dummyProfile.firstName}
surname={dummyProfile.lastName}
location={dummyProfile.location}
/>

<View style={styles.buttonsContainer}>
<View style={profileStyles.buttonsContainer}>
<TouchableOpacity
style={styles.button}
onPress={() => useNav.navigate("UpdateProfile" as never)}>
<Text style={[globalStyles.boldText, styles.buttonText]}>Update</Text>
style={profileStyles.button}
onPress={() => navigation.navigate("UpdateProfile")}>
<Text style={[globalStyles.boldText, profileStyles.buttonText]}>Update</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => useNav.navigate("MyQR" as never)}>
<View style={styles.horizontalContainer}>
style={profileStyles.button}
onPress={() => navigation.navigate("MyQR")}>
<View style={profileStyles.horizontalContainer}>
<Ionicons name="qr-code" size={14} color={black} />
<Text style={[globalStyles.boldText, styles.buttonText]}>QR</Text>
<Text style={[globalStyles.boldText, profileStyles.buttonText]}>QR</Text>
</View>
</TouchableOpacity>
</View>
Expand All @@ -70,20 +76,16 @@ export const MyProfileScreen = () => {
description={dummyProfile.description}
/>

<View style={styles.separatorLine} />
<SectionTabs
tabs={["Events", "Interests"]}
startingTab="Events"
onTabChange={setSelectedTab}
/>

<View style={styles.horizontalContainer}>
<InputField
label=""
placeholder="Search..."
value={search}
onChangeText={text => setSearch(text)}>
</InputField>
</View>

<View style={styles.container}>
<View style={styles.separatorLine} />

</View>
{selectedTab === "Events" && <ProfileEvents/>}
{selectedTab === "Interests" && <ProfileInterests/>}

</View>
</View>
Expand Down
54 changes: 3 additions & 51 deletions screens/Profile/MyProfileScreen/styles.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,16 @@
import { StyleSheet } from "react-native"
import { black, lightPeach, peach } from "../../../assets/colors/colors"
import { black } from "../../../assets/colors/colors"

export const styles = StyleSheet.create({
button: {
alignItems: "center",
backgroundColor: lightPeach,
borderColor: peach,
borderRadius: 10,
borderWidth: 2,
elevation: 6,
height: "33%",
justifyContent: "center",
width: "45%",
},
buttonText: {
alignItems: "center",
fontSize: 13,
justifyContent: "center",
margin: 1,
},
buttonsContainer: {
alignItems: "center",
flexDirection: "row",
justifyContent: "space-between",
width: "55%",
},
container: {
alignItems: "center",
flex: 1,
justifyContent: "center",
},
horizontalContainer: {
alignItems: "center",
flex: 1,
flexDirection: "row",
justifyContent: "space-between",
},
profileContainer: {
flex: 1,
marginHorizontal: 10,
position: "absolute",
top: 0,
},
separatorLine: {
backgroundColor: black,
height: 1,
marginTop: 5,
width: "auto",
},
topBackground: {
backgroundColor: lightPeach,
height: "20%",
position: "absolute",
top: 0,
width: "100%"
},
topProfileContainer: {
flexDirection: "row",
flex: 1,
marginBottom: 4,
marginTop: "35%",
},

},
})

0 comments on commit 965420d

Please # to comment.