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
feat(render): deprecate renderIntoDocument and make it the default #118
Conversation
Codecov Report
@@ Coverage Diff @@
## master #118 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 1 1
Lines 17 18 +1
Branches 0 2 +2
=====================================
+ Hits 17 18 +1
Continue to review full report at Codecov.
|
The README needs to be updated. I can do it if you want. |
What part? This PR makes major updates to the README. |
@kentcdodds nevermind, it's there, I didn't see. |
README.md
Outdated
option, it will not be appended to the `document.body` automatically. | ||
|
||
**baseElement**: This is used as the base element for the queries as well as | ||
what is printed when you use `debug()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which one is the default for this baseElement
?
README.md
Outdated
|
||
renderIntoDocument(<div />) | ||
``` | ||
> `getByText` don't work for your use case. Using data-testid attributes do not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add backticks around data-testid
on this line, too?
README.md
Outdated
|
||
</details> | ||
Failing to call `cleanup` when you've called `render` could result in a memory | ||
leak and tests which are not `idempotent` (which can lead to difficult to debug |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"idempotent" is not a code identifier, use regular quotes instead of backticks here?
README.md
Outdated
> to attach event handlers to the rendered node rather than the `document`. | ||
> Learn more here: | ||
> NOTE: If you don't like having to use `cleanup` (which we have to do because | ||
> we render into document.body) to get `fireEvent` working, then feel free to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add backticks around document.body
README.md
Outdated
|
||
// wait until the callback does not throw an error. In this case, that means | ||
// it'll wait until we can get a form control with a label that matches "username" | ||
await wait(() => expect(queryByText(/loading.../i).not.toBeInTheDOM()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- it'll wait until we can get a form control with a label that matches "username" does not sound aligned with the code it comments: it actually waits for "loading..." to disappear from the DOM, and only after that we look for the form control on the next line
/loading.../i
– the...
matches three arbitrary characters instead of the expected three ASCII dots, worth escaping?
src/__tests__/forms.js
Outdated
// then ensure that there's a submit button. | ||
Simulate.submit(formNode) | ||
fireEvent.click(submitButtonNode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the NOTE
comment above, clicking on the submit button won't work in jsdom
. Does fireEvent.click
take care of that?
// maybe one day we'll expose this (perhaps even as a utility returned by render). | ||
// but let's wait until someone asks for it. | ||
function cleanupAtContainer(container) { | ||
document.body.removeChild(container) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If container
is custom passed by the caller, thus not appended to the document.body
by render
, the caller may not expect that it will be removed by cleanup
which should be a mirror to render
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... So what are you suggesting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see what you mean. I'm not sure how to solve that issue reliably. If they don't like the behavior then they can file an issue and we can add an option to prevent this. Let's wait to add complexity until someone has an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually if a piece of code owns the lifecycle of an object (the caller in the case of custom container; the module with the render function in the case of default container), that piece is responsible for both creation+setup and teardown+destruction.
The suggestion is to make sure not to remove the container from the DOM if it hasn't been added to the DOM by the render module, only remove the map entry (lifecycle of which is owned by the render module) and ReactDOM.unmountComponentAtNode
(which is a mirror to ReactDOM.render
, mounted component's lifecycle is also owned by the render module).
I understand that the object/memory ownership and the allocate/deallocate pattern is often missed/violated in the JavaScript community due to various reasons, so it may look odd to require following it from this library users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Perhaps we should not add items to the set if we don't append it to the body. Would you like to open a PR for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm..... I'm still not certain this is the behavior people would expect our want 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay then, let's assume people move the ownership of the container from their code to the library code by calling render with that container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if instead we did:
container.parentElement && container.parentElement.removeChild(container)
I think that would make sense to happen in the cleanup regardless of whether it's in the body or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would make sense to shorten the caller code to let it manage only container
creation, and, my point still holds, the ownership of the container
object lifecycle is moved from the caller into the render
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused by what you're suggesting. But why don't you make a PR and maybe that'll clear things up for me.
typings/index.d.ts
Outdated
@@ -46,15 +46,14 @@ export interface RenderResult extends GetsAndQueries { | |||
debug: () => void | |||
rerender: (ui: React.ReactElement<any>) => void | |||
unmount: VoidFunction | |||
cleanup: VoidFunction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this an established practice to have a single type definition for functions with different purposes? I would avoid sharing the type because these functions, although look similar, are not the same thing. For example, debug
looks like a VoidFunction
but the type is not shared. Oh by the way, I don't see a definition of VoidFunction
in this file, where is it coming from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a mistake on my part. Originally I had added a helper cleanup
utility, then thought better of it because nobody's asking for that additional helper and not enough people would use it to be worth the docs.
Closes #116 BREAKING CHANGE: `renderIntoDocument` replaces `render` and `Simulate` is no longer exported (use `fireEvent` instead).
bb61e94
to
777cfd3
Compare
🎉 This PR is included in version 4.0.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
I saw you removed the |
No idea 🤷♂️ |
@kentcdodds this is amazing! happy to see |
Wow this is great @kentcdodds ! 👍 |
* waitForDomChange is implemented along with tests, documentation, and types. * Implements changes requested on 10-9-18. Removes matchSnapshots. Correctly formats README.md. Changes Promise to return a mutationsList. Adds documentation for mutationsList. * causes waitForElement to throw an error if callback is not defined. changes tests to account for new behavior. removes the documentation around the default callback. adds MutationObserver documentation for waitForDomChange
What: deprecate renderIntoDocument and make it the default
Why: Closes #116
How:
Checklist:
cc @hnordt @sompylasar