简体   繁体   中英

Enzyme not shallow rendering child

I am trying to test that a child component exists by shallow-rendering it with Enzyme. However, it does not appear to be getting past the return of the component and instead shallow-renders <undefined /> .

MainComponentContainer.js

import PropTypes from 'prop-types'
import React from 'react'
import createReactClass from 'create-react-class'
import ImmutablePropTypes from 'react-immutable-proptypes'
import MainComponent from './MainComponent'
import {addSelection} from '../../actions/betslip'
import {connect} from 'react-redux'

export const MainComponentContainter = createReactClass({
  displayName: 'MainComponentCont',
  propTypes: {
    displayMode: PropTypes.string,
    other: ImmutablePropTypes.map,
    addSelection: PropTypes.func,
    prices: ImmutablePropTypes.map,
    selections: ImmutablePropTypes.map,
  },

  render() {
    return (
      <div>
        {this.props.other.valueSeq().map(this.renderMain)}
      </div>
    )
  },

  renderMain(other) {
    const yesOutcome = other.get('markets').first().get('outcomes').first()
    const newPrice = this.props.prices.getIn([yesOutcome.get('id'), 'price'])

    if (newPrice) {
      return (
        <MainComponent key={other.get('id')}
                    ...some other props/>
      )
    }
    return null
  }
})

const mapStateToProps = () => {
  return (state) => {
    const displayMode = state.ui.get('displayMode')
    const selections = state.stp.get('selections')
    const prices = state.catalog.get('prices')
    const other = state.catalog.get('other')

    return {
      displayMode,
      other,
      prices,
      selections,
    }
  }
}

const mapDispatchToProps = {
  addSelection,
}

export default connect(mapStateToProps, mapDispatchToProps)(MainComponentContainer)

MainComponent.js

This just basically returns another component to the above component.

return (
    <div style={[styles.container, styles.container[displayMode]]}>
      <div style={[styles.logo, styles.logo[displayMode]]}>
        {renderLogo(displayMode, quoteExtraLogo)}
        {displayMode === 'mobile' &&
          renderButton({displayMode, selected, suspended, clickHandler})}
      </div>
      <div style={[styles.content, styles.content[displayMode]]}>
        <h2 style={[styles.headline, styles.headline[displayMode]]}>
          {title}
        </h2>
        <div style={[styles.offer, styles.offer[displayMode]]}>
          <div style={[styles.details, styles.details[displayMode]]}>
            <p style={[styles.market, styles.market[displayMode]]}>
              {text}
            </p>
            <div>
              <p style={[styles.improvedOdds, styles.improvedOdds[displayMode]]}>
                <span style={styles.improvedOddsAt}>a</span> {newPrice}
              </p>
              <p style={[styles.previousOdds, styles.previousOdds[displayMode]]}>
                invece di{' '}
                <span className="strikethrough">
                  {oldPrice}
                </span>
              </p>
            </div>
          </div>
          {displayMode === 'desktop' &&
            renderButton({displayMode, selected, suspended, clickHandler})}
        </div>
      </div>
    </div>
  )

Test

describe.only('MainComponentContainer Component', () => {

  beforeEach(() => {
    sandbox = sinon.sandbox.create()
    addSelectionSpy = sinon.spy()
  })

  afterEach(() => {
    sandbox.restore()
  })

  function getOutput({
    displayMode = 'mobile',
    other = mockData,
    addSelection = spy,
    prices = pricesMock,
    selections = selectionsMock,
  } = {}) {

    return shallow(
      <MainComponentContainer
        displayMode = {displayMode}
        other = {mockData}
        addSelection = {addSelection}
        prices = {prices}
        selections = {selections}
      />
    )
  }

  it('should include a MainComponent component', () => {
    const pb = getOutput().find('MainComponent')
    expect(pb.length).to.equal(1)
  })

When doing the above test (should include a MainComponent component), I get the following error:

 AssertionError: expected 0 to equal 1 + expected - actual -0 +1

However I have logged out getOutput().debug() , and it returns <div><undefined /></div> .

The shallow renderer is intentionally limited to operating on only the root component so as to make the test more isolated. In the case of decorators or "wrapped" components like this, the wrapped component is not what we want to test. Since MainComponentContainer is a HOC, you face this problem.

There are two ways to get around this problem, either

First export the undecorated component

export default connect(mapStateToProps, mapDispatchToProps)(MainComponentContainer)
export {MainComponentContainer as ComponentContainer};

and test like

return shallow(
  <ComponentContainer
    displayMode = {displayMode}
    other = {mockData}
    addSelection = {addSelection}
    prices = {prices}
    selections = {selections}
  />
)

or use .dive

  it('should include a MainComponent component', () => {
    const pb = getOutput().dive().find('MainComponent')
    expect(pb.length).to.equal(1)
  })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM