我正在使用以下测试,该测试给了我错误- TypeError:无法读取未定义的属性“ year” :
import React from "react";
import { shallow, mount, render } from "enzyme";
import HomeScreen from "./HomeScreen";
import renderer from "react-test-renderer";
import { Provider } from "react-redux";
import configureMockStore from "redux-mock-store";
const mockStore = configureMockStore();
describe("Homescreen Component", () => {
it("should render without throwing an error", () => {
const store = mockStore({
credentials: {
year: 1,
group: 1,
student: 2,
showStudent: true
}
});
const navigation = { navigate: jest.fn() };
const tree = renderer
.create(
<Provider store={store}>
<HomeScreen navigation={navigation} />
</Provider>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
});
我的组件render
:
render() {
const {
isLoading,
categories,
hasErrored,
authenticated,
isLoadingCredentials,
credentials: { year, group, student, showStudent }
} = this.props;
我正在将props
传递到我的组件中,为什么它们是undefined
?
组件:
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import {
View,
Text,
Image,
StyleSheet,
TouchableHighlight,
ActivityIndicator,
ImageBackground,
AsyncStorage,
Platform,
Dimensions,
TextInput,
Alert
} from "react-native";
import {
setYear,
setStudent,
setGroup,
setCredentials,
resetForm,
setAuthenticated
} from "../actions/events";
import { fetchEvents } from "../actions/events";
import { isLoading, isLoadingCredentials, hasErrored } from "../actions/loader";
import ResponsiveImage from "react-native-responsive-image";
import Picker from "./common/Picker";
import SpinnerWithBackground from "./common/SpinnerWithBackground";
import Login from "./Login";
import { data } from "../config/calendars.js";
class HomeScreen extends React.PureComponent {
static navigationOptions = {
title: "",
headerMode: "screen",
header: null
};
constructor(props) {
super(props);
this.state = { landscape: false };
this.onLayout = this.onLayout.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.showAlert = this.showAlert.bind(this);
this.onAuthenticate = this.onAuthenticate.bind(this);
this.onParentChange = this.onParentChange.bind(this);
this.onGroupChange = this.onGroupChange.bind(this);
this.onStudentChange = this.onStudentChange.bind(this);
this.reDirect = this.reDirect.bind(this);
}
reDirect() {
const {
navigation: { navigate },
fetchEvents,
credentials: { student }
} = this.props;
if (student) {
fetchEvents(student);
navigate("Month");
}
}
componentWillMount() {
const {
navigation: { navigate },
setCredentials
} = this.props;
//www.googleapis.com/calendar/v3/calendars/fourthyear-spc@rguc.co.uk/events?nextPageToken=2500&key=AIzaSyB77rzW-VzrZAaWJzgiG1Gf-MGEcwn-a-E
AsyncStorage.getItem("auth").then(authenticated => {
if (authenticated) {
this.props.setAuthenticated(true);
}
});
isLoadingCredentials(true);
AsyncStorage.getItem("loggedIn")
.then(user => {
if (user) {
setCredentials(JSON.parse(user));
this.reDirect();
} else {
isLoadingCredentials(false);
}
})
.catch(() => {
isLoadingCredentials(false);
});
isLoadingCredentials(false);
}
onParentChange(e) {
this.props.resetForm();
this.props.setYear(e);
}
onGroupChange(e) {
if (e !== "") {
const {
credentials: { year }
} = this.props;
let label = data.years
.find(option => {
return option.id == year;
})
.options.find(option => {
return option.id == e;
}).label;
this.props.setGroup(e, data.years, year, label);
}
}
onStudentChange(e) {
const {
credentials: { year, group, showStudent }
} = this.props;
if (e !== "") {
let studentName = data.years
.find(option => {
return option.id == year;
})
.options.find(option => {
return option.id == group;
})
.options.find(option => {
return option.id == e;
}).label;
this.props.setStudent(e, studentName);
}
}
showAlert() {
Alert.alert("Incorrect password");
}
onAuthenticate(e) {
if (e == "Undergraduate1") {
AsyncStorage.setItem(
"auth",
JSON.stringify({ authentication: true })
);
this.props.setAuthenticated(true);
} else {
this.showAlert();
}
}
onSubmit(e) {
const {
navigation: { navigate },
credentials: { year, group, student },
fetchEvents
} = this.props;
AsyncStorage.setItem(
"loggedIn",
JSON.stringify(this.props.credentials)
);
fetchEvents(student || group);
navigate("Month");
}
onLayout(e) {
const { width, height } = Dimensions.get("window");
if (width > height) {
this.setState({ landscape: true });
} else {
this.setState({ landscape: false });
}
}
render() {
const {
isLoading,
categories,
hasErrored,
authenticated,
isLoadingCredentials,
credentials: { year, group, student, showStudent }
} = this.props;
if (!authenticated) {
return <Login onPress={this.onAuthenticate} />;
}
return (
<ImageBackground
source={require("../img/bkgPhoto.jpg")}
style={{
flex: 1,
width: null,
height: null
}}
>
<View
style={styles.container}
onLayout={this.onLayout.bind(this)}
>
{!this.state.landscape ? (
<View
style={{
height: "30%",
flexDirection: "row",
justifyContent: "space-between"
}}
>
<ResponsiveImage
source={require("../img/RGUC_Connect_logo.png")}
initWidth="75"
initHeight="90"
/>
<ResponsiveImage
source={require("../img/logo.png")}
initWidth="140"
initHeight="70"
/>
</View>
) : null}
<ResponsiveImage
source={require("../img/CalendarApp_logo.png")}
initWidth="250"
initHeight="100"
style={{ alignSelf: "center" }}
/>
{data ? (
<Picker
selectedValue={year}
label="Year"
onChange={this.onParentChange}
options={data.years}
style={styles.picker}
/>
) : null}
{year ? (
<Picker
selectedValue={group}
label="Group"
style={styles.picker}
onChange={this.onGroupChange}
options={
data.years.find(element => {
return element.id == year;
}).options
}
/>
) : null}
{group && showStudent ? (
<Picker
selectedValue={student}
label="Student"
style={styles.picker}
onChange={this.onStudentChange}
options={
data.years
.find(element => {
return element.id == year;
})
.options.find(element => {
return element.id == group;
}).options
}
/>
) : null}
{(year && group && !showStudent) || student ? (
<TouchableHighlight
style={
this.state.landscape
? {
alignItems: "center",
backgroundColor: "#006666",
padding: 10,
width:
Platform.OS === "ios"
? "100%"
: "90%",
alignSelf: "center"
}
: {
alignItems: "center",
backgroundColor: "#006666",
padding: 10,
width:
Platform.OS === "ios"
? "100%"
: "90%",
alignSelf: "center"
}
}
onPress={this.onSubmit}
>
<Text style={styles.buttonText}> Submit</Text>
</TouchableHighlight>
) : null}
</View>
</ImageBackground>
);
}
}
const mapStateToProps = state => {
return {
categories: state.fetchCategories,
isLoading: state.isLoading,
hasErrored: state.hasErrored,
credentials: state.setCredentials,
isLoadingCredentials: state.isLoadingCredentials,
authenticated: state.authenticated
};
};
const mapDispatchToProps = dispatch => ({
fetchEvents: id => dispatch(fetchEvents(id)),
isLoadingCredentials: loadingCredentials =>
dispatch(isLoadingCredentials(loadingCredentials)),
setCredentials: credentials => dispatch(setCredentials(credentials)),
setYear: year => dispatch(setYear(year)),
setGroup: (group, categories, year, label) =>
dispatch(setGroup(group, categories, year, label)),
setStudent: (id, label) => dispatch(setStudent(id, label)),
resetForm: () => dispatch(resetForm()),
setAuthenticated: value => dispatch(setAuthenticated(value))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(HomeScreen);
const styles = StyleSheet.create({
container: {
padding: 20,
flex: 1
},
button: {
alignItems: "center",
backgroundColor: "#800080",
padding: 10
},
picker: {
alignSelf: "center",
height: 30,
width: "90%",
backgroundColor: "white"
},
buttonText: {
color: "white",
width: "90%",
alignSelf: "center",
textAlign: "center"
},
logo: {
flex: 1,
alignSelf: "center"
}
});