Test

This page shows Test in action, simulating adding, editing, dragging, and deleting todos in the Todo Demo below. It also provides a walk through of the test code.

This page loads in test mode. Make sure your popup blocker is turned off. You'll notice the JavaScriptMVC Console loads in a separate window.

This demo tests the Controller introduced in the Controller Demo. This guide will be easier after you've read through the Controller Demo code walkthrough. Here's what's covered in this page:

Download the demo

Related

Learn, API, Demo

Running the demo

To run the demo, you need to run the collection of functional tests.

2. Click the play icon

1. Click the Functional tab

Code walkthrough

Creating a controller test

A TodoController manages the event handlers for the Todo Demo shown above. The Controller Demo page goes over the TodoController in detail.

To test a controller, use a Controller Test. Controller tests are subclasses of Functional Tests, so they belong in the 'test/functional' directory. This test file is named todos_controller_test.js. Initialize the test as shown.

new Test.Controller('todos',{ ... tests ... });

Testing mouseover

The TodoController has actions that respond to a user mousing over and out of a todo element. The following displays the behaviors and how they are tested.

Behavior How to test
Mousing over a todo causes the background color to change Simulate a mousover and assert the color changed correctly
Mousing out of the todo causes the background color to be restored Simulate a mouseout and assert the color change is gone
test_mouseover : function(){
    // simulate mouseover for the first todo
    // params contains an object with the event and element
    var params = this.TodoMouseover();
    // check the expected color matches the todo's actual background color
    this.assert_equal("#8fba3c", params.element.style.backgroundColor);
},
test_mouseout : function(){
    // simulate mouseout
    var params = this.TodoMouseout();
    // check the background color has been removed
    this.assert_equal('', params.element.style.backgroundColor);
},

Testing checkboxes

Another TodoController action turns the text color gray whenever the checkbox is clicked. Here's how we'll test it:

Behavior How to test
Clicking the checkbox turns the text gray Simulate clicking the checkbox and assert the color changed correctly
Unchecking the checkbox restores the color Simulate clicking the checkbox again and assert the color change is removed
test_check : function() {
    // simulate clicking the checkbox
    // params has the todo element
    var params = this.TodoCheckClick();
    // assert the color change occurs as expected
    this.assert_equal("#808080", params.element.parentNode.style.color);
},
test_uncheck : function() {
    // click the checkbox again to uncheck it
    var params = this.TodoCheckClick();
    // assert the color change goes away
    this.assert_equal('', params.element.parentNode.style.color);
},

Testing edit

Clicking a todo makes it editable, and clicking out of it saves your changes. This functionality is controlled by several TodoController actions.

Behavior How to test
Clicking the a todo's text makes it editable Simulate clicking the label element and check the label has a descendent element (the input)
Clicking out of the input saves the changed todo Modify the todo by writing something in the input. Then simulate a blur event and check the label element was modified.
test_edit : function(){
    // simulate clicking the text for the first todo
    var params = this.TodoLabelClick();
    // assert the class and nodeType have been changed to an input element
    this.assert_equal('working', params.element.className);
    this.assert_equal(1, params.element.firstChild.nodeType);
    // grab the input element
    var input = Query('.todo label input')[0];
    // delete the last word in the todo (\b is backspace), then write 'to fly'
    // call the next function when Write is complete
    this.Write(input, {text: '\b\b\b\b\b\b\b\b\b\b\b\b\bto fly', 
        callback: this.next_callback()});
},
edit_after_write : function() {
    var input = Query('.todo label input')[0];
    // has the correct text been written?
    this.assert_equal("Learn to fly", input.value);
    // simulate a blur action (clicking out of the input)
    var params = this.TodoLabelInputBlur();
    // check if the text has been saved in the todo
    this.assert_equal("Learn to fly", Query('.todo label')[0].innerHTML);
},

Testing todo creation

The next test is for the interactions that lead to creating a new todo. Several TodoController actions control this functionality.

Behavior How to test
Clicking the input box makes the "type new todo here" text to disappear Simulate a focus event on the input, assert the input is blank
After writing in the input, clicking out of the input saves the todo Write text in the input, simulate a blur event, and assert the first todo has the correct text.
test_new : function(){
    // simulate a focus event on the input element
    var params = this.TodosNewInputFocus();
    // does the text in the input disappear?
    this.assert_equal('', params.element.value);
    // write some text in the input
    this.Write(params.element, {text: 'Walk the dog', callback: this.next_callback()});
},
new_after_write : function() {
    var input = Query('#todos .new input')[0];
    // does the input have the correct text?
    this.assert_equal('Walk the dog', input.value);
    // simulate a blur event
    var params = this.TodosNewInputBlur();
    // was the todo created successfully in the first todo slot
    this.assert_equal("Walk the dog", Query('.todo label')[0].innerHTML);
},

Testing drag

The todos in this page's demo have the ability to be sorted by dragging and dropping. Try it yourself.

Behavior How to test
Dragging a todo past another todo will cause them to flip spots in the list Simulate dragging a todo to a spot slightly past another todo, then assert they did indeed flip spots
test_drag: function(){
    // grab the first todo
    var draggable_todo = Query('#todos .todo')[0];
    // get the x, y page coordinates for the second todo
    var to = Test.center(todos[1]);
    // simulate dragging the first todo from its current location to 30 pixels
	// below the second todo
    this.Drag(draggable_todo,{from: draggable_todo, to: {x: to[0], y: to[1]+30}, 
        duration: 0.5, callback: this.next_callback()  }  )
},
// have the todos flipped spots?
done_dragging : function(){
    var todo_labels = MVC.Query('#todos .todo label');
    // check the first todo contains 'Learn to fly'
    this.assert_equal('Learn to fly', todo_labels[0].innerHTML);
    // check the second todo contains 'Walk the dog'
    this.assert_equal('Walk the dog', todo_labels[1].innerHTML);
},

Testing delete

The final piece of functionality to test is delete, which is controlled by an action called 'img click'.

Behavior How to test
Clicking the delete icon deletes a todo Simulate clicking the delete icon, then assert there is one less todo than previously
test_delete : function() {
    // simulate clicking the delete image
    var params = this.TodoImgClick();
    // there should only be one todo left
    this.assert_equal(1, Query('.todo').length);
}});

Conclusion

Step back for a second and put the TodoController test in context. This example shows that you can comprehensively test every interaction you expect users to have with your page. In addition, the code is relatively easy to understand, thanks to the TodoController helper methods automatically created. As you add new features to the todo list, you'd use the tests to verify you haven't broken anything.

Testing is a programming best practice often ignored in JavaScript development. You can run the TodoController test on many different browsers to quickly idenfity and fix any cross browser issues. In this way, Test helps create cross browser, error-free code much faster and more reliably.

This demo has skipped over some important features of Test, such as testing Ajax functionality. Check out the Learn page and the API to continue learning.

Download the demo

Related Learning

Overview
Test's highlights.

Learn
Learn how to use Test for JavaScriptMVC and non-JavaScriptMVC features.

API
Low level documentation for Test's methods.