Как проверить функцию, которая ожидает e: React.ChangeEvent <HTMLInputElement>в качестве параметра? - PullRequest
0 голосов
/ 14 сентября 2018

Как выполнить модульное тестирование метода doStuff, описанного ниже, без необходимости создания полноценного объекта React.ChangeEvent?

// my-form.tsx
export const doStuff = (changeHandler: ChangeHandler, e: React.ChangeEvent<HTMLInputElement>) => {
  // A call to another function takes place here, but for brevity, I'm using console.log
  console.log(e); 
  changeHandler(e);
}

interface ChangeHandler {
  (e: React.ChangeEvent<HTMLInputElement>): void;
}

interface MyFormProps {
  changeHandler: ChangeHandler,
  username: string;
  password: string;
}

const MyForm: React.SFC<MyFormProps> = ({changeHandler, username, password}) => (
  <form>
    <div>
      <label htmlFor="username">Username</label>
      <input
        type="text"
        name="username"
        value={username}
        onChange={doStuff.bind(null, changeHandler)} />
    </div>
    <div>
      <label htmlFor="password">Password</label>
      <input
        type="text"
        name="password"
        value={password}
        onChange={doStuff.bind(null, changeHandler)} />
    </div>
    <button>Submit</button>
  </form>
);

export default MyForm;

Ниже мой тестовый файл. Первый тест - это то, что я хотел бы сделать, чтобы проверить doStuff. Я полагаю, что второй тест - это то, как я могу также протестировать doStuff.

// my-form.test.tsx
import MyForm, { doStuff } from './my-form.tsx';

describe('MyForm' => {
  it('should call the changeHandler', () => {
    // Arrange
    const changeHandlerMock = jest.fn();

    // Act
    // How can I pass a mock for the 2nd parameter?
    // doStuff(changeHandlerMock, {});

    // Assert
    expect(changeHandlerMock.called.length).toEqual(1);
  });

  it('should call the changeHandler too', () => {
    // Arrange
    const changeHandlerMock = jest.fn();

    // Act
    const wrapper = shallow(
      <MyForm
        changeHandler={changeHandlerMock}
        username={username}
        password={password} />
    );
    wrapper.find(`input[name='username']`).simulate('change');

    // Assert
    expect(changeHandlerMock.called.length).toEqual(1);
  })
});

Кроме того, я могу избавиться от doStuff и изменить разметку для каждого элемента ввода на:

onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
  console.log(e);
  changeHandler(e);
}} />

Недостатком является то, что если мне нужно внести изменения в eventHandler, мне придется делать это в каждом объявленном месте, отсюда и метод doStuff.

Для полноты, вот мой контейнерный компонент:

interface MyFormContainerState {
  username: string;
  password: string;
}

// my-form-container.tsx
class MyFormContainer extends React.Component<{}, MyFormContainerState> {
  constructor(props: {}) {
    super(props);

    this.state = {
      username: '',
      password: ''
    };
  }

  public render() {
    const { username, password } = this.state;

    return (
      <MyForm
        changeHandler={this.changeHandler}
        username={username}
        password={password} />
    );

  }

  public changeHandler = (e: React.ChangeEvent<HTMLInputElement>): void => {
    this.setState({
      ...this.state,
      [e.currentTarget.name]: e.currentTarget.value
    });
  }
}

1 Ответ

0 голосов
/ 14 сентября 2018

Вы можете обойти проверку типа для вашего смоделированного объекта, используя Подтверждение типа , чтобы утверждать тип как any:

it('should call the changeHandler', () => {
  // Arrange
  const changeHandlerMock = jest.fn();

  // Act
  doStuff(changeHandlerMock, {} as any);

  // Assert
  expect(changeHandlerMock.called.length).toEqual(1);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...