We are in the process of learning Ember.js. We do all our development TDD, and want Ember.js to be no exception. We have experience building Backbone.js apps test-driven, so we are familiar with testing front-end code using Jasmine or Mocha/Chai.
When figuring out how to test views, we ran into a problem when the template for the view uses has a #linkTo
statement. Unfortunately we are unable to find good test examples and practices. This gist is our quest to get answers how to decently unit-test ember applications.
When looking at the test for linkTo in Ember.js source code, we noticed it contains a full wiring of an ember app to support #linkTo
. Does this mean we cannot stub this behaviour when testing a template?
How do you create tests for ember views using template renders?
Here is a gist with our test and a template that will make the test pass, and a template that will make it fail.
view_spec.js.coffee
# This test is made with Mocha / Chai,
# With the chai-jquery and chai-changes extensions
describe 'TodoItemsView', ->
beforeEach ->
testSerializer = DS.JSONSerializer.create
primaryKey: -> 'id'
TestAdapter = DS.Adapter.extend
serializer: testSerializer
TestStore = DS.Store.extend
revision: 11
adapter: TestAdapter.create()
TodoItem = DS.Model.extend
title: DS.attr('string')
store = TestStore.create()
@todoItem = store.createRecord TodoItem
title: 'Do something'
@controller = Em.ArrayController.create
content: []
@view = Em.View.create
templateName: 'working_template'
controller: @controller
@controller.pushObject @todoItem
afterEach ->
@view.destroy()
@controller.destroy()
@todoItem.destroy()
describe 'amount of todos', ->
beforeEach ->
# $('#konacha') is a div that gets cleaned between each test
Em.run => @view.appendTo '#konacha'
it 'is shown', ->
$('#konacha .todos-count').should.have.text '1 things to do'
it 'is livebound', ->
expect(=> $('#konacha .todos-count').text()).to.change.from('1 things to do').to('2 things to do').when =>
Em.run =>
extraTodoItem = store.createRecord TodoItem,
title: 'Moar todo'
@controller.pushObject extraTodoItem
broken_template.handlebars
<div class="todos-count"><span class="todos">{{length}}</span> things to do</div>
{{#linkTo "index"}}Home{{/linkTo}}
working_template.handlebars
<div class="todos-count"><span class="todos">{{length}}</span> things to do</div>
One way you can handle this is to create a stub for the linkTo helper and then use it in a before block. That will bypass all the extra requirements of the real linkTo (e.g. routing) and let you focus on the contents of the view. Here's how I'm doing it:
Our solution has been to essentially load the whole application, but isolate our test subjects as much as possible. For example,
That is, the router and other globals are available, so it's not complete isolation, but we can easily send in doubles for things closer to the object under test.
If you really want to isolate the router, the
linkTo
helper looks it up ascontroller.router
, so you could do