简体   繁体   English

使用Jest / Enzyme进行React组件单元测试中的D3js

[英]D3js in a React Component Unit Testing using Jest/Enzyme

Problem: When I run my code, the SVG appends to the outer div on the component and renders on the page perfectly. 问题:当我运行我的代码时,SVG会附加到组件的外部div并完美呈现在页面上。 However, during testing, the SVG is not appended to the outer div. 但是,在测试期间,SVG不会附加到外部div。

Stack: I am trying to test my d3js element wrapped in a React component using Jest/Enzyme. Stack:我正在尝试使用Jest / Enzyme测试包含在React组件中的d3js元素。

Research I did so far: Looked up a bunch of guides/posts on testing d3js using google and on stackoverflow. 到目前为止我做过的研究:在谷歌和stackoverflow上测试d3js上看了一堆指南/帖子。 Used a guide on unit testing d3js and React with Jasmine. 使用单元测试d3js和与Jasmine React的指南。 I have also read that testing 3rd party libraries may be difficult with Enzyme so this may be a limitation of the testing framework. 我还读到使用Enzyme测试第三方库可能很困难,因此这可能是测试框架的限制。

I have included a basic sample of code to test. 我已经包含了一个基本的代码示例来测试。

Component: 零件:

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" />;
    }

}

Test: 测试:

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

Doing a find on the d3 element that is supposed to be rendered using wrapper.find(), document.querySelector(), and d3.select() all return undefined or null. 对应该使用wrapper.find(),document.querySelector()和d3.select()进行渲染的d3元素进行查找都返回undefined或null。

Things I have tried but does not append the SVG element to the outer div: 我试过的东西,但没有将SVG元素附加到外部div:

  1. Using mount() on the component. 在组件上使用mount()。

  2. Using instance() of the mounted component and calling the renderCircle() method directly. 使用已安装组件的instance()并直接调用renderCircle()方法。

  3. Using ReactJSDOM to render a whole DOM from top to bottom. 使用ReactJSDOM从上到下渲染整个DOM。

  4. A bunch of other stuff that probably makes no sense including sinon.spy() and mocking a jest.fn(). 一堆其他可能没有意义的东西,包括sinon.spy()和嘲笑jest.fn()。

None of these methods work and if I do a find on the outer div, it does not show that the div has any children elements. 这些方法都不起作用,如果我在外部div上查找,它不会显示div有任何子元素。 Doing a debug on the wrapper shows the same thing. 在包装器上进行调试显示了同样的事情。

Would love some help to get this SVG appended to the div during testing. 在测试过程中,我会非常乐意帮助将这个SVG附加到div中。 Any solutions or other strategies would be greatly appreciated. 任何解决方案或其他策略将不胜感激。 Please let me know if you have any questions or if I should add more information. 如果您有任何疑问或我是否应该添加更多信息,请与我们联系。 Thanks! 谢谢!

First things first, you should separate concerns of your components. 首先,您应该分离组件的问题。

Move d3-related code into separate function (or class) and test your component as you would test any other React component. 将与d3相关的代码移动到单独的函数(或类)中,并像测试任何其他React组件一样测试组件。

After that, test D3-related functionality. 之后,测试D3相关的功能。 Take a look at tests for D3 library itself, for example here . 看看D3库本身的测试,例如这里 They use jsdom to simulate behavior of real DOM. 他们使用jsdom来模拟真实DOM的行为。

I ran into this issue earlier when I was doing something similar with d3js and Jest. 我之前遇到过与d3js和Jest类似的事情时遇到过这个问题。 I was performing d3.select(#id) where id was already rendered in the document body via 我正在执行d3.select(#id) ,其中id已经在文档正文中呈现

barGraphContainer = document.createElement("div");
    barGraphContainer.id = "testBar_d3";
    barGraphContainer.setAttribute(
        "style",
        "width: 1024px; height: 400px;"
    );
    document.body.appendChild(barGraphContainer);

In jest.environment.setup.js I added the following to tie in the document d3 searches in and the JSDom document. 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM