Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add mountToDeepJson and mountToShallowJson #56

Merged
merged 6 commits into from
Sep 15, 2017

Conversation

pedrottimark
Copy link
Contributor

Bonjour! The proof-of-concept for this pull request is a sample project about React testing: https://github.com/pedrottimark/whimper

To understand how valuable a part that enzyme-to-json has in it, start reading here: https://github.com/pedrottimark/whimper#interlude-about-snapshot-testing

Summary, given an enzyme mount wrapper, especially from selector traversal:

  • mountToDeepJson returns a test object rendered to maximum depth (it contains only DOM nodes, no React components)
  • mountToShallowJson returns a test object rendered to minimum depth (it might contain DOM nodes, but any children which are React components are leaves of the tree)

Here are some relevant issues:

The changes to shallow.js and some in utils.js were from prettier in pre-commit hook, I think.

@codecov-io
Copy link

codecov-io commented Apr 25, 2017

Codecov Report

Merging #56 into master will increase coverage by 0.63%.
The diff coverage is 93.33%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #56      +/-   ##
==========================================
+ Coverage    96.2%   96.84%   +0.63%     
==========================================
  Files           5        5              
  Lines          79       95      +16     
  Branches       34       36       +2     
==========================================
+ Hits           76       92      +16     
  Misses          2        2              
  Partials        1        1
Impacted Files Coverage Δ
src/index.js 100% <ø> (ø) ⬆️
src/shallow.js 100% <100%> (ø) ⬆️
src/utils.js 93.33% <88.88%> (+3.33%) ⬆️
src/mount.js 94.87% <94.73%> (+1.76%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bfe0170...20a76d7. Read the comment docs.

@adriantoine
Copy link
Owner

Hey! Thanks a lot for your contribution, I haven't had time to take care of this project recently! Sorry, I'll review this PR when I get time, thanks again!

@adriantoine
Copy link
Owner

Hey @pedrottimark, sorry for not reviewing this in time, I'll review it right now!

@adriantoine
Copy link
Owner

Is there any difference between mountToShallowJson and mountToJson?

@pedrottimark
Copy link
Contributor Author

Thank you for asking. It took me some time to find a use case for that function :)

Here are contrasting snapshots for the CheckboxWithLabel component at http://facebook.github.io/jest/docs/en/tutorial-react.html#dom-testing

exports[`CheckboxWithLabel renders with mountToJson 1`] = `
<CheckboxWithLabel
  labelOff="Off"
  labelOn="On"
>
  <label>
    <input
      checked={false}
      onChange={[Function]}
      type="checkbox"
    />
    Off
  </label>
</CheckboxWithLabel>
`;

exports[`CheckboxWithLabel renders with mountToDeepJson 1`] = `
<label>
  <input
    checked={false}
    onChange={[Function]}
    type="checkbox"
  />
  Off
</label>
`;

exports[`CheckboxWithLabel renders with mountToShallowJson 1`] = `
<CheckboxWithLabel
  labelOff="Off"
  labelOn="On"
/>
`;

Therefore mountToShallowJson is not for the component itself, but for a wrapper from enzyme selector traversal so you can write a new deep-event/shallow-criteria test pattern:

  • realistic interaction: simulate event at DOM node
  • structural contract: test criteria are the elements (especially React components) affected by the change in application state:
    • for toMatchSnapshot assertion: all props
    • for toMatchObject assertion with relevantTestObject helper: relevant subset of props

In an example at https://github.com/pedrottimark/whimper#create notice the tbodyShallow selector function (adapted from the idea of state selectors for Redux store) traverses to the tbody element which contains the already existing and newly created TableRow components.

export const tbodyShallow = ($table) => mountToShallowJson($table.find('tbody'));
expect(tbodyShallow($it)).toMatchObject(relevantTestObject(
  <tbody>
    <TableRow record={recordDefault(fields)} />
    <TableRow record={recordB} />
  </tbody>
));

I am happy to answer your questions, because whenever I see something through the eyes of someone else, I must think more clearly about it.

@pedrottimark
Copy link
Contributor Author

Forgot to say, it seems like intuitive expectation for mountToShallowJson(mount(component)) to be equivalent to:

  • shallowToJson(shallow(component))
  • mountToDeepJson(mount(component)) if render method of component returns only DOM nodes

I forgot about the current return value until you asked, because in my example I used Redux Provider to supply the state, and therefore I had to traverse.

Tests for simpler components could use a better return value for the top-level wrapper.

@adriantoine
Copy link
Owner

Hi @pedrottimark!

I am so sorry I didn't review this PR in time, I understand better what this is about now and I'm happy to merge it, thanks a lot for you contribution!

@adriantoine adriantoine merged commit 7da88dc into adriantoine:master Sep 15, 2017
This was referenced Sep 15, 2017
@pedrottimark pedrottimark deleted the mount-to-object branch September 15, 2017 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants