How to mock HMSLocation with jest - jestjs

I'm trying to mock the #hmscore/react-native-hms-location with jest. The function that one of my providers uses is HMSLocation.FusedLocation.Native.hasPermission(), but in one of my test I always get the following:
TypeError: Cannot read property 'Native' of undefined at call (C:\laragon\www\qmy-project\providers\LocationProvider.js:65:57)
I've tried to mock all the Library like this:
jest.mock('#hmscore/react-native-hms-location');
Even like this another way:
jest.mock('#hmscore/react-native-hms-location', () => {
const original = jest.requireActual('#hmscore/react-native-hms-location');
return original;
});
Always is the same. Any help please?

Related

How to mock fetch call inside of childĀ“s componentDidMount with Jest/Enzyme [duplicate]

I would like to test a small React web app where I use the global fetch method.
I tried to mock fetch in this way:
global.fetch = jest.spyOn(global, 'fetch').mockImplementation(endpoint =>
Promise.resolve({
json: () => Promise.resolve(mockResponse)
})
);
... but the mock seems to be ignored, while the built-in fetch seems to be used: Error: connect ECONNREFUSED 127.0.0.1:80 ... looks like a failed call to the built-in fetch.
I then tried to use jest.fn instead of jest.spyOn:
global.fetch = jest.fn(endpoint =>
Promise.resolve({
json: () => Promise.resolve(mockResponse)
})
);
... and was surprised to see a different error. Now the mock seems to be taken into consideration, but at the same time is not working correctly:
TypeError: Cannot read property 'then' of undefined
8 | this.updateTypes = this.props.updateTypes;
9 | this.updateTimeline = this.props.updateTimeline;
> 10 | fetch('/timeline/tags')
| ^
11 | .then(res => res.json())
12 | .then(tags => tags.map(tag => <option value={tag} key={tag} />))
13 | .then(options => options.sort((a, b) => a.key.localeCompare(b.key)))
I find the documentation of Jest and React Testing Library a bit confusing, honestly. What might be the problem with what I am doing?
Edit
The React component I am trying to test is called "App", was generated with Create React App, and was changed to include a call to fetch. I can gladly provide the code for this component, but I believe that the problem lies in the tests.
At the beginning of my App.test.js file, I import React from 'react';, then import { render, fireEvent, waitFor, screen } from '#testing-library/react';, and finally import App from './App';. I subsequently attempt to mock fetch in one of the ways I described, and then declare the following test:
test('renders a list of items, upon request', async () => {
const app = render(<App />);
fireEvent.click(screen.getByText('Update'));
await waitFor(() => screen.getByRole('list'));
expect(screen.getByRole('list')).toBeInTheDocument();
expect(screen.getByRole('list')).toHaveClass('Timeline');
});
Finally, I end my test file with global.fetch.mockRestore();.
That there's ECONNREFUSED error instead of fetch is not defined means that fetch has been polyfilled. It's not a part of JSDOM and isn't polyfilled by Jest itself but is specific to current setup. In this case the polyfill is provided by create-react-app.
It's always preferable to mock existing global function with jest.spyOn and not by assigning them as global properties, this allows Jest to do a cleanup. A thing like global.fetch = jest.spyOn(global, 'fetch') should never be done because this prevents fetch from being restored. This can explain TypeError: Cannot read property 'then' of undefined error for seemingly correctly mocked function.
A correct and safe way to mock globals is to mock them before each test and restore after each test:
beforeEach(() => {
jest.spyOn(global, 'fetch').mockResolvedValue({
json: jest.fn().mockResolvedValue(mockResponse)
})
});
afterEach(() => {
jest.restoreAllMocks();
});
There should be no other modifications to global.fetch in order for a mock to work correctly.
A preferable way to restore mocks and spies is to use configuration option instead of jest.restoreAllMocks because not doing this may result in accidental test cross-contamination which is never desirable.
Another reason for TypeError: Cannot read property 'then' of undefined error to appear is that Jest incorrectly points at fetch line, and the error actually refers to another line. This can happen if source maps don't work correctly. If fetch is mocked correctly and there are other then in the same component, it's a plausible explanation for the error.

Mock 'fs' module in jest

I'm trying to mock the fs module like so:
jest.mock('fs');
And as seen in this post - Mock fs function with jest
I should be able to treat the functions inside the module as jest.fn() and use - fs.existsSync.mockReturnValue(false); for instance.
That however does not seem to work and typescript gives me a bunch of errors.
All I want to do is assert a couple of functions like mkdirSync to have been called times or with some parameters and I seem to be running into this error -
'The "path" argument must be one of type string, Buffer, or URL. Received type undefined'
I tried to add fs.ts to the __mocks__ folder and mock it there - but that was no luck.
The file I am trying to test is a class and it imports fs. I am creating a new class instance in the beforeEach jest method.
So generally speaking, I don't really care to create a file or see if it exists, I wish to have a mocked return value or an implementation and just check with what parameters the fs module functions have been called.
It appears that running jest and mocking the file system in any way results in a conflict as jest is also using the fs module to handle the run.
The only solution i have found to overcome this issue:
export class SomeClass {
fs: typeof fs;
constructor() { this.fs = fs }
///code
}
Mock the fs methods like so in a test:
someClass.fs = {
mkdirSync: jest.fn()
} as any;
Assertion:
expect(someClass.fs.mkdirSync).toBeCalledWith('parameters');

How i can mock Reselect functions with jest?

I try to test my saga and i have some problems with testing select.
I want to mock createSelector from reselect, but i can't do this, because i have this error:
Cannot read property \'module\' of undefined
my reselect:
//R - is ramda
export const selectFilters = createSelector(R.path(['notification', 'filters']), (filters) => filters)
my saga:
//module gives me error because selectFilters returns undefined
const {module, orderByDate} = yield select(selectors.selectFilters())
You have to pass the reference to of the selector the the select effect. In your saga, you are actually calling the selector, and then passing the return value. If you do it properly, you don't have to mock the selector.
Modify your code like this to fix the error:
const {module, orderByDate} = yield select(selectors.selectFilters)

TypeError: Connot read property 'render' of undefiend while testing a js on node js using mocha and chai

I am doing some testing on my js function and it is my first time doing this and I am getting an error of:
TypeError: Cannot read property 'render' of undefined
I am using chai and mocha. Here is my test code
test1.test.js
it('should return all the data based on the given appname' , function () {
assert.isArray(acc.fetchData().getKeys());
})
This is what on my js function:
exports.fetchData = function (req, res) {
'use strict';
res.render('pages/test1', {
test: a.getKeys(),
arrayToPull: rootValueCombination
});
};
I tried using supertest but I have no luck. I used istanbul as a code coverage which is a bit odd as i am getting 100% but I am getting failed on mocha test.
You are not passing a parameter to fetchData
assert.isArray(acc.fetchData().getKeys());
and res is the second parameter of the function. You need to pass the correct variable to the function, the one which has a render function.

Undefined when trying to use Spy

Using my code:
it('should start application only once', function(done){
var spy = sinon.spy(server, 'startup');
var calledOnce = spy().calledOnce;
calledOnce.should.be.true;
done();
});
I get the error:
Cannot read property should of undefined.
The calledOnce variable is undefined. I'm doing something wrong in how I setup the spy and use it. How can I fix this?
Startup is a method in my object that I exported from a server.js file.
If you want to see if a particular function/method has been called, you need to spy on it before it gets called (otherwise the spy won't know about it):
var server = ...
var spy = sinon.spy(server, 'startup');
server.startup(...);
spy.calledOnce.should.be.true;

Resources