Javascript 如何使用摩卡对在a<;上涂漆的反应成分进行单元测试;画布>;?

Javascript 如何使用摩卡对在a<;上涂漆的反应成分进行单元测试;画布>;?,javascript,unit-testing,reactjs,Javascript,Unit Testing,Reactjs,我有一个React组件,它使用进行用户交互。 我没有使用react canvas或react art之类的东西; 相反,我只是在画布的2D上下文中绘制componentDidMount和componentDidUpdate 我将尽可能多的逻辑提取到两个独立的模块中:一个模块完全由纯函数组成,提供独立于React的核心操作,另一个模块提供要连接到React组件的事件处理程序和生命周期混合。 我可以很容易地测试第一个,而第二个则需要一些嘲弄 但是,我也希望对主画布组件进行最低限度的测试,以确保在提供

我有一个React组件,它使用
进行用户交互。 我没有使用
react canvas
react art
之类的东西; 相反,我只是在画布的2D上下文中绘制
componentDidMount
componentDidUpdate

我将尽可能多的逻辑提取到两个独立的模块中:一个模块完全由纯函数组成,提供独立于React的核心操作,另一个模块提供要连接到React组件的事件处理程序和生命周期混合。 我可以很容易地测试第一个,而第二个则需要一些嘲弄

但是,我也希望对主画布组件进行最低限度的测试,以确保在提供一些合理的道具集的情况下,它可以无错误地渲染。 事实证明,这相当困难,因为
componentDidMount
调用
This.refs.canvas.getContext('2d')
,它似乎没有在节点环境中定义。 所以我提出了以下解决方案,我不太喜欢; 它包括修补
React.createElement
以及创建假上下文对象:

// file: test/components/MyCanvasTest.jsx
import {describe, it} from 'mocha';
import {expect} from 'chai';

import React, {Component} from 'react';

import {declareMochaMock} from '../TestUtils';
import {
    renderIntoDocument,
    scryRenderedDOMComponentsWithTag,
} from 'react-addons-test-utils';

import MyCanvas from '../../src/components/MyCanvas';

describe('MyCanvas', () => {

    const noop = () => {};

    // These things are used in my component
    // but I don't want them to actually do anything,
    // so I mock them as no-ops.
    const propsToMockAsNoop = [
        'addEventListener',
        'removeEventListener',
        'setInterval',
        'clearInterval',
    ];
    propsToMockAsNoop.forEach(prop => declareMochaMock(window, prop, noop));

    // This thing is used in my component
    // and I need it to return a dummy value.
    declareMochaMock(window, 'getComputedStyle', () => ({ width: "720px" }));

    // This class replaces <canvas> elements.
    const canvasMockClassName = 'mocked-canvas-component';
    class CanvasMock extends Component {
        render() {
            return <div className={canvasMockClassName} />;
        }
        constructor() {
            super();
            this.width = 720;
            this.height = 480;
        }
        getContext() {
            // Here I have to include all the methods
            // that my component calls on the canvas context.
            return {
                arc: noop,
                beginPath: noop,
                canvas: this,
                clearRect: noop,
                fill: noop,
                fillStyle: '',
                fillText: noop,
                lineTo: noop,
                measureText: () => 100,
                moveTo: noop,
                stroke: noop,
                strokeStyle: '',
                textAlign: 'left',
                textBaseline: 'baseline',
            };
        }
    }

    const originalCreateElement = React.createElement;
    declareMochaMock(React, 'createElement', (...args) => {
        const newArgs = args[0] === 'canvas' ?
            [CanvasMock, ...args.slice(1)] :
            args;
        return originalCreateElement.apply(React, newArgs);
    });

    it("should render a <canvas>", () => {
        const element = <MyCanvas />;
        const component = renderIntoDocument(element);
        expect(scryRenderedDOMComponentsWithTag
            (component, canvasMockClassName)).to.have.length(1);
    });

});
我无法使用浅层渲染器,因为我的组件通过
ref
访问画布,而浅层渲染器中尚不支持
ref

