рдореЗрд░реЗ рдкрд╛рд╕ рдореЗрд░реЗ рдХрд╕реНрдЯрдо рдмрдЯрди рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдХреНрд╖рд╛ рд╣реИ:
import React, { Component } from 'react';
import { StyleSheet, View, TouchableHighlight, Text, Image } from 'react-native';
class NavBarBackButton extends Component {
static propTypes = {
onClick: React.PropTypes.func.isRequired,
buttonText: React.PropTypes.string,
customStyle: React.PropTypes.object
};
render() {
return (
<TouchableHighlight
style={[styles.backButton, this.props.customStyle]}
onPress={() => {this.props.onClick()}} >
<View style={{flexDirection: 'row'}}>
<Image
style={styles.backImage}
source={require('../img/back-128.png')}
/>
<Text style={styles.backButtonText}>
{this.props.buttonText}
</Text>
</View>
</TouchableHighlight>
);
}
}
const styles = StyleSheet.create({
backButton: {
justifyContent: 'center'
},
backButtonText: {
fontSize: 17,
textAlignVertical: 'center',
color: 'black',
},
backImage: {
width: 40,
height: 40
},
});
export default NavBarBackButton;
рдФрд░ рд╕реНрдиреИрдкрд╢реЙрдЯ рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рд╛рде рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ:
import 'react-native';
import React from 'react';
import NavBarBackButton from '../navBarBackButton';
import renderer from 'react-test-renderer';
function doWork() {
console.log('Back button was clicked!');
}
it('renders all UI elements', () => {
const tree = renderer.create(
<NavBarBackButton onClick = {doWork}/>
).toJSON();
expect(tree).toMatchSnapshot();
});
рд▓реЗрдХрд┐рди рдЬрдм рдореИрдВ <TouchableHighlight/>
рддрддреНрд╡ рдореЗрдВ рдПрдХ рдФрд░ рдкреНрд░реЛрдк рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВ, рдЬреИрд╕реЗ:
underlayColor={'blue'}
рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдПрдВ - рдореБрдЭреЗ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдореЗрдВ рдХреЛрдИ рдЕрдВрддрд░ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕реНрдиреИрдкрд╢реЙрдЯ рдиреЗ рдЗрд╕ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░реЛрдк рдХреА рдЙрдореНрдореАрдж рдирд╣реАрдВ рдХреА рдереАред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдПрдХрдорд╛рддреНрд░ рдкреНрд░реЛрдк рдиреЗ "рд╕реНрдЯрд╛рдЗрд▓" рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реАрдо рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ред
рдХреНрдпрд╛ рдпрд╣ рдХрд╛рд░реНрдп рдкреНрд░рдЧрддрд┐ рдкрд░ рд╣реИ?
рд╕рд╛рде рд╣реА, рд╕рдВрдмрдВрдзрд┐рдд рдиреЛрдЯ рдкрд░ - рд╕реНрдиреИрдкрд╢реЙрдЯ (рдФрд░ рдбреАрдмрдЧрд░) рдореЗрдВ рдЯрдЪ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд╛ рдкреНрд░рдХрд╛рд░ 'рд╡реНрдпреВ' рдХреЗ рд░реВрдк рдореЗрдВ рдХреНрдпреЛрдВ рджрд┐рдЦ рд░рд╣рд╛ рд╣реИ, рди рдХрд┐ 'рдЯрдЪреЗрдмрд▓ рд╣рд╛рдЗрдЯрд▓рд╛рдЗрдЯ'?
рдореЗрд░реЗ package.jason рдореЗрдВ рдореЗрд░реЗ рдкрд╛рд╕ рд╣реИ:
{
"name": <my_project_name>,
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"jest": {
"preset": "jest-react-native",
"collectCoverage": true,
"verbose": true,
"preprocessorIgnorePatterns": [
"node_modules/(?!react-native|<my_project_name>|react-native-button)"
]
},
"dependencies": {
"lodash": "^4.15.0",
"react": "^15.3.1",
"react-native": "^0.33.0",
},
"devDependencies": {
"babel-jest": "^15.0.0",
"babel-polyfill": "^6.13.0",
"babel-preset-react-native": "^1.9.0",
"jest": "^15.1.1",
"jest-cli": "^15.1.1",
"jest-react-native": "^15.0.0",
"react-addons-test-utils": "^15.2.1",
"react-shallow-testutils": "^2.0.0",
"react-test-renderer": "^15.3.1"
}
}
рдФрд░ рдореЗрд░рд╛ .babelrc рд░реВрдЯ рдбреАрдЖрдИрдЖрд░ рдореЗрдВ рд╣реИ:
{
"presets": ["react-native"]
}
рд╣рдо рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ TouchableHighlight рдХрд╛ рдордЬрд╛рдХ рдирд╣реАрдВ рдЙрдбрд╝рд╛рддреЗ рд╣реИрдВред рдЗрд╕реЗ рд╡реНрдпреВ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣реА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рдореВрд▓ рдЗрд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИред
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдЬреИрд╕реЗ TouchableHighlight рд╕реАрдзреЗ рдЕрдкрдиреЗ рдореВрд▓ рдмреИрдХрд┐рдВрдЧ рддрддреНрд╡ рдкрд░ рдкреНрд░реЛрдк рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ: https://github.com/facebook/react-native/blob/master/Libraries/Components/Touchable/TouchableHighlight.js#L200 рдФрд░ рдЖрдкрдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдирдХрд▓реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдЗрд╕рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддрд╛рдХрд┐ рдЖрдкрдХрд╛ рдкреНрд░реЛрдк рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗред
рдПрдХ рдЪреАрдЬ рдЬреЛ рдХрд╛рдо рдХрд░ рд╕рдХрддреА рд╣реИ рд╡рд╣ рд╣реЛ рд╕рдХрддреА рд╣реИ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рджреВрд╕рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╕реБрдЭрд╛рдП рдЧрдП рдЕрдиреБрд╕рд╛рд░ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдореЙрдХ рдмрдирд╛рдирд╛: http://facebook.github.io/jest/docs/tutorial-react-native.html#mock -native-modules- рдкреНрд░рдпреЛрдЧ-рдордЬрд╛рдХ-рдордЬрд╛рдХ
jest.mock('TouchableHighlight', () => {
const jestReactNative = require('jest-react-native');
return jestReactNative.mockComponent('TouchableHighlight');
});
@cpojer рддреНрд╡рд░рд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! рдореЗрд░рд╛ рд╕реНрдиреИрдкрд╢реЙрдЯ рдЕрдм рдмрд╣реБрдд рд╕рд╛рдл рджрд┐рдЦрддрд╛ рд╣реИред
рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рд╢реНрди - рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореЗрд░рд╛ рдЖрдЙрдЯрдкреБрдЯ рд╢рд┐рдХрд╛рдпрдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдПрдХ рд▓рд╛рдЗрди рдХреЛ рдХрд╡рд░ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ onPress
рдкреНрд░реЛрдк рдХреЛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ
static propTypes = {
onClick: React.PropTypes.func.isRequired,
...
};
<TouchableHighlight
onPress={() => {this.props.onClick()}} > //no coverage for this line of code in test
...
</TouchableHighlight>
рдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдореИрдВ рдмрдЯрди рдХреНрд▓рд┐рдХ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХреИрд╕реЗ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ? рдпрд╛ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рдХрд╡рд░ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдХрд░реЗрдВ onPress={() => {this.props.onClick()}} >
? рдореБрдЭреЗ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдЖрдкрдХреЗ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдорд┐рд▓рд╛ред
рдЕрдЧреНрд░рд┐рдо рдореЗрдВ рдзрдиреНрдпрд╡рд╛рдж!
@rosiakr рд╣рд╛рдВ, рдЖрдк рдмрдЯрди рдХреНрд▓рд┐рдХ рдЗрд╡реЗрдВрдЯ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдпрд╣рд╛рдВ рдХреБрдЫ рдХреЛрдб рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдмрдЯрди рдХреНрд▓рд┐рдХ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдерд╛ред
class YourComponent extends Component {
handleButtonClick = () => {};
render() {
return <Button transparent onPress={() => this.handleButtonClick()}></Button>
}
}
//jest
it("Test Component", () => {
const component = renderer.create(
<YourComponent/>
);
// manually trigger the button click.
component.getInstance().handleButtonClick();
};
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
@cpojer рддреНрд╡рд░рд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! рдореЗрд░рд╛ рд╕реНрдиреИрдкрд╢реЙрдЯ рдЕрдм рдмрд╣реБрдд рд╕рд╛рдл рджрд┐рдЦрддрд╛ рд╣реИред
рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рд╢реНрди - рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореЗрд░рд╛ рдЖрдЙрдЯрдкреБрдЯ рд╢рд┐рдХрд╛рдпрдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдПрдХ рд▓рд╛рдЗрди рдХреЛ рдХрд╡рд░ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ
onPress
рдкреНрд░реЛрдк рдХреЛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИрдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдореИрдВ рдмрдЯрди рдХреНрд▓рд┐рдХ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХреИрд╕реЗ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ? рдпрд╛ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рдХрд╡рд░ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдХрд░реЗрдВ
onPress={() => {this.props.onClick()}} >
? рдореБрдЭреЗ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдЖрдкрдХреЗ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдорд┐рд▓рд╛редрдЕрдЧреНрд░рд┐рдо рдореЗрдВ рдзрдиреНрдпрд╡рд╛рдж!