You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This feature is very similar to the requested feature in #65; however, I'd like to take it a bit further by introducing/implementing a reusable factory function to manipulate an instance with some optional method chaining.
The current recommendation was/is to create an updateProps function within each test. However, if we provide a factory mount (or append this to the render ) function, we can eliminate some of the unnecessary boilerplate and just manipulate the instance:
constonClick=jest.fn();// initializes Button with `onClick` and returns all methods provided by RTL // plus some additional methods: "find", "setProps" and "simulate"constwrapper=mount(<InputdataTestId="input"onClick={onClick}/>// updating props// updates the Input instance with props: { dataTestId, onClick, foo: false }wrapper.setProps({foo: false});// updates the Input instance with props: { dataTestId, onClick, foo: false, bar: true })wrapper.setProps({bar: true});
...etc// simulating eventsconstevent={target: {value: "hi"}};// finds an element within the wrapper, at the first position, and simulates an event with some method chainingwrapper.find("[data-testid=input]").at(0).simulate("change",event);// misc// provides the length of the selected element(s)wrapper.find("[data-testid=input]").length// provides the existence of the selected element(s)wrapper.find("[data-testid=input]").exists
Suggested implementation:
Handling instance manipulation internally while providing public methods to either find or setProps or simulate from the same instance. A working prototype with side-by-side tests can be found here:
Factory mount function:
importisEmptyfrom'lodash.isempty'import{cloneElement}from'react'import{render,fireEvent}from'@testing-library/react'/** * A class that wraps RTL's render and supplies it with Enzyme-like methods * @class EnzymeWrapper * @param {node} Component - Component to be mounted * @method find - finds an element by string using querySelector * @method setProps - merges old props with new props and rerenders the Component * @method setSelection - sets additional properties and methods on a selection * @method simulate - simulates a fireEvent by type with passed in options * @returns {object} - an Enzyme-like wrapper */classEnzymeWrapper{constructor(Component){this.Component=Componentthis.props=Component.propsthis.wrapper=render(Component)this.find=this.find.bind(this)this.setProps=this.setProps.bind(this)return{
...this.wrapper,find: this.find,setProps: this.setProps,}}find(byString){constelements=this.wrapper.container.querySelectorAll(byString)letselection=this.wrapper.container.querySelector(byString)selection=this.setSelection(elements,selection)returnselection}setProps(props){this.props={...this.props, ...props}this.wrapper.rerender(cloneElement(this.Component,this.props))}setSelection(elements,selection){selection.simulate=(eventType,opts)=>this.simulate(selection,eventType,opts)selection.length=!isEmpty(elements) ? elements.length : 0selection.exists=selection.length>=1selection.at=pos=>{if(!elements||elements[pos]===undefined)throwError('wrapper::at(): Unable to locate an element at that position.',)letnextSelection=elements[pos]nextSelection=this.setSelection(nextSelection,nextSelection)returnnextSelection}returnselection}simulate(element,eventType,opts){if(isEmpty(element)){throwError(`wrapper::simulate(): unable to locate any elements to simulate an event.`,)}if(!eventType){throwError(`wrapper::simulate(): unable to call simulate without an event type.`,)}fireEvent[eventType](element,opts)returnelement}}/** * Factory function to initialize a RTL rendered React component with an Enzyme-like class * @function mount * @param {node} Component - Component to be mounted * @returns {object} - an Enzyme-like wrapper */exportconstmount=Component=>newEnzymeWrapper(Component);
The above is just a prototype/P.o.C. and will most likely need to be refactored for asynchronous actions and optimized for performance. However, for those familiar with enzyme, the methods provided should be pretty self-explanatory and straight forward. The idea would be to reduce the need of having to pass in the same component to update it with props (like renderer(<Input {...nextProps} />); ) or having to import fireEvent to execute an event change on an element that may already exist within the container instance (like fireEvent.change(queryByTestId("input"), event).
The text was updated successfully, but these errors were encountered:
material-ui has implemented it. I don't know why it is not implemented here
Because it's generally not something you should use. It's only ever useful if you're writing a component library. At that point you should know what you're doing and can write that helper yourself.
Describe the feature you'd like:
This feature is very similar to the requested feature in #65; however, I'd like to take it a bit further by introducing/implementing a reusable factory function to manipulate an instance with some optional method chaining.
The current recommendation was/is to create an updateProps function within each test. However, if we provide a factory
mount
(or append this to therender
) function, we can eliminate some of the unnecessary boilerplate and just manipulate the instance:Suggested implementation:
Handling instance manipulation internally while providing public methods to either

find
orsetProps
orsimulate
from the same instance. A working prototype with side-by-side tests can be found here:Factory mount function:
Teachability, Documentation, Adoption, Migration Strategy:
The above is just a prototype/P.o.C. and will most likely need to be refactored for asynchronous actions and optimized for performance. However, for those familiar with
enzyme
, the methods provided should be pretty self-explanatory and straight forward. The idea would be to reduce the need of having to pass in the same component to update it with props (likerenderer(<Input {...nextProps} />);
) or having to importfireEvent
to execute an event change on an element that may already exist within the container instance (likefireEvent.change(queryByTestId("input"), event)
.The text was updated successfully, but these errors were encountered: