Hi, i got an error when i try to run a test with Jest and a wrapped <Icon.ToolbarAndroid />.
<Toolbar />
import React, { PropTypes } from 'react';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { STYLE, TOOLBAR } from '../styles';
export default class Toolbar extends React.Component {
static propTypes = {
visible: PropTypes.bool.isRequired,
navigator: PropTypes.object.isRequired,
page: PropTypes.object.isRequired,
pages: PropTypes.array.isRequired,
title: PropTypes.string,
}
static defaultProps = {
visible: true,
style: [ STYLE.base, TOOLBAR.base ],
title: 'Pinja',
navIconName: 'face',
}
constructor (props) {
super(props);
let pageIndex = 1;
this.state = {
toolbarPages: props.pages
.filter(route => route.toolbar.display)
.map(route => ({
id: pageIndex++,
title: route.title,
show: route.toolbar.show,
iconName: route.toolbar.icon
})),
};
}
render () {
let props = this.props;
return !props.visible ? null : <Icon.ToolbarAndroid
title={props.title || props.page.title}
style={props.style}
navIconName={props.navIconName}
onIconClicked={() => props.navigator.replace(props.pages[0])}
actions={this.state.toolbarPages}
onActionSelected={position => this.onActionSelected(position)}
/>;
}
onActionSelected (position) {
let route = this.props.pages[position+1];
if (typeof route.onAction === 'function') {
route.onAction();
} else {
this.props.navigator.replace(route);
}
}
}
Jest test:
import React from 'react';
import renderer from 'react-test-renderer';
import Toolbar from '../toolbar';
describe('renders correctly', () => {
it('on visible=true', () => {
const navigator = { replace: jest.fn() };
const page = { title: 'Toolbar Test #1' };
const pages = [{
id: 0,
title: 'Toolbar Test #2',
tagName: 'ToolbarTest',
toolbar: {
show: 'never',
icon: 'check',
display: true,
},
}];
const toolbar = (
<Toolbar
visible={true}
navigator={navigator}
page={page}
pages={pages}
/>
);
const tree = renderer.create(toolbar).toJSON();
expect(tree).toMatchSnapshot();
});
});
The error:
x FAIL src/components/__tests__/toolbar.js
● renders correctly › on visible=true
RNVectorIconsManager not available, did you add the library to your project and link with libRNVectorIcons.a?
at getImageSource (node_modules/react-native-vector-icons/lib/create-icon-set.js:93:7)
at IconToolbarAndroid.updateIconSources (node_modules/react-native-vector-icons/lib/toolbar-android.js:38:1)
at IconToolbarAndroid.componentWillMount (node_modules/react-native-vector-icons/lib/toolbar-android.js:56:6)
at node_modules/react/lib/ReactCompositeComponent.js:347:23
at measureLifeCyclePerf (node_modules/react/lib/ReactCompositeComponent.js:74:12)
at ReactCompositeComponentWrapper.performInitialMount (node_modules/react/lib/ReactCompositeComponent.js:346:9)
at ReactCompositeComponentWrapper.mountComponent (node_modules/react/lib/ReactCompositeComponent.js:257:21)
at Object.mountComponent (node_modules/react/lib/ReactReconciler.js:47:35)
at ReactCompositeComponentWrapper.performInitialMount (node_modules/react/lib/ReactCompositeComponent.js:370:34)
at ReactCompositeComponentWrapper.mountComponent (node_modules/react/lib/ReactCompositeComponent.js:257:21)
renders correctly
✕ on visible=true (7ms)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.815s, estimated 1s
Ran all test suites matching "toolbar".
Somone has an Idea and can help?
// Edit
If i remove the navIconName the test will pass.
After a bit of research, looks more like an ios problem. But. I use android and write the code on a linux machine.
You need to mock the native module.
Thanks for the fast answer. But how should i mock it?
Refer to the jest docs: https://facebook.github.io/jest/docs/tutorial-react-native.html#mock-native-modules-using-jestmock
Ok, i will have a look. :) Thanks.
@oblador, for me, it's unclear how i should mock the native module. Because i don't know which. Please can you explain it with more details?
I had the same problem and at the end on android it works just mocking the library like that:
jest.mock('react-native-vector-icons/Ionicons', () => ({ ToolbarAndroid: 'ToolbarAndroid' }));
On the other hand, pretty much the same code on ios, with the TabBarItemIOS will complain with: Invariant Violation: There is no registered component for the tag TabBarItemIOS
This is the ios mock:
jest.mock('react-native-vector-icons/Ionicons', () => ({ TabBarItemIOS: 'TabBarItemIOS' }));
Do you know why?
@dbertella awesome, thanks. Looks good now. :)
You're problem looks very common. Maybe you can find help there: https://github.com/facebook/react-native/issues/2066 ?
@danbruegge Actually I found out that it was the TabBarIOS component that cause the problem, I had to mock it jest.mock('TabBarIOS', () => 'TabBarIOS') and then the snapshot went through. Still concern about it but it worked.
I was just having this issue and @dbertella suggestion worked for me :
jest.mock('react-native-vector-icons/MaterialIcons', () => { return {TabBarItemIOS:""}}) resolved my problem
Fixed it with:
jest.mock('react-native-vector-icons', () => {
const ActualTabBarIOS = require.requireActual('TabBarIOS');
const React = require('react');
return {
createIconSet: () => {
const Icon = class extends React.Component {
render() {
return jest.fn();
}
}
Icon.TabBarItem = ActualTabBarIOS.Item;
return Icon;
},
createIconSetFromFontello: () => {
return {
TabBarItem: ActualTabBarIOS.Item
}
},
createIconSetFromIcoMoon: jest.fn(),
}
});
Though I am working on TabBarIOS, but getting the same error
RNVectorIconsManager not available, did you add the library to your project and link with libRNVectorIcons.a? before the mock.
This code is just enough for my use case. In case if this helps anyone in the future.
I'm a littlebit lost here where do you put the jest.mock part if I place it inside the test file it doesn't seem to have any effect
@ParAnton you need to create a file with the mocks and add it to jest config
"jest": {
...
"setupFiles": [
"./path/to/mocks.js"
]
...
}
Most helpful comment
@danbruegge Actually I found out that it was the
TabBarIOScomponent that cause the problem, I had to mock itjest.mock('TabBarIOS', () => 'TabBarIOS')and then the snapshot went through. Still concern about it but it worked.