Skip to content

Allow ReactShallowRenderer to expose JSX for test debugging #4835

@johnnyreilly

Description

@johnnyreilly

Hi,

I've been making use of ReactShallowRenderer for testing. I really like it. You mention in your docs that you would appreciate the React community's feedback on how it should evolve; here's a suggestion!

The one problem I have is when it comes to investigating failing tests.

First a little digression. I'm just using vanilla Jasmine for my testing. When it comes to deep objects not matching up I've been using a custom matcher I wrote called toEqualAsObject:

import jsondiffpatch from 'jsondiffpatch';

const jdp = jsondiffpatch.create({
  arrays: {
    detectMove: true
  }
});

const customMatchers = {
  toEqualAsObject(util, customEqualityTesters) {
    return {
      compare(actual, expected) {
        const result = {
          pass: util.equals(actual, expected, customEqualityTesters)
        };

        if (!result.pass) {
          const delta = jdp.diff(actual, expected);
          result.message = `The objects were different.

Expected:

${ JSON.stringify(expected, null, 2) }

Actual:
${ JSON.stringify(actual, null, 2) }

Difference:
${ JSON.stringify(delta, null, 2) }

Difference format info can be found here: https://github.com/benjamine/jsondiffpatch/blob/master/docs/deltas.md
`;
        }

        return result;
      }
    };
  }
};

export default customMatchers;

This matcher builds on jsondiffpatch to help you to isolate where the difference between 2 objects lie. This is really useful for general testing but doesn't help particularly when it comes to JSX testing like this:

result = renderer.getRenderOutput();
expect(result.type).toBe('div');
expect(result.props.children).toEqual([
  <span className="heading">Title</span>,
  <Subcomponent foo="bar" />
]);

The reason is, a subtle difference in JSX can result in a fairly different objects being constructed. Comparing them is not massively revealing and investigation can take some time. I've a suggestion: It would be really handy if you could extract a JSX representation of an object from the renderer output. What I'm imagining is the ability to do something like this:

result.props.children.asJSX();

Which would would produce a string like this:

"
  <span className="heading">THE WRONG TITLE</span>
  <Subcomponent foo="bar" />
"

This would allow the writing of a custom matcher to be used when comparing JSX which would, upon failure, use the asJSX() to report a helpful error message. I've spent more time than I would like digging through differences in object structure when investigating failing tests and think that a feature like this could be a real win.

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions