我的角度应用程序中有一个图表指令,它使用了d3.js库。
该指令的一部分将鼠标事件处理程序添加到某些svg元素中,如此
svg.selectAll('g rect')
.on('click', function(d) {
scope.clickHandler(d, scope.data);
})
.on('mouseover', function () {
d3.select(this).classed('data-item-hover', true);
})
.on('mouseout', function () {
d3.select(this).classed('data-item-hover', false);
});
我想在一些单元测试中覆盖这些处理程序,但我正在努力实现如何动态地调用这些事件。
我在我的测试规范
中尝试这个describe('scope.clickHandler', function() {
var rect;
beforeEach(function(){
spyOn(scope, 'clickHandler');
rect = svg.select('g rect')[0][0];
rect.on('click')();
});
it('should call scope.render after a window resize event occurs', function () {
expect(scope.clickHandler).toHaveBeenCalled();
});
});
然而,这会引发错误
TypeError:undefined不是构造函数(评估 ' rect.on('单击')'
我遇到了这个SO How to invoke "click" event programmatically in d3?,第二个答案是让我尝试这种技术的原因。
如何在我在d3.js中注册事件的svg元素上调用鼠标事件?
由于
答案 0 :(得分:3)
主要问题是svg.select('g rect')[0][0]
是一个DOM元素而不是正确的D3选择,这就是导致undefined
错误的原因。来自文档:
选择是元素数组 - 字面意思(可能不是字面意思......)。 D3将其他方法绑定到数组,以便您可以应用 运营商到选定的元素......
您实际上可以检查,因为DOM元素实现了Element
接口:
(svg.select('g rect')[0][0] instanceof Element) // true
因此,为了触发某个元素上的某个事件,您可以执行以下操作:
var rect = svg.select('g rect') // first rect element found is assumed
rect.on('click').call(rect.node(), rect.datum()); // as commented in above link
你可以找到一个简单的工作小提琴here。