24

I am trying to use enzyme to assert DOM nodes. My Component looks like

import React, {Component} from 'react';
import TransactionListRow from './TransactionListRow';
import {Table, TableBody, TableHeader, TableHeaderColumn, TableRow} from 'material-ui/Table';

export default class TransactionList extends Component {
  render() {
    const { transactions } = this.props;

    return (
      <Table>
        <TableHeader displaySelectAll={false}>
          <TableRow>
            <TableHeaderColumn>Name</TableHeaderColumn>
            <TableHeaderColumn>Amount</TableHeaderColumn>
            <TableHeaderColumn>Transaction</TableHeaderColumn>
            <TableHeaderColumn>Category</TableHeaderColumn>
          </TableRow>
        </TableHeader>
        <TableBody>
          {transactions.map(transaction =>
            <TransactionListRow key={transaction.id} transaction={transaction}/>
          )}
        </TableBody>
      </Table>
    );
  }
};

My test looks like

import expect from 'expect';
import React from 'react';
import {mount} from 'enzyme';
import TransactionList from '../TransactionList';
import {TableHeaderColumn} from 'material-ui/Table';
import getMuiTheme from 'material-ui/styles/getMuiTheme';

describe("<TransactionList />", () => {
  const mountWithContext = (node) => mount(node, {
    context: {
      muiTheme: getMuiTheme(),
    },
    childContextTypes: {
      muiTheme: React.PropTypes.object.isRequired,
    }
  });


  it('renders five <TableHeaderColumn /> components', () => {
    const wrapper = mountWithContext(<TransactionList transactions={[]}/>)

    console.log(wrapper.html());
    // expect(wrapper.find('thead').length).toBe(1);
    expect(wrapper.contains(<TableHeaderColumn>Name</TableHeaderColumn>)).to.equal(true)
  });
});

When I run this, I get

  ● <TransactionList /> › renders five <TableHeaderColumn /> components

    TypeError: Cannot read property 'equal' of undefined

      at Object.<anonymous> (src/components/transactions/__tests__/TransactionList.test.js:24:250)
      at process._tickCallback (internal/process/next_tick.js:103:7)

As per Enzyme docs,

.contains() expects a ReactElement, not a selector (like many other methods). Make sure that when you are calling it you are calling it with a ReactElement or a JSX expression.

What am I doing wrong?

Thanks

UPDATE
I removed the import expect from 'expect and ran it as

import React from 'react';
import {mount} from 'enzyme';
import TransactionList from '../TransactionList';
import TableHeaderColumn from 'material-ui/Table';
import getMuiTheme from 'material-ui/styles/getMuiTheme';

describe("<TransactionList />", () => {
  const mountWithContext = (node) => mount(node, {
    context: {
      muiTheme: getMuiTheme(),
    },
    childContextTypes: {
      muiTheme: React.PropTypes.object.isRequired,
    }
  });


  it('renders five <TableHeaderColumn /> components', () => {
    const wrapper = mountWithContext(<TransactionList transactions={[]}/>)

    // console.log(wrapper.html());
    expect(wrapper.find('thead').length).toBe(1);
    expect(wrapper.find('td').length).toBe(0);

    // this is not working
    expect(wrapper.contains(<TableHeaderColumn/>)).toEqual(true);
  });
});

It fails now with

 FAIL  src/components/transactions/__tests__/TransactionList.test.js
  ● <TransactionList /> › renders five <TableHeaderColumn /> components

    expect(received).toEqual(expected)

    Expected value to equal:
      true
    Received:
      false

      at Object.<anonymous> (src/components/transactions/__tests__/TransactionList.test.js:26:164)

and with

expect(wrapper.contains(<TableHeaderColumn/>)).to.equal(true);

I get

      Warning: Unknown props `onMouseEnter`, `onMouseLeave`, `onClick` on <th> tag. Remove these props from the element. 
 FAIL  src/components/transactions/__tests__/TransactionList.test.js
  ● <TransactionList /> › renders five <TableHeaderColumn /> components

    TypeError: Cannot read property 'equal' of undefined

      at Object.<anonymous> (src/components/transactions/__tests__/TransactionList.test.js:26:166)
      at process._tickCallback (internal/process/next_tick.js:103:7)

I still can not assert on ReactElement

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
daydreamer
  • 87,243
  • 191
  • 450
  • 722

1 Answers1

75

That's not an Enzyme problem.

expect(...).to is undefined because you have installed expect.js and you are using chai syntax.

this

expect(wrapper.contains(<TableHeaderColumn>Name</TableHeaderColumn>)).to.equal(true)

should be

expect(wrapper.contains(<TableHeaderColumn>Name</TableHeaderColumn>)).toEqual(true)
QoP
  • 27,388
  • 16
  • 74
  • 74
  • Thanks for the help, please see my update. I am still confused – daydreamer Oct 07 '16 at 22:43
  • 1
    Have you tried using `expect(wrapper.find('TableHeaderColumn').length === 5).toEqual(true); ` / `expect(wrapper.find(TableHeaderColumn).length === 5).toEqual(true);` ? – QoP Oct 07 '16 at 23:06
  • 3
    Thanks @QoP your first two lines helped me immediately. I suspect this would happen a lot for someone like me who went from unit testing with expect, to using the helper libraries, chia etc, and not noticing the subtle nuances with syntax. – Faktor 10 Mar 29 '17 at 09:23
  • Here comes another tripped up chai user! thank you QoP! – Kyle Richardson Jul 19 '17 at 04:02
  • 15
    Interestingly enough, the Enzyme [docs](http://airbnb.io/enzyme/docs/api/ShallowWrapper/contains.html) show the `to.equal()` syntax usage without any reference to Chai. – Doug Wilhelm Dec 15 '17 at 18:02
  • yes in Enzyme docs they are using the `to.equal()` Any comment for it – Anupam Maurya Jan 02 '19 at 07:53
  • @doug-wilhelm, "The documentation and examples for enzyme use mocha and chai." https://airbnb.io/enzyme/ – karfus Aug 08 '19 at 12:03