Description
preact-testing-library
version: 2.0.0preact
version: 10.5.2node
version: 14.8.0yarn
version: 1.22.4
If rerender()
was called and then component's (function or class) state gets updated (for example with 'setTimeout'), component will not render.
Relevant code or config
// src/test.js
const { h } = require('preact')
const { useState, useEffect } = require('preact/hooks')
const { render, waitFor } = require('@testing-library/preact')
function Comp({}) {
const [val, setVal] = useState('original value')
useEffect(() => {
setTimeout(() => setVal('new value'), 300) // <- 300ms delay
}, [])
return <div>{val}</div>
}
it('fails', async () => {
const { container, rerender } = render(<Comp />)
rerender(<Comp />) // <- cause
// await new Promise(r => setTimeout(r, 350)) // <- fix
await waitFor(() => {
expect(container.textContent).toEqual('new value')
})
})
// babel.config.js
module.exports = {
plugins: [['@babel/plugin-transform-react-jsx', { pragma: 'h' }]],
}
What I did:
Run test with ./node_modules/.bin/jest
What happened:
Expected: "new value"
Received: "original value"
Same happens for class components https://github.com/3bl3gamer/preact-testing-library-bug-example/blob/master/src/test.js#L13
Same happens even if rerender()
was called in different test https://github.com/3bl3gamer/preact-testing-library-bug-example/blob/master/src/test.js#L38-L54
If rerender()
is removed, test passes.
If test is manually paused with setTimeout
until update has happened, it passes. Despite container.textContent
still returns old value just before waitFor
:
await new Promise(r => setTimeout(r, 350))
console.log(container.textContent) // <-- 'original value'
await waitFor(() => {
If preact
is replaced with react
(and @testing-library/react
), test also passes.
Reproduction repository: https://github.com/3bl3gamer/preact-testing-library-bug-example
Full failure output:
FAIL src/test.js
✕ fails (1016 ms)
● fails
expect(received).toEqual(expected) // deep equality
Expected: "new value"
Received: "original value"
<html>
<head />
<body>
<div>
<div>
original value
</div>
</div>
</body>
</html>
31 | // await new Promise(r => setTimeout(r, 350)) // <- fix
32 | await waitFor(() => {
> 33 | expect(container.textContent).toEqual('new value')
| ^
34 | })
35 | })
36 |
at src/test.js:33:33
at runWithExpensiveErrorDiagnosticsDisabled (node_modules/@testing-library/dom/dist/config.js:51:12)
at checkCallback (node_modules/@testing-library/dom/dist/wait-for.js:102:75)
at Timeout.task [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:391:19)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 2.425 s
Ran all test suites.