我在试图通过测试时遇到了麻烦。我希望能够使用间谍来检查鼠标悬停事件是否被正确调用。目前我收到以下错误,“错误:预计至少被调用一次,但从未被调用”。我的部分困惑与d3和jQuery选择器之间的差异有关,我非常乐意使用后者,但我不确定如何在测试中正确使用前者来获得我想要的结果。
我的依赖是d3,jQuery,mocha,chai,sinon和sinon-chai。
我的index.html文件中的相关代码,
<script src="fixtures.js"></script>
<div id="mocha"></div>
<script src="mocha.js"></script>
<script src="chai.js"></script>
<script src="sinon-chai.js"></script>
<script src="sinon-1.10.2.js"></script>
<script>
mocha.ui('bdd');
mocha.reporter('html');
var expect = chai.expect;
</script>
<script src="tests.js"></script>
<script>
mocha.run();
</script>
fixtures.js,
var path = svg.selectAll("path")
.data(pie(data))
.enter().append("path").attr("class", "path")
.style("fill", function(d, i) { return color(i); })
.attr("d", arc)
.on("mouseover", function() { d3.select(this).style("fill", "#ff0000"); })
.on("mouseout" , function() { d3.selectAll("path").style("fill", function(d, i) { return color(i); }); });
// I wanted to test my understanding of d3 selectors
var path_one = d3.select('.path').attr("id", "path_one");
tests.js,
describe('Donut Chart', function() {
describe("Mouseover events", function() {
it("should call on('mouseover')", function () {
var spy = sinon.spy(path, "on");
$('path').mouseenter();
sinon.assert.called(spy);
});
});
});
答案 0 :(得分:8)
这里有一些问题;我们可以理清你的语法,但我们也必须弄清楚这个意图。
错误消息&#34;错误:预期on
至少被调用一次,但从未被调用过#34;是准确的。在测试期间 on
未被调用。它只在您的灯具中调用,以设置事件处理程序。您还会触发mouseenter
个活动,但您的听众适用于mouseover
和mouseout
。在现实世界中,您在mouseover
事件发生后很快就会获得mouseenter
,但是当您使用不会发生的jQuery伪造它时。无论如何,jQuery是一个非首发;见下文。
您可以尝试通过将它们从匿名函数更改为命名的内容来解决此问题,如下所示:
var mouseOverHandler = function() {
d3.select(this).style('fill', '#ff0000');
};
然后使用path
将其绑定到path.on('mouseover', mouseOverHandler)
。您认为现在可以监视mouseOverHandler
,但不能继续监视。当你打电话给on
时,你的功能会受到约束,所以将它换成一个罪人间谍后来不会有任何影响。
另一个问题是you can't use jQuery to trigger D3 events because jQuery events aren't DOM events。因此,您应该将对$('path').mouseenter()
的调用替换为类似document.getElementById('path_one').dispatchEvent(new MouseEvent('mouseover'));
的内容(注意这是在更改代码来自&#34;在所有路径上触发mouseenter
&#34;到&#34;在ID为mouseover
&#34;)的元素上触发path_one
。
你可以通过重构来实现这一点,这样你可以用你可以窥探的东西来换掉你的回调,但从根本上你是在测试错误的东西。从本质上讲,你正在尝试为D3编写测试; &#34;当我添加一个事件监听器时,请确保调用事件监听器。&#34;相反,你应该测试你的实际代码的行为:&#34;当有人鼠标悬停在图表上时,它的颜色应该改变&#34;。
如果您确实想断言您的事件处理程序已绑定,您可以这样做:
expect(path.on('mouseover')).to.be.a('function')
但是如果你想确保改变你的颜色,你希望你的测试如下:
describe("Mouseover events", function() {
it("should update the colours when a user mouses over the paths", function () {
var oldColor = path.style('fill');
document.getElementById('path_one').dispatchEvent(new MouseEvent('mouseover'));
expect(path.style('fill')).to.not.equal(oldColor);
});
});