How to mock DOM element in Javascript/JQuery using Jest

Mock JQuery Selector using Jest

Jest is a JavaScript testing framework maintained by Facebook, Inc. designed and built by Christoph Nakazawa with a focus on simplicity and support for large web applications. It works with projects using Babel, TypeScript, Node.js, React, Angular, Vue.js and Svelte. Wikipedia

In this post, I will show you how to use the jest mocking feature to test dom elements without loading the actual dom. Before that let’s understand why mocking is important

Why mocking

Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behaviour or state of external dependencies.

Let’s suppose you have the following code in javascript

const $ = require("jquery");
function showHide() {
    let element = $('#test');
    const top = element[0].getBoundingClientRect().top;
    if (top >= 100) {
        element[0].addClass("success");
    } else {
        element[0].removeClass("failed");
    }
}

module.exports = { showHide };

You can see that in the above function we are using the JQuery selector and also calling JQuery function addClass and removeClass method of JQuery. If you want to test the above function then either you can load the real HTML or you can use the jest mocking feature to avoid loading the DOM (external dependencies).

In the post, I will show how to test the above function without loading the actual DOM.

const $ = require("jquery");

const { showHide, showTooltip } = require("../playground");

describe('Jquery DOM ', () => {

    it('should call document.getElementById', () => {

        const getBoundingClientRectSpy = jest.fn(() => ({ top: 100 }));
        var myObj = [{
            name: 'test',
            getBoundingClientRect: getBoundingClientRectSpy,
            addClass: jest.fn(),
        }];
        jest.spyOn($.fn, 'init').mockReturnValue(myObj);
        showHide();
        expect(getBoundingClientRectSpy).toBeCalled();


    })
    it('should call document.getElementById2', () => {

        const getBoundingClientRectSpy = jest.fn(() => ({ top: 10 }));
        const removeClass = jest.fn();
        var myObj = [{
            name: 'test',
            getBoundingClientRect: getBoundingClientRectSpy,
            addClass: jest.fn(),
            removeClass
        }];
        jest.spyOn($.fn, 'init').mockReturnValue(myObj);
        showHide();
        expect(getBoundingClientRectSpy).toBeCalled();
        expect(removeClass).toBeCalledTimes(1);


    })
    it('Should be mocked through fn.find()',function(){
        var mockElement = {
            parentNode:true,
            expression:"#myId .myClass"
        };
        var fn_find = $.fn.find;
        var spy = jest.spyOn($.fn, "find").mockImplementation((expression)=>{
            if(expression===mockElement.expression){
                return mockElement;
            }
            return fn_find(expression);
        });
        var foundElement = $(mockElement.expression);
        expect(foundElement).toBe(mockElement);
        $.fn.find = fn_find;
    });
    it('Should be mocked through document.getElementById',function(){
        var mockElement = {
            id:"someId", 
            parentNode:true
        };
        var document_getElementById = document.getElementById;
        var spy = jest.spyOn(document, "getElementById").mockImplementation((id)=>{
            if(id===mockElement.id){
                return mockElement;
            }
            return document_getElementById(id);
        });
        var foundElement = $("#"+mockElement.id);
        expect(foundElement[0]).toBe(mockElement);
        document.getElementById = document_getElementById;
    });

})

Reactions

Post a Comment

0 Comments

Close Menu