QUnit - sample

https://groups.google.com/d/topic/knockoutjs/GMDYFOq2-yg/discussion

by johnpapa

HTML

<script src="https://github.com/jquery/jquery-tmpl/raw/master/jquery.tmpl.js"></script>
<script src="https://github.com/SteveSanderson/knockout/raw/master/build/output/knockout-latest.debug.js"></script>
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css">
<ul data-bind="template: { name: 'itemsTmpl', foreach: items }"></ul>
<button id="addItem" data-bind="click: addItem">Add Item</button>

<script id="itemsTmpl" type="text/html">
    <li>
        <input data-bind="value: id" />
        <input data-bind="value: name" />
        <a href="#" data-bind="click: function() { viewModel.removeItem($data); }">Delete</a>
    </li>
</script>

<hr/>

<h1 id="qunit-header">Unit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>

CSS

input { width: 75px; }

JavaScript

function Item(id, name) {
    this.id = ko.observable(id);
    this.name = ko.observable(name);
}

var viewModel = {
    items: ko.observableArray([new Item(1, "One"), new Item(2, "Two")]),
    addItem: function() {
        this.items.push(new Item(0, "new"));
    },
    removeItem: function(item) {
        this.items.remove(item);
    }
};

ko.applyBindings(viewModel);

//tests

$(function() {
   //tests just against the view model
   module("view model tests");
 
        test("initial item length", function() {
            equals(viewModel.items().length, 2, "items length");
        });
        
        test("initial first item", function() {
           expect(2);
           equals(viewModel.items()[0].id(), 1, "first item's id is 1");
           equals(viewModel.items()[0].name(), "One", "first item's name is One");
        });
        
        test("initial second item", function() {
           expect(2);
           equals(viewModel.items()[1].id(), 2, "second item's id is 2");
           equals(viewModel.items()[1].name(), "Two", "second item's name is Two");
        });
            
        test("adding an item", function() {
            viewModel.addItem();
            expect(3);
            equals(viewModel.items().length, 3, "items length is now 3");
            equals(viewModel.items()[2].id(), 0, "new item's id is 0");
            equals(viewModel.items()[2].name(), "new", "new item's name is new");     
        });
        
        test("removing an item", function() {
           viewModel.removeItem(viewModel.items()[2]);
           expect(3);
           equals(viewModel.items().length, 2, "items length is back to 2");
           equals(viewModel.items()[1].id(), 2, "second item's id is still 2");
           equals(viewModel.items()[1].name(), "Two", "second item's name is still Two"); 
        });
       
   //act on the view model and verify UI changes appropriately
   module("view model -> view tests");
    test("inital display contains two list...