zoukankan      html  css  js  c++  java
  • [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} />)
    }
  • 相关阅读:
    Vmware 虚拟硬盘 合并多个分割文件
    一步步带你做vue后台管理框架(三)——登录功能
    一步步带你做vue后台管理框架(二)——上手使用
    webpack教程(六)——分离组件代码
    webpack教程(五)——图片的加载
    webpack教程(四)——css的加载
    input输入框自动填充黄色背景解决方案
    webpack教程(三)——热刷新
    webpack教程(二)——webpack.config.js文件
    webpack教程(一)——初体验
  • 原文地址:https://www.cnblogs.com/Answer1215/p/7556059.html
Copyright © 2011-2022 走看看