Javascript Reactsj和d3v4集成——带有jest测试的表格和饼图应用程序

Javascript Reactsj和d3v4集成——带有jest测试的表格和饼图应用程序,javascript,reactjs,d3.js,jestjs,Javascript,Reactjs,D3.js,Jestjs,我试图创建一个react、d3和jest测试的基本集成示例。我已经创建了一个饼图和表格组件——我非常希望将数据从主应用程序推送到表格和饼图组件中。只有当用户单击表时,才会填充饼图 --沙箱 -我想出了这个例子 6月9日——目前的一体化 数据看起来有点像这样 [ { "Country": "Afghanistan", "TotalConfirmed": 20917, "TotalDeaths": 369, "TotalRecovered"

我试图创建一个react、d3和jest测试的基本集成示例。我已经创建了一个饼图和表格组件——我非常希望将数据从主应用程序推送到表格和饼图组件中。只有当用户单击表时,才会填充饼图

--沙箱 -我想出了这个例子

6月9日——目前的一体化

数据看起来有点像这样

[
    {
      "Country": "Afghanistan",
      "TotalConfirmed": 20917,
      "TotalDeaths": 369,
      "TotalRecovered": 2171,
    },
    {
      "Country": "Albania",
      "TotalConfirmed": 1263,
      "TotalDeaths": 34,
      "TotalRecovered": 945,
    },
    {
      "Country": "Algeria",
      "TotalConfirmed": 10265,
      "TotalDeaths": 715,
      "TotalRecovered": 6799,
    }
]
  • 我在重新分析道具中的数据时遇到问题。我将不得不将饼图数据重构为标签、值格式——但我也不确定这方面的jest测试
//App.js

import React from 'react';

import Pie from './Pie/Pie';
import Table from './Table/Table';
import './App.css';


class App extends React.Component {
  componentDidMount() {
    //get data 
  }

  render() {


    const data = [
      {
        "Country": "Afghanistan",
        "TotalConfirmed": 20917,
        "TotalDeaths": 369,
        "TotalRecovered": 2171,
      },
      {
        "Country": "Albania",
        "TotalConfirmed": 1263,
        "TotalDeaths": 34,
        "TotalRecovered": 945,
      },
      {
        "Country": "Algeria",
        "TotalConfirmed": 10265,
        "TotalDeaths": 715,
        "TotalRecovered": 6799,
      }
  ];



    const piedata =[
            {
                label: 'Jam',
                value: 50,
            },
            {
                label: 'Coconut',
                value: 10,
            },
            {
                label: 'Nutmeg',
                value: 20,
            },
            {
                label: 'Tumeric',
                value: 20,
            },
        ];


    return (
      <div className="App">    

        <div className="row">
          <div className="col col-6"> 
            <Table data={data} />
          </div>
          <div className="col col-6">
            <Pie 
              data={piedata} 
              width="300"
              height="300"
              r="110"
              ir="0"
            />
          </div>
        </div>
      </div>
    );
  }
}

export default App;
从“React”导入React;
从“./Pie/Pie”导入饼图;
从“./Table/Table”导入表;
导入“/App.css”;
类应用程序扩展了React.Component{
componentDidMount(){
//获取数据
}
render(){
常数数据=[
{
“国家”:“阿富汗”,
“已确认总数”:20917,
“死亡总数”:369人,
“恢复总数”:2171,
},
{
“国家”:“阿尔巴尼亚”,
“已确认总数”:1263,
“死亡总数”:34,
“恢复总数”:945,
},
{
“国家”:“阿尔及利亚”,
“已确认总数”:10265,
“死亡总数”:715人,
“恢复总数”:6799,
}
];
常数piedata=[
{
标签:“果酱”,
价值:50,
},
{
标签:'椰子',
数值:10,
},
{
标签:“肉豆蔻”,
价值:20,
},
{
标签:“Tumeric”,
价值:20,
},
];
返回(
);
}
}
导出默认应用程序;
//Pie.js

import React from 'react';
import * as d3 from "d3";
import ReactDOM from 'react-dom';
import $ from 'jquery';
import './Pie.css';


class Pie extends React.Component {

    constructor(props) {
        super(props);
        this.myRef = React.createRef();
    }

    componentDidMount() {

                var $this = $(this.myRef.current);

                const data  = this.props.data;

                const width = parseInt(this.props.width,10),
                    height = parseInt(this.props.height,10),
                    radius = parseInt(this.props.r,10),
                    innerradius = parseInt(this.props.ir,10);


                var color = d3.scaleOrdinal().range(["#f0cf85", "#e7f0c3", "#a4d4ae", "#32afa9"]);


                var arc = d3.arc()
                    .outerRadius(radius - 10)
                    .innerRadius(innerradius);

                data.forEach(function(d) {
                    d.total = +d.value;
                });

                var pie = d3.pie()
                    .sort(null)
                    .value(function(d) { return d.total; });

                var svg = d3.select($this[0])
                    .append("svg")
                    .attr("width", width)
                    .attr("height", height)
                    .append("g")
                    .attr('class', 'piechart')
                    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

                var segments = svg.append('g').attr('class', 'segments');

                var slices = segments.selectAll(".arc")
                    .data(pie(data))
                    .enter().append("g")
                    .attr("class", "arc");

                slices.append("path")
                    .attr("d", arc)
                    .attr('fill', function(d, i) {
                        return color(i);
                    })

    }

    render() {

        return (
            <div 
                ref={this.myRef} 
                className="Pie"
            />
        );
    }
}
export default Pie;
从“React”导入React;
从“d3”导入*作为d3;
从“react dom”导入react dom;
从“jquery”导入美元;
导入“/Pie.css”;
类扩展了React.Component{
建造师(道具){
超级(道具);
this.myRef=React.createRef();
}
componentDidMount(){
var$this=$(this.myRef.current);
const data=this.props.data;
const width=parseInt(this.props.width,10),
高度=parseInt(此.props.height,10),
半径=parseInt(这个.props.r,10),
innerradius=parseInt(this.props.ir,10);
var color=d3.scaleOrdinal().range([“f0cf85”、“e7f0c3”、“a4d4ae”、“32afa9”);
var arc=d3.arc()
.外层(半径-10)
.内半径(内半径);
data.forEach(函数(d){
d、 总计=+d.值;
});
var pie=d3.pie()
.sort(空)
.value(函数(d){返回d.total;});
var svg=d3.select($this[0])
.append(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.附加(“g”)
.attr('class','piechart')
.attr(“变换”、“平移”(+width/2+)、“+height/2+”);
var segments=svg.append('g').attr('class','segments');
变量切片=分段。选择全部(“.arc”)
.数据(pie(数据))
.enter().append(“g”)
.attr(“类”、“弧”);
附加(“路径”)
.attr(“d”,弧)
.attr('fill',函数(d,i){
返回颜色(i);
})
}
render(){
返回(
);
}
}
导出默认饼图;
//Table.js

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import './Table.css';


class Table extends React.Component {

    constructor(props) {
        super(props);
        this.myRef = React.createRef();
    }

    componentDidMount() {
        var $this = $(this.myRef.current);
    }

    rows(data) {
        return  (data.map((listValue, index) => {
          return (
            <tr key={index}>
              <td>{listValue.Country}</td>
              <td>{listValue.TotalConfirmed}</td>
              <td>{listValue.TotalDeaths}</td>
              <td>{listValue.TotalRecovered}</td>
            </tr>
          );
        }));
    }

    render() {
        return (
        <div 
            ref={this.myRef} 
            className="Table"
        >

          <table>
            <thead>
                <tr>
                    {Object.keys(this.props.data[0]).map((key, index) => {
                        return (<th key={index}>{key}</th>);
                    })}
                </tr>
            </thead>
            <tbody>
             {this.rows(this.props.data)}
            </tbody>
          </table>

        </div>
        );
    }
}
export default Table;
从“React”导入React;
从“react dom”导入react dom;
从“jquery”导入美元;
导入“/Table.css”;
类表扩展了React.Component{
建造师(道具){
超级(道具);
this.myRef=React.createRef();
}
componentDidMount(){
var$this=$(this.myRef.current);
}
行(数据){
return(data.map)((listValue,index)=>{
返回(
{listValue.Country}
{listValue.totalconfirm}
{listValue.TotalDeathers}
{listValue.TotalRecovered}
);
}));
}
render(){
返回(
{Object.keys(this.props.data[0]).map((key,index)=>{
返回({key});
})}
{this.rows(this.props.data)}
);
}
}
导出默认表;

这些测试正确吗

App.test.js

import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
import Table from './Table/Table';
import Pie from './Pie/Pie';
import allData from './data.json';

fetch = jest.fn().mockImplementation(() => {
    const data = allData;

    data.json = jest.fn().mockImplementation(() => Promise.resolve(data));
    return Promise.resolve(data);
});
describe('App', () => {
    const wrapper = shallow(<App />);

    it('initial render', () => {
        expect(wrapper.find(Table).prop('cols')).toHaveLength(4);

        expect(wrapper.find(Pie).prop('data')).toEqual([
            {
                label: '',
                value: 100,
            },
        ]);
    });

    it('should update pie data when row is selected', () => {
        const row = wrapper.state('data')[0];
        const pieDataRefactor = wrapper.instance().pieDataRefactor(row);
        console.log(pieDataRefactor);
        wrapper.instance().rowSelected(row);

        expect(wrapper.find(Pie).prop('data')).toEqual(pieDataRefactor);
    });
});
从“React”导入React;
从“酶”导入{shall};
从“./App”导入应用程序;
从“./Table/Table”导入表;
从“./Pie/Pie”导入饼图;
从“/data.json”导入所有数据;
fetch=jest.fn().mockImplementation(()=>{
常量数据=所有数据;
data.json=jest.fn().mockImplementation(()=>Promise.resolve(data));
返回承诺。解析(数据);
});
描述('App',()=>{
常量包装器=浅();
它('初始渲染',()=>{
expect(wrapper.find(Table.prop('cols')).toHaveLength(4);
expect(wrapper.find(Pie.prop('data')).toEqual([
{
标签:“”,
数值:100,
},
]);
});
它('选择行时应更新饼图数据',()=>{
const row=wrapper.state('data')[0];
const pieDataRefactor=wrapper.instance().pieDataRefactor(行);
log(pieDataRefactor);
wrapper.instance().rowSelected(行);
import React from 'react';
import Table from './Table';
import allData from '../data.json';
import { shallow } from 'enzyme';

const columns = [
    'Country',
    'CountryCode',
    'Slug',
    'NewConfirmed',
    'TotalConfirmed',
    'NewDeaths',
    'TotalDeaths',
    'NewRecovered',
    'TotalRecovered',
    'Date',
];
describe('Table', () => {
    const defaultProps = {
        cols: columns,
        data: allData.Countries,
        rowSelected: jest.fn(),
    };

    const wrapper = shallow(<Table {...defaultProps} />);

    it('should render table', () => {
        expect(wrapper.find('.Table th')).toHaveLength(10);
        expect(wrapper.find('.Table tbody tr')).toHaveLength(allData.Countries.length);
    });

    it('should call rowSelected', () => {
        const row = wrapper.find('.Table tbody tr').at(0);

        row.simulate('click');

        expect(defaultProps.rowSelected).toHaveBeenCalled();
        expect(defaultProps.rowSelected).toHaveBeenCalledWith(allData.Countries[0]);
    });
});
import React from 'react';
import Pie from './Pie';
import $ from 'jquery';
import * as d3 from 'd3';
import { mount } from 'enzyme';
describe('Pie', () => {
    const defaultProps = {
        data: [
            { label: 'TotalConfirmed', value: 20917 },
            { label: 'TotalDeaths', value: 369 },
            { label: 'TotalRecovered', value: 2171 },
        ],
        height: 200,
        width: 200,
        r: 30,
        ir: 10,
    };

    // const wrapper = mount(<Pie {...defaultProps} />);

    it('should render Pie', () => {
        const arcSpy = jest.spyOn(d3, 'arc');
        const selectSpy = jest.spyOn(d3, 'select');
        const scaleOrdinalSpy = jest.spyOn(d3, 'scaleOrdinal');
        const pieSpy = jest.spyOn(d3, 'pie');

        const wrapper = mount(<Pie {...defaultProps} />);
        expect(wrapper.find('.Pie')).toHaveLength(1);

        expect(arcSpy).toHaveBeenCalled();
        expect(pieSpy).toHaveBeenCalled();
        expect(selectSpy).toHaveBeenCalled();
        expect(scaleOrdinalSpy).toHaveBeenCalled();
    });
});