Open jsjoeio opened 2 years ago
As you suspected, the hydrate
function is only intended to be called in a client environment with a document available while render
should be callable in a purely node environment without a document.
As such, I don’t see option 1 so much as a Band-Aid as ensuring the test environment matches the scenario you are wanting to test.
That said, I think there are improvements we can make to the hydrate
function to improve the error received in this situation. I’m on my phone so I won’t attempt a code block, but I could envision an else block on that if statement in option 2 that throws an error explaining that a global document is required before you can call hydrate
rather than just silently doing nothing. It might be worthwhile extending that nicety to the DOM renderer’s render
function.
As for option 3, I’m not opposed to the idea of being able to pass in a document to render into, which could be defaulted to the global document for backwards compatibility. I would think it needs to be supported in the DOM renderer as well for consistency though.
Speaking of consistency, another option might be to follow what react-testing-library
does and allow the user to pass in a container
to render into and bypasses creating one from the document all together (docs).
As such, I don’t see option 1 so much as a Band-Aid as ensuring the test environment matches the scenario you are wanting to test.
Ah, happy to hear you say that. I think I confused myself around the original PR and what it was fixing. I think I can add a test that ensures renderHook
does work in a SSR environment. I'll see if I can get a PR in soon.
That said, I think there are improvements we can make to the hydrate function to improve the error received in this situation. I’m on my phone so I won’t attempt a code block, but I could envision an else block on that if statement in option 2 that throws an error explaining that a global document is required before you can call hydrate rather than just silently doing nothing. It might be worthwhile extending that nicety to the DOM renderer’s render function.
That's a great point! Should I open a separate issue for that, add details and then you can mark as a "good first issue"? (I can comment on it saying I'm happy to mentor whoever picks it up).
I don’t mind if you want to use this issue for it, or raise a new one if that makes it more consumable to new comers, whichever you prefer.
I don’t mind if you want to use this issue for it
Guess that's easier. I'll update the title and add some notes here.
hydrate()
is assumed to be called in a client environment (it uses document
). However, if you do so in a non-client environment, you get ReferenceError: document is not defined
.
Check for document
in hydrate
call and throw user-friendly error.
I know how to solve this but I'd rather let someone else do it and offer mentorship in return. If someone else wants to take this on and wants guidance, ping me.
@mpeyper can you add the "good first issue" label?
This is a great resource: Assertion Functions in TypeScript
@mpeyper can I pick this up? If so, the user friendly error message can be Hydrate function can only be called in a client environment with a document available.
?
react-hooks-testing-library
version: v8.0.0-alpha.1 - created a commit starting herereact
version: N/Areact-dom
version (if applicable): N/Areact-test-renderer
version (if applicable): N/Anode
version: v14.17.6npm
(oryarn
) version: v1.22.17Relevant code or config:
See below
What you did:
I added a test that runs in a Node environment to see if https://github.com/testing-library/react-hooks-testing-library/issues/605 was fixed (sidenote: using this issue/solution in a TypeScript course I'm authoring).
What happened:
I thought the solution would allow
renderHook
to be called in SSR environments but we get the same issue.Note: I added the original author on Discord to try and contact them about this PR. I saw in the comments they said they tested in a Node environment so I may be doing something differently.
Reproduction:
git clone https://github.com/testing-library/react-hooks-testing-library.git
touch src/server/__tests__/ssr.test.ts
yarn test --watch=false
Problem description:
Even though https://github.com/testing-library/react-hooks-testing-library/pull/607 modified
src/server/pure.ts
to fill the container with the ReactDOM tree inhydrate()
, this still assumesdocument
is always available.Suggested solution:
I see three potential solutions.
Option 1: add DOM to test before
hydrate
Based on my understanding,
hydrate
is supposed to be called on the client. So in our test, we could create a mockdocument
and make sure it's available globally before callinghydrate
. I see this more like a bandaid though.Option 2: check if
document
is definedAdd a check to see if
document
is available before using it.Option 3: pass in
document
This is the approach I usually take, but it would be a breaking change and most people don't like passing in globals this way.