тестирование событий просмотра backbone.js с помощью jasmine

Я пытаюсь реализовать тесты просмотра для реализации Coffeescript вездесущего примера «todo» backbone.js (см. github.com/rsim/backbone_coffeescript_demo.)

Мои жасминовые тесты приведенной выше демонстрации работают довольно хорошо, за исключением событий просмотра. Я ожидаю, что застрял на одном или обоих из следующих: i) я не понимаю привязку событий в коде представления, ii) я не понимаю, как правильно настроить тест Jasmine для событий кода представления.

Вот пример события 'edit'...

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) фокуса не оправдываются.

Есть ли особенность тестирования кода события backbone.js, о которой я должен знать в Jasmine?


person Lille    schedule 28.09.2011    source источник
comment
Я сталкиваюсь с той же проблемой. Вы нашли решение для этого?   -  person Michal Kuklis    schedule 11.02.2012
comment
Тоже столкнулся с похожей проблемой, до сих пор нет идей?   -  person M_rivermount    schedule 17.12.2014


Ответы (4)


вы шпионите за методом представления edit. это заменяет метод шпионским объектом, что означает, что фактический метод редактирования не будет вызываться. следовательно, вы @input.focus никогда не будете стрелять.

поскольку вы хотите, чтобы тест действительно вызывал ваш метод редактирования, я бы удалил для него шпиона.

примечание: не вызывайте методы expect в файле beforeEach. если вам действительно нужно установить для них ожидания, создайте для них блок it.

person Derick Bailey    schedule 29.09.2011
comment
Спасибо, я удалил все слежки за Жасмин, но я все еще не могу получить ожидаемый фокус. - person Lille; 29.09.2011
comment
Я думаю, что вы сбиваете с толку шпионов и заглушек. Шпионы обертывают метод, но разрешают вызов. - person user1464581; 29.12.2016

Я не очень хорошо разбираюсь в кофескрипте, поэтому могу что-то упустить, но где вы настраиваете своего шпиона?

Чтобы протестировать вызов событий, вам может потребоваться обновить события представления после настройки шпиона.

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

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

Проблема в том, что объект Backbone.View events использует делегирование событий. Чтобы события можно было назвать работой, элемент должен быть частью DOM, вы можете сделать это, выполнив что-то вроде $('body').append(someView.el) в вашем beforeEach. Лично я стараюсь не проверять, правильно ли Backbone устанавливает events и инициирует клики вручную, для модульных тестов более практично вызывать обработчики обратного вызова напрямую, полностью избегая DOM, что может сильно замедлить ваши тесты.

Для :focus та же проблема, в DOM должен быть элемент, чтобы jQuery мог определить, сфокусирован ли элемент. В этом случае лучше установить некоторое состояние как часть вашего компонента, а не проверять состояние с помощью запроса к DOM, например: someView.hasFocus === true. В качестве альтернативы вы можете следить за реализацией элементов focus и проверять, была ли она вызвана.

person Mario Estrada    schedule 23.06.2015

Я не писал свой тест на 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, а не версию для командной строки). Это делает его частью дерева dom и, следовательно, позволяет ему иметь фокус, а также позволяет проверить, есть ли у него фокус.

person Tara Roys    schedule 19.02.2013