[React & Testing] Simulate Event testing

Here we want to test a toggle button component, when the button was click, state should change, style should change also.

 

Toggle component:

复制代码
// see this live: https://codesandbox.io/s/GvWpGjKQ
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import glamorous from 'glamorous'
import {darken} from 'polished'

// imagine this is in a "components" file
const primaryColor = '#337ab7'
const toggledOnStyles = {
  backgroundColor: darken(0.15, primaryColor),
  borderColor: darken(0.25, primaryColor),
  '&:hover,&:active,&:focus': {
    backgroundColor: darken(0.2, primaryColor),
    borderColor: darken(0.3, primaryColor),
  },
}
const toggledOffStyles = {
  backgroundColor: primaryColor,
  borderColor: darken(0.1, primaryColor),
  '&:hover,&:active,&:focus': {
    backgroundColor: darken(0.1, primaryColor),
    borderColor: darken(0.2, primaryColor),
  },
}
const ToggleButton = glamorous.button(
  {
    display: 'inline-block',
    padding: '6px 12px',
    marginBottom: '0',
    fontSize: '14px',
    fontWeight: '400',
    lineHeight: '1.4',
    textAlign: 'center',
    cursor: 'pointer',
    borderRadius: '4px',
    color: '#fff',
  },
  props => (props.on ? toggledOnStyles : toggledOffStyles),
)

class Toggle extends Component {
  constructor(props, ...rest) {
    super(props, ...rest)
    this.state = {
      toggledOn: props.initialToggledOn || false,
    }
  }

  handleToggleClick = () => {
    const toggledOn = !this.state.toggledOn
    this.props.onToggle(toggledOn)
    this.setState({toggledOn})
  }

  render() {
    const {children} = this.props
    const {toggledOn} = this.state
    return (
      <ToggleButton
        on={toggledOn}
        onClick={this.handleToggleClick}
        data-test="button"
      >
        {children}
      </ToggleButton>
    )
  }
}

Toggle.propTypes = {
  initialToggledOn: PropTypes.bool,
  onToggle: PropTypes.func.isRequired,
  children: PropTypes.any.isRequired,
}

export default Toggle
复制代码

 

Test:

复制代码
import React from 'react'
import {render, mount} from 'enzyme'
import Toggle from '../toggle'

test('component render with default state', () => {
    const wrapper = renderToggle();
    expect(wrapper).toMatchSnapshotWithGlamor();
})

test('when button is clicked, the style of button should change', () => {
    const onToggle = jest.fn() // jest mock function
    const wrapper = mountToggle({
        onToggle
    })
    // It is recommended that for the element we need to test
    // we can add 'data-test' attr, so that we can reference
    // the element inside testing
    const button = wrapper.find('[data-test="button"]')
    // we can verify the style changes inside snapshots
    expect(wrapper).toMatchSnapshotWithGlamor('1. Before toggle')
    button.simulate('click')
    expect(wrapper).toMatchSnapshotWithGlamor('2. After toggle')
})

test('onToggle function should be called when the button is clicked', () => {
    const onToggle = jest.fn() // jest mock function
    const wrapper = mountToggle({
        onToggle
    })
    // It is recommended that for the element we need to test
    // we can add 'data-test' attr, so that we can reference
    // the element inside testing
    const button = wrapper.find('[data-test="button"]')
    button.simulate('click')
    expect(onToggle).toHaveBeenCalledTimes(1)
    expect(onToggle).toHaveBeenCalledWith(true)
})

/**
 * The difference between mount and render function is that
 * 1. render is faster, because after rendered, it output string,
 * so there is no lifecycle hooks bind with it.
 * 2. mount, on the other hand, will bind lifecycle hooks and events,
 * the output is actual DOM element
 * */

function mountToggle(props = {}) {
    const propToUse = Object.assign(
        {},
        {
            onToggle() {
            },
            children: 'I am a child'
        },
        props
    )

    return mount(<Toggle {...propToUse} />)
}

function renderToggle(props = {}) {
    const propToUse = Object.assign(
        {},
        {
            onToggle() {
            },
            children: 'I am a child'
        },
        props
    )

    return render(<Toggle {...propToUse} />)
}
复制代码

 

posted @   Zhentiw  阅读(677)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2016-09-20 [Angular 2] Angular 2 Smart Components vs Presentation Components
2016-09-20 [Angular 2] Share a Service Across Angular 2 Components and Modules
2016-09-20 [Angular 2] How To Debug An Angular 2 Application - Debugging via Augury or the Console
点击右上角即可分享
微信分享提示