- Getting Started
- DOM Interactions
- jQuery to the Rescue!
- Stubbing Functions
- Mocking AJAX Requests
- Wrapping Up
jQuery to the Rescue!
OMG.Views.TodoView is a great example of JavaScript interacting with the DOM, and it's one of the most common things you'll be testing. As you've probably noticed, this view is doing its DOM interactions using jQuery, so why shouldn't the tests do the same?
One of the beautiful elements of testing a JavaScript or CoffeeScript application is that you can write user interaction tests that use the same libraries you're already using to write your user interactions. (I know, this discussion is all very "meta," but in its own way it's very beautiful.)
Now we need to create a file:
spec/javascripts/views/todos/todo_view_spec.coffee
This file will be where we write tests for the OMG.Views.TodoView class. We'll set it up like this:
# spec/javascripts/views/todos/todo_view_spec.coffee #= require spec_helper describe "OMG.Views.TodoView", -> beforeEach -> @model = new OMG.Models.Todo(id: 1, body: "Do something!", completed: false) @view = new OMG.Views.TodoView(model: @model) page.html(@view.el)
First we need to require the spec_helper.coffee file we created earlier. I've shown how you would do that in Rails, but your framework might be different. The spec helper file will pull in all of the JavaScript/CoffeeScript files that our application needs, as well as any helper libraries, functions, and variables we may have set, such as the page variable.
Next, tell Mocha that we want to describe "OMG.Views.TodoView" and then pass a function to it. In this function, we'll write all of our tests.
Finally we need to make sure that all of our tests have some basic information with which they can work. For our purposes, that would be an instance of a Todo (@model) and an instance of the view we're testing (@view), and we need to place the HTML from that view on the page, like this:
page.html(@view.el)
You might think we'd finally be ready to write some tests, but not quite. To make our tests easier to read and write, we should use the chai-jquery plug-in. This plug-in will give us access to some custom matchers that match familiar jQuery API functions. Now we're ready to write our tests.
# spec/javascripts/views/todos/todo_view_spec.coffee describe "displaying of todos", -> it "contains the body of the todo", -> $('.todo-body').should.have.text("Do something!") it "is not marked as completed", -> $('[name=completed]').should.not.be.checked $('.todo-body').should.not.have.class("completed")
In these two tests, we're asserting that the body of the todo is being rendered to the page where we expect it. Since the todo we created wasn't marked as completed, we're also asserting that the checkbox remains unchecked and that the CSS style completed has not been applied.
Since todos can be marked as completed, we should test for that scenario as well. Using jQuery, we can simulate a user interacting with the checkbox to mark the todo as completed:
# spec/javascripts/views/todos/todo_view_spec.coffee it "renders completed todos correctly", -> $('[name=completed]').click() $('[name=completed]').should.be.checked $('.todo-body').should.have.class("completed")
In this test, we're actually testing two different things. First, we're testing that when a user clicks the "completed" checkbox, the view listens to that event and redraws the HTML. Second, we're testing that the view draws the correct HTML for a completed todo.