有没有一种方法可以使用我当前的单元测试框架(即,不添加笑话或类似的东西)来进行此测试,同时减少测试工具需要知道的数量


(完整画布组件可用。)

您应该能够使用:

还有JSDOM。 (请确保遵循操作系统的安装过程)

示例测试:

import React from 'react';
import { mount } from 'enzyme';
import { expect } from 'chai';
import { jsdom } from 'jsdom';

import Chart from '../../src/index';

const createDOM = () => jsdom('<!doctype html><html><body><div></div></body></html>');

describe('<Chart />', () => {
  let DOM;

  const data = {
    labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
    datasets: [
      {
        label: 'My First dataset',
        backgroundColor: 'rgba(255,99,132,0.2)',
        borderColor: 'rgba(255,99,132,1)',
        borderWidth: 1,
        hoverBackgroundColor: 'rgba(255,99,132,0.4)',
        hoverBorderColor: 'rgba(255,99,132,1)',
        data: [65, 59, 80, 81, 56, 55, 40]
      }
    ]
  };

  const mountComponent = props => mount(
    <Chart data={data} {...props} />,
    { attachTo: DOM.body.firstChild }
  );

  beforeEach(() => {
    DOM = createDOM();
  });

  it('renders', () => {
    const wrapper = mountComponent();
    console.log(wrapper.html());

    expect(true).to.be.true;
  });
});
从“React”导入React;
从“酶”导入{mount};
从“chai”导入{expect};
从'jsdom'导入{jsdom};
从“../../src/index”导入图表;
const createDOM=()=>jsdom(“”);
描述(“”,()=>{
让DOM;
常数数据={
标签:[“一月”、“二月”、“三月”、“四月”、“五月”、“六月”、“七月”],
数据集:[
{
标签:“我的第一个数据集”,
背景颜色:“rgba(255,99132,0.2)”,
边框颜色:“rgba(255,99132,1)”,
边框宽度:1,
hoverBackgroundColor:'rgba(255,99132,0.4)',
hoverBorderColor:'rgba(255,99132,1)',
数据:[65,59,80,81,56,55,40]
}
]
};
常量mountComponent=props=>mount(
,
{attachTo:DOM.body.firstChild}
);
在每个之前(()=>{
DOM=createDOM();
});
它('呈现',()=>{
const wrapper=mountComponent();
log(wrapper.html());
期望(真实)是真实的;
});
});
它正在测试挂载到画布元素的Chart.js。
我正在使用摩卡咖啡和酶,但对于您正在使用的w/e测试套件来说应该没有什么不同。

我遇到了这个问题,使用AVA测试乐蒂动画。在
gor181
解决方案的帮助下,以下是我如何在2020年使用最新版本的
jsdom16.2.1
实现它的

首先安装canvas和JSDOM
npm i画布jsdom——保存开发

下面是一个使用JSDOM的示例测试:

import { mount } from 'enzyme';
import { JSDOM } from 'jsdom';

const DOM = new JSDOM('<!doctype html><html><body><div></div></body></html>');
const mountComponent = props =>
    mount(<AnimationComponent options={defaultOptions} />, {
        attachTo: DOM.body
    });

test('Animation', t => {
    const wrapper = mountComponent();
    console.log(wrapper.html()); 
    t.is(wrapper.find('div').length, 2);
});
希望这有帮助

import { mount } from 'enzyme';
import { JSDOM } from 'jsdom';

const DOM = new JSDOM('<!doctype html><html><body><div></div></body></html>');
const mountComponent = props =>
    mount(<AnimationComponent options={defaultOptions} />, {
        attachTo: DOM.body
    });

test('Animation', t => {
    const wrapper = mountComponent();
    console.log(wrapper.html()); 
    t.is(wrapper.find('div').length, 2);
});
console.log('DOM:', DOM);