d3js单元测试去除元素

时间:2017-03-01 17:29:19

标签: d3.js jasmine

我正在使用jasmined3.js图表中的某些互动进行单元测试。我一直在使用d3.timerFlush()来完成动画的执行。这适用于输入新元素或更新属性时,我能够准确地测试新值。但是,我很难将其删除元素。

我有这样的方法:

exit() {
    let arcs = svg.selectAll("path.arc");

    arcs.transition().duration(1000)
        .attrTween("d", function(d, i) { return vm._arcTween(this, d) })
        .remove();
}

我的测试看起来像这样:

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

失败了。如果我调试测试,我可以看到元素没有被删除。但是如果我改变了期望:

expect(pieChartSvc._arcTween).toHaveBeenCalled();

传递,所以我知道该方法正在正确执行并且计时器已刷新,但元素未被删除。

我做错了什么?

此问题:Disabling all D3 animations (for testing) 不回答我的问题。正在执行转换,并且元素已经更改为它们从DOM中删除之前所处的状态,但是它们仍然出现在DOM上

1 个答案:

答案 0 :(得分:4)

好吧,想通了,d3版本3曾用date.now来衡量时间。版本4移至performance.now

所以,正确的代码应该是:

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

这是一些测试代码:

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