I have two models, Program
and Project
. A Program
has many Project
s.
App.Program = DS.Model.extend
projects: DS.hasMany 'project', async: true
App.Project = DS.Model.extend
program: DS.belongsTo 'program'
I have an ArrayController
responsible for displaying all the projects in a program. Each project rendered has a destroy
link (a simple action on the ArrayController
).
App.ProjectsIndexController = Ember.ArrayController.extend
needs: 'program'
program: Ember.computed.alias 'controllers.program.model'
actions:
destroy: (project) ->
@get('program.projects').then (projects) ->
projects.removeObject(project) # how can I test this line?
@get('program').save()
project.destroyRecord()
Since the relationships are async, calling program.get('projects')
returns a promise.
I'm using Firebase (and emberFire
) as my backend, which stores relationships like
programs: {
programId: {
projects: {
projectId: true
}
}
}
projects: {
program: 'programId'
}
I'm using ember-qunit
and sinon
for a stub/mock library. My first attempt at testing this makes really heavy use of sinon.spy()
.
moduleFor 'controller:projects.index', 'Unit - Controller - Projects Index',
needs: ['controller:program']
test 'actions - destroy', ->
ctrl = @subject()
programCtrl = ctrl.get('controllers.program')
project1 = Em.Object.create(title: 'Project #1', destroyRecord: sinon.spy())
project2 = Em.Object.create(title: 'Project #2', destroyRecord: sinon.spy())
projects = Em.Object.create(removeObject: sinon.spy())
program = Em.Object.create
title: 'Program #1'
projects:
then: sinon.stub().yields(projects)
save: sinon.spy()
Ember.run ->
programCtrl.set 'model', program
ctrl.send 'destroy', project1
ok(program.projects.then.calledOnce, 'Removes the project from the program')
ok(program.save.calledOnce, 'Saves the program')
ok(project1.destroyRecord.calledOnce, 'Destroys the project')
I'm creating new Ember objects, since there is no clear way for me to instantiate an instance of my models in my tests (at least that I know about). Every function that gets called in the action uses a sinon.spy()
so I can make assertions that they did in fact get called.
Coming from a Rails background this seems like a lot of test code for four relatively simple lines of CoffeeScript, which leads me to believe I might be going about this the wrong way.
Either way, my overall question is this:
How can I test (using sinon, or any other way) that removeObject()
was in fact called on program.projects
in the async callback function?
Also, is there an easier way for me to stub my models without creating new Ember objects in every test, in such a way that I can make assertions like I am above?