mercredi 23 novembre 2016

Testing complex React components with Mocha/Chai

I'm working on addons for fixed-data-table and its sibling but I'm struggling with setting up the tests using a Mocha/Chai setup. The error I get is:

 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)

All the tutorials that I've managed to locate show how to handle testing trivial components, I believe the error results from that the node is a complex component.

My question: How do I more complex components? In particular I would like some help with:

  1. Finding the node that contains the value of that cell
  2. Remain ignorant when testing of how a cell is implemented, e.g. if it's a div or a td
  3. See if an element/cell in row 1 appears before or after an element that is supposed to be in row 2 (for validating sorting)

Background

Core test-setup:

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

The data stub:

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;

The actual test:

describe('Basic test', () => {
  it('some test', () => {
    const data = new Data();

    const node = renderComponent(props =>
      (<Table
        rowHeight={50}
        headerHeight={50}
        height={500}
        width={500}
        filters=
        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}`);
    }
  });
});

Aucun commentaire:

Enregistrer un commentaire