16
votes

I'm using React v15.4, babel-jest v18 and enzyme v2.5.1

I have a simple React Component:

import React, {Component} from 'react'
import {FormattedRelative} from 'react-intl'
import pageWithIntl from '../components/PageWithIntl'
import Layout from '../components/Layout'

class About extends Component {
  static async getInitialProps ({req}) {
    return {someDate: Date.now()}
  }

  render () {
    return (
      <Layout>
        <h1>About</h1>
        <p>
          <FormattedRelative
            value={this.props.someDate}
            updateInterval={1000}
          />
        </p>
      </Layout>
    )
  }
}

export default pageWithIntl(About)

And a simple Jest/Enzyme Test:

/* global it, expect, describe */

import React from 'react'
import { shallow } from 'enzyme'
import renderer from 'react-test-renderer'
import About from '../pages/about.js'

describe('With Enzyme', () => {
  it('App shows "About"', () => {
    const about = shallow(
      <About />
    )
    expect(about.find('h1').text()).toEqual('About')
  })
})

The Jest test should pass but I'm getting an error:

Method “text” is only meant to be run on a single node. 0 found instead.

What am I missing?

=== Update

The snapshot test passes:

describe('With Snapshot Testing', () => {
  it('About shows "About"', () => {
    const component = renderer.create(<About />)
    const tree = component.toJSON()
    expect(tree).toMatchSnapshot()
  })
})

Is there a way to integrate the enzyme expect test inside the snapshot test? And how?

4

4 Answers

15
votes

Its caused by the fact that shallow does not render child componnets and your component been wrapped by a function. So shallow only returns a representation of the function not of the component. You can use dive() to reach the real component

/* global it, expect, describe */

import React from 'react'
import { shallow } from 'enzyme'
import renderer from 'react-test-renderer'
import About from '../pages/about.js'

describe('With Enzyme', () => {
  it('App shows "About"', () => {
    const about = shallow(
      <About />
    ).dive()
    expect(about.find('h1').text()).toEqual('About')
  })
})
4
votes

Please see this link on how to use the .findWhere on a shallow copy: https://blogs.sequoiainc.com/an-enzyme-gotcha/

Below is an example looking for nodes/html-elements of type "p" that contain the desired text which represents a salary "$100,000.00".

displayemployee = shallow(<DisplayEmployee employeeData={employee}

it('renders the employees salary', () => {
  expect(
    displayemployee.findWhere(
    n => n.type() === 'p' && n.contains('$100,000.00')
  )
)

The shallow copy returns all the nodes that the react component returns, and I'm searching through those nodes with .findWhere rather than .text. This is because .text expects to look through a single node; .text doesn't know how to scan through many nodes.

3
votes

Use .first()

example const wrapper = shallow()

wrapper.find('h1 or p or .ClassName or #id').first();

import React from 'react'
import { shallow } from 'enzyme'
import renderer from 'react-test-renderer'
import About from '../pages/about.js'

describe('With Enzyme', () => {
  it('App shows "About"', () => {
    const about = shallow(
      <About />
   )
  expect(about.find('h1').first().text()).toEqual('About')
 })
})
0
votes

You can also 'export class' along with 'export default' and import component in test with the destructuring import version.

For example:

import React, {Component} from 'react'
import {FormattedRelative} from 'react-intl'
import pageWithIntl from '../components/PageWithIntl'
import Layout from '../components/Layout'

export class About extends Component {
  static async getInitialProps ({req}) {
    return {someDate: Date.now()}
  }

  render () {
    return (
      <Layout>
        <h1>About</h1>
        <p>
          <FormattedRelative
            value={this.props.someDate}
            updateInterval={1000}
          />
        </p>
      </Layout>
    )
  }
}

export default pageWithIntl(About)

And the test:

/* global it, expect, describe */

import React from 'react'
import { shallow } from 'enzyme'
import renderer from 'react-test-renderer'
import { About } from '../pages/about.js'

describe('With Enzyme', () => {
  it('App shows "About"', () => {
    const about = shallow(
      <About />
    )
    expect(about.find('h1').text()).toEqual('About')
  })
})