๋ด ์ฌ์ฉ์ ์ ์ ๋ฒํผ์ ๋ํ ํด๋์ค๊ฐ ์์ต๋๋ค.
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'}
๊ทธ๋ฆฌ๊ณ ํ
์คํธ๋ฅผ ๋ค์ ์คํํ์ญ์์ค - ์ค๋
์ท์ด ์ด ์ถ๊ฐ ์ํ์ ๊ธฐ๋ํ์ง ์์๋ค๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๋ diff๋ฅผ ์ป์ง ๋ชปํ์ต๋๋ค. ์ฌ์ค, ์ ์ผํ ์ํ์ ์๊ธฐ๋ฅผ "์คํ์ผ"๋ก ํ๊ฐํ์ต๋๋ค.
์ด ์์
์ด ์งํ ์ค์
๋๊น?
๋ํ ๊ด๋ จ ๋ฉ๋ชจ์์ TouchableHighlight์ ์ ํ์ด ์ค๋
์ท(๋ฐ ๋๋ฒ๊ฑฐ)์ 'TouchableHightlight'๊ฐ ์๋ 'View'๋ก ํ์๋๋ ์ด์ ๋ ๋ฌด์์
๋๊น?
๋ด 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๋ฅผ ์กฐ๋กฑํ์ง ์์ต๋๋ค. ๊ทธ๊ฒ์ด ๋ฐ์ ๋ค์ดํฐ๋ธ๊ฐ ๋ ๋๋งํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ View๋ก ๋ ๋๋ง๋ฉ๋๋ค.
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
prop์ ์ง์ ํ๋ ๋ผ์ธ์ ๋ค๋ฃจ์ง ์๋๋ค๊ณ ๋ถํํฉ๋๋ค.
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
prop์ ์ง์ ํ๋ ๋ผ์ธ์ ๋ค๋ฃจ์ง ์๋๋ค๊ณ ๋ถํํฉ๋๋ค.๋ฒํผ ํด๋ฆญ์ ์๋ฎฌ๋ ์ด์ ํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์์ต๋๊น? ์๋๋ฉด ๋ด ํ ์คํธ๊ฐ
onPress={() => {this.props.onClick()}} >
์ปค๋ฒํ๋๋ก ํ๋ ค๋ฉด ๋ฌด์์ด๋ ํ์๊ฒ ์ต๋๊น? ์ฃผ์ ์ ๋ํ ์์ต์์์ ์๋ฌด ๊ฒ๋ ์ฐพ์ ์ ์์ต๋๋ค.๋ฏธ๋ฆฌ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!