问题
I am using jasmine
to unit test some interactions in a d3.js
chart. I have been using d3.timerFlush()
to complete the executions of animations. This works great for when entering new elements or updating attribute, and I am able to accurately test the new values. However, I am having a hard time getting it to remove elements.
I have a method like this:
exit() {
let arcs = svg.selectAll("path.arc");
arcs.transition().duration(1000)
.attrTween("d", function(d, i) { return vm._arcTween(this, d) })
.remove();
}
And my test looks something like this:
it('it will remove all of the pie related elements from the DOM', () => {
chartSvc.exit();
d3.timerFlush();
let elements = svg.querySelectorAll(/* selects my elements */);
expect(elements.length).toEqual(0);
});
which fails. If I debug the tests, I can see that the elements are not being removed. However if I change the expect:
expect(pieChartSvc._arcTween).toHaveBeenCalled();
that passes, so I know that the method is being executed correctly and the timer flushed, but the elements aren't removed.
What am I doing wrong?
This issue: Disabling all D3 animations (for testing) does not answer my question. The transition is being executed and the elements have been changed to the state they are in before they are removed from the DOM, however they still appear on the DOM
回答1:
Alright, figured it out, d3
version 3 used to use date.now
to measure time. Version 4 moved to performance.now.
So, the correct code should be:
it('it will remove all of the pie related elements from the DOM', () => {
chartSvc.exit();
performance.now = function() { return Infinity; };
d3.timerFlush();
let elements = svg.querySelectorAll(/* selects my elements */);
expect(elements.length).toEqual(0);
});
Here's some test code:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
<style>
path {
fill: none;
stroke: steelblue;
}
</style>
</head>
<body>
<svg width="300" height="300">
<g transform="translate(20,20)">
<path class="arc" d="M0,0L100,0"></path>
<path class="arc" d="M0,50L100,50"></path>
<path class="arc" d="M0,100L100,100"></path>
<path class="arc" d="M0,150L100,150"></path>
</g>
</svg>
<script>
var svg = d3.select('svg');
let arcs = svg.selectAll("path.arc");
arcs.transition()
.duration(10000)
.remove();
performance.now = function() { return Infinity; };
d3.timerFlush();
</script>
</body>
</html>
来源:https://stackoverflow.com/questions/42538240/d3js-unit-testing-removal-of-elements