web-dev-qa-db-ja.com

JestでのonChange関数のテスト

私はJestとテスト全般に比較的不慣れです。入力要素を持つコンポーネントがあります:

import * as React from "react";

export interface inputProps{
    placeholder: string;
    className: string;
    value: string;
    onSearch: (depID: string) => void;
}

onSearch(event: any){
    event.preventDefault();
    //the actual onclick event is in another Component
    this.props.onSearch(event.target.value.trim());
}

export class InputBox extends React.Component<inputProps, searchState> {
  render() {
        return (
            <input
                onChange={this.onSearch} //need to test this
                className={this.props.className} 
                type="text"
                value={this.props.value}
                placeholder={this.props.placeholder} />
        );
    }
}

入力要素のonChangeが入力要素のvalue属性をパラメーターとして受け取る関数であることを確認するテストが必要です。これは私がこれまでに得た距離です:

//test to see the input element's onchange 
//returns a function that takes its value as a param
it("onChange param is the same value as the input value", () => {
    const mockFn = jest.fn();
    const input = enzyme.shallow(<InputBox 
                                    value="TestVal"
                                    placeholder="" 
                                    className="" 
                                    onSearch={mockFn}/>);


       input.find('input').simulate('change',  { preventDefault() {} });
       expect(mockFn.mock.calls).toBe("TestVal");
    });

私はここで最初のソリューションから出発します Jestでボタンクリックをシミュレート そして: https://facebook.github.io/jest/docs/en/mock-functions.html

編集:上記を実行すると、次のエラーがスローされます。

 TypeError: Cannot read property 'value' of undefined
10
ZeroDarkThirty

コードスニペットの構文:

import React from 'react';

export default class InputBox extends React.Component {
  onSearch(event) {
    event.preventDefault();
    this.props.onSearch(event.target.value.trim());
  }
  render () { return <input onChange={this.onSearch.bind(this)} />; }
}

イベントオブジェクトでpreventDefault関数を定義するのと同様に、onSearch関数で使用される他のプロパティも定義する必要があるため、テストは失敗します。

it('should call onChange prop', () => {
  const onSearchMock = jest.fn();
  const event = {
    preventDefault() {},
    target: { value: 'the-value' }
  };
  const component = enzyme.shallow(<InputBox onSearch={onSearchMock} />);
  component.find('input').simulate('change', event);
  expect(onSearchMock).toBeCalledWith('the-value');
});

浅いレンダリングを使用しているため、以前のテストコードではイベントの形状を定義する必要があります。代わりに、実際の入力値がonSearch関数で使用されていることをテストする場合は、enzyme.mountで完全なレンダリングを試す必要があります。

it('should call onChange prop with input value', () => {
  const onSearchMock = jest.fn();
  const component = enzyme.mount(<InputBox onSearch={onSearchMock} value="custom value" />);
  component.find('input').simulate('change');
  expect(onSearchMock).toBeCalledWith('custom value');
});
19
Carloluis

私は解決策を見つけました。

そのため、以下に示すように、InputBox内の値を渡す代わりに、simulateの2番目のパラメーター内に値を渡す必要があります。次に、mockFnの最初の呼び出しの最初の引数と等しいかどうかを確認します。また、event.preventDefault();を取り除くことができます。

it("onChange param is the same value as the input element's value property", () => {
    const mockFn = jest.fn();
    const input = enzyme.shallow(<InputBox 
                                    value=""
                                    placeholder="" 
                                    className="" 
                                    onSearch={mockFn}/>);

    input.find('input').simulate('change', {target: {value: 'matched'} });
    expect(mockFn.mock.calls[0][0]).toBe('matched');
});
2
ZeroDarkThirty