【问题标题】:Trigger d3 event within Jasmine spec test在 Jasmine 规范测试中触发 d3 事件
【发布时间】:2013-05-15 21:38:31
【问题描述】:

我正在尝试使用 Jasmine 触发 d3 事件。特别是,我想检查我的事件侦听器是否正在使用 Jasmine 间谍被调用。

例如,如果我将 d3 缩放行为附加到 svg 元素(我的前端使用 Backbone.js):

代码(a):

class MyView extends Backbone.View
  initialize: ->
    zoom = d3.behavior.zoom().on("zoom", this.zoom_listener)   
    d3.select(this.el).append("svg").attr("class", "viewport").call(zoom)

  zoom_listener: ->
    console.log("zoom called") 

Jasmine 中的以下测试失败:

代码(b):

it "calls zoom listener on dblclick", ->
  zoom_spy = spyOn(MyView.prototype, "zoom_listener").andCallThrough()
  view = new MyView()
  view.$(".viewport").trigger("dblclick")
  waitsFor((-> zoom_spy.callCount == 1), "Call zoom", 1000) 

另一方面,(作为健全性检查)如果我将一个 'dblclick' 事件绑定到我的视图,如下所示,上述测试,即代码 (b) 将通过:

代码(c):

class MyView extends Backbone.View
  events:
    "dblclick" : "zoom_listener"

  initialize: ->
    zoom = d3.behavior.zoom().on("zoom", this.zoom_listener)   
    d3.select(this.el).append("svg").attr("class", "viewport")
    # .call(zoom)     # commented off this line for the sanity check  

  zoom_listener: ->
    console.log("zoom called")  

谁能告诉我为什么我似乎无法在 Jasmine 测试中触发 D3 缩放事件,即使用我上面的原始视图即代码 (a) 时触发的代码 (b)?

【问题讨论】:

    标签: backbone.js d3.js jasmine


    【解决方案1】:

    Backbone 触发 jQuery 事件,这似乎没有在 jQuery 世界之外注册。 here 解释了一些解决方法。但这是使用 Jasmine 测试 D3 事件的一般方法。

    it('should trigger a callback on custom events', function() {
      fixture.datum(dataset)
        .call(barChart);
    
      var callback = jasmine.createSpy("filterCallback");
      barChart.on('customHover', callback);
    
      var bars = fixture.selectAll('.bar');
      bars[0][0].__onmouseover();
      var callBackArguments = callback.argsForCall[0][0];
    
      expect(callback).toHaveBeenCalled();
      expect(callBackArguments).toBe(dataset[0]);
    });
    

    D3 在 DOM 对象上公开事件。所以你可以附加一个间谍并触发它。

    【讨论】:

      【解决方案2】:

      正如 M. Bostock 在https://github.com/mbostock/d3/issues/906 中所说:“jQuery 触发器不调度真实事件;它只调用它自己的侦听器。”

      使用 vanilla JS 调度真实事件的一种方法是(基于How to invoke "click" event programmatically in d3? 中用户“handler”的回复):

      代码(b-修改)

      it "calls zoom listener on dblclick", ->
        zoom_spy = spyOn(MyView.prototype, "zoom_listener").andCallThrough()
        view = new MyView()
      
        jQuery.fn.custom_mouse_dblclick = (->
          this.each(((i, element) ->
            evt = document.createEvent("MouseEvent")
            evt.initMouseEvent(
              "dblclick",
              true,
              true,
              window,
              0,
              0,
              0,
              0,
              0,
              false,
              false,
              false,
              false,
              0,
              null)
            element.dispatchEvent(evt)
          ))
        )
        view.$(".viewport").custom_mouse_dblclick()
        waitsFor((-> zoom_spy.callCount == 1), "Call zoom", 1000) 
      

      因此,当在原始问题中的代码 (a) 上执行时,代码(b 修改)中的 Jasmine 测试通过,即具有 d3.zoom() 行为的 svg 元素。

      【讨论】:

        【解决方案3】:

        @Biovisualize 示例的变体:

        fixture.datum(dataset).call(barChart);
        
        var callback = jasmine.createSpy("filterCallback");
        barChart.on('customHover', callback);
        //to trigger all elements    
        fixture.selectAll('.bar').each(function() {
            this.__onmouseover();
        });
        
        expect(callback).toHaveBeenCalled();
        

        【讨论】:

        • 你应该扩展你自己的答案,因为你永远不知道 Biovisualize 的帖子是否会因任何原因被删除。
        猜你喜欢
        • 2016-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-02
        • 1970-01-01
        • 1970-01-01
        • 2021-11-04
        • 1970-01-01
        相关资源
        最近更新 更多