From 044cbe07f99ee13ddbc46ee957ae24fc48961165 Mon Sep 17 00:00:00 2001 From: HenryShan <zshan2@illinois.edu> Date: Mon, 29 Mar 2021 23:38:34 +0800 Subject: [PATCH 1/4] assignment3.1 ver2.0: all functionalities are implemented, going for testing --- README.md | 19 ++ src/App.js | 257 ++++++++++++-- src/Components/Loading.js | 6 +- src/Components/Profile.js | 11 +- src/Components/Repo.js | 8 +- src/Components/Unfound.js | 4 +- src/__tests__/App-test.js | 24 ++ src/__tests__/__snapshots__/App-test.js.snap | 335 ++++++++++++++++++- 8 files changed, 617 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 42eeedf..7ab5a6a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ # sp21-cs242-assignment3 +Description: this repo is for UIUC CS242 SP21's assignment3 + +## 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 fdc4270..32ca65a 100644 --- a/src/App.js +++ b/src/App.js @@ -6,6 +6,7 @@ import Loading from './Components/Loading' import Profile from './Components/Profile' import Repo from './Components/Repo' import Unfound from './Components/Unfound' +import Users from './Components/Users' import DataGenerator from './Components/DataGenerator' const Stack = createStackNavigator(); @@ -23,6 +24,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 @@ -44,11 +46,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 +73,117 @@ 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 + 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 + console.log(login) + return ( + <Users data={dataFile}/> + ); +} + +/** Following page **/ +function FollowingScreen({ route, navigation }) { + const user = route.params + 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}/> + ); +} + /** Unfound page **/ function UnfoundScreen({ route, navigation }) { const {errorMsg} = route.params @@ -101,9 +195,12 @@ function UnfoundScreen({ route, navigation }) { ); } + + /** Loading Profile page **/ -function LoadProfileScreen({navigation}) { - const dataJson = require('C:/Coding/cs242-assignment3/env.json'); +function LoadProfileScreen({route, navigation}) { + const dataJson = require('C:/Coding/cs242-assignment3/env.json') + const {login} = route.params fetch(dataJson['endPoint'], { method: 'POST', headers: { @@ -113,7 +210,7 @@ function LoadProfileScreen({navigation}) { body: JSON.stringify({ query: ` query { - viewer { + user(login:"`+ login + `") { name login avatarUrl @@ -133,11 +230,17 @@ function LoadProfileScreen({navigation}) { }) .then(res => res.json()) .then((data)=> { - navigation.navigate('Profile', data['data']['viewer']) + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Wrong!'}) + console.log('Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!') + } else { + navigation.push('Profile', data['data']['user']) + } }) .catch(error => { console.error('Error:', error) - navigation.navigate('Unfound', {errorMsg: error}) + navigation.push('Unfound', {errorMsg: error}) }) return ( @@ -146,10 +249,8 @@ function LoadProfileScreen({navigation}) { } /** Loading Repo page **/ -function LoadRepoScreen({navigation}) { - // setTimeout(function(){ - // navigation.navigate('Unfound'); - // }, 1000) +function LoadRepoScreen({route, navigation}) { + const {login} = route.params const dataJson = require('C:/Coding/cs242-assignment3/env.json'); fetch(dataJson['endPoint'], { method: 'POST', @@ -160,7 +261,8 @@ function LoadRepoScreen({navigation}) { body: JSON.stringify({ query: ` query { - viewer{ + user(login:"`+login+`"){ + login repositories(last:100, privacy:PUBLIC){ nodes{ name @@ -176,14 +278,65 @@ function LoadRepoScreen({navigation}) { }) }) .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']) + if (data['data']['user'] === null) { + /** User not found! **/ + navigation.push('Unfound', {errorMsg: 'Wrong!'}) + console.log('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 => { + console.error('Error:', error) + navigation.push('Unfound', {errorMsg: error}) + }) + + return ( + <Loading/> + ); +} + +/** Loading Followers page **/ +function LoadFollowersScreen({route, navigation}) { + const {login} = route.params + 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 { + 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: 'Wrong!'}) + console.log('Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!') + } else { + navigation.push('Followers', data['data']['user']) + } }) .catch(error => { console.error('Error:', error) - navigation.navigate('Unfound', {errorMsg: error}) + navigation.push('Unfound', {errorMsg: error}) }) return ( @@ -191,17 +344,69 @@ function LoadRepoScreen({navigation}) { ); } +/** Loading Followings page **/ +function LoadFollowingScreen({route, navigation}) { + const {login} = route.params + 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 { + 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: 'Wrong!'}) + console.log('Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!') + } else { + navigation.push('Following', data['data']['user']) + } + }) + .catch(error => { + console.error('Error:', error) + navigation.push('Unfound', {errorMsg: error}) + }) + + return ( + <Loading/> + ); +} + + /** 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/Loading.js b/src/Components/Loading.js index 2e3ee0c..694ff72 100644 --- a/src/Components/Loading.js +++ b/src/Components/Loading.js @@ -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 a6d95f8..2856a2d 100644 --- a/src/Components/Profile.js +++ b/src/Components/Profile.js @@ -25,18 +25,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: 100, height: 100}} 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 +50,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 05b44e6..811276f 100644 --- a/src/Components/Repo.js +++ b/src/Components/Repo.js @@ -18,12 +18,16 @@ const Repo = (props) => { const file = props.data const cards = file['cards'] 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}> + <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 1bfc4a9..6b3772a 100644 --- a/src/Components/Unfound.js +++ b/src/Components/Unfound.js @@ -19,10 +19,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/__tests__/App-test.js b/src/__tests__/App-test.js index 79c4721..f76ba57 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__/__snapshots__/App-test.js.snap b/src/__tests__/__snapshots__/App-test.js.snap index 365ee0e..3f7171f 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> +`; -- GitLab From 6ce28402d297e7f09b8affe43a6ac5eff00843c9 Mon Sep 17 00:00:00 2001 From: HenryShan <zshan2@illinois.edu> Date: Tue, 30 Mar 2021 08:11:57 +0800 Subject: [PATCH 2/4] assignment3.0 ver3: all snapshot tests deployed, going for navigation test --- src/App.js | 271 ++++---------------------------------- src/Components/Loading.js | 2 +- src/Components/Profile.js | 4 +- src/Components/Repo.js | 4 +- src/Components/Unfound.js | 2 - src/package.json | 7 +- 6 files changed, 36 insertions(+), 254 deletions(-) diff --git a/src/App.js b/src/App.js index 32ca65a..b9549e1 100644 --- a/src/App.js +++ b/src/App.js @@ -7,7 +7,14 @@ import Profile from './Components/Profile' import Repo from './Components/Repo' import Unfound from './Components/Unfound' import Users from './Components/Users' -import DataGenerator from './Components/DataGenerator' +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({ @@ -35,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 @@ -102,86 +109,13 @@ function RepoScreen({ route, navigation }) { /** Follower page **/ function FollowerScreen({ route, navigation }) { const user = route.params - 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 - console.log(login) - return ( - <Users data={dataFile}/> - ); + return Follower(user, navigation) } /** Following page **/ function FollowingScreen({ route, navigation }) { const user = route.params - 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}/> - ); + return Following(user, navigation) } /** Unfound page **/ @@ -201,48 +135,9 @@ function UnfoundScreen({ route, navigation }) { function LoadProfileScreen({route, navigation}) { const dataJson = require('C:/Coding/cs242-assignment3/env.json') const {login} = route.params - fetch(dataJson['endPoint'], { - method: 'POST', - headers: { - "Content-Type": "application/json", - "Authorization": dataJson['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'] === null) { - /** User not found! **/ - navigation.push('Unfound', {errorMsg: 'Wrong!'}) - console.log('Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!') - } else { - navigation.push('Profile', data['data']['user']) - } - }) - .catch(error => { - console.error('Error:', error) - navigation.push('Unfound', {errorMsg: error}) - }) - + const endPoint = dataJson['endPoint'] + const token = dataJson['token'] + LoadProfileScreenModule(login, endPoint, token, navigation) return ( <Loading/> ); @@ -250,48 +145,11 @@ function LoadProfileScreen({route, navigation}) { /** Loading Repo page **/ function LoadRepoScreen({route, navigation}) { + const dataJson = require('C:/Coding/cs242-assignment3/env.json') const {login} = route.params - 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 { - 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: 'Wrong!'}) - console.log('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 => { - console.error('Error:', error) - navigation.push('Unfound', {errorMsg: error}) - }) - + const endPoint = dataJson['endPoint'] + const token = dataJson['token'] + LoadRepoScreenModule(login, endPoint, token, navigation) return ( <Loading/> ); @@ -301,94 +159,21 @@ function LoadRepoScreen({route, navigation}) { function LoadFollowersScreen({route, navigation}) { const {login} = route.params 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 { - 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: 'Wrong!'}) - console.log('Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!') - } else { - navigation.push('Followers', data['data']['user']) - } - }) - .catch(error => { - console.error('Error:', error) - navigation.push('Unfound', {errorMsg: error}) - }) - - return ( - <Loading/> - ); + 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'); - fetch(dataJson['endPoint'], { - method: 'POST', - headers: { - "Content-Type": "application/json", - "Authorization": dataJson['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: 'Wrong!'}) - console.log('Error, cannot find the github user by the login username:' + login + ', maybe this is an organization!') - } else { - navigation.push('Following', data['data']['user']) - } - }) - .catch(error => { - console.error('Error:', error) - navigation.push('Unfound', {errorMsg: error}) - }) - - return ( - <Loading/> - ); + 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) + } diff --git a/src/Components/Loading.js b/src/Components/Loading.js index 694ff72..0bc32a3 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%' }, diff --git a/src/Components/Profile.js b/src/Components/Profile.js index 2856a2d..ea75c83 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'}, @@ -31,7 +29,7 @@ const Profile = (props) => { <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={{uri: iconUrl}} /> + <Image style={{width: 120, height: 120}} source={{uri: iconUrl}}/> </View> <View style={styles.viewStyleHorizon}> <Pressable style={styles.pressableStyle} onPress={() => navigation.push('LoadingFollowers', {login: login})}> diff --git a/src/Components/Repo.js b/src/Components/Repo.js index 811276f..67038d8 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'}, @@ -18,7 +17,6 @@ const Repo = (props) => { const file = props.data const cards = file['cards'] const navigation = file['navi'] - const login = file['login'] return ( <View style={styles.container}> <ImageBackground source={{uri: "https://www.fonewalls.com/wp-content/uploads/2020/04/Ice-Phone-Wallpaper.jpg"}} style={styles.image}> diff --git a/src/Components/Unfound.js b/src/Components/Unfound.js index 6b3772a..7098417 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'}, diff --git a/src/package.json b/src/package.json index 87fc242..9273acf 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", -- GitLab From 30719ac6a01d5b468cad3d72da390c5186c560ce Mon Sep 17 00:00:00 2001 From: HenryShan <zshan2@illinois.edu> Date: Tue, 30 Mar 2021 12:27:55 +0800 Subject: [PATCH 3/4] repairing uploading --- src/Components/Followers.js | 56 +++ src/Components/Following.js | 55 +++ src/Components/LoadFollowersScreenModule.js | 48 +++ src/Components/LoadFollowingScreenModule.js | 47 +++ src/Components/LoadProfileScreenModule.js | 46 +++ src/Components/LoadRepoScreenModule.js | 42 +++ src/Components/Users.js | 36 ++ src/__tests__/Button-test.js | 59 ++++ src/__tests__/ErrorInFollowers-test.js | 57 ++++ src/__tests__/ErrorInProfile-test.js | 87 +++++ src/__tests__/FollowerScreen-test.js | 74 ++++ src/__tests__/FollowingScreen-test.js | 74 ++++ src/__tests__/Loading-test.js | 17 + src/__tests__/LoadingFollowersScreen-test.js | 40 +++ src/__tests__/LoadingFollowingScreen-test.js | 39 +++ src/__tests__/Profile-test.js | 26 ++ src/__tests__/Repo-test.js | 27 ++ src/__tests__/Unfound-test.js | 21 ++ src/__tests__/Users-test.js | 27 ++ .../ErrorInFollowers-test.js.snap | 155 +++++++++ .../__snapshots__/Loading-test.js.snap | 78 +++++ .../LoadingFollowersScreen-test.js.snap | 78 +++++ .../LoadingFollowingScreen-test.js.snap | 78 +++++ .../__snapshots__/Profile-test.js.snap | 321 ++++++++++++++++++ src/__tests__/__snapshots__/Repo-test.js.snap | 120 +++++++ .../__snapshots__/Unfound-test.js.snap | 110 ++++++ .../__snapshots__/Users-test.js.snap | 120 +++++++ src/package.json | 1 + 28 files changed, 1939 insertions(+) create mode 100644 src/Components/Followers.js create mode 100644 src/Components/Following.js create mode 100644 src/Components/LoadFollowersScreenModule.js create mode 100644 src/Components/LoadFollowingScreenModule.js create mode 100644 src/Components/LoadProfileScreenModule.js create mode 100644 src/Components/LoadRepoScreenModule.js create mode 100644 src/Components/Users.js create mode 100644 src/__tests__/Button-test.js create mode 100644 src/__tests__/ErrorInFollowers-test.js create mode 100644 src/__tests__/ErrorInProfile-test.js create mode 100644 src/__tests__/FollowerScreen-test.js create mode 100644 src/__tests__/FollowingScreen-test.js create mode 100644 src/__tests__/Loading-test.js create mode 100644 src/__tests__/LoadingFollowersScreen-test.js create mode 100644 src/__tests__/LoadingFollowingScreen-test.js create mode 100644 src/__tests__/Profile-test.js create mode 100644 src/__tests__/Repo-test.js create mode 100644 src/__tests__/Unfound-test.js create mode 100644 src/__tests__/Users-test.js create mode 100644 src/__tests__/__snapshots__/ErrorInFollowers-test.js.snap create mode 100644 src/__tests__/__snapshots__/Loading-test.js.snap create mode 100644 src/__tests__/__snapshots__/LoadingFollowersScreen-test.js.snap create mode 100644 src/__tests__/__snapshots__/LoadingFollowingScreen-test.js.snap create mode 100644 src/__tests__/__snapshots__/Profile-test.js.snap create mode 100644 src/__tests__/__snapshots__/Repo-test.js.snap create mode 100644 src/__tests__/__snapshots__/Unfound-test.js.snap create mode 100644 src/__tests__/__snapshots__/Users-test.js.snap diff --git a/src/Components/Followers.js b/src/Components/Followers.js new file mode 100644 index 0000000..778230d --- /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 0000000..79a8a9d --- /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 0000000..785c471 --- /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 0000000..44e8631 --- /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 0000000..60c63fa --- /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 0000000..9181ea2 --- /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/Users.js b/src/Components/Users.js new file mode 100644 index 0000000..ef70491 --- /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__/Button-test.js b/src/__tests__/Button-test.js new file mode 100644 index 0000000..911bf83 --- /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 0000000..99798c5 --- /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 0000000..73e6c32 --- /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 0000000..0d419e7 --- /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 0000000..082581b --- /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 0000000..2fee5fd --- /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 0000000..2b18f62 --- /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 0000000..6abcee1 --- /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 0000000..031ed57 --- /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 0000000..2ac8c22 --- /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 0000000..70973c3 --- /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 0000000..2699b83 --- /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__/ErrorInFollowers-test.js.snap b/src/__tests__/__snapshots__/ErrorInFollowers-test.js.snap new file mode 100644 index 0000000..d557758 --- /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 0000000..9834e0e --- /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 0000000..9834e0e --- /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 0000000..9834e0e --- /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 0000000..04de496 --- /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 0000000..7fc91eb --- /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 0000000..7822434 --- /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 0000000..7fc91eb --- /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 9273acf..8486e4a 100644 --- a/src/package.json +++ b/src/package.json @@ -39,6 +39,7 @@ }, "devDependencies": { "@babel/core": "~7.9.0", + "@testing-library/react-native": "^7.2.0", "jest": "^26.6.3" }, "private": true -- GitLab From 06f3386adb81fe259b4112a84ec5e573c16670fb Mon Sep 17 00:00:00 2001 From: HenryShan <zshan2@illinois.edu> Date: Tue, 30 Mar 2021 12:29:36 +0800 Subject: [PATCH 4/4] ReadMe updated --- GitView | 2 +- README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/GitView b/GitView index 6902827..f7225e5 160000 --- a/GitView +++ b/GitView @@ -1 +1 @@ -Subproject commit 690282746b8a50666215d24d2bf4c8cb7801b9de +Subproject commit f7225e509f6d0c009ab70f58c906ec2d474caa7e diff --git a/README.md b/README.md index 7ab5a6a..6ea8ec1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ 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. -- GitLab