-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
👋 Hello! I am opening this issue to start a discussion about how the mount
rendering strategy in Enzyme could be built more on top of React rather than using the internals of React.
The problem
When doing a full DOM render using mount
, Enzyme directly works with instances of React virtual DOM nodes.
One example is the ReactSixteenAdapter
, where it needs to return information about the virtual DOM so the core library can run queries and other operations against it. ReactSixteenAdapter
's toTree
function maps instances of VDOM nodes to an object that the Wrapper can use. This is an adaptation of logic that achieves a similar purpose in the react-test-renderer
package.
Inside the core enzyme
package there is a lot of logic to traverse and query the component tree. Very similar to the behaviour provided by ReactTestInstance. Additionally, utility functions like propsOfNode
, typeOfNode
and childrenOfNode
also have some reliance on React internals.
The symptoms of this coupling are visible when Enzyme breaks due to React upgrades. Issues like #1553 require a large amount of work. New node types that are introduced by React need to be introduced in Enzyme.
A solution
Use what exists in react-test-renderer
as a layer between Enzyme and React's virtual DOM. Instead of interacting directly with VDOM objects, Enzyme uses the API of ReactTestInstance objects. This decouples Enzyme from React internals and means that changes inside React are less likely to break Enzyme functionality.
Last week I spent some time spiking how this could work. What I came up with relies on two things:
- A way of creating a ReactTestInstance from a component ref. At the moment, there is no exposed way to create a new instance of
ReactTestInstance
. Only methods inside thereact-test-renderer
package can do this. - A way of plugging in Wrappers to Enzyme. This would be a higher level of configuration than what is available with adapters at the moment. While this is pretty much opting out of reusing any logic currently in the core library, it means that all the tree traversal and querying can be based on what
ReactTestInstance
provides. Basically it would be a way to tell Enzyme to use myReactTestRendererWrapper
class instead ofReactWrapper
. By using methods likefindAll
as well as properties likeparent
andchildren
that exist ofReactTestInstance
, I was able to significantly reduce the amount of logic that was needed to live in Enzyme.
I will raise a PR with my spike. It is very much WIP but most of the core Enzyme concepts are working.
What do you think?
I would love to get some feedback from contributors and maintainers of this library. I realise that this is a big change, but I think that the stability that can be gained is worthwhile.