title: Testing complex React components with Mocha/Chai
body: <p>I'm working on <a href="https://github.com/gforge/fixed-data-table-addons" rel="nofollow noreferrer">addons</a> for <a href="https://github.com/facebook/fixed-data-table" rel="nofollow noreferrer">fixed-data-table</a> and <a href="https://github.com/schrodinger/fixed-data-table-2/" rel="nofollow noreferrer">its sibling</a> but I'm struggling with setting up the tests using a Mocha/Chai setup. The error I get is:</p>
  
  <pre><code> 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.&lt;anonymous&gt; (test/HOC/addFilter_test.jsx:48:23)
  </code></pre>
  
  <p>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. </p>
  
  <p>My question: <strong>How do I more complex components?</strong> In particular I would like some help with:</p>
  
  <ol>
  <li>Finding the node that contains the value of that cell</li>
  <li>Remain ignorant when testing of how a cell is implemented, e.g. if it's a <code>div</code> or a <code>td</code></li>
  <li>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)</li>
  </ol>
  
  <h2>Background</h2>
  
  <h3>Core test-setup:</h3>
  
  <pre><code>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('&lt;!doctype html&gt;&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;');
  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(
        &lt;Wrapper ref={n =&gt; (node = n)}&gt;
          &lt;ComponentClass {...props} /&gt;
        &lt;/Wrapper&gt;);
    } else {
      TestUtils.renderIntoDocument(&lt;ComponentClass {...props} ref={n =&gt; (node = n)} /&gt;);
    }
  
    return node;
  }
  
  // Set up chai-jquery
  chaiJquery(chai, chai.util, $);
  
  const TextCell = ({ rowIndex, columnKey, data }) =&gt; (
    &lt;Cell&gt;
      {data.getObjectAt(rowIndex)[columnKey]}
    &lt;/Cell&gt;);
  
  TextCell.propTypes = {
    rowIndex: React.PropTypes.number,
    columnKey: React.PropTypes.string,
      data: React.PropTypes.object,
  };
  </code></pre>
  
  <h3>The data stub:</h3>
  
  <pre><code>class Data {
    constructor(nrows = 4) {
      this.size = nrows;
    }
  
    getSize() {
      return (this.size);
    }
  
    getObjectAt(index) {
      if (index &lt; 0 || index &gt;= this.size) {
        return (null);
      }
  
      return {
        id: index,
        name: `Test name no ${index}`,
      };
    }
  }
  
  export default Data;
  </code></pre>
  
  <h3>The actual test:</h3>
  
  <pre><code>describe('Basic test', () =&gt; {
    it('some test', () =&gt; {
      const data = new Data();
  
      const node = renderComponent(props =&gt;
        (&lt;Table
          rowHeight={50}
          headerHeight={50}
          height={500}
          width={500}
          filters={{ name: '' }}
          rowsCount={data.getSize()}
          {...props}
        &gt;
          &lt;Column
            columnKey="id"
            width={250}
            header={&lt;Cell&gt;ID&lt;/Cell&gt;}
            cell={&lt;TextCell data={data} /&gt;}
          /&gt;
          &lt;Column
            columnKey="name"
            width={250}
            header={&lt;Cell&gt;Name&lt;/Cell&gt;}
            cell={&lt;TextCell data={data} /&gt;}
          /&gt;
        &lt;/Table&gt;));
  
      for (let i = 0; i &lt; data.getSize(); i += 1) {
        expect(node).to.contains(`Test name no ${i}`);
      }
    });
  });
  </code></pre>
  
  <h1>Update</h1>
  
  <p>Changed to <a href="https://github.com/airbnb/enzyme" rel="nofollow noreferrer">enzyme</a> as suggested:</p>
  
  <pre><code>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 }) =&gt; (
    &lt;Cell id={`${rowIndex}_${columnKey}`}&gt;
      {data.getObjectAt(rowIndex)[columnKey]}
    &lt;/Cell&gt;);
  
  TextCell.propTypes = {
    rowIndex: React.PropTypes.number,
    columnKey: React.PropTypes.string,
      data: React.PropTypes.object,
  };
  
  describe('Basic test', () =&gt; {
    it('some test', () =&gt; {
      const data = new Data();
  
      const node = shallow(&lt;Table
        rowHeight={50}
        headerHeight={50}
        height={500}
        width={500}
        filters={{ name: '' }}
        rowsCount={data.getSize()}
      &gt;
        &lt;Column
          columnKey="id"
          width={250}
          header={&lt;Cell&gt;ID&lt;/Cell&gt;}
          cell={&lt;TextCell data={data} /&gt;}
        /&gt;
        &lt;Column
          columnKey="name"
          width={250}
          header={&lt;Cell&gt;Name&lt;/Cell&gt;}
          cell={&lt;TextCell data={data} /&gt;}
        /&gt;
      &lt;/Table&gt;);
  
      for (let i = 0; i &lt; data.getSize(); i += 1) {
        expect(node.find(`#${i}_name`)).to.have.length(1, `Can't find cell with id: ${i}_name`);
      }
    });
  });
  </code></pre>
  
  <p>I've added an auto-generated id-marker to the <code>Textcell</code> and tried to find it using <code>.find(`#${i}_name`)</code> but it doesn't find the object. I've checked the output of the wrapped element using <code>node.html()</code> and it does contain the cell with the proper ID:</p>
  
  <pre><code>&lt;div class="fixedDataTableCellLayout_wrap1 public_fixedDataTableCell_wrap1" id="0_name"&gt;
    &lt;div class="fixedDataTableCellLayout_wrap2 public_fixedDataTableCell_wrap2"&gt;
      &lt;div class="fixedDataTableCellLayout_wrap3 public_fixedDataTableCell_wrap3"&gt;
        &lt;div class="public_fixedDataTableCell_cellContent"&gt;
          Test name no 0
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>