3

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

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

代码(一):

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")  

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

4

3 回答 3

5

Backbone 触发 jQuery 事件,这似乎没有在 jQuery 世界之外注册。此处解释了一些解决方法。但这是使用 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 对象上公开事件。所以你可以附加一个间谍并触发它。

于 2013-05-15T23:57:31.530 回答
0

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

使用 vanilla JS 调度真实事件的一种方法是(基于如何在 d3 中以编程方式调用“click”事件?):

代码(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 元素。

于 2013-05-17T03:47:58.013 回答
0

@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();
于 2013-07-23T00:22:00.207 回答