-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
useEffect
not called when the component is shallow
renderered
#2086
Comments
Same here. Do you have any idea when this is going to be supported? 🙏 |
Hopefully in the next version of enzyme. |
Was there a plan to support that? I made an issue in react to support this from the shallow renderer with an option. I figured that would be the only way to do it without trying to mock out useEffect or something |
ah, fair enough - you're right that it still won't work in shallow, and that that issue, or mocking it out in enzyme, would be the only way to make it work. |
Is there a plan or PR to fix this? Makes hard include hoos/useEffect if we can't test it |
@mangel0111 see the previous 2 comments. we're waiting to see if we can add a feature to react which will make it easier to fix this |
Having the same issue here. Is there any alternative to creating a snapshot that runs the useeffect hooks? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Are you sure? With useEffect. The implementation of use it in shallow is
just a noop so that would be surprising.
…On Sun, Jul 21, 2019 at 6:49 AM James Pike ***@***.***> wrote:
It looks like the render and update calls just need to be called inside a
ReactTestUtils.act() callback and this will flush the events, whether
using shallow rendering or not. I have this working in a hacked together
enzyme now.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2086>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA6MGDRAM45GH5FRNTH5E33QAPMDVANCNFSM4HEGYKHQ>
.
|
@bdwain Sorry I had a bunch of changes to |
yea i wonder if they would be more interested if it was completed already. If you got it all working maybe post that in a PR and see what they say? |
@bdwain My PR is here: facebook/react#16168 would be really grateful for your feedback. |
BTW it's possible to get this working from enzyme without having to touch react, but you have to override Would be nicer if the code was in React's shallow renderer though. |
I needed this feature like... 5 months ago. Which is about the length of time the react maintainers have been ignoring the issue for. If they don't respond to my PR in another few weeks could I maybe do the private method override thing? I would make enzyme's code test for the existence of the private method first so as not to break if the internals change. Then when (or more like if) react accept the PR or code then it could just be removed. Although it is super hacky :( In my own project I switched from enzyme to the test renderer and do the hack now so I can at least test my effects, but I'd much rather be using enzyme. |
@ohjames as long as your tests here are good, that is totally fine. |
@ljharb Cool, I've written the code now. Having trouble testing it. After running the steps listed in
Hmmm... not sure why it wants to install things to system owned directories. Don't really want to contaminate my system :( |
Okay... so I decided to run it in a container (I chose Here's some examples of failing tests:
Now I kinda feel like giving up. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Hey guys, if I would like to test my mock of
I have tried this as well but it seems
Any guide on how to test the |
@kevinding0218 I suggest you observe the effects wired up inside your But to answer your question: jest.mock('react', () => ({
__esModule: true, // maybe required?
...jest.requireActual('react'),
useEffect: jest.fn(f => f()),
}));
import React, { useEffect } from 'react';
// before each reset the mock
// in the test
expect(useEffect).toHaveBeenCalled(); |
I got it to work using mount instead of shallow |
Seriously guys, just use
that was changed to the following when a class component was converted to a functional component, and logic from lifecycle events (e.g.
|
Deleting my previous comments since they are a bit confusing; to summarize: This adapter supports It does so by monkey-patching the dispatcher's handlers. It also uses I could adapt these changes for inclusion in the official adapter and open a PR.... but note:
|
Lets say I have a component <>
<Y bar={baz} />
<Z shouldFetch>Hello</Z>
<p>Lorem ipsum</p>
<button onClick={onClick}>Click me</button>
</> If we use It is certainly possible to do this in smaller components, components with few test cases, or components with many test cases where each root can be setup by a shared function, but that is not the case for many of our tests. Replacing |
Perhaps opinions on testing approaches could be moved to forums better suited to discussion? |
+1 to last comment from @Gyllsdorff . Yes, it may be possible to use mount instead with proper mocks, but that adds additional overhead and complication to the tests. It also may have other side effects. The entire point of using shallow is to provide a single reference to the component without going deeper. This issue is one I've had my eye on for a while and am really hoping for a fix! For now, I guess we'll keep with the more complicated way. At least we have a workaround. |
Works fine, but keep in mind that it will run for every effect and on every render even if their dependencies are still the same. There's a pretty ugly workaround, but it works: let mockLastDeps = {};
jest.mock("react", () => ({
...jest.requireActual("react"),
useEffect: (f, deps) => {
const effect = new Error().stack.split("\n")[2]; // <-- to find fileName and lineNumber, since we can't identify by `f`
if (!mockLastDeps[effect] || deps.some((dep, i) => dep !== mockLastDeps[effect][i])) {
f();
mockLastDeps[effect] = deps;
}
},
})); |
Ran into a use case for this; ended up going with |
I spent a fair bit of time working on this and even made an enzyme adapter with hook support (see above), but in the end I decided to create a replacement for enzyme shallow that supports the full set of hooks and is self-contained: https://www.npmjs.com/package/isolate-components I think it should support most of what |
@davidmfoley interesting! could you help me understand the difference between |
The big difference in implementation is that isolate-components does not use an external renderer. For the most part, the features are similar to enzyme shallow with only react 16+ support, but there are some other cases that I want to support in future versions that don't really fit into enzyme (the big ones: 1) ability to "inline" a subcomponent to support cases where you refactor a component into smaller compnents without breaking tests and 2) "mount" without a virtual DOM). I did start down the path of building a hook-compatible renderer for enzyme, but forking the enzyme repo so that I could fork react-shallow-renderer, or alternatively monkey patching the shallow renderer as I did in the adapter above, was painful. The unfortunate reality is that react is not built with component testability in mind. You could probably build an adapter for enzyme using isolate-components (at least I can't think of any reasons you couldn't off the top of my head?). That would be cool. Enzyme is great. But I'm not inclined to spend my time on that given the speed of development on enzyme and react-shallow-renderer. Enzyme moves slowly, which is understandable since it's an established project, supports old react versions, and has thousands of users whose tests could be broken if the shallow renderer suddenly started supporting effects. This issue -- which is effectively "enzyme shallow is not useful for react 16 components" is 18 months old and there is no sign it will be addressed any time soon. An issue about transferring the shallow renderer to enzyme is 8 months old. So, given all that, I decided to start from scratch without the baggage of supporting old react versions or depending on other packages. |
I totally agree that React is not built with component testability in mind :-/ I'm also totally happy to remove the dependency on react-shallow-renderer/react-test-renderer, if it makes an API for shallowly testing a component more robust. If we could fix |
@ljharb sure; let's chat -- email me at my github name at gmail? |
@davidmfoley @ljharb any update on this? Should we expect a solution any time soon? |
No update, nothing any time soon. Help is welcome. |
@dolsem we chatted about potentially making an enzyme adapter that uses isolate-components under the hood but I haven't had time since then to do more than look into the enzyme adapter interface at a high-level and see that it will be a fair amount of work. If anyone is interested in helping on that, I'd be happy to chat about it. |
See the relevant issue here: enzymejs/enzyme#2086
Needed to add [jest-canvas-mock](https://www.npmjs.com/package/jest-canvas-mock) library to mock canvas on Jest, our unit test runner, as Monaco requires canvas. I tried doing a shallow test to avoid this, but unfortunately [Enzyme's shallow rendering does not call `React.useEffect`](enzymejs/enzyme#2086), which is necessary to test this functionality.
This works like a charm. Thanks @mikeborozdin |
Current behavior
useEffect
fonction does not seem to be executed when the component is rendered withshallow
.Given the following simple component using
useEffect
hook to call a method given as a prop:And the following tests checking that the
callback
function is indeed called accordingly:We observe that the method is called as expected when "mounted", but not when using a
shallow
renderer:You may find this reproducible example here.
Expected behavior
When using
shallow
to render the components, the function passed touseEffect
should be executed, as it is when usingmount
.Your environment
API
Version
Adapter
The text was updated successfully, but these errors were encountered: