使用Mocha / Chai测试复杂的React组件

时间:2016-11-23 17:06:41

标签: reactjs testing mocha fixed-data-table

我正在为addonsfixed-data-table its sibling工作,但我正在努力设置使用Mocha / Chai设置的测试。我得到的错误是:

 TypeError: obj.indexOf is not a function
      at Assertion.include (node_modules/chai/lib/chai/core/assertions.js:228:45)
      at Assertion.assert (node_modules/chai/lib/chai/utils/addChainableMethod.js:84:49)
      at Context.<anonymous> (test/HOC/addFilter_test.jsx:48:23)

我设法找到的所有教程都展示了如何处理测试琐碎的组件,我相信错误是由于节点是一个复杂的组件。

我的问题:我如何更复杂的组件?特别是我想要一些帮助:

  1. 查找包含该单元格值的节点
  2. 在测试细胞如何实施时保持无知,例如如果是divtd
  3. 查看第1行中的元素/单元格是否出现在应该位于第2行的元素之前或之后(用于验证排序)
  4. 背景

    核心测试设置:

    import React from 'react';
    import { describe, it } from 'mocha';
    import { Table, Column, Cell } from 'fixed-data-table';
    import jsdom from 'jsdom';
    import jquery from 'jquery';
    import chaiJquery from 'chai-jquery';
    import TestUtils from 'react-addons-test-utils';
    import chai, { expect } from 'chai';
    import Data from '../stub/Data';
    
    // Set up testing environment to run like a browser in the command line
    global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
    global.window = global.document.defaultView;
    const $ = jquery(global.window);
    
    class Wrapper extends React.Component {
      render() {
        return this.props.children;
      }
    }
    
    Wrapper.propTypes = {
      children: React.PropTypes.node,
    };
    
    // build 'renderComponent' helper that should render a given react class
    function renderComponent(ComponentClass, props) {
      let node = null;
      if (typeof (ComponentClass) === 'function') {
        TestUtils.renderIntoDocument(
          <Wrapper ref={n => (node = n)}>
            <ComponentClass {...props} />
          </Wrapper>);
      } else {
        TestUtils.renderIntoDocument(<ComponentClass {...props} ref={n => (node = n)} />);
      }
    
      return node;
    }
    
    // Set up chai-jquery
    chaiJquery(chai, chai.util, $);
    
    const TextCell = ({ rowIndex, columnKey, data }) => (
      <Cell>
        {data.getObjectAt(rowIndex)[columnKey]}
      </Cell>);
    
    TextCell.propTypes = {
      rowIndex: React.PropTypes.number,
      columnKey: React.PropTypes.string,
        data: React.PropTypes.object,
    };
    

    数据存根:

    class Data {
      constructor(nrows = 4) {
        this.size = nrows;
      }
    
      getSize() {
        return (this.size);
      }
    
      getObjectAt(index) {
        if (index < 0 || index >= this.size) {
          return (null);
        }
    
        return {
          id: index,
          name: `Test name no ${index}`,
        };
      }
    }
    
    export default Data;
    

    实际测试:

    describe('Basic test', () => {
      it('some test', () => {
        const data = new Data();
    
        const node = renderComponent(props =>
          (<Table
            rowHeight={50}
            headerHeight={50}
            height={500}
            width={500}
            filters={{ name: '' }}
            rowsCount={data.getSize()}
            {...props}
          >
            <Column
              columnKey="id"
              width={250}
              header={<Cell>ID</Cell>}
              cell={<TextCell data={data} />}
            />
            <Column
              columnKey="name"
              width={250}
              header={<Cell>Name</Cell>}
              cell={<TextCell data={data} />}
            />
          </Table>));
    
        for (let i = 0; i < data.getSize(); i += 1) {
          expect(node).to.contains(`Test name no ${i}`);
        }
      });
    });
    

    更新

    按照建议更改为enzyme

    import React from 'react';
    import { describe, it } from 'mocha';
    import chai, { expect } from 'chai';
    import { shallow } from 'enzyme';
    import chaiEnzyme from 'chai-enzyme';
    import { Table, Column, Cell } from 'fixed-data-table';
    import Data from '../stub/Data';
    
    Error.stackTraceLimit = 10;
    chai.use(chaiEnzyme);
    
    const TextCell = ({ rowIndex, columnKey, data }) => (
      <Cell id={`${rowIndex}_${columnKey}`}>
        {data.getObjectAt(rowIndex)[columnKey]}
      </Cell>);
    
    TextCell.propTypes = {
      rowIndex: React.PropTypes.number,
      columnKey: React.PropTypes.string,
        data: React.PropTypes.object,
    };
    
    describe('Basic test', () => {
      it('some test', () => {
        const data = new Data();
    
        const node = shallow(<Table
          rowHeight={50}
          headerHeight={50}
          height={500}
          width={500}
          filters={{ name: '' }}
          rowsCount={data.getSize()}
        >
          <Column
            columnKey="id"
            width={250}
            header={<Cell>ID</Cell>}
            cell={<TextCell data={data} />}
          />
          <Column
            columnKey="name"
            width={250}
            header={<Cell>Name</Cell>}
            cell={<TextCell data={data} />}
          />
        </Table>);
    
        for (let i = 0; i < data.getSize(); i += 1) {
          expect(node.find(`#${i}_name`)).to.have.length(1, `Can't find cell with id: ${i}_name`);
        }
      });
    });
    

    我已为Textcell添加了自动生成的ID标记,并尝试使用.find(`#${i}_name`)找到它,但找不到该对象。我使用node.html()检查了包装元素的输出,它确实包含具有正确ID的单元格:

    <div class="fixedDataTableCellLayout_wrap1 public_fixedDataTableCell_wrap1" id="0_name">
      <div class="fixedDataTableCellLayout_wrap2 public_fixedDataTableCell_wrap2">
        <div class="fixedDataTableCellLayout_wrap3 public_fixedDataTableCell_wrap3">
          <div class="public_fixedDataTableCell_cellContent">
            Test name no 0
          </div>
        </div>
      </div>
    </div>
    

