用玩笑和酵素测试按钮

时间:2019-07-19 07:39:06

标签: reactjs react-native jestjs enzyme

在我的React-Native应用程序中,我有一个按钮组件,其用法如下。

// primary button (default button)
<Button
  text='Continue'
  onPress={() => this.onContinue()}
/>

// secondary button
<Button
  type='Secondary'
  text='Continue'
  onPress={() => this.onContinue()}
/>

// disabled button
<Button
  text='Continue'
  disabled={true}
  onPress={() => this.onContinue()}
/>

我为此编写了以下测试。

import { shallow } from 'enzyme';
import React from 'react';
import Button from '../../src/components/button';

describe('Button', () => {
  it('expect to render a primary button component', () => {
    const mockLabel = 'Test Button';
    const wrapper = shallow(<Button label={mockLabel} />);
    expect(wrapper).toMatchSnapshot('primary button snapshot');
  });

  it('expect to render a secondary button component', () => {
    const type = Button.Types.SECONDARY;
    const mockLabel = 'Test Button';
    const wrapper = shallow(<Button type={type} label={mockLabel} />);
    expect(wrapper).toMatchSnapshot('secondary button snapshot');
  });

  it('expect to render a disabled button component', () => {
    const disabled = true;
    const mockLabel = 'Test Button';
    const wrapper = shallow(<Button label={mockLabel} disabled={disabled} />);
    expect(wrapper).toMatchSnapshot();
  });
});

这是编写测试的正确方法吗?虽然可以正常运行,但是这些测试是否可以正确涵盖方案?

这是我的按钮组件。如何检查类型是主要还是次要?如果禁用按钮功能正常? onPress()是否按预期工作?任何帮助将不胜感激。

import React, { Component } from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';

import { TextLabel } from '../components';
import colors from '../res/colors';

class Button extends Component<IProps> {
  static defaultProps: IProps;

  static Types = {
    PRIMARY: 'primary',
    SECONDARY: 'secondary',
  };

  state = {
    pressed: false,
  };

  handlePressIn = () => {
    this.setState({ pressed: true });
  }

  handlePressOut = () => {
    this.setState({ pressed: false });
  }

  buttonStyles = () => {
    const { pressed } = this.state;
    const { type, disabled } = this.props;

    if (type === Button.Types.PRIMARY) {
      if (disabled) return styles.primaryButtonDisabled;
      if (!pressed) return styles.primaryButtonDefault;
      if (pressed) return styles.primaryButtonPressed;
    }

    if (type === Button.Types.SECONDARY) {
      if (disabled) return styles.secondaryButtonDisabled;
      if (!pressed) return styles.secondaryButtonDefault;
      if (pressed) return styles.secondaryButtonPressed;
    }
  }

  textStyles = () => {
    const { pressed } = this.state;
    const { type, disabled } = this.props;

    if (type === Button.Types.PRIMARY) return styles.primaryText;

    if (type === Button.Types.SECONDARY) {
      if (disabled) return styles.secondaryTextDisabled;
      if (!pressed) return styles.secondaryTextDefault;
      if (pressed) return styles.secondaryTextPressed;
    }
  }

  render() {
    const {
      disabled,
      text,
      buttonStyle,
      onPress,
    } = this.props;

    return (
      <TouchableOpacity
        onPress={() => onPress()}
        activeOpacity={1}
        onPressIn={this.handlePressIn}
        onPressOut={this.handlePressOut}
        disabled={disabled}
        style={[styles.button, this.buttonStyles(), buttonStyle]}
      >
        <TextLabel
          type={TextLabel.Types.BUTTON_LBL}
          style={[styles.text, this.textStyles()]}
          label={text}
        />
      </TouchableOpacity>
    );
  }
}

const styles = StyleSheet.create({
  button: {
    borderRadius: 4,
    borderWidth: 1,
    justifyContent: 'center',
    // position: 'absolute',
    height: 48,
    width: '100%',
    marginTop: 20,
    marginBottom: 20,
  },
  primaryButtonDefault: {
    backgroundColor: colors.primary,
    borderColor: colors.primary,
  },
  primaryButtonPressed: {
    backgroundColor: colors.darkRed,
    borderColor: colors.darkRed,
  },
  primaryButtonDisabled: {
    backgroundColor: colors.gray,
    borderColor: colors.gray,
  },
  secondaryButtonDefault: {
    borderColor: colors.primary,
  },
  secondaryButtonPressed: {
    borderColor: colors.darkRed,
  },
  secondaryButtonDisabled: {
    borderColor: colors.gray,
  },
  text: {
    textAlign: 'center',
    textTransform: 'uppercase',
  },
  primaryText: {
    color: colors.white,
  },
  secondaryTextDefault: {
    color: colors.primary,
  },
  secondaryTextPressed: {
    color: colors.darkRed,
  },
  secondaryTextDisabled: {
    color: colors.gray,
  },
});

export interface IProps {
  disabled?: boolean;
  text: string;
  type?: string;
  buttonStyle?: object;
  onPress: Function;
}

Button.defaultProps = {
  disabled: false,
  text: '',
  type: Button.Types.PRIMARY,
  buttonStyle: {},
  onPress: () => {},
};

export default Button;

1 个答案:

答案 0 :(得分:0)

快照测试不同于单元测试。

快照测试对于了解给定组件的渲染输出的差异很有用。尤其是在代码审查练习中或浏览项目的源代码管理历史记录时。但是,它们不能保证一定的行为。

您写的是快照测试,最好用单元测试来补充它们。在您的情况下,您需要测试Button组件的内部工作原理:

给定一组特定的参数(例如您的3种情况),是render()的{​​{1}}函数呈现预期的代码。由于您尚未发布Button组件的代码,因此我无法帮助您编写这些测试。