Skip to content

Instantly share code, notes, and snippets.

@slamus
Last active May 2, 2016 11:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slamus/46b320e3bba8195baa6d3c25a82ec5ae to your computer and use it in GitHub Desktop.
Save slamus/46b320e3bba8195baa6d3c25a82ec5ae to your computer and use it in GitHub Desktop.
My react-native Jest configuration
{
"presets": ["react-native"]
}
// PUT IN src/__mocks__/
const dimensions = {
window: {
width: 320,
height: 667,
scale: 2,
fontScale: 2,
},
};
const Dimensions = {
set(dims) {
Object.assign(dimensions, dims);
return true;
},
get(dim) {
return dimensions[dim];
},
};
export default Dimensions;
https://github.com/bartonhammond/snowflake
http://hosain.net/2016/01/31/unit-testing-react-native-components.html
https://medium.com/@jcfrancisco/unit-testing-react-native-components-a-firsthand-guide-cea561df242b
"use strict"
import React from "react-native";
// Constants
import UIStyle from "./UIStyle";
const {
View,
Text,
StyleSheet,
Component,
Platform,
TextInput,
} = React;
class MyTextInput extends Component {
showError() {
if (this.props.error && typeof this.props.error !== 'boolean') {
return {borderColor: UIStyle.COLOR_WARNING};
}
if (this.props.value && this.props.value.length > 0) {
if (this.props.error !== null && this.props.error === false) {
return {borderColor: UIStyle.COLOR_VALID};
}
}
return {borderColor: UIStyle.TEXTINPUT_BORDER_COLOR};
}
getLabel() {
if (this.props.label && this.props.label.length > 0) {
return (
<Text style={styles.input_label}>{this.props.label}</Text>
);
}
return false;
}
getTextInput() {
if (this.props.editable === false) {
return (
<Text
ref={c => this._TextInput = c}
style={[styles.text, this.props.textStyle, {
opacity: this.props.value ? 1 : 0.4
}]}
>
{this.props.value ? this.props.value : this.props.placeholder}
</Text>
);
}
return (
<TextInput {...this.props}
underlineColorAndroid={'transparent'}
placeholderTextColor={UIStyle.COLOR_GREY}
style={[styles.text, styles.input_text, this.props.textStyle]}
ref={c => this._TextInput = c}
/>
);
}
getError() {
if (this.props.error !== null && typeof this.props.error !== 'boolean') {
return (
<Text style={styles.input_error}>{this.props.error}</Text>
);
}
return false;
}
render() {
return(
<View style={[styles.container, this.props.style]}>
{this.getLabel()}
<View style={[styles.input_container, this.showError()]}>
{this.getTextInput()}
</View>
{this.getError()}
</View>
);
}
}
let styles = StyleSheet.create({
// your styles
});
export default MyTextInput;
{
...,
"jest": {
"testPathIgnorePatterns": [
"/node_modules/"
],
"testFileExtensions": [
"es6",
"js"
],
"moduleFileExtensions": [
"js",
"json",
"es6"
],
"unmockedModulePathPatterns": [
"react",
"react-addons-test-utils",
"react-native-router-flux",
"promise",
"source-map",
"key-mirror",
"immutable",
"fetch",
"redux",
"redux-thunk",
"fbjs"
],
"collectCoverage": false,
"verbose": true
},
"dependencies": {
"lodash": "^4.11.1",
"react": "^0.14.7",
"react-native": "^0.23.1",
...
},
"scripts": {
"test": "rm -rf ./node_modules/jest-cli/.haste_cache && jest --no-cache"
},
"devDependencies": {
"babel-core": "^6.4.5",
"babel-jest": "^9.0.3",
"babel-preset-react-native": "^1.5.6",
"jest-cli": "^0.9.2",
"react-addons-test-utils": "^0.14.7",
"react-shallow-testutils": "^1.0.0",
"redux-mock-store": "^1.0.2"
}
}
// PUT IN src/__mocks__/
"use strict"
let { each } = require('lodash');
const React = require('react');
const ReactNative = React;
// Base Components
function createMockComponent(componentName) {
return React.createClass({
render: function() { return false }
});
};
each([
'View',
'ScrollView',
'Text',
'TouchableOpacity',
'TouchableHighlight',
'TouchableWithoutFeedback',
'ToolbarAndroid',
'TextInput',
'Image',
], (componentName) => {
ReactNative[componentName] = createMockComponent(componentName);
});
// Special components
ReactNative.NativeModules= {};
ReactNative.StyleSheet = {
create: function create(styles) {
return styles;
},
}
ReactNative.Platform = {
OS: 'ios',
Version: undefined,
};
export default ReactNative;
'use strict';
import { each } from 'lodash';
import { findAll, findAllWithType } from 'react-shallow-testutils';
import React from 'react-native';
const {
View,
Text,
TextInput,
} = React;
import TestUtils from 'react-addons-test-utils';
// Tested
jest
.unmock('../MyTextInput')
import UIStyle from '../UIStyle';
import MyTextInput from '../MyTextInput';
describe('MyTextInput', function() {
function render(jsx) {
const renderer = TestUtils.createRenderer();
renderer.render(jsx);
return renderer.getRenderOutput();
}
function renderWithState(jsx, state) {
const renderer = TestUtils.createRenderer();
renderer.render(jsx);
if (state) {
const instance = renderer._instance._instance;
instance.setState(state);
}
return renderer.getRenderOutput();
}
function elemHasText(e, strings) {
if (e && e.type === Text) {
let hasText = false;
each(strings, (str) => {
if (e.props.children == str) {
hasText = true;
return false;
}
});
return hasText;
}
return false
}
it('should render label if provided', function() {
const result = render(
<MyTextInput
error={true}
label={"LABEL"}
/>
);
// const elems = findAll(result, (e) => {
// return (e && e.type === View);
// })
const strings = ['LABEL'];
const elems = findAll(result, (e) => {return elemHasText(e, strings)});
expect(elems.length).toEqual(strings.length);
});
it('should NOT render label if NOT provided', function() {
const result = render(
<MyTextInput
error={true}
/>
);
expect(result.props.children[0]).toEqual(false);
});
it('should hide error if boolean', function() {
const result = render(
<MyTextInput
error={true}
/>
);
expect(result.props.children[1].props.style[1]["borderColor"]).toEqual(UIStyle.TEXTINPUT_BORDER_COLOR);
});
it('should show error if error is text', function() {
const result = render(
<MyTextInput
error={"This is an error !"}
/>
);
const strings = ['This is an error !'];
const elems = findAll(result, (e) => {return elemHasText(e, strings)});
expect(elems.length).toEqual(strings.length);
expect(result.props.children[1].props.style[1]["borderColor"]).toEqual(UIStyle.COLOR_WARNING);
});
it('should render a Text element instead of a TextInput if this.props.editable === false', function() {
const result = render(
<MyTextInput
editable={false}
value={"Immutable Value !"}
/>
);
const strings = ['Immutable Value !'];
const elems = findAll(result, (e) => {return elemHasText(e, strings)});
expect(elems.length).toEqual(strings.length);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment