Enzyme testing: mount vs render - reactjs

Besides render uses "traversal library Cheerio"..
I've just replaced all my mount's with render's and it works the same.
They look similar to me.
What should I choose? Is API of those two is somehow not identical?
What are particular recommendations when to use render over mount?

Render doesn't need a global DOM to be available. So it allows the tests to be run outside of an environment like a browser. In your case, if your test cases were working before it would seem you are running the tests in a browser (since mount worked) and you wouldn't need to use render. If however, your tests were failing because there was no global DOM available, then render might be a good solution
http://airbnb.io/enzyme/docs/api/render.html

Mount is FullDom rendering. Take a look at the official documentation for examples. From my understanding if you want to test lifecycle events such as componentDidMount you should use mount.
Docs: http://airbnb.io/enzyme/docs/api/mount.html

Related

Mock an internally used function from a sub package with Jest

I have a Lerna monorepo, a #project/shared-component sub package and a #project/consumer sub package. The #project/shared-component package exposes a SharedComponent react component, which internally uses a useData hook which is also exposed. In the #project/consumer, I have a ConsumerComponent which renders the SharedComponent component. In #project/consumer, I also have a test which tests the ConsumerComponent. There I want to mock the innards of the useData hook with Jest. This is the code I use to mock:
jest.mock("#project/shared-component", () => ({
...jest.requireActual("#project/shared-component"),
useData: jest.fn(),
}));
This would be possible if everything would be in one package, but since I am trying to mock a function that is internally used in the mocked package, the SharedComponent uses the actual function rather than the mocked one. Does anyone have an idea on how to mock the useData hook internally used by SharedComponent? Thanks!
I have a similar issue. The comment by #Steven Scott does indeed seem like a proper solution, but in my case, extracting and then injecting the dependencies takes away the need to extract the shared components in the first place because my consumer components would then need to know about the dependencies, and to be honest, I don't like the idea of changing my code purely for the tests, since I don't use my hooks in that way.
#Lukas, If you find/found a way in the meantime, please post it back here. My current solution is to just test the SharedComponent thoroughly in it's package, and then just test that my ConsumerComponent calls the SharedComponent correctly. Then I depend on the idea that I can use (and trust) every component I use because they are properly tested internally.
But again, if you find a better solution, I would love to hear about it.

always use renderToStaticMarkup() over renderToString()?

According to the react docs, renderToString() creates extra DOM attributes that React uses internally such as data-reactroot whereas renderToStaticMarkup does not.
And I thought that ReactDOM.hydrate() enables event handlers to be attached to the markup which is string-rendered via renderToString(), thanks to that extra DOM attributes such as data-reactroot.
But I've tested myself that ReactDOM.hydrate() also works with the static markup which is rendered via renderToStaticMarkup(), which means that the combination of ReactDOM.hydrate and renderToStaticMarkup() successfully attaches event handlers to the string-rendered DOM.
According to the Dan Abramov's issue, hydrate() does not rely on the internal react attribute (data-reactroot)
Instead, use hydrate() to explicitly tell React to hydrate existing
HTML. Then it won't depend on whether data-reactroot exists or not.
So I might guess that it would always be better to use renderToStaticMarkup() instead of renderToString(), since performance would be more optimized by renderToStaticMarkup()
Is that ReactDOM.renderToString() just an old way before hydrate() released on React v16, only to be used with render() and dangerouslySetInnerHTML()?
Is it okay for me to think that we can always use renderToStaticMarkup() over renderToString()?
This question is related to my issue, but yet has no clarified answer.

Using testing-library findBy* on a component that uses setState causes a "not wrapped in act" warning

I've got a React component which retrieves data using a Promise and then calls setState when the promise resolves. It then uses the updated state to change what's rendered.
When testing this, I use the testing library's findBy* methods to wait for the rendered component to have been updated with the content from the Promise:
await findByText("Failure details", { exact: false });
My tests pass - they correctly wait until the component has re-rendered. However, I get a warning like this when running them (I'm using Jest, but I don't think that's relevant):
Warning: An update to MyComponent inside a test was not wrapped in act(...).
Everything I've found online that's related to this is either about components using useEffect or about tests which include explicit calls to act in them (mine don't), which I don't think should be necessary here - my test itself isn't changing the component, apart from the fact that it calls render.
In short, my situation seems simpler than those that others are writing about - I'm just using setState and the findBy* queries, nothing more complex.
Is there an equally simple solution to this problem?
Thankfully, the solution was simple - upgrading React and React-DOM to >= 16.9.0. I didn't have to change my tests or my component.
16.9.0 includes an asynchronous version of act. As I say, I didn't have to explicitly use it, but it was obviously being used behind the scenes because it solved my problem.

React testing using snapshots

I'm wondering, what's your approach while testing React component using Jest snapshots.
Are you testing every component?
How do you determine if you should create a snapshot for component?
Are you testing whole views or only smaller components (view pieces)?
When should one add props to tested components? Should functions always be mocked using jest.fn() ?
AFAIK, snapshots are more inclined towards "how" your component look like.
My Approach,
Identify the props or state which can alter the presentation of my component. Then I write snapshots for them.
If you cannot achieve setting the state using props, you can use simulate to make the relevant state set and then create a snapshot.
And using jest.fn() in snapshots, doesnot seems much of an advantage as we mock functions when we actually need to unit test whether they were invoked.

Examples or use cases to use enzyme mount when unit test react components?

There used to be a common use case to full render the component with componentDidMount/componentDidUpdate lifecycles which shallow render doesn't have.
But since enzyme 3+, shallow rendering turned lifecycles on by default, and it simply feels more like real unit test with good isolation between virtual Dom and real Dom. Could anymore share some examples where using mount still shines? (personally don't think HOC necessarily has to be tested by mount)
Full DOM rendering is ideal for use cases where you have components that may interact with DOM APIs or need to test components that are wrapped in higher order components.

Resources