diff --git a/GitView b/GitView index 690282746b8a50666215d24d2bf4c8cb7801b9de..f7225e509f6d0c009ab70f58c906ec2d474caa7e 160000 --- a/GitView +++ b/GitView @@ -1 +1 @@ -Subproject commit 690282746b8a50666215d24d2bf4c8cb7801b9de +Subproject commit f7225e509f6d0c009ab70f58c906ec2d474caa7e diff --git a/README.md b/README.md index 42eeedf713744d1a206ff9cecc7d73bc3aa6582a..6ea8ec1deae14f9f0e381f6b260d714fc136601c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ # sp21-cs242-assignment3 +Description: this repo is for UIUC CS242 SP21's assignment3 + +## Important: +Necessary files are all in /src directory since /GitView is considered as a submodule by git now, please check that folder. + +## Functionalities: +- Giving github's graphQL API endpoint address, user OAuth token, and username, get personal info of this user and rendered it in mobile devices. +- Find other github user's info through following & follower lists and public repo owners. + +## Environment Requirement: +- Windows 7 or above +- Javascript Environment +- React-Native + +## External Resources: +- React Navigation +- Jest + +## Update Notes: +- 3/29: Basic functionalities are completed. +- 3/22: User's personal info pages are completed. + diff --git a/src/App.js b/src/App.js index fdc4270fcbb337f71d1ff06471019d504d6be49c..b9549e13b1a11a9e522a117a95758034c5c75c3f 100644 --- a/src/App.js +++ b/src/App.js @@ -6,7 +6,15 @@ import Loading from './Components/Loading' import Profile from './Components/Profile' import Repo from './Components/Repo' import Unfound from './Components/Unfound' -import DataGenerator from './Components/DataGenerator' +import Users from './Components/Users' +import LoadFollowingScreenModule from './Components/LoadFollowingScreenModule' +import LoadFollowersScreenModule from './Components/LoadFollowersScreenModule' +import LoadProfileScreenModule from './Components/LoadProfileScreenModule' +import LoadRepoScreenModule from './Components/LoadRepoScreenModule' +import Follower from './Components/Followers' +import Following from './Components/Following' + + const Stack = createStackNavigator(); const styles = StyleSheet.create({ @@ -23,6 +31,7 @@ const styles = StyleSheet.create({ function generateData(route, navigation) { const {name, login, avatarUrl, bio, createdAt, email, websiteUrl, repositories} = route.params; const dataFile = {} + dataFile['login'] = login dataFile['navi'] = navigation dataFile['nameContent'] = 'Name: \n' + name dataFile['userNameContent'] = 'UserName\n: ' + login @@ -33,9 +42,9 @@ function generateData(route, navigation) { dataFile['repoCount'] = 'Repository count: ' + repositories['nodes'].length var iconUrl if (avatarUrl != null) { - iconUrl = { uri: avatarUrl } + iconUrl = avatarUrl } else { - iconUrl = require('C:/Coding/cs242-assignment3/GitView/assets/default.png') + iconUrl = "https://png.pngtree.com/element_our/20200610/ourlarge/pngtree-cat-default-avatar-image_2246581.jpg" } dataFile['iconUrl'] = iconUrl return dataFile @@ -44,11 +53,15 @@ function generateData(route, navigation) { /** Home page **/ function HomeScreen({ navigation }) { + const dataJson = require('C:/Coding/cs242-assignment3/env.json') + const myUserName = dataJson['login'] + const data = {} + data['login'] = myUserName return ( <View style={styles.container}> - <ImageBackground source={require('C:/Coding/cs242-assignment3/GitView/assets/ice.jpg')} style={styles.image}> + <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> <View style={styles.viewStyleVertical}> - <Pressable style={styles.pressableStyle} onPress={() => navigation.navigate('LoadingProfile')}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.push('LoadingProfile', data)}> <Text> Start </Text> </Pressable> </View> @@ -67,29 +80,44 @@ function ProfileScreen({ route, navigation }) { /** Repo page **/ function RepoScreen({ route, navigation }) { - const {nodes} = route.params + const user = route.params + const nodes = user['repositories']['nodes'] + const login = user['login'] let cards = []; for (let i = 0; i < nodes.length; i++) { var repoName = 'Repo name: \n' + nodes[i]['name'] + '\n' var repoDescription = 'Repo description: \n' + nodes[i]['description'] + '\n' var repoOwner = 'Repo owner: \n' + nodes[i]['owner']['login'] + '\n' - var nativeID = 'repo#' + i + var key = 'repo#' + i cards.push( - <View style={styles.textBox} nativeID={nativeID}> + <Pressable style={styles.textBox} key={key} Pressable style={styles.textBox} onPress={() => navigation.push('LoadingProfile', {login: nodes[i]['owner']['login']})}> <Text> {repoName} </Text> <Text> {repoDescription} </Text> <Text> {repoOwner} </Text> - </View> + </Pressable> ) } const dataFile = {} dataFile['cards'] = cards dataFile['navi'] = navigation + dataFile['login'] = login return ( <Repo data={dataFile}/> ); } +/** Follower page **/ +function FollowerScreen({ route, navigation }) { + const user = route.params + return Follower(user, navigation) +} + +/** Following page **/ +function FollowingScreen({ route, navigation }) { + const user = route.params + return Following(user, navigation) +} + /** Unfound page **/ function UnfoundScreen({ route, navigation }) { const {errorMsg} = route.params @@ -101,107 +129,69 @@ function UnfoundScreen({ route, navigation }) { ); } -/** Loading Profile page **/ -function LoadProfileScreen({navigation}) { - const dataJson = require('C:/Coding/cs242-assignment3/env.json'); - fetch(dataJson['endPoint'], { - method: 'POST', - headers: { - "Content-Type": "application/json", - "Authorization": dataJson['token'] - }, - body: JSON.stringify({ - query: ` - query { - viewer { - name - login - avatarUrl - bio - createdAt - email - websiteUrl - repositories(last:100, privacy:PUBLIC){ - nodes{ - name - } - } - } - } - ` - }) - }) - .then(res => res.json()) - .then((data)=> { - navigation.navigate('Profile', data['data']['viewer']) - }) - .catch(error => { - console.error('Error:', error) - navigation.navigate('Unfound', {errorMsg: error}) - }) + +/** Loading Profile page **/ +function LoadProfileScreen({route, navigation}) { + const dataJson = require('C:/Coding/cs242-assignment3/env.json') + const {login} = route.params + const endPoint = dataJson['endPoint'] + const token = dataJson['token'] + LoadProfileScreenModule(login, endPoint, token, navigation) return ( <Loading/> ); } /** Loading Repo page **/ -function LoadRepoScreen({navigation}) { - // setTimeout(function(){ - // navigation.navigate('Unfound'); - // }, 1000) - const dataJson = require('C:/Coding/cs242-assignment3/env.json'); - fetch(dataJson['endPoint'], { - method: 'POST', - headers: { - "Content-Type": "application/json", - "Authorization": dataJson['token'] - }, - body: JSON.stringify({ - query: ` - query { - viewer{ - repositories(last:100, privacy:PUBLIC){ - nodes{ - name - owner{ - login - } - description - } - } - } - } - ` - }) - }) - .then(res => res.json()) - // .then((data) => console.log(data['data']['viewer']['repositories']['nodes'])) - // .then((data) => console.log(data)) - .then((data)=> { - navigation.navigate('Repo', data['data']['viewer']['repositories']) - }) - .catch(error => { - console.error('Error:', error) - navigation.navigate('Unfound', {errorMsg: error}) - }) - +function LoadRepoScreen({route, navigation}) { + const dataJson = require('C:/Coding/cs242-assignment3/env.json') + const {login} = route.params + const endPoint = dataJson['endPoint'] + const token = dataJson['token'] + LoadRepoScreenModule(login, endPoint, token, navigation) return ( <Loading/> ); } +/** Loading Followers page **/ +function LoadFollowersScreen({route, navigation}) { + const {login} = route.params + const dataJson = require('C:/Coding/cs242-assignment3/env.json'); + const endPoint = dataJson['endPoint'] + const token = dataJson['token'] + /** Call function in module part to fetch data and send to view part */ + return LoadFollowersScreenModule(login, endPoint, token, navigation) +} + +/** Loading Followings page **/ +function LoadFollowingScreen({route, navigation}) { + const {login} = route.params + const dataJson = require('C:/Coding/cs242-assignment3/env.json'); + const endPoint = dataJson['endPoint'] + const token = dataJson['token'] + /** Call function in module part to fetch data and send to view part */ + return LoadFollowingScreenModule(login, endPoint, token, navigation) + +} + + /** Page loader **/ function App() { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home"> - <Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Github User Info' }}/> - <Stack.Screen name="Profile" component={ProfileScreen} /> - <Stack.Screen name="Repo" component={RepoScreen} options={{ title: 'Repositories' }}/> - <Stack.Screen name="LoadingProfile" component={LoadProfileScreen} /> - <Stack.Screen name="LoadingRepo" component={LoadRepoScreen} /> - <Stack.Screen name="Unfound" component={UnfoundScreen} options={{ title: 'Error' }}/> + <Stack.Screen name='Home' component={HomeScreen} options={{ title: 'Github User Info', animationEnabled: true}}/> + <Stack.Screen name='Profile' component={ProfileScreen} options={{animationEnabled: true}}/> + <Stack.Screen name='Repo' component={RepoScreen} options={{ title: 'Repositories', animationEnabled:true }}/> + <Stack.Screen name="LoadingProfile" component={LoadProfileScreen} options={{animationEnabled: true}} /> + <Stack.Screen name='LoadingRepo' component={LoadRepoScreen} options={{animationEnabled: true}}/> + <Stack.Screen name='Unfound' component={UnfoundScreen} options={{ title: 'Error', animationEnabled:true }}/> + <Stack.Screen name='LoadingFollowers' component={LoadFollowersScreen} options={{animationEnabled: true}}/> + <Stack.Screen name='LoadingFollowing' component={LoadFollowingScreen} options={{animationEnabled: true}}/> + <Stack.Screen name='Followers' component={FollowerScreen} options={{animationEnabled: true}}/> + <Stack.Screen name='Following' component={FollowingScreen} options={{animationEnabled: true}}/> </Stack.Navigator> </NavigationContainer> ); diff --git a/src/Components/Followers.js b/src/Components/Followers.js new file mode 100644 index 0000000000000000000000000000000000000000..778230de48b8a44db0253527f1273c7cce4175a7 --- /dev/null +++ b/src/Components/Followers.js @@ -0,0 +1,56 @@ +import * as React from 'react'; +import { Pressable, View, Text, Image, StyleSheet } from 'react-native'; +import Users from './Users' + +const styles = StyleSheet.create({ + viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, + viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, + pressableStyle : {flex: 1, flexDirection: 'row', justifyContent: 'space-between', backgroundColor:'lavender', paddingHorizontal:20, + paddingVertical:10, borderColor:'thistle', borderWidth:2, borderRadius:5, marginHorizontal: 10, marginTop: 10}, + image: { flex: 1, resizeMode: "cover", justifyContent: "center"}, + container : {flex: 1}, + textBox : {flex: 1, marginTop: 20, backgroundColor:'white', borderColor:'black', borderWidth:2, borderRadius:5, + marginHorizontal: 10, paddingVertical:10, paddingHorizontal: 50, alignItems: 'flex-start'} +}); + +function Followers (user, navigation) { + const nodes = user['followers']['nodes'] + const login = user['login'] + let cards = [] + if (nodes.length === 0) { + cards.push( + <Pressable style={styles.textBox} key={'Nobody'}> + <Text style={{ fontSize: 30 }}> + Oops! Nobody is in this list! + </Text> + </Pressable> + ) + } else { + for (let i = 0; i < nodes.length; i++) { + var name = 'Name: \n' + nodes[i]['name'] + '\n' + var userName = 'Github Username: \n' + nodes[i]['login'] + '\n' + var key = 'user#' + i + var avatarUrl = nodes[i]['avatarUrl'] + cards.push( + <Pressable style={styles.textBox} key={key} onPress={()=>navigation.push('LoadingProfile', {login: nodes[i]['login']})}> + <View style={styles.viewStyleVertical}> + <Image style={{width:90, height:90}} source={{uri: avatarUrl}}/> + </View> + <View style={styles.viewStyleVertical}> + <Text> {name} </Text> + <Text> {userName} </Text> + </View> + </Pressable> + ) + } + } + const dataFile = {} + dataFile['cards'] = cards + dataFile['navi'] = navigation + dataFile['login'] = login + return ( + <Users data={dataFile}/> + ); +} + +export default Followers \ No newline at end of file diff --git a/src/Components/Following.js b/src/Components/Following.js new file mode 100644 index 0000000000000000000000000000000000000000..79a8a9de40ea86651f4385acb106e9cafffe4b8d --- /dev/null +++ b/src/Components/Following.js @@ -0,0 +1,55 @@ +import * as React from 'react'; +import { Pressable, View, Text, Image, StyleSheet } from 'react-native'; +import Users from './Users' + +const styles = StyleSheet.create({ + viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, + viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, + pressableStyle : {flex: 1, flexDirection: 'row', justifyContent: 'space-between', backgroundColor:'lavender', paddingHorizontal:20, + paddingVertical:10, borderColor:'thistle', borderWidth:2, borderRadius:5, marginHorizontal: 10, marginTop: 10}, + image: { flex: 1, resizeMode: "cover", justifyContent: "center"}, + container : {flex: 1}, + textBox : {flex: 1, marginTop: 20, backgroundColor:'white', borderColor:'black', borderWidth:2, borderRadius:5, + marginHorizontal: 10, paddingVertical:10, paddingHorizontal: 50, alignItems: 'flex-start'} +}); + +function Following (user, navigation) { + const nodes = user['following']['nodes'] + const login = user['login'] + let cards = [] + if (nodes.length === 0) { + cards.push( + <Pressable style={styles.textBox} key={'Nobody'}> + <Text style={{ fontSize: 30 }}> + Oops! Nobody is in this list! + </Text> + </Pressable> + ) + } else { + for (let i = 0; i < nodes.length; i++) { + var name = 'Name: \n' + nodes[i]['name'] + '\n' + var userName = 'Github Username: \n' + nodes[i]['login'] + '\n' + var key = 'user#' + i + var avatarUrl = nodes[i]['avatarUrl'] + cards.push( + <Pressable style={styles.textBox} key={key} onPress={()=>navigation.push('LoadingProfile', {login: nodes[i]['login']})}> + <View style={styles.viewStyleVertical}> + <Image style={{width:90, height:90}} source={{uri: avatarUrl}}/> + </View> + <View style={styles.viewStyleVertical}> + <Text> {name} </Text> + <Text> {userName} </Text> + </View> + </Pressable> + ) + } + } + const dataFile = {} + dataFile['cards'] = cards + dataFile['navi'] = navigation + dataFile['login'] = login + return ( + <Users data={dataFile}/> + ); +} +export default Following \ No newline at end of file diff --git a/src/Components/LoadFollowersScreenModule.js b/src/Components/LoadFollowersScreenModule.js new file mode 100644 index 0000000000000000000000000000000000000000..785c471716f01ae9f98253cf442e4d710127ea73 --- /dev/null +++ b/src/Components/LoadFollowersScreenModule.js @@ -0,0 +1,48 @@ +import * as React from 'react'; +import Loading from './Loading' + +/** Module part of followers screen, used to fetch data and send to View part */ +function LoadFollowersScreenModule(login, endPoint, token, navigation) { + fetch(endPoint, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": token + }, + body: JSON.stringify({ + query: ` + query { + user(login:"`+ login +`"){ + login + followers(last:100) { + nodes { + name + login + avatarUrl + } + } + } + } + ` + }) + }) + .then(res => res.json()) + .then((data)=> { + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Error, cannot find the github user by the login username:' + + login + ', maybe this is an organization! \n Also maybe your internet was unstable'}) + } else { + navigation.push('Followers', data['data']['user']) + } + }) + .catch(error => { + navigation.push('Unfound', {errorMsg: 'Error happened' + error}) + }) + + return ( + <Loading/> + ); +} + +export default LoadFollowersScreenModule \ No newline at end of file diff --git a/src/Components/LoadFollowingScreenModule.js b/src/Components/LoadFollowingScreenModule.js new file mode 100644 index 0000000000000000000000000000000000000000..44e863154c21fcfcaa14a5244d00a387b1b8f301 --- /dev/null +++ b/src/Components/LoadFollowingScreenModule.js @@ -0,0 +1,47 @@ +import * as React from 'react'; +import Loading from './Loading' + +/** Module part of following screen, used to fetch data and send to View part */ +function LoadFollowingScreenModule(login, endPoint, token, navigation) { + fetch(endPoint, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": token + }, + body: JSON.stringify({ + query: ` + query { + user(login:"` + login + `"){ + login + following(last:100) { + nodes { + name + login + avatarUrl + } + } + } + } + ` + }) + }) + .then(res => res.json()) + .then((data)=> { + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Error, cannot find the github user by the login username:' + + login + ', maybe this is an organization! \n Also maybe your internet was unstable'}) + } else { + navigation.push('Following', data['data']['user']) + } + }) + .catch(error => { + navigation.push('Unfound', {errorMsg: 'Error happened' + error}) + }) + return ( + <Loading/> + ); +} + +export default LoadFollowingScreenModule; \ No newline at end of file diff --git a/src/Components/LoadProfileScreenModule.js b/src/Components/LoadProfileScreenModule.js new file mode 100644 index 0000000000000000000000000000000000000000..60c63faeaf916ec00b8d13bf994a1b987267d61e --- /dev/null +++ b/src/Components/LoadProfileScreenModule.js @@ -0,0 +1,46 @@ +async function LoadProfileScreenModule(login, endPoint, token, navigation) { + await fetch(endPoint, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": token + }, + body: JSON.stringify({ + query: ` + query { + user(login:"`+ login + `") { + name + login + avatarUrl + bio + createdAt + email + websiteUrl + repositories(last:100, privacy:PUBLIC){ + nodes{ + name + } + } + } + } + ` + }) + }) + .then(res => res.json()) + .then((data)=> { + if (data['data']['user'] === undefined) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Error, cannot find the github user by the login username:' + + login + ', maybe this is an organization!'}) + throw new Error('User Unfound!') + } else { + navigation.push('Profile', data['data']['user']) + } + }) + .catch(error => { + navigation.push('Unfound', {errorMsg: 'Error: ' + error}) + }) + +} + +export default LoadProfileScreenModule; \ No newline at end of file diff --git a/src/Components/LoadRepoScreenModule.js b/src/Components/LoadRepoScreenModule.js new file mode 100644 index 0000000000000000000000000000000000000000..9181ea2758b92337f1cd0e1b9adeb54ab698f125 --- /dev/null +++ b/src/Components/LoadRepoScreenModule.js @@ -0,0 +1,42 @@ +function LoadRepoScreenModule(login, endPoint, token, navigation) { + fetch(endPoint, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": token + }, + body: JSON.stringify({ + query: ` + query { + user(login:"`+login+`"){ + login + repositories(last:100, privacy:PUBLIC){ + nodes{ + name + owner{ + login + } + description + } + } + } + } + ` + }) + }) + .then(res => res.json()) + .then((data)=> { + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!'}) + } else { + navigation.push('Repo', data['data']['user']) + } + }) + .catch(error => { + navigation.push('Unfound', {errorMsg: 'Error: ' + error}) + }) + +} + +export default LoadRepoScreenModule; \ No newline at end of file diff --git a/src/Components/Loading.js b/src/Components/Loading.js index 2e3ee0ca643c90383c19dabe92d37dfea733c5b6..0bc32a329110c07f1754f47b6812010e52230fef 100644 --- a/src/Components/Loading.js +++ b/src/Components/Loading.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Pressable, View, Text, Image, StyleSheet, ImageBackground } from 'react-native'; +import { View, Text, Image, StyleSheet, ImageBackground } from 'react-native'; const styles = StyleSheet.create({ viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, @@ -13,13 +13,13 @@ const styles = StyleSheet.create({ }); const Loading = () => { - const pic = require('C:/Coding/cs242-assignment3/GitView/assets/loading.png') + const pic = "http://simpleicon.com/wp-content/uploads/refresh.png" return ( <View style={styles.container}> - <ImageBackground source={require('C:/Coding/cs242-assignment3/GitView/assets/ice.jpg')} style={styles.image}> + <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> <View style={styles.viewStyleVertical}> <Text style={{ fontSize: 30 }}>Loading......</Text> - <Image source={pic} style={{width: 200, height: 200}}/> + <Image source={{uri: pic}} style={{width: 200, height: 200}}/> </View> </ImageBackground> </View> diff --git a/src/Components/Profile.js b/src/Components/Profile.js index a6d95f8cb944ad07129eea719d39ba64d697e617..ea75c83265a8faeb8938aba46910e4f8e04e2c1d 100644 --- a/src/Components/Profile.js +++ b/src/Components/Profile.js @@ -1,8 +1,6 @@ import * as React from 'react'; import { Pressable, View, Text, Image, StyleSheet, ImageBackground } from 'react-native'; -import { createStackNavigator } from '@react-navigation/stack'; -const Stack = createStackNavigator(); const styles = StyleSheet.create({ viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, @@ -25,18 +23,19 @@ const Profile = (props) => { const createDate = file['createDate'] const repoCount = file['repoCount'] const navigation = file['navi'] + const login = file['login'] return ( <View style={styles.container}> - <ImageBackground source={require('C:/Coding/cs242-assignment3/GitView/assets/ice.jpg')} style={styles.image}> + <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> <View style={styles.viewStyleVertical}> <View style={styles.viewStyleVertical}> - <Image style={{width: 100, height: 100}} source={iconUrl} /> + <Image style={{width: 120, height: 120}} source={{uri: iconUrl}}/> </View> <View style={styles.viewStyleHorizon}> - <Pressable style={styles.pressableStyle}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.push('LoadingFollowers', {login: login})}> <Text> Followers </Text> </Pressable> - <Pressable style={styles.pressableStyle}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.push('LoadingFollowing', {login: login})}> <Text> Followings </Text> </Pressable> </View> @@ -49,7 +48,7 @@ const Profile = (props) => { <Text style={styles.textBox}> {createDate} </Text> </View> <View style={styles.viewStyleVertical} > - <Pressable style={styles.pressableStyle} onPress={() => navigation.navigate('LoadingRepo')}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.push('LoadingRepo', {login: login})}> <Text> {repoCount} </Text> </Pressable> </View> diff --git a/src/Components/Repo.js b/src/Components/Repo.js index 05b44e6cdac3d6bdebb7b1103ff6901330aca894..67038d82876fd27c9036b004c60d26f971b175e2 100644 --- a/src/Components/Repo.js +++ b/src/Components/Repo.js @@ -1,8 +1,7 @@ import * as React from 'react'; import { Pressable, View, Text, Image, StyleSheet, ImageBackground } from 'react-native'; -import { createStackNavigator } from '@react-navigation/stack'; -const Stack = createStackNavigator(); + const styles = StyleSheet.create({ viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, @@ -20,10 +19,13 @@ const Repo = (props) => { const navigation = file['navi'] return ( <View style={styles.container}> - <ImageBackground source={require('C:/Coding/cs242-assignment3/GitView/assets/ice.jpg')} style={styles.image}> + <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> <View style={styles.viewStyleVertical}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.pop(2)}> + <Text> Go to Profile </Text> + </Pressable> {cards} - <Pressable style={styles.pressableStyle} onPress={() => navigation.navigate('Profile')}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.pop(2)}> <Text> Go to Profile </Text> </Pressable> </View> diff --git a/src/Components/Unfound.js b/src/Components/Unfound.js index 1bfc4a9715547d06d58d3e929b91d1fbaeb7b0af..7098417216fafd67fa2c556db95dad12bd03eff9 100644 --- a/src/Components/Unfound.js +++ b/src/Components/Unfound.js @@ -1,8 +1,6 @@ import * as React from 'react'; import { Pressable, View, Text, Image, StyleSheet, ImageBackground } from 'react-native'; -import { createStackNavigator } from '@react-navigation/stack'; -const Stack = createStackNavigator(); const styles = StyleSheet.create({ viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, @@ -19,10 +17,10 @@ const Unfound = (props) => { const navigation = dataFile['navi'] return ( <View style={styles.container}> - <ImageBackground source={require('C:/Coding/cs242-assignment3/GitView/assets/ice.jpg')} style={styles.image}> + <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> <View style={styles.viewStyleVertical}> <Text style={{ fontSize: 30 }}> Error! Check log to see details </Text> - <Image style={{width: 200, height: 200}} source={require('C:/Coding/cs242-assignment3/GitView/assets/warn.png')} /> + <Image style={{width: 200, height: 200}} source={{uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Warning.svg/156px-Warning.svg.png"}} /> <Pressable style={styles.pressableStyle} onPress={() => navigation.navigate('Home')}> <Text> Go back to Home Page </Text> </Pressable> diff --git a/src/Components/Users.js b/src/Components/Users.js new file mode 100644 index 0000000000000000000000000000000000000000..ef70491c7aecd0a33008147caf7b41fd217949e7 --- /dev/null +++ b/src/Components/Users.js @@ -0,0 +1,36 @@ +import * as React from 'react'; +import { Pressable, View, Text, Image, StyleSheet, ImageBackground } from 'react-native'; + +const styles = StyleSheet.create({ + viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, + viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, + pressableStyle : {flex: 1, flexDirection: 'row', justifyContent: 'space-between', backgroundColor:'lavender', paddingHorizontal:20, + paddingVertical:10, borderColor:'thistle', borderWidth:2, borderRadius:5, marginHorizontal: 10, marginTop: 10}, + image: { flex: 1, resizeMode: "cover", justifyContent: "center"}, + container : {flex: 1}, + textBox : {flex: 1, marginTop: 20, backgroundColor:'white', borderColor:'black', borderWidth:2, borderRadius:5, + marginHorizontal: 10, paddingVertical:10, paddingHorizontal: 50, alignItems: 'flex-start'} +}); + +const Users = (props) => { + const file = props.data + const cards = file['cards'] + const navigation = file['navi'] + return ( + <View style={styles.container}> + <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> + <View style={styles.viewStyleVertical}> + <Pressable style={styles.pressableStyle} onPress={() => navigation.pop(2)}> + <Text> Go to Profile </Text> + </Pressable> + {cards} + <Pressable style={styles.pressableStyle} onPress={() => navigation.pop(2)}> + <Text> Go to Profile </Text> + </Pressable> + </View> + </ImageBackground> + </View> + ) +} + +export default Users; diff --git a/src/__tests__/App-test.js b/src/__tests__/App-test.js index 79c4721138f1ec19a2b1b602a773699cfb9b03c3..f76ba57cd62705017283b8ab20564cc5bb013a92 100644 --- a/src/__tests__/App-test.js +++ b/src/__tests__/App-test.js @@ -11,6 +11,7 @@ import Unfound from '../Components/Unfound'; const Stack = createStackNavigator(); +/** Testing all loading pages */ test('renders correctly', () => { const tree = renderer.create( <Loading /> @@ -36,6 +37,7 @@ test('renders correctly', () => { expect(tree).toMatchSnapshot(); }); + /** Testing repo pages */ test('renders correctly', ({navigation}) => { const dataFile = { iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", @@ -54,6 +56,28 @@ test('renders correctly', () => { expect(tree).toMatchSnapshot(); }); + + /** Testing all Users pages (Followers and Following) */ + test('renders correctly', ({navigation}) => { + const dataFile = { + iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + nameContent: null, + userNameContent: null, + bioContent: null, + websiteLink: null, + emailContent: null, + createData: null, + repoCount: 0, + navi: navigation + } + const tree = renderer.create( + <Users data={dataFile}/> + ).toJSON(); + expect(tree).toMatchSnapshot(); + }); + + + /** Testing unfound/error pages */ test('renders correctly', ({navigation}) => { const dataFile = { navi: navigation diff --git a/src/__tests__/Button-test.js b/src/__tests__/Button-test.js new file mode 100644 index 0000000000000000000000000000000000000000..911bf835dc0e46802106755f18d84b1c0633a61a --- /dev/null +++ b/src/__tests__/Button-test.js @@ -0,0 +1,59 @@ +import * as React from 'react'; +import { View, Text, Pressable, StyleSheet } from 'react-native'; +import { render, fireEvent } from '@testing-library/react-native'; +import Profile from '../Components/Profile' + +const styles = StyleSheet.create({ + viewStyleVertical : { alignItems: 'center', justifyContent: 'center', margin: '10%' }, + viewStyleHorizon : { flex: 1, flexDirection: 'row', justifyContent: 'space-between'}, + pressableStyle : {flex: 1, flexDirection: 'row', justifyContent: 'space-between', backgroundColor:'lavender', paddingHorizontal:20, + paddingVertical:10, borderColor:'thistle', borderWidth:2, borderRadius:5, marginHorizontal: 10, marginTop: 10}, + image: { flex: 1, resizeMode: "cover", justifyContent: "center"}, + container : {flex: 1}, + textBox : {flex: 1, marginTop: 20, backgroundColor:'white', borderColor:'black', borderWidth:2, borderRadius:5, + marginHorizontal: 10, paddingVertical:10, paddingHorizontal: 50, alignItems: 'flex-start'} +}); + +test('Followers button should trigger navigating', () => { + const push = jest.fn() + const dataFile = { + iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + nameContent: null, + userNameContent: null, + bioContent: null, + websiteLink: null, + emailContent: null, + createData: null, + repoCount: 0, + navi: {push}, + login: "test1" + } + const { getByText } = render( + <Profile data={dataFile} /> + ); + + fireEvent.press(getByText(' Followers ')); + expect(push).toHaveBeenNthCalledWith(1, "LoadingFollowers" ,{"login": "test1"}); +}) + +test('Following button should trigger navigating', () => { + const push = jest.fn() + const dataFile = { + iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + nameContent: null, + userNameContent: null, + bioContent: null, + websiteLink: null, + emailContent: null, + createData: null, + repoCount: 0, + navi: {push}, + login: "test2" + } + const { getByText } = render( + <Profile data={dataFile} /> + ); + + fireEvent.press(getByText(' Followings ')); + expect(push).toHaveBeenNthCalledWith(1, "LoadingFollowing", {"login": "test2"}); +}) \ No newline at end of file diff --git a/src/__tests__/ErrorInFollowers-test.js b/src/__tests__/ErrorInFollowers-test.js new file mode 100644 index 0000000000000000000000000000000000000000..99798c514a5b402cdc4429c20017fd33662444c5 --- /dev/null +++ b/src/__tests__/ErrorInFollowers-test.js @@ -0,0 +1,57 @@ +import 'react-native'; +import renderer from 'react-test-renderer'; +import LoadFollowersScreenModule from '../Components/LoadFollowersScreenModule' + +beforeEach(() => { + fetch.resetMocks(); +}); + +/** Testing Loading View of Followers with Empty avatarUrl link */ +test('In the case that a user has no avatarUrl, its avatar should be a default one set in main page', () => { + fetch.mockResponseOnce(JSON.stringify({ + data: { + user: { + login: "HenryShan", + followers: { + nodes: [{ + name: "RX-78-2", + login: "G plan", + avatarUrl: null + }] + } + } + } + })); + const login = "HenryShan" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + const tree = renderer.create( + LoadFollowersScreenModule(login, endPoint, token, navigation) + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); + + /** Testing the loading view of followers when the followers value is empty, a textbox should be shown and informing this */ + test('In the case that a user has no avatarUrl, its avatar should be a default one set in main page', () => { + fetch.mockResponseOnce(JSON.stringify({ + data: { + user: { + login: "HenryShan", + followers: { + nodes: [{}] + } + } + } + })); + const login = "HenryShan" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + const tree = renderer.create( + LoadFollowersScreenModule(login, endPoint, token, navigation) + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); \ No newline at end of file diff --git a/src/__tests__/ErrorInProfile-test.js b/src/__tests__/ErrorInProfile-test.js new file mode 100644 index 0000000000000000000000000000000000000000..73e6c32aac50b0eae9cb23050367b691c06705b1 --- /dev/null +++ b/src/__tests__/ErrorInProfile-test.js @@ -0,0 +1,87 @@ +import LoadProfileScreenModule from '../Components/LoadProfileScreenModule' +import 'react-native'; + +beforeEach(() => { + fetch.resetMocks(); + }); + + +/** Testing the case when the username/login is not a person but other thing like an org */ +test('expect throwing error', () => { + + fetch.mockResponseOnce(JSON.stringify({ + "data": { + "user": null + }, + "errors": [ + { + "type": "NOT_FOUND", + "path": [ + "user" + ], + "locations": [ + { + "line": 32, + "column": 3 + } + ], + "message": "Could not resolve to a User with the login of '???'." + } + ] + })) + const onResponse = jest.fn(); + const onError = jest.fn(); + const login = "???" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + return LoadProfileScreenModule(login, endPoint, token, navigation) + .then(onResponse) + .catch(onError) + .finally(() => { + // since in this situation, return value still contains data PKT thus still get in response state + expect(onResponse).toHaveBeenCalled(); + expect(onError).not.toHaveBeenCalled(); + }); + }, 70000); + + /** Testing the case when the Internet is down and loading Profile should return the error page and throw error*/ +test('expect throwing error', () => { + + fetch.mockResponseOnce(JSON.stringify({ + "data": { + "user": null + }, + "errors": [ + { + "type": "INTERNET_DOWN", + "path": [ + "user" + ], + "locations": [ + { + "line": 32, + "column": 3 + } + ], + "message": "Cannot connect to graphQL API server." + } + ] + })) + const onResponse = jest.fn(); + const onError = jest.fn(); + const login = 'HenryShan' + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + return LoadProfileScreenModule(login, endPoint, token, navigation) + .then(onResponse) + .catch(onError) + .finally(() => { + // since in this situation, return value still contains data PKT thus still get in response + expect(onResponse).toHaveBeenCalled(); + expect(onError).not.toHaveBeenCalled(); + }); + }, 70000); diff --git a/src/__tests__/FollowerScreen-test.js b/src/__tests__/FollowerScreen-test.js new file mode 100644 index 0000000000000000000000000000000000000000..0d419e7624700ea96646b3dd70a005694e6a6a4b --- /dev/null +++ b/src/__tests__/FollowerScreen-test.js @@ -0,0 +1,74 @@ +import 'react-native'; +import Followers from '../Components/Followers' +import renderer from 'react-test-renderer'; + +beforeEach(() => { + fetch.resetMocks(); + }); + +test('renders correctly', () => { + fetch.mockResponseOnce(JSON.stringify({ + data: { + user: { + login: "HenryShan", + followers: { + nodes: [{ + name: "RX-78-2", + login: "G plan", + avatarUrl: "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/7b10552b-57d8-42a7-8dba-d4aaad8e7c82/" + + "d7p3uno-38b831f7-4933-4f09-b366-b951231e1751.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ" + +"1cm46YXBwOiIsImlzcyI6InVybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvN2IxMDU1MmItNTdkOC00MmE3LThkYmEtZDRhYWFk" + +"OGU3YzgyXC9kN3AzdW5vLTM4YjgzMWY3LTQ5MzMtNGYwOS1iMzY2LWI5NTEyMzFlMTc1MS5qcGcifV1dLCJhdWQiOlsidXJuOnNlcnZpY2" + +"U6ZmlsZS5kb3dubG9hZCJdfQ.PsPJAzWqHC1z07YMdxE4zYtFuUMXCtEMMI6VRr7Hq-k" + }] + } + } + } + })); + const login = "HenryShan" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + fetch(endPoint, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": token + }, + body: JSON.stringify({ + query: ` + query { + user(login:"`+ login +`"){ + login + followers(last:100) { + nodes { + name + login + avatarUrl + } + } + } + } + ` + }) + }) + .then(res => res.json()) + .then((data)=> { + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Error, cannot find the github user by the login username:' + login + ', maybe this is an organization! \n Also maybe your internet was unstable'}) + } else { + // navigation.push('Followers', data['data']['user']) + const tree = renderer.create( + Followers(data['data']['user'], navigation) + ).toJSON(); + expect(tree).toMatchSnapshot(); + } + }) + .catch(error => { + navigation.push('Unfound', {errorMsg: 'Error:' + error}) + }) + + + }, 70000); \ No newline at end of file diff --git a/src/__tests__/FollowingScreen-test.js b/src/__tests__/FollowingScreen-test.js new file mode 100644 index 0000000000000000000000000000000000000000..082581bb528b2c96aaead6876e9205b778687878 --- /dev/null +++ b/src/__tests__/FollowingScreen-test.js @@ -0,0 +1,74 @@ +import 'react-native'; +import renderer from 'react-test-renderer'; +import Following from '../Components/Following'; + +beforeEach(() => { + fetch.resetMocks(); + }); + +test('renders correctly', () => { + fetch.mockResponseOnce(JSON.stringify({ + data: { + user: { + login: "HenryShan", + following: { + nodes: [{ + name: "RX-78-2", + login: "G plan", + avatarUrl: "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/7b10552b-57d8-42a7-8dba-d4aaad8e7c82/" + + "d7p3uno-38b831f7-4933-4f09-b366-b951231e1751.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ" + +"1cm46YXBwOiIsImlzcyI6InVybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvN2IxMDU1MmItNTdkOC00MmE3LThkYmEtZDRhYWFk" + +"OGU3YzgyXC9kN3AzdW5vLTM4YjgzMWY3LTQ5MzMtNGYwOS1iMzY2LWI5NTEyMzFlMTc1MS5qcGcifV1dLCJhdWQiOlsidXJuOnNlcnZpY2" + +"U6ZmlsZS5kb3dubG9hZCJdfQ.PsPJAzWqHC1z07YMdxE4zYtFuUMXCtEMMI6VRr7Hq-k" + }] + } + } + } + })); + const login = "HenryShan" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + fetch(endPoint, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": token + }, + body: JSON.stringify({ + query: ` + query { + user(login:"`+ login +`"){ + login + followers(last:100) { + nodes { + name + login + avatarUrl + } + } + } + } + ` + }) + }) + .then(res => res.json()) + .then((data)=> { + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Error, cannot find the github user by the login username:' + login + ', maybe this is an organization! \n Also maybe your internet was unstable'}) + } else { + // navigation.push('Followers', data['data']['user']) + const tree = renderer.create( + Following(data['data']['user'], navigation) + ).toJSON(); + expect(tree).toMatchSnapshot(); + } + }) + .catch(error => { + navigation.push('Unfound', {errorMsg: 'Error: ' + error}) + }) + + + }, 70000); \ No newline at end of file diff --git a/src/__tests__/Loading-test.js b/src/__tests__/Loading-test.js new file mode 100644 index 0000000000000000000000000000000000000000..2fee5fda49d218c9ab5c3c562bd68030b8d83b45 --- /dev/null +++ b/src/__tests__/Loading-test.js @@ -0,0 +1,17 @@ +import 'react-native'; +import React from 'react'; +import renderer from 'react-test-renderer'; +import Loading from '../Components/Loading'; +import { createStackNavigator } from '@react-navigation/stack'; + +beforeEach(() => { + fetch.resetMocks(); + }); + +/** Testing all loading pages */ +test('renders correctly', () => { + const tree = renderer.create( + <Loading /> + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); \ No newline at end of file diff --git a/src/__tests__/LoadingFollowersScreen-test.js b/src/__tests__/LoadingFollowersScreen-test.js new file mode 100644 index 0000000000000000000000000000000000000000..2b18f62b4164bf89f81988888e2b07a17628f1be --- /dev/null +++ b/src/__tests__/LoadingFollowersScreen-test.js @@ -0,0 +1,40 @@ +import * as React from 'react'; +import 'react-native'; +import renderer from 'react-test-renderer'; +import LoadFollowersScreenModule from '../Components/LoadFollowersScreenModule' + +beforeEach(() => { + fetch.resetMocks(); +}); + + /** Testing Loading View of Followers */ + test('renders correctly', () => { + fetch.mockResponseOnce(JSON.stringify({ + data: { + user: { + login: "HenryShan", + followers: { + nodes: [{ + name: "RX-78-2", + login: "G plan", + avatarUrl: "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/7b10552b-57d8-42a7-8dba-d4aaad8e7c82/" + + "d7p3uno-38b831f7-4933-4f09-b366-b951231e1751.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ" + +"1cm46YXBwOiIsImlzcyI6InVybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvN2IxMDU1MmItNTdkOC00MmE3LThkYmEtZDRhYWFk" + +"OGU3YzgyXC9kN3AzdW5vLTM4YjgzMWY3LTQ5MzMtNGYwOS1iMzY2LWI5NTEyMzFlMTc1MS5qcGcifV1dLCJhdWQiOlsidXJuOnNlcnZpY2" + +"U6ZmlsZS5kb3dubG9hZCJdfQ.PsPJAzWqHC1z07YMdxE4zYtFuUMXCtEMMI6VRr7Hq-k" + }] + } + } + } + })); + const login = "HenryShan" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const push = jest.fn(); + const tree = renderer.create( + LoadFollowersScreenModule(login, endPoint, token, {push}) + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); + diff --git a/src/__tests__/LoadingFollowingScreen-test.js b/src/__tests__/LoadingFollowingScreen-test.js new file mode 100644 index 0000000000000000000000000000000000000000..6abcee1d7398fa16868bba68f12b594e47dc20a7 --- /dev/null +++ b/src/__tests__/LoadingFollowingScreen-test.js @@ -0,0 +1,39 @@ +import 'react-native'; +import renderer from 'react-test-renderer'; +import LoadFollowingScreenModule from '../Components/LoadFollowingScreenModule' + +beforeEach(() => { + fetch.resetMocks(); + }); + + /** Testing Loading View for Following */ + test('renders correctly', () => { + fetch.mockResponseOnce(JSON.stringify({ + data: { + user: { + login: "HenryShan", + following: { + nodes: [{ + name: "RX-78-2", + login: "G plan", + avatarUrl: "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/7b10552b-57d8-42a7-8dba-d4aaad8e7c82/" + + "d7p3uno-38b831f7-4933-4f09-b366-b951231e1751.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ" + +"1cm46YXBwOiIsImlzcyI6InVybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvN2IxMDU1MmItNTdkOC00MmE3LThkYmEtZDRhYWFk" + +"OGU3YzgyXC9kN3AzdW5vLTM4YjgzMWY3LTQ5MzMtNGYwOS1iMzY2LWI5NTEyMzFlMTc1MS5qcGcifV1dLCJhdWQiOlsidXJuOnNlcnZpY2" + +"U6ZmlsZS5kb3dubG9hZCJdfQ.PsPJAzWqHC1z07YMdxE4zYtFuUMXCtEMMI6VRr7Hq-k" + }] + } + } + } + })); + const login = "HenryShan" + const envData = require('C:/Coding/cs242-assignment3/env.json') + const endPoint = envData['endPoint'] + const token = envData['token'] + const navigation = { push: jest.fn() }; + const tree = renderer.create( + LoadFollowingScreenModule(login, endPoint, token, navigation) + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); + \ No newline at end of file diff --git a/src/__tests__/Profile-test.js b/src/__tests__/Profile-test.js new file mode 100644 index 0000000000000000000000000000000000000000..031ed575dcc4e9120a4cf945e1843f8f7f17027a --- /dev/null +++ b/src/__tests__/Profile-test.js @@ -0,0 +1,26 @@ +import 'react-native'; +import React from 'react'; +import Profile from '../Components/Profile'; +import renderer from 'react-test-renderer'; + +beforeEach(() => { + fetch.resetMocks(); + }); + +test('renders correctly', () => { + const dataFile = { + iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + nameContent: null, + userNameContent: null, + bioContent: null, + websiteLink: null, + emailContent: null, + createData: null, + repoCount: 0, + navi: { navigate: jest.fn() } + } + const tree = renderer.create( + <Profile data={dataFile}/> + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); \ No newline at end of file diff --git a/src/__tests__/Repo-test.js b/src/__tests__/Repo-test.js new file mode 100644 index 0000000000000000000000000000000000000000..2ac8c22e0525e2a7a354dd0401ad2e7a00b52df3 --- /dev/null +++ b/src/__tests__/Repo-test.js @@ -0,0 +1,27 @@ +import 'react-native'; +import React from 'react'; +import renderer from 'react-test-renderer'; +import Repo from '../Components/Repo'; + +beforeEach(() => { + fetch.resetMocks(); + }); + + /** Testing repo pages */ + test('renders correctly', () => { + const dataFile = { + iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + nameContent: null, + userNameContent: null, + bioContent: null, + websiteLink: null, + emailContent: null, + createData: null, + repoCount: 0, + navi: { navigate: jest.fn() } + } + const tree = renderer.create( + <Repo data={dataFile}/> + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); diff --git a/src/__tests__/Unfound-test.js b/src/__tests__/Unfound-test.js new file mode 100644 index 0000000000000000000000000000000000000000..70973c30c34ecc9475de082c24ccc3c5715b09f7 --- /dev/null +++ b/src/__tests__/Unfound-test.js @@ -0,0 +1,21 @@ +import 'react-native'; +import React from 'react'; +import renderer from 'react-test-renderer'; +import Unfound from '../Components/Unfound'; + +beforeEach(() => { + fetch.resetMocks(); + }); + + + +/** Testing unfound/error pages */ +test('renders correctly', () => { + const dataFile = { + navi: jest.fn() + } + const tree = renderer.create( + <Unfound data={dataFile}/> + ).toJSON(); + expect(tree).toMatchSnapshot(); +}, 50000); \ No newline at end of file diff --git a/src/__tests__/Users-test.js b/src/__tests__/Users-test.js new file mode 100644 index 0000000000000000000000000000000000000000..2699b836af917af0bbf15031d8e1b2280045cf82 --- /dev/null +++ b/src/__tests__/Users-test.js @@ -0,0 +1,27 @@ +import 'react-native'; +import React from 'react'; +import renderer from 'react-test-renderer'; +import Users from '../Components/Users' + +beforeEach(() => { + fetch.resetMocks(); +}); + + /** Testing all Users pages (Followers and Following) */ + test('renders correctly', () => { + const dataFile = { + iconUrl: "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + nameContent: null, + userNameContent: null, + bioContent: null, + websiteLink: null, + emailContent: null, + createData: null, + repoCount: 0, + navi: { navigate: jest.fn() } + } + const tree = renderer.create( + <Users data={dataFile}/> + ).toJSON(); + expect(tree).toMatchSnapshot(); + }, 70000); \ No newline at end of file diff --git a/src/__tests__/__snapshots__/App-test.js.snap b/src/__tests__/__snapshots__/App-test.js.snap index 365ee0e77e7228c48f517b3cd3b2f31f19c0011c..3f7171f0878293df658b21b293b334334c5e3353 100644 --- a/src/__tests__/__snapshots__/App-test.js.snap +++ b/src/__tests__/__snapshots__/App-test.js.snap @@ -19,7 +19,88 @@ exports[`renders correctly 1`] = ` } > <Image - source="test-file-stub" + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Loading...... + </Text> + <Image + source={ + Object { + "uri": "http://simpleicon.com/wp-content/uploads/refresh.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + </View> + </View> +</View> +`; + +exports[`renders correctly 2`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } style={ Array [ Object { @@ -56,7 +137,7 @@ exports[`renders correctly 1`] = ` } > <Image - source="test-file-stub" + source="https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4" style={ Object { "height": 100, @@ -164,7 +245,8 @@ exports[`renders correctly 1`] = ` } } > - nameContent + + </Text> <Text style={ @@ -182,7 +264,8 @@ exports[`renders correctly 1`] = ` } } > - userNameContent + + </Text> <Text style={ @@ -200,7 +283,8 @@ exports[`renders correctly 1`] = ` } } > - bioContent + + </Text> <Text style={ @@ -218,7 +302,8 @@ exports[`renders correctly 1`] = ` } } > - websiteLink + + </Text> <Text style={ @@ -236,7 +321,8 @@ exports[`renders correctly 1`] = ` } } > - emailContent + + </Text> <Text style={ @@ -254,7 +340,8 @@ exports[`renders correctly 1`] = ` } } > - createDate + + </Text> </View> <View @@ -295,7 +382,9 @@ exports[`renders correctly 1`] = ` } > <Text> - repoCount + + 0 + </Text> </View> </View> @@ -303,3 +392,231 @@ exports[`renders correctly 1`] = ` </View> </View> `; + +exports[`renders correctly 3`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go to Profile + </Text> + </View> + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go to Profile + </Text> + </View> + </View> + </View> +</View> +`; + +exports[`renders correctly 4`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Error! Check log to see details + </Text> + <Image + source={ + Object { + "uri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Warning.svg/156px-Warning.svg.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go back to Home Page + </Text> + </View> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/ErrorInFollowers-test.js.snap b/src/__tests__/__snapshots__/ErrorInFollowers-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..d557758ba71382e6cbf7ff6697c57a922642b265 --- /dev/null +++ b/src/__tests__/__snapshots__/ErrorInFollowers-test.js.snap @@ -0,0 +1,155 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`In the case that a user has no avatarUrl, its avatar should be a default one set in main page 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Loading...... + </Text> + <Image + source={ + Object { + "uri": "http://simpleicon.com/wp-content/uploads/refresh.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + </View> + </View> +</View> +`; + +exports[`In the case that a user has no avatarUrl, its avatar should be a default one set in main page 2`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Loading...... + </Text> + <Image + source={ + Object { + "uri": "http://simpleicon.com/wp-content/uploads/refresh.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/Loading-test.js.snap b/src/__tests__/__snapshots__/Loading-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..9834e0e3e6003e42a610a233a5517d8418b79fd9 --- /dev/null +++ b/src/__tests__/__snapshots__/Loading-test.js.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Loading...... + </Text> + <Image + source={ + Object { + "uri": "http://simpleicon.com/wp-content/uploads/refresh.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/LoadingFollowersScreen-test.js.snap b/src/__tests__/__snapshots__/LoadingFollowersScreen-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..9834e0e3e6003e42a610a233a5517d8418b79fd9 --- /dev/null +++ b/src/__tests__/__snapshots__/LoadingFollowersScreen-test.js.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Loading...... + </Text> + <Image + source={ + Object { + "uri": "http://simpleicon.com/wp-content/uploads/refresh.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/LoadingFollowingScreen-test.js.snap b/src/__tests__/__snapshots__/LoadingFollowingScreen-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..9834e0e3e6003e42a610a233a5517d8418b79fd9 --- /dev/null +++ b/src/__tests__/__snapshots__/LoadingFollowingScreen-test.js.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Loading...... + </Text> + <Image + source={ + Object { + "uri": "http://simpleicon.com/wp-content/uploads/refresh.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/Profile-test.js.snap b/src/__tests__/__snapshots__/Profile-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..04de496cb694f9729f8ccc0df9daf0e7e1cc5ef1 --- /dev/null +++ b/src/__tests__/__snapshots__/Profile-test.js.snap @@ -0,0 +1,321 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Image + source={ + Object { + "uri": "https://avatars.githubusercontent.com/u/42978932?u=b4a7beb2752bb6059cd13d12ca26d097767abf77&v=4", + } + } + style={ + Object { + "height": 120, + "width": 120, + } + } + /> + </View> + <View + style={ + Object { + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + } + } + > + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Followers + </Text> + </View> + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Followings + </Text> + </View> + </View> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "alignItems": "flex-start", + "backgroundColor": "white", + "borderColor": "black", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "marginHorizontal": 10, + "marginTop": 20, + "paddingHorizontal": 50, + "paddingVertical": 10, + } + } + > + + + </Text> + <Text + style={ + Object { + "alignItems": "flex-start", + "backgroundColor": "white", + "borderColor": "black", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "marginHorizontal": 10, + "marginTop": 20, + "paddingHorizontal": 50, + "paddingVertical": 10, + } + } + > + + + </Text> + <Text + style={ + Object { + "alignItems": "flex-start", + "backgroundColor": "white", + "borderColor": "black", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "marginHorizontal": 10, + "marginTop": 20, + "paddingHorizontal": 50, + "paddingVertical": 10, + } + } + > + + + </Text> + <Text + style={ + Object { + "alignItems": "flex-start", + "backgroundColor": "white", + "borderColor": "black", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "marginHorizontal": 10, + "marginTop": 20, + "paddingHorizontal": 50, + "paddingVertical": 10, + } + } + > + + + </Text> + <Text + style={ + Object { + "alignItems": "flex-start", + "backgroundColor": "white", + "borderColor": "black", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "marginHorizontal": 10, + "marginTop": 20, + "paddingHorizontal": 50, + "paddingVertical": 10, + } + } + > + + + </Text> + <Text + style={ + Object { + "alignItems": "flex-start", + "backgroundColor": "white", + "borderColor": "black", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "marginHorizontal": 10, + "marginTop": 20, + "paddingHorizontal": 50, + "paddingVertical": 10, + } + } + > + + + </Text> + </View> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + + 0 + + </Text> + </View> + </View> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/Repo-test.js.snap b/src/__tests__/__snapshots__/Repo-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..7fc91eb882bea00c5022ea7ba88ca6273e0c28c1 --- /dev/null +++ b/src/__tests__/__snapshots__/Repo-test.js.snap @@ -0,0 +1,120 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go to Profile + </Text> + </View> + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go to Profile + </Text> + </View> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/Unfound-test.js.snap b/src/__tests__/__snapshots__/Unfound-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..7822434371f858c2aba33c54f12302a2833bb4da --- /dev/null +++ b/src/__tests__/__snapshots__/Unfound-test.js.snap @@ -0,0 +1,110 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <Text + style={ + Object { + "fontSize": 30, + } + } + > + Error! Check log to see details + </Text> + <Image + source={ + Object { + "uri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Warning.svg/156px-Warning.svg.png", + } + } + style={ + Object { + "height": 200, + "width": 200, + } + } + /> + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go back to Home Page + </Text> + </View> + </View> + </View> +</View> +`; diff --git a/src/__tests__/__snapshots__/Users-test.js.snap b/src/__tests__/__snapshots__/Users-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..7fc91eb882bea00c5022ea7ba88ca6273e0c28c1 --- /dev/null +++ b/src/__tests__/__snapshots__/Users-test.js.snap @@ -0,0 +1,120 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +<View + style={ + Object { + "flex": 1, + } + } +> + <View + accessibilityIgnoresInvertColors={true} + style={ + Object { + "flex": 1, + "justifyContent": "center", + "resizeMode": "cover", + } + } + > + <Image + source={ + Object { + "uri": "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg", + } + } + style={ + Array [ + Object { + "bottom": 0, + "left": 0, + "position": "absolute", + "right": 0, + "top": 0, + }, + Object { + "height": undefined, + "width": undefined, + }, + undefined, + ] + } + /> + <View + style={ + Object { + "alignItems": "center", + "justifyContent": "center", + "margin": "10%", + } + } + > + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go to Profile + </Text> + </View> + <View + accessible={true} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "backgroundColor": "lavender", + "borderColor": "thistle", + "borderRadius": 5, + "borderWidth": 2, + "flex": 1, + "flexDirection": "row", + "justifyContent": "space-between", + "marginHorizontal": 10, + "marginTop": 10, + "paddingHorizontal": 20, + "paddingVertical": 10, + } + } + > + <Text> + Go to Profile + </Text> + </View> + </View> + </View> +</View> +`; diff --git a/src/package.json b/src/package.json index 87fc242d355b276e01b759058495c5cab6227626..8486e4a12af6c5498242bdd5a5cd55470d8fc1fb 100644 --- a/src/package.json +++ b/src/package.json @@ -9,9 +9,10 @@ "test": "jest" }, "jest": { - "preset": "react-native", + "preset": "jest-expo", + "automock": false, "setupFiles": [ - "./node_modules/react-native-gesture-handler/jestSetup.js" + "./setupJest.js" ], "moduleNameMapper": { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js", @@ -24,6 +25,8 @@ "@react-navigation/stack": "^5.14.3", "expo": "~40.0.0", "expo-status-bar": "~1.0.3", + "jest-expo": "^40.0.2", + "jest-fetch-mock": "^3.0.3", "react": "16.13.1", "react-dom": "16.13.1", "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz", @@ -36,6 +39,7 @@ }, "devDependencies": { "@babel/core": "~7.9.0", + "@testing-library/react-native": "^7.2.0", "jest": "^26.6.3" }, "private": true