'Mocking jQuery $() and $ functions in jest
I have a set of tests for the functions in an ES6 class that use $.get()
. I was able to mock $.get()
. I'm working on testing another function in the same class that uses $.get()
and $(data, ownerDocument).find()
, and I haven't been able to figure out how to add mocking for the $().find()
function.
How I'm mocking $.get()
:
const jQuery = require(path/to/jquery);
jest.mock(path/to/jquery);
describe("Description", () => {
test("Test", () => {
// multiple tests with different mocks of $.get, so clearing
jQuery.get.mockClear();
jQuery.get.mockImplementation((path) => path);
// test function that uses $.get
});
});
Based on this section from the jest docs, I tried adding mocking for the jQuery constructor by using the 2 argument version of jest.mock
:
// jest.mock(path/to/jquery);
jest.mock(path/to/jquery, () => {
return jest.fn().mockImplementation(arg1, arg2) => {
return {
find: () => console.log('find'); // just to see if structure works
};
});
});
describe("Description", () =>
test("Test", () => {
jQuery.get.mockClear();
jQuery.get.mockImplementation((path) => path);
// test function that uses $.get() and $(...).find()
});
});
However, adding this broke the mocking of $.get()
and I started getting this error:
TypeError: cannot read property 'mockClear' of undefined
jQuery.get.mockClear()
^
Based on this article, what I believe I'm struggling with is the right way to mock functions in the $
namespace and the $.fn
namespaces at the same time.
This question talks about how to mock $.ajax
, and I do something like that to mock $.get
but I'm not sure if it would help me mock $(...).find()
as well.
Is there a way I can cleanly mock both functions I need simultaneously?
(As a side note, I'm not sure how I would create a Minimally Reproducible Example with jest, but if someone can point me to a way to do that, I'll make an MRE)
Solution 1:[1]
For future reference, I was able to resolve this by modifying the technique in the "Mock jQuery globally" portion of the accepted answer on this question. My resulting mock code looks like this:
//__mocks__/jquery.js:
const jQ = jest.requireActual("jquery");
const get = jest.fn((path) => {
return Promise.resolve(path);
});
const when = jest.fn((prom1, prom2, prom3, prom4) => {
return Promise.resolve();
});
const jQuery = jQ;
jQuery.get = get;
jQuery.when = when;
exports.jQuery = jQuery;
As I understand it, this is essentially a pre-ES6 version of the code provided in that answer. I'm using it as follows. I don't have to worry about mocking $().find
because the mock uses the real implementation of the find
function.
// foo_ut.js
const jQuery = require("../__mocks__/jquery").jQuery;
describe("Description", () =>
test("Test", () => {
jQuery.get.mockClear();
// test function that uses $.get() and $(...).find()
});
});
Solution 2:[2]
I use JSDom to inject the JQuery package into my window.
var jsdom = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
var window = dom.window;
var $ = require("jquery")(window);
expect($).to.be.not.undefined;
I also wrote an article about how i did it for vitest, should be similar to jest.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jon G |
Solution 2 | alexcodes |