Search code examples
htmlcssunit-testingreactjsreactjs-testutils

ReactTestUtils.renderIntoDocument a component with children - children seem to "not render in DOM"


I render a component in my test like so:

component = TestUtils.renderIntoDocument(
  <SlidingContainer {...props}>
    <div style={divStyle}>foo</div>
    <div style={divStyle}>foo</div>
    <div style={divStyle}>foo</div>
  </SlidingContainer>
);

$bodyElement = $(ReactDOM.findDOMNode(component.refs.body));

This is from SlidingContainer's render method

return (
  <div className={rootClassName} >
    <div className="sliding-container_arrow sliding-container_arrow--left"
         onClick={this.slide.bind(this, 'left')}>
      <div className={leftArrowClassName}></div>
    </div>
    <div className="sliding-container_body" ref="body">
      { this.props.children }
    </div>
    <div className="sliding-container_arrow sliding-container_arrow--right"
         onClick={this.slide.bind(this, 'right')}>
      <div className={rightArrowClassName}></div>
    </div>
  </div>
);

As you can see, $bodyElement is a DOM element that contains the children. It has a set width, whitespace: nowrap, overflow: hidden

This is updateScrollState method of `SlidingContainer'

updateScrollState($bodyElement) {
  var bodyElement = $bodyElement[0];
  var maxScrollLength = bodyElement.scrollWidth - bodyElement.offsetWidth;
  let maxToTheRight = maxScrollLength === $bodyElement.scrollLeft()
  let maxToTheLeft = $bodyElement.scrollLeft() === 0;

  this.setState({
    maxToTheRight: maxToTheRight,
    maxToTheLeft: maxToTheLeft
  });
}

This code works when I test it in the browser, but when running the karma/jasmine unit tests, bodyElement.scrollWidth and bodyElement.offsetWidth both equal 0. I searched around, and it seems this is an issue with an element being rendered in memory only and without real DOM, even though renderIntoDocument is supposed to render the element into a dom.


Solution

  • You need to mount it to DOM. Use window.body.appendChild($bodyElement)