Skip to content

state updates do not trigger render after rerender() call #33

Closed
@3bl3gamer

Description

@3bl3gamer
  • preact-testing-library version: 2.0.0
  • preact version: 10.5.2
  • node version: 14.8.0
  • yarn 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions