【问题标题】:D3js in a React Component Unit Testing using Jest/Enzyme使用 Jest/Enzyme 在 React 组件单元测试中的 D3js
【发布时间】:2019-08-01 21:48:03
【问题描述】:

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

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

到目前为止我所做的研究:查找了一堆关于使用 google 和 stackoverflow 测试 d3js 的指南/帖子。使用了关于单元测试 d3js 和 React with Jasmine 的指南。我还读到使用 Enzyme 测试 3rd 方库可能很困难,因此这可能是测试框架的限制。

我已经包含了一个基本的代码示例来测试。

组件:

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 中。任何解决方案或其他策略将不胜感激。如果您有任何问题或者我是否应该添加更多信息,请告诉我。谢谢!

【问题讨论】:

  • 你发现了吗?请告诉我们。

标签: reactjs d3.js jestjs enzyme jsdom


【解决方案1】:

我之前在使用 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 搜索与 JSDom 文档联系起来。

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;

【讨论】:

  • 嗯.. 我认为我的问题有所不同。测试时我无法让 D3 渲染任何东西,而不是我找不到元素。如果我查看容器 div,它没有任何子项。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2017-02-12
    • 2018-08-20
    • 2019-05-06
    • 2020-02-06
    • 2018-12-16
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多