使用 Mocha/Chai 测试复杂的 React 组件
Testing complex React components with Mocha/Chai
我正在研究 addons for fixed-data-table and 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)
我设法找到的所有教程都展示了如何处理测试琐碎的组件,我相信错误是由于节点是一个复杂的组件。
我的问题:如何使用更复杂的组件?特别是我需要一些帮助:
- 查找包含该单元格值的节点
- 在测试单元如何实现时保持无知,例如如果是
div
或 td
- 查看第 1 行中的 element/cell 是否出现在本应位于第 2 行中的元素之前或之后(用于验证排序)
背景
核心测试设置:
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`);
}
});
});
我已将自动生成的 ID 标记添加到 Textcell
并尝试使用 .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>
感谢 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, '()').match(second)).to.not.be.null;
}
});
});
我正在研究 addons for fixed-data-table and 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)
我设法找到的所有教程都展示了如何处理测试琐碎的组件,我相信错误是由于节点是一个复杂的组件。
我的问题:如何使用更复杂的组件?特别是我需要一些帮助:
- 查找包含该单元格值的节点
- 在测试单元如何实现时保持无知,例如如果是
div
或td
- 查看第 1 行中的 element/cell 是否出现在本应位于第 2 行中的元素之前或之后(用于验证排序)
背景
核心测试设置:
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`);
}
});
});
我已将自动生成的 ID 标记添加到 Textcell
并尝试使用 .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>
感谢 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, '()').match(second)).to.not.be.null;
}
});
});