Configuring PrettyDOM when testing React hook
oscaralanpierce opened this issue · 4 comments
What is your question:
Hi folks, I'm trying to test a library with a React hook that adds a script tag to the document. (This is a script supporting Google identity services that unfortunately is not available as a package, so adding it to the document is the only way.) I need to test that the script's onload callback is run when the script loads successfully (and that its onerror callback is run otherwise). The core functionality of the hook is contained in this callback. Unfortunately, the callback is not running during the test. Because the output includes Ignored nodes: comments, <script />, <style />, I believe the reason for the issue is that PrettyDOM filters script nodes by default.
I understand that PrettyDOM can be configured by passing in a filterNode function as an option, however, since my tests don't explicitly include/use PrettyDOM, I'm not sure how to achieve this or if it's even possible.
I'm using:
- v. 13.3.0 of
@testing-library/react, - React >= 18.0.0
- v. 8.0.1 of
@testing-library/react-hooks - v. 18.2.0 of
react-test-renderer
Please let me know if you need any additional information. Thanks in advance for your help!
Details
This is my test code (simplified):
import { renderHook, waitFor } from '@testing-library/react'
import useGoogleLogin from '../src/hooks/use-google-login'
describe('useGoogleLogin', () => {
const clientId = 'somestring'
const onLoad = jest.fn(() => {})
const onError = jest.fn(() => {})
describe('when the script loads successfully', () => {
it('calls the onload callback', async () => {
renderHook(() => useGoogleLogin({ clientId, onLoad, onError })
await waitFor(() => expect(onLoad).toHaveBeenCalled())
})
})
})This is the test output:
yarn run v1.22.19
$ jest
PASS __tests__/login-component-test.js
FAIL __tests__/use-google-login-test.js
● useGoogleLogin › when the script loads successfully › calls the onload callback
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
Ignored nodes: comments, <script />, <style />
<html>
<head />
<body>
<div />
</body>
</html>
30 | renderHook(() => useGoogleLogin({ clientId, onLoad, onError }))
31 |
> 32 | await waitFor(() => { expect(onLoad).toHaveBeenCalled() })
| ^
33 | })
34 | })
35 | })
at toHaveBeenCalled (__tests__/use-google-login-test.js:32:55)
at runWithExpensiveErrorDiagnosticsDisabled (node_modules/@testing-library/dom/dist/config.js:50:12)
at checkCallback (node_modules/@testing-library/dom/dist/wait-for.js:141:77)
at checkRealTimersCallback (node_modules/@testing-library/dom/dist/wait-for.js:133:16)
at Timeout.task [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:514:19)Finally, this is the code of the function that adds the script to the document (which is called from within the hook):
const loadGapiScript = (document, src, onLoad, onError) => {
const script = document.getElementsByTagName('script')[0]
let js = document.createElement('script')
js.id = 'google-auth'
js.src = src
js.async = true
js.defer = true
js.onerror = onError
js.onload = onLoad
if (script && script.parentNode) {
script.parentNode.insertBefore(js, script)
} else {
document.head.appendChild(js)
}
}
export default loadGapiScriptWe don't support react@18, does the issue still remain if you use react@17?
Oh gotcha, in that case I’ll have to figure something else out because my library is specifically replacing one that doesn’t support React 18. Sorry to bother you!
Hey @danascheider,
I noticed you are importing renderHook from @testing-library/react which is not this library, but rather the React 18 replacement from React Testing Library. You can try raising your issue with them instead.
Oh good catch, thanks!