2011-09-28 55 views
8

我想要实现查看测试的实施的CoffeeScript无处不Backbone.js的“待办事项”例如事件(见github.com/rsim/backbone_coffeescript_demo。)测试Backbone.js的查看与茉莉

我的茉莉花上述演示工作的测试非常好,除了视图事件。我期望我被困在以下一个或两个方面i)我不理解视图代码中的事件绑定,ii)我不明白如何正确设置视图代码事件的Jasmine测试。

这里是“编辑”事件的例子...

class TodoApp.TodoView extends Backbone.View 
    tagName: "li" 
    template: TodoApp.template '#item-template' 
    events: 
    "dblclick div.todo-content" : "edit" 
    ... 

    initialize: -> 
    _.bindAll this, 'render', 'close' 
    @model.bind 'change', @render 
    @model.bind 'destroy', => @remove() 

    render: -> 
    $(@el).html @template @model.toJSON() 
    @setContent() 
    this 

    edit: -> 
    $(@el).addClass "editing" 
    @input.focus() 
    ... 

......现在,这里的重点是否一个测试后双击被获得:

describe "edit state", -> 
     li = null 

    beforeEach -> 
     setFixtures('<ul id="todo-list"></ul>') 
     model = new Backbone.Model id: 1, content: todoValue, done: false 
     view = new TodoApp.TodoView model: model, template: readFixtures("_item_template.html") 
     $("ul#todo-list").append(view.render().el) 
      li = $('ul#todo-list li:first') 
     target = li.find('div.todo-content') 
     expect(target).toExist() 
       target.trigger('dblclick') # here's the event! 

    it "input takes focus", -> 
     expect(li.find('.todo-input').is(':focus')).toBe(true) 

上的期望我也没有)间谍,也没有ii)重点得到满足。

测试backbone.js事件代码是否有特殊性,我应该在Jasmine中知道这些代码?

+0

我遇到了同样的问题。你有没有找到解决方案? –

+0

@Michal - 不,我没有。 – Lille

+0

也有类似的问题,仍然没有想法? –

回答

2

您正在监视视图的edit方法。这会用间谍对象替换该方法,这意味着实际的编辑方法不会被调用。因此,你是@input.focus永远不会开火。

既然你想测试实际上调用你的编辑方法,我会删除它的间谍。

备注:不要在beforeEach中调用expect方法。如果您确实需要对这些设置一个期望,请为它们创建一个it块。

+0

谢谢,我已经删除了任何茉莉花间谍活动,但仍未能获得预期的重点。 – Lille

+0

我觉得你的混乱的间谍和存根。 Spys包裹该方法,但允许通话。 – user1464581

2

我不喜欢coffescript,所以我可能会错过一些东西,但是你在哪里设置你的间谍?

为了测试事件调用,您可能需要在设置间谍后刷新视图的事件。

spyOn(view, 'edit'); 
view.delegateEvents(); 
target.trigger('dblclick'); 

it("should call edit when target is double clicked", function() { 
    expect(view.edit).toHaveBeenCalled() 
}); 
0

我没有写我在CoffeeScript中测试,但我也有同样的问题,所以我希望你能原谅我javadcript回答。我最终把你的测试分解为两个不同的测试。首先,我测试了如果调用视图的编辑功能将焦点设置在输入框上。之后,我测试了当双击标签时是否调用了编辑,还没有通过该测试。但是这里是我如何测试编辑功能是否工作。

describe ("A todo item view", function(){ 
    var my_model; 
    var todo_view; 

    beforeEach(function(){ 
     my_model = new Todo({content:"todo value", done:false}); 
     todo_view = new TodoView({model:my_model}); 

    }); 


    it("should set the focus on the input box when the edit function is called", function(){ 
     $('body').append(todo_view.$el); //append the view to Specrunner.html 
     todo_view.edit(); //call the view's edit function 
     var focus= document.activeElement; //finds what element on the page has focus 
     expect(focus).toBe('.todo-input'); //jasmine-jquery matcher checks if focused element has the .todo-input class 
}); 

东西可能会导致一个问题是,您的模型和视图在里面beforeEach声明。在beforeEach中声明它们意味着它们只存在于beforeEach的范围内,并且在运行它时不再存在。

此外,setFixtures做你认为它做的?焦点不能设置在不属于DOM树的元素上,所以我将视图的el添加到了茉莉花规范本身的主体中。 (我正在使用html specrunner,而不是命令行版本)这使它成为dom树的一部分,因此可以让它具有焦点,并且使它具有焦点可测试性。

0

与此问题是,Backbone.View events对象正在使用event delegation。要使事件能够被调用,元素必须是DOM的一部分,您可以通过在beforeEach中执行类似$('body').append(someView.el)的操作来完成此操作。就个人而言,我尽量不测试Backbone是否正确设置events并手动触发点击,对于单元测试更直接地调用回调处理程序直接避免DOM,这可能会使测试变慢。

对于:focus是同样的问题,DOM中必须有一个元素,以便jQuery可以判断某个元素是否被聚焦。在这种情况下,最好将某些状态设置为组件的一部分,而不是通过查询DOM来检查状态,例如:someView.hasFocus === true。或者,你可以窥探元素focus的实现,并检查它是否被调用。