How to disable React Native YellowBox messages in jest tests - react-native

I know how to disable YellowBox warning when running in the device:
YellowBox.ignoreWarnings(ignoredYellowBox);
But I don't know how to silence them in a jest test. There are some deprecation warnings that we cannot deal with atm and they are making our tests very noisy. I'd rather not block every YellowBox warning from our tests, but if necessary, that would work too.

It is a pretty annoying thing. This is what we came up with:
const warnings = [
'Warning: NetInfo has been extracted from react-native core and will be removed in a future release.',
'inside a test was not wrapped in act(...).',
];
const oldError = console.error;
jest.spyOn(console, 'error').mockImplementation((...args) => {
const string = args.join(' ');
if (warnings.some(warning => string.match(warning))) return;
oldError(...args);
});
Add that snippet to your jest setup file, and edit the warnings array as appropriate for your situation.

For future readers, there is a simple way to do this.
jest.spyOn(console, 'warn').mockImplementation(() => {})
jest.spyOn(console, 'error').mockImplementation(() => {})
For TypeScript:
jest.spyOn(console, 'warn').mockImplementation(() => undefined)
jest.spyOn(console, 'error').mockImplementation(() => undefined)
Remember that by using an approach like this you are disabling all console errors and warnings.
If you want to keep other errors and warnings, just use the first answer in this question.

Related

TypeError: Cannot read properties of undefined (reading 'get')

Hi I'm trying to mock react-native modules, for example Dimensions.get, Stylesheet.create, Platform.OS, etc. I tried all the ways I found but none of them work, it seems like it doesn't detect the mocks for react-native, but the mocks from other libs work fine, like react-native-device-info. For example this and its variants don't work:
const Dimensions = {
get: jest.fn().mockReturnValue({width: 100, height:100})
}
I had the same problem. Here is how i resolved it (credit to my senior developer).
Problem :
My console was displaying this error :
Error Message
Solution 1:
I added the code below into my test file.
jest.mock("react-native-status-bar-height", () => "height");
jest.mock("react-native-status-bar-height", () => ({
getStatusBarHeight: jest.fn().mockReturnValue(54),
}));
it("renders correctly", () => {
const elem = renderer.create(<MyComponent />).toJSON();
expect(elem).toMatchSnapshot();
});
Solution 2:
I added the code below in my jest.config.js, this code can be also placed into the packages.json under "Jest" according where you decided to write your configuration.
transformIgnorePatterns: [
"<rootDir>/node_modules/(?!(#?react-native|react-native-status-bar-
height)",
]
I would say the solution 2 is cleaner, and no need to repeat it for each test, but solution 1, you can choose the value of the Status Bar.
Hope this helped !

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!

How to disable the "Global error handler detected" warning in vue test utils

I'm creating async tests using vue-test-utils and jest using the approach described here:
https://vue-test-utils.vuejs.org/guides/#what-about-nexttick
where you set Vue.config.errorHandler = done like shown below
test('Then we are shown events in EventCreate component', done => {
Vue.config.errorHandler = done
This is working and when an error is thrown in a promise handler in a component my tests will fail. However I'm getting this warning.
console.error node_modules/#vue/test-utils/dist/vue-test-utils.js:1421
[vue-test-utils]: Global error handler detected (Vue.config.errorHandler).
Vue Test Utils sets a custom error handler to throw errors thrown by instances. If you want this behavior in your tests, you must remove the global error handler.
I don't want to spam my test output with this warning. Is there a way to disable it?
This is how I did
beforeEach(() => {
jest.spyOn(console, 'error');
console.error.mockImplementation(() => 'some error');
});
afterEach(() => {
console.error.mockRestore();
});

Any way to avoid memory leaks with shallowMount in vue-test-utils?

We have a custom unit testing setup for vue that works on Node, Mocha and jsdom package which simulates browser environment (no webpack, karma). We have wrote about 3k specs already (big app with hundreds of components), and now when mocha is running it becomes slower and slower, and eventually the process just hangs. We thought that maybe there is a memory leak in "jsdom", so we changed it to a "domino" (alternative package), but it still hangs.
We checked the heap memory usage and it just keeps growing (up to 1.5 GB!).
So we think that the problem is with either vue or vue-test-utils. It looks like each time we use mount/shallowMount it needs to be destroyed/unmounted after each test to release memory?
Any ideas? Thanks in advance!
The best way i found is to set the wrapper to null after the test suit
example below using mocha
describe(" View ", () => {
let wrapper;
beforeEach() {
wrapper = mount(Com.Vue, { localVue }) ;
});
after( ()=> {
wrapper = null ;
});
});
It made a huge difference in my case was having memory leaks of about 8gb after running test multiple times now using about 300mb
JavaScript has automatic memory management and garbage collection. If you get rid of all references to a piece of data, the memory will be reclaimed
Hope this helps
Thanks for voting
make sure that you call wrapper.destroy(); in afterEach method and if you use mount or shallowMount in tests bodies call wrapper.destroy(); before mount the new Vue instance.
it works for me.
describe(" View ", () => {
let wrapper;
beforeEach() {
wrapper = mount(Com.Vue, { localVue }) ;
});
afterEach(() => {
wrapper.destroy();
});
});

Detox test failed on typeText if text is "long"

Have some interesting problem with detox testing!
All configs are clearly right (cause in another case it wasn't even work, yeah?)
Work with Mocha tests, and yes, it works.
I use redux to work with state and custom components in my main component.
<OpacityInput
idTest="LoginEmailInput"
icon="account"
placeholder="Login..."
value={this.props.email}
onChangeText={this.emailChanged}
/>
So i pass all data by props to component (testID and value for inputs i pass too)...and here is my test (i make two restricted test to catch an error)
it('should find input login', async () => {
await expect(element(by.id('LoginEmailInput'))).toBeVisible()
})
it('should type text login', async () => {
await element(by.id('LoginEmailInput')).typeText('test#test.com')
})
And it is really interesting...if i want to type 'a'(two-three symbol max) - it is ok! Text passing with no problem! But when i change my 'a' to real e-mail...it crash!
I have a strange feeling that detox has only few seconds for typeText, and if it can't so...it crash :)
Here is the error after crash. I used
detox test —loglevel trace
for details. Test on IOS 6