简体   繁体   English

如何使用酶和笑话来检测 React 状态的变化

[英]How to use enzyme and jest to detect change React state

I have a simple React component, when user click the button I want to increase the internal value of state and render in an input button.我有一个简单的 React 组件,当用户单击按钮时,我想增加 state 的内部值并在输入按钮中呈现。

The component works, but I am not able to write a test with enzyme, basically the internal value is not being updated.该组件有效,但我无法用酶编写测试,基本上内部值没有被更新。

I think it is connected with setState being asynch, do you have any idea how to fix my test?我认为这与 setState 异步有关,您知道如何修复我的测试吗?

import * as React from 'react'

type TestCounterProps = Readonly<{
  defaultValue: number
  onClick: (value: number) => void
}>

export const TestCounter = ({ defaultValue, onClick }: TestCounterProps) => {
  const [value, setValue] = React.useState(defaultValue)

  const handleIncrease = () => {
    setValue(value + 1)
    onClick(value)
  }

  return (
    <div>
      <input value={value} readOnly />
      <button onClick={handleIncrease}>Click to increase</button>
    </div>
  )
}

Test:测试:

import * as React from 'react'
import { mount } from 'enzyme'
import { TestCounter } from './TestCounter'

describe('TestCounter', () => {
  it('should increase counter by 1 when user click button', () => {
    const cbClick = jest.fn()
    const container = mount(<TestCounter defaultValue={0} onClick={cbClick} />)
    const input = container.find('input')
    const button = container.find('button')
    button.simulate('click')
    container.update()

    expect(input.props().value).toBe(1) // issue here still 0 <<<
    expect(cbClick).toBeCalledWith(1)
  })
})

I have a similar example/component, I am going to past it here so could be useful as example:我有一个类似的示例/组件,我将在这里跳过它,因此可以用作示例:

import * as React from 'react'

type CounterProps = Readonly<{
  initialCount: number
  onClick: (count: number) => void
}>

export default function Counter({ initialCount, onClick }: CounterProps) {
  const [count, setCount] = React.useState(initialCount)

  const handleIncrement = () => {
    setCount((prevState) => {
      const newCount = prevState + 1
      onClick(newCount)
      return newCount
    })
  }

  const handleIncrementWithDelay = () => {
    setTimeout(() => {
      setCount((prevState) => {
        const newCount = prevState + 1
        onClick(newCount)
        return newCount
      })
    }, 2000)
  }

  return (
    <div>
      Current value: {count}
      <button onClick={handleIncrement}>Increment</button>
      <button onClick={handleIncrementWithDelay}>Increment with delay</button>
    </div>
  )
}

The test:考试:

import * as React from 'react'
import { mount, ReactWrapper } from 'enzyme'
import Counter from './Counter'
import { act } from 'react-dom/test-utils'

const COUNT_UPDATE_DELAY_MS = 2000

const waitForComponentToPaint = async (wrapper: ReactWrapper) => {
  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0))
    wrapper.update()
  })
}

describe('Counter', () => {
  beforeAll(() => {
    jest.useFakeTimers()
  })

  afterAll(() => {
    jest.useRealTimers()
  })

  it('should display initial count', () => {
    const cbClick = jest.fn()
    const wrapper = mount(<Counter initialCount={5} onClick={cbClick} />)

    expect(wrapper.text()).toContain('Current value: 5')
    expect(cbClick).not.toBeCalled()
  })

  it('should increment after "Increment" button is clicked', () => {
    const cbClick = jest.fn()
    const wrapper = mount(<Counter initialCount={5} onClick={cbClick} />)

    wrapper.find('button').at(0).simulate('click')

    expect(wrapper.text()).toContain('Current value: 6')
    expect(cbClick).toHaveBeenCalledWith(6)
  })

  it('should increment with delay after "Increment with delay" button is clicked', () => {
    const cbClick = jest.fn()
    const wrapper = mount(<Counter initialCount={5} onClick={cbClick} />)
    waitForComponentToPaint(wrapper)

    wrapper.find('button').at(1).simulate('click')

    jest.advanceTimersByTime(COUNT_UPDATE_DELAY_MS + 1000)

    expect(wrapper.text()).toContain('Current value: 6')
    expect(cbClick).toHaveBeenCalledWith(6)
  })
})


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM