Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unit testing custom knockoutjs binding

How can I unit test this knockoutjs binding where I call a certain function 'myValueAccessor' when the element is swiped on my touchpad?

I am also unsure what the unit should or is able to test at all here.

It would be ok for the first time to assert wether myValueAccessor is called.

But how can I trigger/imitate or should I say mock... the swiperight event?

ko.bindingHandlers.tap = {
    'init': function (element, valueAccessor) {
        var value = valueAccessor();    

        var hammertime1 = Hammer(element).on("swiperight", function (event) {
            $(element).fadeOut('fast', function () {
                value();
            });
        });
    }
};

 self.myValueAccessor = function () {
    location.href = 'set a new url'
};

UPDATE

I have put here my unit test with mocha.js

I can outcomment the 'value()' in the binding but still the test succeeded thats odd.

Is it not correct to put this (as a test):

function (element,args) {
                    alert('assertion here');
                }

as a 3rd parameter into the ko.test function?

  ko.bindingHandlers.tap = {
                    'init': function (element, valueAccessor) {
                        var value = valueAccessor();

                        var hammertime1 = $(element).on("swiperight", function (event) {
                            $(element).fadeOut('fast', function () {
                                //value();
                            });
                        });
                    }
                };

                // Subscribe the swiperight event to the jquery on function
                $.fn.on = function (event, callback) {
                    if (event === "swiperight") {
                        callback();
                    }
                };

                // Subscribe the fadeOut event to the jquery fadeOut function
                $.fn.fadeOut = function (speed, callback) {
                    callback();
                };


                ko.test("div", {
                    tap: function () {
                        assert.ok(true, "It should call the accessor");
                    }
                }, function () {
                });

UPDATE:

custom.bindings.js:

define(['knockout','hammer'], function (ko,Hammer) {
    return function Bindings() {

        ko.bindingHandlers.tap = {
            'init': function (element, valueAccessor) {
                var value = valueAccessor();

                var hammertime1 = Hammer(element).on("swiperight", function (event) {
                    $(element).fadeOut('fast', function () {
                        value();
                    });
                });
            }
        };
    };
});

unittest.js:

how can I connect this code to knockout in my test?

UPDATE

The Bindings is injected via require.js from my bindings.js file:

describe("When swiping left or right", function () {
            it("then the accessor function should be called", function () {

                ko.bindingHandlers.tap = new Bindings();

                Hammer.Instance.prototype.on = function (event, callback) {
                    if (event === "swiperight") {
                        callback();
                    }
                };

                $.fn.fadeOut = function (speed, callback) {
                    callback();
                };
                var accessorCalled = false;
                ko.test("div", {
                    tap: function () {
                        accessorCalled = true;
                    }
                }, function () {
                    assert.ok(accessorCalled, "It should call the accessor");
                });

            });
        });

bindings.js

define(['knockout','hammer'], function (ko,Hammer) {
    return function () {

        return {
            'init': function (element, valueAccessor) {
                var value = valueAccessor();

                var hammertime1 = Hammer(element).on("swiperight", function (event) {
                    $(element).fadeOut('fast', function () {
                        value();
                    });
                });
            }
        };
    };
});

myviewmodel.js

...

ko.bindingHandlers.tap = new Bindings();

...
like image 773
HelloWorld Avatar asked May 27 '13 13:05

HelloWorld


1 Answers

You can check my binding collection for how to test https://github.com/AndersMalmgren/Knockout.Bindings/tree/master/test

This is my function that all my tests using

ko.test = function (tag, binding, test) {
    var element = $("<" + tag + "/>");
    element.appendTo("body");
    ko.applyBindingsToNode(element[0], binding);
    var args = {
        clean: function () {
            element.remove();
        }
    };
    test(element, args);

    if (!args.async) {
        args.clean();
    }
};

edit: Sorry forgot mocking, you just do

$.fn.on = function() {
}

I do not know what exact logic you want to test in that code since there hardly is any, but something like this http://jsfiddle.net/Akqur/

edit: May you get confused where i hook up your binding? Its done here

{ 
   tap: function() {
      ok(true, "It should call the accessor");
   }
}

I tell ko to hook up a "tap" binding and instead of hooking in up to a observable I use a mocking function, when your custom bindnig calls value() from the fadeout function the test assert will fire

edit: Maybe this approuch makes more sense to you? http://jsfiddle.net/Akqur/5/ Note that it only works if your code is executed synchronous

edit: Here i use the third argument of ko.test http://jsfiddle.net/Akqur/8/

like image 160
Anders Avatar answered Oct 18 '22 06:10

Anders