使用Jest / Enzyme

时间:2019-03-11 14:36:05

标签: reactjs d3.js jestjs enzyme jsdom

问题::运行代码时,SVG会附加到组件的外部div上,并完美地呈现在页面上。但是,在测试期间,SVG不会附加到外部div。

堆栈:我正在尝试使用Jest / Enzyme测试包装在React组件中的d3js元素。

我到目前为止所做的研究:查找了有关使用google测试d3js以及stackoverflow的大量指南。使用了有关对d3js和React with Jasmine进行单元测试的指南。我还读到,用Enzyme测试第三方库可能很困难,因此这可能是测试框架的局限性。

我提供了一个基本的代码示例进行测试。

组件:

import React from "react";
import * as d3 from "d3";

export default class Circle extends React.Component {

    componentDidMount = () => {
        return this.renderCircle();
    }

    renderCircle = () => {
        d3.select("#outerDiv")
            .append("svg")
            .attr("width", 600)
            .attr("height", 300)
            .append("circle")
            .attr("id", "d3-el")
            .attr("cx", 300)
            .attr("cy", 150)
            .attr("r", 30)
            .attr("fill", "#ff0000")
            .on("click", function (d, i) {
                var item = d3.select(this);
                item.attr("fill", "#00ff00");
            });
    }

    render() {
        return <div id="outerDiv" />;
    }

}

测试:

import React from "react";
import * as d3 from "d3";
const jsdom = require("jsdom");
const ReactJSDOM = require('react-jsdom');
const { JSDOM } = jsdom;
import Circle from "./Circle.js";
import { mount } from "enzyme";
import sinon from 'sinon';

describe("Circle", () => {
    it("d3js element should be appended to outer div", () => {
        let wrapper = mount(<Circle />);
        let instance = wrapper.instance();
        const jsdomElem = ReactJSDOM.render(<html><body><p><Circle /></p></body></html>);
        console.log(jsdomElem.querySelector("#d3-el")); // returns null
        console.log(wrapper.find("d3-ele").get(0));; // returns undefined
        console.log(d3.select("d3-el")); // returns null
        expect(wrapper.find("d3-el").exists()).toEqual(true);
    }
}

在应该使用wrapper.find(),document.querySelector()和d3.select()呈现的d3元素上进行查找都返回undefined或null。

我尝试过但未将SVG元素附加到外部div的操作:

  1. 在组件上使用mount()。

  2. 使用已安装组件的instance()并直接调用renderCircle()方法。

  3. 使用ReactJSDOM从顶部到底部渲染整个DOM。

  4. 一堆其他可能毫无意义的东西,包括sinon.spy()和嘲笑jest.fn()。

这些方法都不起作用,如果我在外部div上进行查找,则不会显示div有任何子元素。在包装器上进行调试会显示相同的结果。

在测试过程中,希望将SVG附加到div上会有帮助。任何解决方案或其他策略将不胜感激。如果您有任何疑问或需要添加更多信息,请告诉我。谢谢!

2 个答案:

答案 0 :(得分:1)

首先,您应该将组件的关注点分开。

将与d3相关的代码移动到单独的函数(或类)中,并像测试其他任何React组件一样测试组件。

然后,测试与D3相关的功能。看一下D3库本身的测试,例如here。他们使用jsdom模拟真实DOM的行为。

答案 1 :(得分:0)

当我使用d3js和Jest做类似的事情时,我遇到了这个问题。我正在执行d3.select(#id),其中id已通过

呈现在文档主体中
barGraphContainer = document.createElement("div");
    barGraphContainer.id = "testBar_d3";
    barGraphContainer.setAttribute(
        "style",
        "width: 1024px; height: 400px;"
    );
    document.body.appendChild(barGraphContainer);

jest.environment.setup.js中,我添加了以下内容以将d3搜索到的文档与JSm文档绑定在一起。

const JSDOM = require("jsdom").JSDOM;
const jsdom = new JSDOM(`<!doctype html><html lang="en"><body></body></html>`);
global.window = jsdom.window;
global.document = jsdom.window.document;