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

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.

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.

Why doesn't ref.current.focus() work when running tests via the #testing-library/react-native libary?

I'm attempting to write some tests for my react native app. A component in my app focuses a TextInput after a parent Pressable receives a press. I'm using a ref to identify and focus the TextInput element.
My desired functionality works just fine when running my app through expo, but my test is failing because it seems that the onFocus event is not being called.
Why isn't ref.current.focus() being called when running tests via the #testing-library/react-native library?
Here's my code:
Foo.js
import {Pressable, TextInput} from "react-native";
import {useRef} from "react";
const Foo = (props) => {
const inputRef = useRef()
return (
<Pressable testID={"pressable"} onPress={() => inputRef.current.focus()}>
<TextInput ref={inputRef} testID={"input"} onFocus={props.onFocus} />
</Pressable>
)
}
export default Foo;
Foo.test.js
import { render, screen, fireEvent } from '#testing-library/react-native';
import Foo from "./foo";
test('onFocus is called after press', () => {
const mockFocus = jest.fn();
render(<Foo onFocus={mockFocus} />)
// fireEvent(screen.getByTestId("input"), 'focus');
fireEvent.press(screen.getByTestId("pressable"));
expect(mockFocus).toHaveBeenCalled()
});
This test fails with the following message:
Error: expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
I created an issue on the RNTL GitHub page and received a response from a contributor. Copying and pasting here for easy reference for anyone who might stumble upon this thread.
This is expected as React Test Renderer which we use for rendering
does not support refs. Check #1006 for more details.
Since the behaviour of focus() triggering onFocus event would probably
involve roundtrip to native side (from JS side), then you actually
cannot test such behaviour using RNTL as we do not run native code (see
here for details).
That leaves you with following options:
Call fireEvent.focus to manually trigger onFocus on relevant
TextInput. Recommended in case focus assertion would be a part of a
step in a bigger test.
Use createNodeMock to pass ref creating function to render method, More details here. Recommended in case you
just want to assert pressing button triggers onFocus.

React native getInitialURL not nullify after use

After using Linking.getInitialURL() the URL stay there.
I am using react-native-router-flux to navigate.
when users log out I run
import { NativeModules } from 'react-native';
NativeModules.DevSettings.reload()
What happens is the react-navigation do Linking.getInitialURL()
and if there any result so it navigates automatically to the page.
how to reset Linking.getInitialURL() after use ?
happens only on android
React Navigation 5 provides an option to specify a custom getInitialURL method which you can use:
<NavigationContainer
linking={{
// ... linking config
getInitialURL() {
return YourCustomModule.getInitialURL();
},
}}
>
{/* content */}
</NavigationContainer>
https://reactnavigation.org/docs/navigation-container/#linkinggetinitialurl
For the implementation, since you're reloading the whole JS, the code cannot be in JS as the state is lost on reload. You'll need to write a custom native module where you can clear the initial URL when reloading.

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

How to use enzyme for react-native with jest

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.