Detox, Enzyme, Jest Setup in React Native
Installation
Install something required by detox:
$ xcode-select --install
$ brew tap wix/brew
$ brew install applesimutils
Install detox command line.
$ npm install -g detox-cli
Install detox.
npm install detox --save-dev --no-package-lock
Option with Jest: Install Jest.
npm install jest jest-circus --save-dev --no-package-lock
Initialise configuration script for Detox with Jest.
detox init -r jest
Configuration
(For simulator release) In your .detoxrc.json
file:
{
"testRunner": "jest",
"runnerConfig": "e2e/config.json",
"configurations": {
"ios.sim.release": {
"type": "ios.simulator",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "...",
"device": {
"type": "iPhone 11 Pro"
}
}
}
}
(For simulator debugging) In your .detoxrc.json
file:
{
"testRunner": "jest",
"runnerConfig": "e2e/config.json",
"configurations": {
"ios.sim.debug": {
"type": "ios.simulator",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "...",
"device": {
"type": "iPhone 11 Pro"
}
}
}
}
Build your app.
detox build
Test your app.
detox test
API
Refresh the app. Hot reload.
describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
});
});
Visible or not. Get document by id and value.
A sample component.
<Text testID={'textID'}>Hello World</Text>
By id:
it('should have welcome screen', async () => {
await expect(element(by.id('textID'))).toBeVisible();
});
By value:
it('should have welcome screen', async () => {
await expect(element(by.text('Hello World'))).toBeVisible();
});
Read to test more at https://jestjs.io/docs/en/getting-started
Event Handlers
onTap:
await element(by.id('hello_button')).tap();
Read more at https://github.com/wix/Detox/tree/master/docs
Enzyme
Used for shallow, full and static component rendering.
Install enzyme.
npm i --save-dev enzyme enzyme-adapter-react-16
Setup default props for a component.
import React from 'react';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import LocalComponent from './LocalComponent';configure({ adapter: new Adapter() });const defaultProps = { itemObjects: [{ title: "something", item: [1, 2, 3] }, { title: "something", item: [1, 2, 3] }] };const setup = (props = {}) => {
const setupProps = { ...defaultProps, ...props };
return shallow(<LocalComponent {...setupProps} />)
}const findByTestIDAttribute = (wrapper, val) => {
return wrapper.find(`[testID="${val}"]`);
}describe('Component testing', () => {
it('renders with default props', () => {
const wrapper = setup();
const component = findByTestIDAttribute(wrapper, 'component-nothing-title');
expect(component.exists()).toBe(false);
});
});
Setup redux default state/props:
Let’s say this is TestUtil.js
:
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers';
import { middlewares } from '../configureStore'; export const storeFactory = (initialState) => { const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore);
return createStoreWithMiddleware(rootReducer, initialState);}
Let’s say this is configureStore.js
:
import { createStore, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import rootReducer from './reducers'; export const middlewares = [ReduxThunk];const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore); export default createStoreWithMiddleware(rootReducer);
Read more enzyme at https://enzymejs.github.io/enzyme/docs/api/