How to test HTML of a rendered React component?
Asked Answered
F

2

8

My React component has a suggestionRenderer property that allows to specify how the component is rendered. For example:

<Autosuggest suggestions={getSuburbs}
             suggestionRenderer={renderLocation} />
function renderLocation(suggestion, input) {
  return (
    <span><strong>{suggestion.slice(0, input.length)}</strong>{suggestion.slice(input.length)}</span>
  );
}

Now, I'd like to write a jest test to make sure that suggestionRenderer does its job. Inspecting myElement.getDOMNode().innerHTML reveals:

<span data-reactid=".9.1.$suggestion0.0"><strong data-reactid=".9.1.$suggestion0.0.0">M</strong><span data-reactid=".9.1.$suggestion0.0.1">ill Park</span></span>

which is not particularly useful.

Is there a way to get a clean HTML, without React attributes?

Fibrous answered 11/3, 2015 at 5:53 Comment(1)
I ended up using .innerHTML.indexOfJulietjulieta
C
6

You can use React.renderToStaticMarkup for this.

expect(React.renderToStaticMarkup(
  <Autosuggest ... suggestionRenderer{renderLocation}/>
))
.to.be('<div>...')

Or just grab innerHTML and strip it manually, but I don't know how reliable that will be cross-browser:

var reactAttrs = / data-react[-\w]+="[^"]+"/g

myElement.getDOMNode().innerHTML.replace(reactAttrs, '')

I used to use React.renderComponentToString and manually strip out the data-react- attrs prior to React.renderToStaticMarkup being added.

Competitor answered 11/3, 2015 at 6:9 Comment(4)
React.renderToStaticMarkup gets ReactElement as a parameter, while I have a ReactComponent (the result of TestUtils.scryRenderedDOMComponentsWithClass is array of ReactComponents). Any idea how to get ReactElement from ReactComponent?Fibrous
You don't need to render to DOM to test with it if you just want to assert the correct output was rendered: expect(React.renderToStaticMarkup(<Autosuggest suggestionRenderer={renderLocation}/>)).to.be('<div>...') - your component needs to support having any data it renders passed as props, though.Competitor
The element that I want to test is rendered as a response to user events (e.g. user types 'm'). This is why I render it to DOM. Still wondering if there is a better way that stripping data-react-* attributes manually...Fibrous
Use ReactDOMServer.renderToStaticMarkup as React.renderToStaticMarkup.renderToStaticMarkup is deprecated.Methylamine
F
2

I generally don't unit test HTML (I figure if React's unit tests are passing, then the HTML generated is good plus I intend to have integration test with selenium to test the HTML anyways) but I do test that the component is generating the correct virtual DOM.

I have a similar component and the way I test auto complete items looks like this.

var testAutoCompleteItems = [{
  display: 'test 1',
  value: 1
}, {
  display: 'test 2',
  value: 2
}, {
  display: 'test 3',
  value: 3
}];

//...

it('should set items based on pass getData property', function(done) {
  Fiber(function() {
    testGlobals.component = React.render(<ExtendText onChange={testHelper.noop} getData={getData} />, div);
    var input = TestUtils.findRenderedDOMComponentWithClass(testGlobals.component, 'extend-text__display-input');

    TestUtils.Simulate.focus(input);

    testHelper.sleep(5);

    var autoCompleteContainer = TestUtils.findRenderedDOMComponentWithClass(testGlobals.component, 'extend-text__auto-complete-container');
    var autoCompleteItems = TestUtils.scryRenderedDOMComponentsWithTag(autoCompleteContainer, 'li');

    //make sure elements are correct
    autoCompleteItems.forEach(function(item, key) {
      expect(item.props['data-key']).to.equal(key);
      expect(item.props.children).to.equal(testAutoCompleteItems[key].display);
    });

    //make sure there is the correct number of elements
    expect(autoCompleteItems.length).to.equal(3);
    done();
  }).run();
});
Fabricant answered 11/3, 2015 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.