测试D3中的鼠标悬停事件与Sinon [英] Testing Mouseover event in D3 with Sinon

查看:458
本文介绍了测试D3中的鼠标悬停事件与Sinon的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试让我的测试通过时遇到问题。我想能够使用间谍来检查mouseover事件是否正确调用。目前我得到以下错误,错误:预计已被调用至少一次,但从未被调用。部分困惑我的部分涉及到d3和jQuery选择器之间的差异,我很乐意使用后者,但我不知道如何正确使用前者在测试中得到我想要的结果。

I'm having trouble trying to get my test to pass. I would like to be able to use a spy to check whether or not the mouseover event was correctly called. Currently I am getting the following error, "Error: expected on to have been called at least once but was never called". Part of the confusion on my part relates to the differences between d3 and jQuery selectors, I'm more than happy to use the latter, but I'm not sure how to correctly use the former in a test to get the result I want.

我的依赖关系是d3,jQuery,mocha,chai,sinon和sinon-chai。

My dependencies are d3, jQuery, mocha, chai, sinon, and sinon-chai.

相关代码来自我的index.html文件,

Relevant code from my index.html file,

<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,

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);
        });
    });
});


推荐答案

我们可以整理出你的语法,但我们也必须整理出来的意图。

There's a few issues here; we can sort out your syntax, but we also have to sort out the intention.

至少已调用过一次但未被调用的错误消息错误:预期 在测试时未调用。它只在您的灯具中调用,设置事件处理程序。你还触发了 mouseenter 事件,但你的监听器是 mouseover mouseout 。在现实世界中,在 mouseenter 事件后很快会得到 mouseover ,但是当你伪造它jQuery不会发生。 jQuery是一个非初级反正;

The error message "Error: expected on to have been called at least once but was never called" is accurate. on isn't called during your test. It's only called in your fixtures, to set up the event handlers. You're also triggering a mouseenter event but your listeners are for mouseover and mouseout. In the real world, you'd get a mouseover very soon after a mouseenter event, but when you fake it with jQuery that won't happen. jQuery is a non-starter anyway; see below.

您可以尝试通过将其从匿名函数更改为命名的函数来解决此问题,如下所示:

You could try to fix this by changing them from anonymous functions to something named, like this:

var mouseOverHandler = function() { 
    d3.select(this).style('fill', '#ff0000');
};

然后将其绑定到您的路径 path.on('mouseover',mouseOverHandler)。你会认为你现在可以监视 mouseOverHandler ,但不会工作。当您在 c>上调用时,您的函数将被绑定,因此稍后交换为Sinon间谍不会产生任何效果。

And then bind it to your path with path.on('mouseover', mouseOverHandler). You'd think you can now spy on mouseOverHandler, but that won't work either. Your function will be bound when you call on, so swapping it out for a Sinon spy later won't have any effect.

另一个问题是你不能使用jQuery来触发D3事件,因为jQuery事件不是DOM事件。所以你应该把 $('path')。mouseenter()替换为 document.getElementById('path_one')。dispatchEvent new MouseEvent('mouseover')); (注意,这是将所有路径上的触发器 mouseenter 的代码更改为 c $ c> mouseover path_one 的元素上。

Another problem is you can't use jQuery to trigger D3 events because jQuery events aren't DOM events. So you should replace your call to $('path').mouseenter() to something like document.getElementById('path_one').dispatchEvent(new MouseEvent('mouseover')); (Noting that this is changing the code from "trigger mouseenter on all paths" to "trigger mouseover on the element with id path_one").

您可以通过重构来实现,因此您可以 使用可以间谍的东西来交换回调,但从根本上来说,错了的东西。基本上,你试图为D3写一个测试; 当我添加一个事件监听器时,请确保事件监听器被调用。相反,你应该测试你的实际代码的行为:当有人在图表上滑鼠,它的颜色应该改变。

You could futz around with refactoring so you can swap out your callback with something you can spy, but fundamentally you're testing the wrong thing. Essentially, you're trying to write a test for D3; "When I add an event listener, make sure that event listener gets called." Instead, you should test your actual code's behaviour: "When someone mouses over the chart, its colour should change".

如果您真的想要声明事件处理程序已绑定,您可以这样做:

If you really want to assert that your event handler was bound, you could do that:

expect(path.on('mouseover')).to.be.a('function')

但是如果你想确保你的颜色改变,你的测试如下:

But if you want to make sure your colour is changed, you want your test to be as follows:

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);
    });
});

这篇关于测试D3中的鼠标悬停事件与Sinon的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