How to use enzyme for react-native with jest - react-native

I have followed –or tried to– several posts on how to do it, including the airbnb enzyme's guide for (separatedly) react-native and jest. (E.g: https://medium.com/#childsmaidment/testing-react-native-components-with-enzyme-d46bf735540#.6sxq10kgt, https://blog.callstack.io/unit-testing-react-native-with-the-new-jest-i-snapshots-come-into-play-68ba19b1b9fe#.4iqylmqh5 or How to use Jest with React Native)
But I keep getting lots of warnings (I have multiple set of concurrent tests) whenever I try to render (not mount, it crashes) any native component. Warnings are always about a native prop not being recognised.
Warning: Unknown props `focus`, `secureTextEntry` on <TextInput> tag. Remove these props from the element.
in TextInput (created by TextInput)
in TextInput (created by PasswordInput)
Anyone who has a set up working, recognises how to remove the warning or how to solve it?
Thanks

So I know this is a bit old but I was having issues with Jest, Enzyme, and React Native and I found this post - hopefully this solution will help.
To start with - Enzyme doesn't support mounting React Native and only supports shallow rendering. This wasn't good enough for me as I needed end-to-end tests from the component to the api which lead me to react-native-mock-render. What this does is allow us to run react native inside a browser environment which let's us test using Enzyme - all the calls for React Native and the components work as you would expect.
To set this up you'll need to install JSDOM, react-native-mock-render, Enzyme 3.0+, and Jest 20.0.0+. And then inside your jest setup file (which is specified in your package.json) include the following code:
const { JSDOM } = require('jsdom');
const jsdom = new JSDOM();
const { window } = jsdom;
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter(prop => typeof target[prop] === 'undefined')
.map(prop => Object.getOwnPropertyDescriptor(src, prop));
Object.defineProperties(target, props);
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: 'node.js',
};
copyProps(window, global);
// Setup adapter to work with enzyme 3.2.0
const Enzyme = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');
Enzyme.configure({ adapter: new Adapter() });
// Ignore React Web errors when using React Native
console.error = (message) => {
return message;
};
require('react-native-mock-render/mock');
And that's it - you're all setup to mount components in Enzyme and test them.
If you want to see a full sample check out react-native-mock-render-example. This is working with React 16, React Native 0.51, and Enzyme 3.2.

In order to unit test your component with jest you can use enzyme-to-json
npm install --save enzyme-to-json
then your test would look like this:
import { shallow } from 'enzyme';
import { shallowToJson } from 'enzyme-to-json';
import MyComponent from './MyComponent';
it('should render component', => {
expect(shallowToJson(shallow(<MyComponent />))).toMatchSnapshot();
});

I'm not sure regarding your case with react-native.
I can share my case of using jest + enzyme with standard react.
When I needed to test some component and isolate it from others I used jest.mock, e.g.
jest.mock('../ComponentToBeMocked', () => {
return () => null;
});
Initially I found examples when the second argument (a function) should return just a string representing a name of the mocked component. But in that case I saw that distracting Unknown props warning.

Related

Mocking Native Module with React Native Jest

I want to mock a native module for jest test case.
I tried this -
jest.mock('NativeModules', () => {
return {
UtilityFunc.getConstants: jest.fn(),
};
});
I know we can't access a property in such a way.
My Native module is UtilityFunc and my property is getConstant that returns appversion.
react-native-device-info - I'm using this library as native module for internal stable usage.
Pls share how to use mock with nativeModules in react native.

Expo React Native: Code Splitting Incompatible Web Packages

I have a component that uses #stripe/stripe-react-native named NativeCheckout.
This package does not work on web (Chrome), and when I import it I get an error:
Failed to compile
/home/joey/Projects/project/project_frontend/node_modules/#stripe/stripe-react-native/lib/module/components/StripeProvider.js
Module not found: Can't resolve '../../package.json' in '/home/joey/Projects/project/project_frontend/node_modules/#stripe/stripe-react-native/lib/module/components'
So if I run it in my browser, I do not want this component. This component is only rendered on native apps. I have found three alternative ways to import the Component. If my code is working fine then I add any of the follow lines, the above error is happening. I thought this would not load in the problem code.
const loadNative = async () => {
await import("./NativeCheckout")
}
const NativeCheckout = lazy(() => import("./NativeCheckout"));
const NativeCheckout = lazy(() => import("./NativeCheckout"));
Does anyone know a way to make this work?
TIA

result.current is null when using renderHook () Custom Hook to test custom hook in react-native using jest and testing-library

For My project I am using one custom hook for navigation some of my screens as from one screen to another screen based on the parameters provide to the function of custom hook. How could I Unit Test it for React Native Custom
const {result} = renderHook(() => {useShoppingCartNavigator()});
The problem is I am getting result.current as void and unable to call function of the hook
But according to the doc it should be like
result.current.customHookFn();
The callback inside your renderHook is not returning anything because you wrapped your customHook on curlybraces. It should be
const {result} = renderHook(() => useShoppingCartNavigator());

React native Enzyme Mount Native elements "unrecognized in this browser"

React Native app with Expo.
Installed Jest and Enzyme
Want to run Enzyme Mount on the component so I can test state updates.
I have this simple test
describe("State checking", () => {
test("Make sure that State gets added from Route params", () => {
const component = mount(<Categories/>);
const instance = component.instance();
console.log(instance);
})
})
When running this, I get this error from the test:
Warning: <View /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
Warning: The tag <View> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
What is going on here? Does it not recognize that I am using React Native?
I have researched this issue but get nothing useful.
Thank you for your time.

Can we use enzyme mount for testing react-native redux connected(higher order) components which are written in typescript

To test the react-native redux connected(higher order) components,we need to use enzyme mount for accessing mapStateToProps,mapDispatchToProps etc...As enzyme mount api uses jsdom .Is mount supported in react-native or not?.
I went through different articles and it was mentioned that we can use mount for testing react-native redux connected components.
In my jest setup file I have given this piece of code.
/** jest setup file **/
import { configure } from "enzyme";
import EnzymeAdapter from "enzyme-adapter-react-16";
configure({ adapter: new EnzymeAdapter() });
/**
* Set up DOM in node.js environment for Enzyme to mount to
*/
const { JSDOM } = require("jsdom");
const jsdom = new JSDOM("");
const { window } = jsdom;
function copyProps(src: any, target: NodeJS.Global) {
Object.defineProperties(target, {
...Object.getOwnPropertyDescriptors(src),
...Object.getOwnPropertyDescriptors(target)
});
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: "node.js"
};
copyProps(window, global);
const originalConsoleError = console.error;
console.error = (message: string) => {
if (message.startsWith("Warning:")) {
return;
}
originalConsoleError(message);
};
If I commented originalConsoleError method.,even though test case got passed we are getting this error.
console.error node_modules/react-dom/cjs/react-dom.development.js:506
Warning: <Text /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
in Text (created by Text)
in Text (at create-icon-set.js:92)
in Icon (created by Avatar)
in Avatar (created by WrapperComponent)
in WrapperComponent
Can we really use mount for testing react-native higherorder
components.If not, how can we test using jest and enzyme?If yes, how
to avoid these errors without suppressing it like originalConsoleError
method?