Как протестировать OnSubmit в React с использованием Jest и Enzyme - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть следующий код для onSubmit функции

handleSubmit(event) {
    event.preventDefault();

    this.setState({ isDone: true });

    const nameMatch= () => {
      return !(this.state.firstName.match("^Cel.*") && this.state.firstName.endsWith("on"))
    }
    if (nameMatch()) {
      alert("Please enter a valid name");
      return;
    }

    if (!this.state.lastName.endsWith("on")) {
      alert("check lastname too");
      return;
    }
    this.getFullName();

}

Чтобы запустить тест, описанный выше, я делаю:

it('check submit', () => {
    wrapper.handleSubmit({preventDefault: () => {}});
    console.log(wrapper.handleSubmit());
});

В этом мне нужно состояние первогоимя и фамилия.Как мне это сделать в тестовом примере?Как передать их в качестве параметров для теста?

1 Ответ

1 голос
/ 25 сентября 2019

Вот решение, вы можете использовать .simulate(event[, ...args]) метод enzyme для запуска реакции dom SyntheticEvent .Документы: https://airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html

Например:

index.tsx:

import React, { Component } from 'react';

export interface ISomeComponentState {
  firstName: string;
  lastName: string;
  isDone: boolean;
  [key: string]: any;
}

export class SomeComponent extends Component<any, ISomeComponentState> {
  constructor(props) {
    super(props);

    this.state = {
      firstName: '',
      lastName: '',
      isDone: false
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  public render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <label>
            firstName:
            <input
              type="text"
              name="firstName"
              placeholder="enter your first name"
              value={this.state.firstName}
              onChange={this.handleInputChange}
            />
          </label>
          <label>
            lastName:
            <input
              type="text"
              name="lastName"
              placeholder="enter your last name"
              value={this.state.lastName}
              onChange={this.handleInputChange}
            />
          </label>
          <div>
            <input type="submit" value="Submit" />
          </div>
        </form>
      </div>
    );
  }

  private handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
    const target = event.target;
    const name = target.name;
    const value = target.value;

    this.setState({ [name]: value });
  }

  private handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();

    this.setState({ isDone: true });

    const nameMatch = () => {
      return !(this.state.firstName.match('^Cel.*') && this.state.firstName.endsWith('on'));
    };

    if (nameMatch()) {
      alert('Please enter a valid name');
      return;
    }

    if (!this.state.lastName.endsWith('on')) {
      alert('check lastname too');
      return;
    }
    this.getFullName();
  }

  private getFullName() {
    const { firstName, lastName } = this.state;
    return firstName + ' ' + lastName;
  }
}

index.spec.tsx:

import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { SomeComponent, ISomeComponentState } from './';

describe('SomeComponent', () => {
  let wrapper: ShallowWrapper;
  let getFullNameSpy;
  let alertSpy;
  beforeEach(() => {
    alertSpy = jest.spyOn(window, 'alert');
    getFullNameSpy = jest.spyOn(SomeComponent.prototype as any, 'getFullName');
    wrapper = shallow(<SomeComponent></SomeComponent>);
  });
  afterEach(() => {
    jest.resetAllMocks();
  });

  it('check submit', () => {
    expect(wrapper.find('form')).toHaveLength(1);
    const formEventMocked = { preventDefault: jest.fn() };
    const state: ISomeComponentState = {
      firstName: 'Cel.du.on',
      lastName: 'lin.on',
      isDone: false
    };
    wrapper.setState(state);
    expect(wrapper).toMatchSnapshot();
    wrapper.find('form').simulate('submit', formEventMocked);
    expect(getFullNameSpy).toBeCalledTimes(1);
    expect(formEventMocked.preventDefault).toBeCalledTimes(1);
    expect(wrapper.state('isDone')).toBeTruthy();
  });

  it('should alert when first name is invalid', () => {
    expect(wrapper.find('form')).toHaveLength(1);
    const formEventMocked = { preventDefault: jest.fn() };
    const state: ISomeComponentState = {
      firstName: 'du',
      lastName: 'lin.on',
      isDone: false
    };
    wrapper.setState(state);
    expect(wrapper).toMatchSnapshot();
    wrapper.find('form').simulate('submit', formEventMocked);
    expect(alertSpy).toBeCalledWith('Please enter a valid name');
    expect(formEventMocked.preventDefault).toBeCalledTimes(1);
    expect(wrapper.state('isDone')).toBeTruthy();
  });

  it('should alert when last name is invalid', () => {
    expect(wrapper.find('form')).toHaveLength(1);
    const formEventMocked = { preventDefault: jest.fn() };
    const state: ISomeComponentState = {
      firstName: 'Cel.du.on',
      lastName: 'lin',
      isDone: false
    };
    wrapper.setState(state);
    expect(wrapper).toMatchSnapshot();
    wrapper.find('form').simulate('submit', formEventMocked);
    expect(alertSpy).toBeCalledWith('check lastname too');
    expect(formEventMocked.preventDefault).toBeCalledTimes(1);
    expect(wrapper.state('isDone')).toBeTruthy();
  });
});

Юнит-тест сотчет о покрытии:

PASS  src/stackoverflow/58085900/index.spec.tsx
  SomeComponent
    ✓ check submit (17ms)
    ✓ should alert when first name is invalid (8ms)
    ✓ should alert when last name is invalid (4ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |    88.24 |      100 |    85.71 |    86.21 |                   |
 index.tsx |    88.24 |      100 |    85.71 |    86.21 |       56,57,58,60 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   3 passed, 3 total
Time:        3.113s, estimated 8s

Вот демоверсия: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58085900

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...