Jest Unit test with React native for firebase analytics - react-native

I am new to jest unit test, I need advice on how to write a jest unit test with React native for cover the following lines of code:
export const logSeekerMeditationCancelReason = (scene, reason) => {
logEvent('cancel_reason', scene, { reason });
logForFBAnalytics(`cancel_reason_${reason}`); };
Can some one please help me. Thank you.

Related

Jest unit test fails everytime Vue component gets mounted

I am currently trying to write some unit tests for my web application that I made with Nuxt, Vue and Vuetify. I decided to use the Jest framework and the vue-test-utils to write unit tests, but it seems like Jest or vue-test-utils refuses to mount my components.
Example
Let’s take this very simple test where i shallowMount my component and see if the component renders a div:
require("jsdom-global")();
import AlbumHeader from "#/components/Album/AlbumHeader";
import { shallowMount } from "#vue/test-utils";
describe("AlbumHeader.vue", () => {
it("renders a div", () => {
const wrapper = shallowMount(AlbumHeader);
expect(wrapper.contains("div")).toBe(true);
});
});
When I run this unit test it always fails with the error:
TypeError: Cannot read property 'child' of undefined
I feel like the problem has something to do with Vuetify. But even after creating new Vuetify instances in my test and creating a localVue I still cannot get it to pass the test. I feel like I have read every article on this topic and none of them seem to help. This is also the first time I use this framework so I really do not have a clue where this problem takes place.
I hope someone can explain to me what i am doing wrong and how i can fix it, i would really appreciate that.

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 properly test if a Toast has been shown in react native using native base?

I am trying to write a test that checks if the screen is showing a Toast with an error message. The test passes, but there is a warning:
console.error
Warning: You called act(async () => ...) without await.
This could lead to unexpected testing behaviour, interleaving multiple act calls
and mixing their scopes. You should - await act(async () => ...);
The screen is working fine, I am just learning how to write tests. This is my test:
it('shows error correctly', async () => {
mockAxios.get.mockRejectedValueOnce(new Error('Async error'))
const { queryByText } = renderWithRedux(<DiscoverScreen />)
await waitFor(() => {
expect(queryByText(ErrorMessages.GeneralErrorToast)).not.toBeNull()
})
await waitForElementToBeRemoved(() => queryByText(ErrorMessages.GeneralErrorToast), { timeout: 5000 })
})
What am I not doing right? Definitely there is an issue with react native testing, because there are problems for certain async querying, especially when you have several of them. I found that here: https://github.com/callstack/react-native-testing-library/issues/379#issuecomment-720734366
I am using native base for showing the Toast, which is using Animated I think. Should I use jest.useFakeTimers() and how?
After researching how the Toast in native base works (this could be done when you open the source code in github - https://github.com/GeekyAnts/NativeBase/blob/master/src/basic/ToastContainer.js), I found that it uses Animated.timing.
So I had to find out how to deal with react native animations in tests. That article had a solution that worked for me: https://medium.com/#joncardasis/react-native-how-to-test-components-implementing-animated-with-jest-8cabb5fc2730
After I added the code in my jest setup file, this is how my test looks:
global.withAnimatedTimeTravelEnabled(async () => {
const { queryByText } = renderedComponent
await waitFor(() => {
expect(queryByText(ErrorMessages.GeneralErrorToast)).not.toBeNull()
})
global.timeTravel(Constants.ErrorToastDelay)
expect(queryByText(ErrorMessages.GeneralErrorToast)).toBeNull()
})
It works and now the test passes with no warnings!
One little adjustment in my jest configuration was also missing. I had to add this:
"testEnvironment": "jsdom"
I hope this could help someone else, too!

Had so issue with jest react-native and bugsnag

I tried run Jest unit tests on React-Native with Bugsnag, but I got error:
The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/en/configuration#testenvironment-string.
Consider using the "jsdom" test environment.
ReferenceError: window is not defined
1 | import React from 'react';
> 2 | import Bugsnag from '#bugsnag/react-native';
Solution which is working for me:
we need to add mock bugsnag interceptor to jestSetupFile.js
jest.mock('#bugsnag/react-native', () => ({
use(plugin) {
const boundary = plugin.init();
// we don't need the error boundary to swallow the errors, we want jest see them and fail the test
delete boundary.prototype.componentDidCatch;
return boundary;
}
}));
I fixed it with just mocking Bugsnag: jest.mock("#bugsnag/react-native", () => jest.fn());

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.