-
-
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
Mocking arrow function refs in shallow, messed up by updates. #1407
Comments
The issue here is that you shouldn't be using arrow functions inside class properties. Instead, you should be using a constructor-bound (or class-property-bound) instance method, like this: handleSave = this.handleSave.bind(this);
handleSave() {
this.modal.close();
…
} Additionally, the ref callback you use needs to be the same reference every render - ie: setModal = this.setModal.bind(this);
setModal(e) {
this.modal = e;
}
…
<Modal ref={this.setModal}>
… |
@ljharb Could you elaborate on "you shouldn't be using arrow functions inside class properties". Is that an enzyme thing or a react thing or a javascript thing? Or is this just general wisdom that I have yet to grok? |
@hally9k Read #697 for a very long discussion about the topic. TL;DR: some, such as @ljharb, argue that not using arrow functions inside class properties is better for a number of reasons (i.e. it's a JS thing), including that it's easier to mock methods and refs on the component. Many others are displeased with that stance, and a lengthy discourse about performance and redundant code ensued. My personal takeaway: I quite like arrow functions inside class properties despite the many reasonable arguments against it (that, and it's how our entire codebase does it), and will selectively adopt the approach suggested above when necessary for testing purposes. |
"There's tons of reasonable arguments against it, but we already do it this way and I like it" is, at the least, a totally valid and honest defense :-D |
Better than getting vitriolic. 😉 Thanks for the quick response, btw. I don't know how you field so many questions on so many repos, but it makes a big difference to figuring out the finer points of some of these libraries. |
@AndrewSouthpaw Sorry, I got pulled off into an interview. Thanks for the link. I missed your comment and was already on the other thread leaving my 2 cents. I don't want to go and open a can of worms that everyone is tired of (That thread is quite long) but I do think the reasoning (and support) is a little lop sided. Keen to hear some solid reasoning. Also I struggled to get consistent behaviour even with the work arounds so I'd like to learn more. Any tips on using enzyme @ljharb? (other than not use class property arrow functions of course 😉 ) |
@hally9k to your earlier question, it's a React thing and a JavaScript thing and a testing thing, all together. General tips? Lean on |
That's a new tip for me. I heard some people saying it's better to interact with the DOM elements through simulate than knowing what the prop functions are called. Can you expand on your side? |
@hally9k Also for your reference, mocking refs for me works as long as I use the same ref callback each time. i.e. setRef = (e) => (this.modal = e)
...
<Modal ref={this.setRef}> works fine, the don't-use-arrow-functions-in-class-properties is not an issue in this case. What's the inconsistent behavior you're encountering? |
@ljharb is there a reason why you're recommending avoiding simulate? |
Yeah, I'm moving toward simulate and it's cousins, rather than leaning more heavily on invoking prop functions. But I think that's because I am migrating more toward testing user behavior as much as possible, rather than implementation details. (This also means writing more integration tests than unit tests.) I'd be curious to hear about @ljharb's reason for avoiding simulate though. Philosophical discussions are fun. 😉 |
I lean towards shallow rendering, but that sometimes makes it impossible to use event simulation. |
@AndrewSouthpaw here's another excerpt on my philosophy regarding testing the behaviour of the component and not it's implementation details. |
I'd avoid simulate because it doesn't actually faithfully simulate anything. If you want to invoke a prop, invoke it directly. |
This is answered: never put arrow functions in class fields, and you won't have any trouble. |
Note: I'm using enzyme 2.9.1.
Because of the nature of some of our components, we need to use refs. React calls for us to create those with arrow functions, which enzyme
shallow
in turn can not figure out. If I have something like...the
this.modal
isundefined
.I've taken to doing
PresentLessonModal.prototype.modal = myMockModal
in my tests, but subsequent updates to the wrapper, e.g. withsetState
orupdate
, makes the ref undefined again. Any input on how to do this properly?The text was updated successfully, but these errors were encountered: