42

I need to unit test some DOM manipulation functions with Jasmine (currently I run my tests in the browser and with Karma)

I was wondering what the best approach would be to do this?

For example, I can mock and stub the window and document objects and spyOn a couple of their functions. But this doesn't really look like an easy solution, so thats why I'm asking this question!

Or is there a better way (not using jasmine maybe) to do this ?

Thanks a lot

urosc
  • 1,938
  • 3
  • 24
  • 33
Jeanluca Scaljeri
  • 26,343
  • 56
  • 205
  • 333
  • 1
    Check out this question http://stackoverflow.com/questions/7672389/testing-dom-manipulating-in-jasmine-test – xverges Sep 25 '13 at 08:34
  • 1
    Another library with DOM matchers that I found useful is [jasmine_dom_matchers](https://github.com/charleshansen/jasmine_dom_matchers) by Charles Hansen. The advantage is that it's based purely on DOM APIs, no jQuery requirements. I've just published a small plugin to integrate it with Karma [here](https://www.npmjs.com/package/karma-jasmine-dom-matchers). – Yaroslav Admin Jul 04 '17 at 15:33

2 Answers2

30

I've been using a helpful addition to jasmine called jasmine-jquery available on github.

It gives you access to a number of useful extra matcher functions, to assert jquery objects and their properties.

In particular the features I have found useful so far are asserting on attributes of dom elements, and spying on events such as clicks and submits...

Here is a somewhat contrived example... :)

describe("An interactive page", function() {
    it("'s text area should not contain any text before pressing the button", function() {
        expect(Page.textArea).toBeEmpty();
    });

    it("should contain a text area div", function() {
        expect(Page.textArea).toBe('div#textArea');
    });

    it("should append a div containing a random string to the text area when clicking the button", function() {
        var clickEvent = spyOnEvent('#addTextButton', 'click');
        $('button#addTextButton').click();

        expect('click').toHaveBeenTriggeredOn('#addTextButton');
        expect(clickEvent).toHaveBeenTriggered();

        expect($('div.addedText:last')).not.toBeEmpty());
    });
});

and here is the code:

var Page = {
    title : 'a title',
    description : 'Some kind of description description',
    textArea : $('div#textArea'),
    addButton : $('button#addTextButton'),


    init : function() {
        var _this = this;
        this.addButton.click(function(){
        var randomString = _this.createRandomString();
            _this.addTextToPage(randomString);
        });
    },

    addTextToPage : function( text ) {
        var textDivToAdd = $('<div>').html('<p>'+text+'</p>');

        this.textArea.append( textDivToAdd );
    },

    createRandomString : function() {
        var text = "";
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

        for( var i=0; i < 5; i++ )
             text += possible.charAt(Math.floor(Math.random() * possible.length));

        return text;
    },
};

Page.init();

I've found jasmine to be really flexible and agreeable to use so far, I always appreciate pointers for making it the code better though!

tlcowling
  • 1,034
  • 1
  • 10
  • 11
  • For the DOM manipulation I don't use jQuery. I guess that is a problem then ? – Jeanluca Scaljeri Apr 25 '13 at 08:01
  • I'd assume it'd be fine - jQuery here is probably only being used for fetching elements; in general, all of these libraries are just doing the same kind of DOM manipulation underneath the hood. – dchang Sep 25 '13 at 16:37
4

I was looking for something for myself and finally I made a little library with 19 custom matchers. Maybe you'll find it helpful. https://github.com/devrafalko/jasmine-DOM-custom-matchers

Paweł
  • 4,238
  • 4
  • 21
  • 40