简体   繁体   中英

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(). 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.

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:

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. 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.

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') . Is this the intended effect? If so, you can change your test to validate whether navigationService.navigate('PreferredName') was called somehow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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