React Native App
所以基本上我收到以下错误:
[Network error]: ReferenceError: XMLHttpRequest is not defined
在我的测试中,我使用的是模拟提供程序,因此我认为模拟阿波罗客户端正在尝试进行一些调用是不正确的。
client.js
import { ApolloClient } from "apollo-client";
import { ApolloLink } from "apollo-link";
import { InMemoryCache } from "apollo-cache-inmemory";
import { createHttpLink } from "apollo-link-http";
import { onError } from "apollo-link-error";
import fetch from "unfetch";
const apolloClient = new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.error(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError) console.error(`[Network error]: ${networkError}`);
}),
createHttpLink({
uri: "https://qxlmyzfj27.execute-api.eu-west-1.amazonaws.com/dev/graphql",
credentials: "same-origin",
fetch: fetch
})
]),
cache: new InMemoryCache()
});
export default apolloClient;
RecipeListScreen.js
import React, { Component } from "react";
import {
StyleSheet,
View,
Text,
Image,
ImageBackground,
TouchableHighlight,
StyleProp,
TextStyle,
FlatList,
ListRenderItem,
ImageSourcePropType,
TouchableOpacity,
TextInput,
Button
} from "react-native";
import { Query, QueryProps } from "react-apollo";
import { withNavigation } from 'react-navigation';
import { connect, Provider } from 'react-redux';
import { Colors, Metrics, Fonts } from "../themes";
import MainImages from "../images/mainImages/mainImages";
import ApplicationStyles from "../styles/ApplicationStyles";
import apolloClient from "../graphql/client";
import {GET_RECIPIES_QUERY, GetRecipesQueryResult} from "../graphql/queries";
import Images from "../images/mainImages/mainImages";
import store from "../components/Store";
class RecipeListScreen extends Component {
_onPressButton = (item) => {
this.props.navigation.navigate(
'RecipeDetail', {
recipeId: item.recipeId, mainImageEntry: item.mainImageEntry
}
);
}
_renderRecipe = ({item}) => {
return (
<TouchableOpacity testID={`${item.recipeName}`} onPress={() => this._onPressButton(item)}>
<View style={styles.recipeContainer}>
<ImageBackground
source={Images[item.mainImageEntry]}
style={styles.recipeImage}
resizeMode='cover'
>
<View style={styles.textContainer}>
<Text style={styles.recipeName}>{item.recipeName.toUpperCase()}</Text>
</View>
</ImageBackground>
</View>
</TouchableOpacity>
);
}
_filterRecipes = (recipes, search) => {
if (this.props.favoritesFilter) {
return recipes.filter(recipe => {
return this.props.selectedFavorites.includes(recipe.recipeId)
})
}
return recipes.filter(recipe => {
return recipe.recipeName.includes(search)
})
}
render() {
return (
<View style={ApplicationStyles.mainContainer}>
<Query client={apolloClient} query={GET_RECIPIES_QUERY}>
{({ loading, error, data }) => {
if (loading) return <Text>Loading...</Text>
if (error) {
return <Text>Error</Text>
}
const filteredRecipes = this._filterRecipes(
data.getRecipes,
this.props.searchFilter.toLowerCase()
);
return (
<View >
<TextInput
testID='InputSearch'
placeholder={"Search for some recipes!"}
style={styles.searchInput}
value={this.props.searchFilter}
onChangeText={(textValue) => {
this.props.onSearchUpdated(textValue)
}}
/>
<View>
<Button testID='FavoritesButton' title="Show my favorites"
onPress={() => this.props.toggleFavFilter()}
/>
</View>
{filteredRecipes.length ?
<FlatList
data={filteredRecipes}
testID='FlatList'
keyExtractor={(item, index) => `${index}`}
renderItem={this._renderRecipe}
numColumns={1}
horizontal={false}
/>
: <View style={styles.nothingMessageContainer}>
<Text testID='NothingFound' style={styles.nothingMessage}>Nothing was found</Text>
</View>}
</View>
)
}}
</Query>
</View>
);
}
}
const styles = StyleSheet.create({
recipeContainer: {
flex: 1,
margin: Metrics.baseMargin,
justifyContent: 'center',
alignItems: 'center',
},
recipeImage: {
width: Metrics.images.main,
height: Metrics.images.main,
},
searchInput: {
backgroundColor: Colors.white,
borderWidth: Metrics.borderWidth.small,
borderColor: Colors.grayLight,
margin: Metrics.baseMargin,
padding: Metrics.basePadding
},
textContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.transparentWhite
},
recipeName: {
fontSize: Fonts.size.large,
fontWeight: 'bold',
color: Colors.grayDark
},
nothingMessageContainer: {
alignItems: 'center',
justifyContent: 'center',
},
nothingMessage: {
fontSize: Fonts.size.medium
}
})
mapStateToProps = (state) => {
return {
searchFilter: state.searchFilter,
favoritesFilter: state.toggleFilterForFavorites,
selectedFavorites: state.selectedFavorites
}
}
mapDispatchToProps = (dispatch) => {
return {
onSearchUpdated: (textValue) => {
dispatch({
type: 'ADD_SEARCH_FILTER',
searchFilter: textValue
})
},
toggleFavFilter: () => {
dispatch({
type: 'TOGGLE_FILTER_FOR_FAVORITES'
})
}
}
}
export const RecipeListScreenWithoutHocs = RecipeListScreen;
export default withNavigation(connect(mapStateToProps, mapDispatchToProps)(RecipeListScreen));
RecipeListScreen.test.js的一部分
it('renders correctly', async () => {
const screen = renderer.create(
<MockedProvider mocks={mocks} addTypename={false}>
<RecipeListScreenWithoutHocs />
</MockedProvider>
)
// renders Loading... as expected
console.log(screen.root.findByType(Text).props);
// renders Error
await wait(0);
console.log(screen.root.findByType(Text).props);
})
这是那些console.logs的输出:
console.log __tests__/RecipeListScreen.test.js:86
{ children: 'Loading...' }
console.error src/graphql/client.ts:18
[Network error]: ReferenceError: XMLHttpRequest is not defined
console.log __tests__/RecipeListScreen.test.js:88
{ children: 'Error' }
我不确定这是否可能与嘲笑ApolloLink
有关。