简体   繁体   English

酶按钮模拟无法正常工作

[英]Enzyme button simulate doesn't work as expected

I have the following react-native test code. 我有以下反应本机测试代码。

import { shallow } from 'enzyme';
import React from 'react';

import {
  BorderlessButton,
  InputBox,
  ProgressBar,
} from 'components';

import Name from '../name.component';

describe('Name component', () => {
  let wrapper: any;

  const mockOnPress = jest.fn();
  const mockSaveStep = jest.fn();

  const mockProps: any = {
    errors: null,
    values: [{ givenName: 'givenName', familyName: 'familyName' }],
  };

  beforeEach(() => {
    wrapper = shallow(<Name signUpForm={mockProps} saveStep={mockSaveStep} />);
  });

  it('should render Name component', () => {
    expect(wrapper).toMatchSnapshot();
  });

  it('should render 2 <InputBox />', () => {
    expect(wrapper.find(InputBox)).toHaveLength(2);
  });

  it('should render a <ProgressBar />', () => {
    expect(wrapper.find(ProgressBar)).toHaveLength(1);
  });

  it('should render a <BorderlessButton /> with the text NEXT', () => {
    expect(wrapper.find(BorderlessButton)).toHaveLength(1);
    expect(wrapper.find(BorderlessButton).props().text).toEqual('NEXT');
  });

  it('should press the NEXT button', () => {
    wrapper.find(BorderlessButton).simulate('click');
    expect(mockOnPress).toHaveBeenCalled();
  });
});

But the last test doesn't work properly. 但是最后的测试不能正常工作。 How can I simulate a this button click? 如何模拟此按钮的单击? This gives me an error saying 这给我一个错误的说法

expect(jest.fn()).toHaveBeenCalled(). Expect(jest.fn())。toHaveBeenCalled()。 Expected mock function to have been called, but it was not called. 预期已调用了模拟函数,但未调用。

This is the component. 这就是组件。

class NameComponent extends Component {
  componentDidMount() {
    const { saveStep } = this.props;
    saveStep(1, 'Name');
  }

  disableButton = () => {
    const {
      signUpForm: {
        errors, values,
      },
    } = this.props;

    if (errors && values && errors.givenName && errors.familyName) {
      if (errors.givenName.length > 0 || values.givenName === '') return true;
      if (errors.familyName.length > 0 || values.familyName === '') return true;
    }
  }

  handleNext = () => {
    navigationService.navigate('PreferredName');
  }

  resetForm = () => {
    const { resetForm } = this.props;
    resetForm(SIGN_UP_FORM);
    navigationService.navigate('LoginMain');
  }

  render() {
    const { name, required } = ValidationTypes;
    const { step } = this.props;

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <KeyboardAvoidingView style={{ flex: 1 }}
          behavior={Platform.OS === 'ios' ? 'padding' : null}
          enabled>
          <ScreenContainer
            navType={ScreenContainer.Types.LEVEL_THREE}
            levelThreeOnPress={this.resetForm}>

            <View style={styles.container}>
              <View style={{ flex: 1 }}>
                <SinglifeText
                  type={SinglifeText.Types.H1}
                  label='Let’s start with your legal name'
                  style={styles.textLabel}
                />

                <View style={styles.names}>
                  <InputBox
                    name='givenName'
                    form={SIGN_UP_FORM}
                    maxLength={22}
                    placeholder='Given name'
                    containerStyle={styles.givenNameContainer}
                    inputContainerStyle={styles.inputContainer}
                    errorStyles={styles.inputError}
                    keyboardType={KeyBoardTypes.default}
                    validations={[required, name]}
                  />
                  <InputBox
                    name='familyName'
                    form={SIGN_UP_FORM}
                    maxLength={22}
                    placeholder='Family name'
                    inputContainerStyle={styles.inputContainer}
                    errorStyles={styles.inputError}
                    keyboardType={KeyBoardTypes.default}
                    validations={[required, name]}
                  />
                </View>

                <SinglifeText
                  type={SinglifeText.Types.HINT}
                  label='Please use the same name you use with your bank'
                  style={styles.hint}
                />
              </View>
            </View>
          </ScreenContainer>

          <ProgressBar presentage={(step / MANUAL_SIGNUP_STEP_COUNT) * 100} />

          <View style={styles.bottomButtonContainer}>
            <BorderlessButton
              text='NEXT'
              disabled={this.disableButton()}
              onPress={this.handleNext}
            />
          </View>

        </KeyboardAvoidingView>
      </SafeAreaView>
    );
  }
}

How can I solve this?? 我该如何解决?

You create the function mockOnPress() , but mockOnPress() is never injected into the component. 您创建了函数mockOnPress() ,但是mockOnPress()从未注入到组件中。

In the component you wrote, NameComponent has a child BorderlessButton component, in which the line, onPress={this.handleNext} is hard-coded in. handleNext() is defined elsewhere as: 在您编写的组件中, NameComponent有一个子级BorderlessButton组件,其中onPress={this.handleNext}这行硬编码在其中handleNext()在其他地方定义为:

handleNext = () => {
    navigationService.navigate('PreferredName');
}

To test that the functionality of the button is working, I see two viable options. 为了测试按钮的功能是否正常,我看到了两个可行的选项。 One is to use dependency injection . 一种是使用依赖注入 Instead of hard-coding the button to call navigationService.navigate('PreferredName') , you could have it execute code that is passed in as a prop. 您可以使按钮执行作为道具传入的代码,而不是对按钮进行硬编码以调用navigationService.navigate('PreferredName') See the following as an example: 请参阅以下示例:

it('Button should handle simulated click', function (done) {
  wrappedButton = mount(<MyButton onClick={() => done()}>Click me!</BaseButton>)
  wrappedButton.find('button').simulate('click')
}

Note that you could take the principle provided in the above example and expand it to your example by passing in the functionality you want to occur onClick as a prop to your NameComponent. 请注意,您可以采用上面示例中提供的原理,并通过将要发生onClick的功能作为对NameComponent的支持,将其扩展为示例。

Another option you have, is to test whether clicking the button causes the side effects you want to occur. 您还有另一个选择,就是测试单击按钮是否会导致您想要发生的副作用。 As written, pressing the button should call, navigationService.navigate('PreferredName') . 按照书面规定,按下按钮应调用navigationService.navigate('PreferredName') Is this the intended effect? 这是预期的效果吗? If so, you can change your test to validate whether navigationService.navigate('PreferredName') was called somehow. 如果是这样,则可以更改测试以验证是否以某种方式调用了navigationService.navigate('PreferredName')

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

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