1 个答案:

答案 0 :(得分:1)

感谢 Lucas Katayama 为您提供使用enzyme的建议。请注意,mount必须使用,find不会识别子元素。

排序问题通过找到第一个ID,之前替换所有内容然后在剩余部分中搜索下一个ID来解决。

import React from 'react';
import { describe, it, beforeEach } from 'mocha';
import { Table, Column, Cell } from 'fixed-data-table';
import chai, { expect } from 'chai';
import { mount } from 'enzyme';
import chaiEnzyme from 'chai-enzyme';
import Data from '../stub/Data';

Error.stackTraceLimit = 10;
chai.use(chaiEnzyme);

const TextCell = ({ rowIndex, columnKey, data }) => (
  <Cell id={`${rowIndex}_${columnKey}`}>
    {data.getObjectAt(rowIndex)[columnKey]}
  </Cell>);

TextCell.propTypes = {
  rowIndex: React.PropTypes.number,
  columnKey: React.PropTypes.string,
  data: React.PropTypes.instanceOf(Data),
};

describe('Basic test', () => {
  const data = new Data();
  let node;
  beforeEach(() => (
    node = mount(<Table
      rowHeight={50}
      headerHeight={50}
      height={500}
      width={500}
      filters={{ name: '' }}
      rowsCount={data.getSize()}
    >
      <Column
        columnKey="id"
        width={250}
        header={<Cell>ID</Cell>}
        cell={<TextCell data={data} />}
      />
      <Column
        columnKey="name"
        width={250}
        header={<Cell>Name</Cell>}
        cell={<TextCell data={data} />}
      />
    </Table>)
  ));

  it('test that cells exist', () => {
    for (let i = 0; i < data.getSize(); i += 1) {
      expect(node.find(`#${i}_id`)).to.have.length(1, `Can't find cell with id: ${i}_id`);
      expect(node.find(`#${i}_name`)).to.have.length(1, `Can't find cell with id: ${i}_name`);
    }
  });

  it('sort test', () => {
    const txt = node.html();
    for (let i = 0; i < data.getSize() - 1; i += 1) {
      const first = new RegExp(`.+id="${i}_id"(.+)`);
      const second = new RegExp(`id="${i + 1}_id"`);
      expect(txt.replace(first, '($1)').match(second)).to.not.be.null;
    }
  });
});