Testing your JavaScript and/or CofffeeScript applications is not nearly as difficult as you think. Learn how to quickly setup Jasmine in your Rails application and start testing your *script applications now!
11. app/controllers/todos_controller.rb
class TodosController < ApplicationController
respond_to :html, :json
def index
respond_to do |format|
format.html {}
format.json do
@todos = Todo.order("created_at asc")
respond_with @todos
end
end
end
def show
@todo = Todo.find(params[:id])
respond_with @todo
end
def create
@todo = Todo.create(params[:todo])
respond_with @todo
end
def update
@todo = Todo.find(params[:id])
@todo.update_attributes(params[:todo])
respond_with @todo
end
def destroy
@todo = Todo.find(params[:id])
@todo.destroy
respond_with @todo
end
end
12. spec/controllers/todos_controller_spec.rb
require 'spec_helper'
it "responds with errors" do
expect {
describe TodosController do
post :create, todo: {}, format: 'json'
let(:todo) { Factory(:todo) }
response.should_not be_successful
json = decode_json(response.body)
describe 'index' do
json.errors.should have(1).error
json.errors.body.should include("can't be blank")
context "HTML" do
}.to_not change(Todo, :count)
end
it "renders the HTML page" do
get :index
end
response.should render_template(:index)
end
assigns(:todos).should be_nil
end
describe 'update' do
end
context "JSON" do
context "JSON" do
it "updates a todo" do
put :update, id: todo.id, todo: {body: "do something else"}, format: 'json'
it "returns JSON for the todos" do
get :index, format: "json"
response.should be_successful
todo.reload
response.should_not render_template(:index)
todo.body.should eql "do something else"
assigns(:todos).should_not be_nil
end
end
it "responds with errors" do
end
put :update, id: todo.id, todo: {body: ""}, format: 'json'
end
response.should_not be_successful
json = decode_json(response.body)
describe 'show' do
json.errors.should have(1).error
json.errors.body.should include("can't be blank")
context "JSON" do
end
it "returns the todo" do
end
get :show, id: todo.id, format: 'json'
end
response.should be_successful
response.body.should eql todo.to_json
describe 'destroy' do
end
context "JSON" do
end
it "destroys the todo" do
end
todo.should_not be_nil
expect {
describe 'create' do
delete :destroy, id: todo.id, format: 'JSON'
}.to change(Todo, :count).by(-1)
context "JSON" do
end
it "creates a new todo" do
end
expect {
post :create, todo: {body: "do something"}, format: 'json'
end
response.should be_successful
end
}.to change(Todo, :count).by(1)
end
40. spec/javascripts/views/todos/todo_view_spec.coffee
describe "displaying of todos", ->
it "contains the body of the todo", ->
expect($('.todo-body')).toHaveText("Do something!")
it "is not marked as completed", ->
expect($('[name=completed]')).not.toBeChecked()
expect($('.todo-body')).not.toHaveClass("completed")
describe "completed todos", ->
beforeEach ->
@model.set(completed: true)
it "is marked as completed", ->
expect($('[name=completed]')).toBeChecked()
expect($('.todo-body')).toHaveClass("completed")
41. spec/javascripts/views/todos/todo_view_spec.coffee
describe "checking the completed checkbox", ->
beforeEach ->
expect($('[name=completed]')).not.toBeChecked()
$('[name=completed]').click()
it "marks it as completed", ->
expect($('[name=completed]')).toBeChecked()
expect($('.todo-body')).toHaveClass("completed")
describe "unchecking the completed checkbox", ->
beforeEach ->
@model.set(completed: true)
expect($('[name=completed]')).toBeChecked()
$('[name=completed]').click()
it "marks it as not completed", ->
expect($('[name=completed]')).not.toBeChecked()
expect($('.todo-body')).not.toHaveClass("completed")
46. spec/javascripts/views/todos/todo_view_spec.coffee
describe "clicking the delete button", ->
describe "if confirmed", ->
beforeEach ->
spyOn(window, "confirm").andReturn(true)
it "will remove the todo from the page", ->
expect(@_page.html()).toContain($(@view.el).html())
$(".delete").click()
expect(@_page.html()).not.toContain($(@view.el).html())
describe "if not confirmed", ->
beforeEach ->
spyOn(window, "confirm").andReturn(false)
it "will not remove the todo from the page", ->
expect(@_page.html()).toContain($(@view.el).html())
$(".delete").click()
expect(@_page.html()).toContain($(@view.el).html())
48. spec/javascripts/spec_helper.coffee
# Require the appropriate asset-pipeline files:
require '/assets/application.js'
require '/assets/jasmine.jquery.js'
# Any other testing specific code here...
# Custom matchers, etc....
beforeEach ->
@_page = $('#test')
@addMatchers
toContainView: (view) ->
actual_html = $(@actual).html()
view_html = $(view.el).html()
@message = ->
"Expected #{actual_html} to contain #{view_html}"
return @env.contains_(actual_html, view_html)
49. spec/javascripts/views/todos/todo_view_spec.coffee
describe "clicking the delete button", ->
describe "if confirmed", ->
beforeEach ->
spyOn(window, "confirm").andReturn(true)
it "will remove the todo from the page", ->
expect(@_page).toContainView(@view)
$(".delete").click()
expect(@_page).not.toContainView(@view)
describe "if not confirmed", ->
beforeEach ->
spyOn(window, "confirm").andReturn(false)
it "will not remove the todo from the page", ->
expect(@_page).toContainView(@view)
$(".delete").click()
expect(@_page).toContainView(@view)
52. spec/javascripts/views/todos/todo_list_view_spec.coffee
describe "OMG.Views.TodosListView", ->
beforeEach ->
@_page.html("<ul id='todos'></ul>")
@collection = new OMG.Collections.Todos()
@view = new OMG.Views.TodosListView(collection: @collection)
it "fetches the collection", ->
expect(@collection.length).toEqual(2)
it "renders the todos from the collection", ->
expect($(@view.el).html()).toMatch("Do something!")
expect($(@view.el).html()).toMatch("Do something else!")
it "renders new todos added to the collection", ->
@collection.add(new OMG.Models.Todo(body: "Do another thing!"))
expect($(@view.el).html()).toMatch("Do another thing!")
53. rake spec:javascripts
...FF...........
Failed: OMG.Views.TodosListView fetches the collection.
Expected 0 to equal 2.
in :
Failed: OMG.Views.TodosListView renders the todos from the collection.
Expected '' to match 'Do something!'.
in :
Finished in 3.12 seconds
16 examples, 2 failures
60. spec/javascripts/views/todos/todo_list_view_spec.coffee
describe "OMG.Views.TodosListView", ->
beforeEach ->
jasmine.Ajax.useMock()
@_page.html("<ul id='todos'></ul>")
@collection = new OMG.Collections.Todos()
@view = new OMG.Views.TodosListView(collection: @collection)
it "fetches the collection", ->
expect(@collection.length).toEqual(2)
it "renders the todos from the collection", ->
expect($(@view.el).html()).toMatch("Do something!")
expect($(@view.el).html()).toMatch("Do something else!")
it "renders new todos added to the collection", ->
@collection.add(new OMG.Models.Todo(body: "Do another thing!"))
expect($(@view.el).html()).toMatch("Do another thing!")
62. spec/javascripts/views/todos/todo_list_view_spec.coffee
describe "OMG.Views.TodosListView", ->
beforeEach ->
jasmine.Ajax.useMock()
@_page.html("<ul id='todos'></ul>")
@collection = new OMG.Collections.Todos()
@view = new OMG.Views.TodosListView(collection: @collection)
request = mostRecentAjaxRequest()
request.response(Mocks.todos.collection)
it "fetches the collection", ->
expect(@collection.length).toEqual(2)
it "renders the todos from the collection", ->
expect($(@view.el).html()).toMatch("Do something!")
expect($(@view.el).html()).toMatch("Do something else!")
it "renders new todos added to the collection", ->
@collection.add(new OMG.Models.Todo(body: "Do another thing!"))
expect($(@view.el).html()).toMatch("Do another thing!")