【问题标题】:testing backbone.js view events with jasmine用茉莉花测试backbone.js视图事件
【发布时间】:2011-09-28 23:14:42
【问题描述】:

我正在尝试为普遍存在的主干.js 'todo' 示例的 Coffeescript 实现实现视图测试(请参阅 github.com/rsim/backbone_coffeescript_demo。)

我对上述演示的 jasmine 测试运行良好,但视图事件除外。我预计我会被以下一项或两项卡住 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)

i) 间谍和 ii) 焦点都没有得到满足。

在 Jasmine 中测试我应该注意的backbone.js 事件代码有什么特殊性吗?

【问题讨论】:

  • 我遇到了同样的问题。您找到解决方案了吗?
  • 也有类似的问题,还是没有思路?

标签: backbone.js jasmine jasmine-jquery


【解决方案1】:

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

由于您希望测试实际调用您的编辑方法,我会删除它的间谍。

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

【讨论】:

  • 谢谢,我已删除所有 Jasmine 间谍活动,但仍无法获得预期的关注。
  • 我认为你的间谍和存根令人困惑。间谍包装了方法,但允许调用通过。
【解决方案2】:

我对咖啡脚本不是很好,所以我可能会遗漏一些东西,但是你在哪里设置你的间谍?

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      我没有用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 附加到 jasmine 规范本身的主体中。 (我使用的是 HTML specrunner,而不是命令行版本)这使它成为 dom 树的一部分,因此允许它具有焦点,并且还使得它是否具有可测试的焦点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        相关资源
        最近更新 更多