glenjamin/skin-deep

Could not find component in tree which was rendered as string

Closed this issue · 4 comments

Background

I am using React starter kit for my react application. Inside the server.js they are rendering component using renderToStaticMarkup and then passing it to Html component which include it using dangerouslySetInnerHTML as you can see here

I am trying to create a unit test for my AboutUs page. But because it was rendered as string inside the html component, the unit test does not work for it because it is unable to find this component

UNIT TEST

/*REACT*/
var React = require('react');
import ReactDOM from 'react-dom/server';
var TestUtils = require('react-addons-test-utils');

/*Components*/
var AboutUsPage = require('../../src/components/AboutUsPage');
var App = require('../../src/components/App');
var Html = require('../../src/components/Html');

/*UNIT TESTING*/
import sd from 'skin-deep';
var expect = require("chai").expect;

describe('AboutUsPage component', function(){
  let tree;
  let aboutElement;
  before('render and locate element', function() {
    const data = { title: '', description: '', css: '', body: '' };
    const css = [];
    const context = {
      onInsertCss: value => css.push(value),
      onSetTitle: value => data.title = value,
      onSetMeta: (key, value) => data[key] = value,
      onPageNotFound: () => statusCode = 404,
    };
    data.body = ReactDOM.renderToString(<App context={context}><AboutUsPage /></App>);
    data.css = css.join('');

    tree = sd.shallowRender(<Html {...data} />);
    aboutElement = tree.dive(['App','AboutUsPage']); //could not find App or AboutUsPage components
  });

  it('it should have text hi"', function() {
    expect(tree.subTree('.htmlHead').text()).to.equal("hi"); //pass because it was in html component
  });
  it('it should have text hello"', function() {
    expect(aboutElement.subTree('.aboutHead').text()).to.equal("hello"); //fail because it was in aboutus component
  });
});

I am using mocha, chai & skin-deep for shallow rendering.

So how to write a unit test for the component which was rendered as string?

You're right that we don't do anything to handle dangerouslySetInnerHTML at the moment, but I think this particular case could be handled differently.

In general I advise testing a single "layer" at a time when using shallow rendering (and skin-deep).

In this case I would have the following tests:

  • <Html> assert that the body prop is rendered as dangerous HTML.
  • <App> assert that it renders children & does wraps in whatever else it's supposed to
  • <AboutUsPage /> assert that it renders the expected content
    and so on.

You'd only need to test <Html> in one place, and each page component would have it's own tests which don't care about <Html>

Does that help?

Thanks for the quick response. The <AboutUsPage /> is taking context from <App /> when i shallow render just the <AboutUsPage /> it gives the error TypeError: this.context.onSetTitle is not a function. So that is why i tried to shallow render all the components including the parent & children. Although i agree with your approach but how to avoid such errors?

You can pass context as the second argument to render().

See https://github.com/glenjamin/skin-deep/blob/one-point-oh/test/new.js#L162 for an example

Thank you very much 👍