web-dev-qa-db-fra.com

Test de la fonction onChange en Jest

Je suis relativement nouveau en Jest et en test en général. J'ai un composant avec un élément d'entrée:

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} />
        );
    }
}

Je veux un test qui vérifie que la variable onChange de l'élément d'entrée est une fonction qui prend l'attribut value de l'élément d'entrée en tant que paramètre. Voici à quel point je suis arrivé jusqu'ici:

//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");
    });

Je pars de la première solution ici Simuler un clic de bouton dans Jest Et: https://facebook.github.io/jest/docs/en/mock-functions.html

Edit: L'exécution de ce qui précède génère l'erreur suivante:

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

La syntaxe de votre extrait de code devrait être:

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)} />; }
}

Le test échoue car, tout comme vous définissez la fonction preventDefault sur l'objet événement, vous devez également définir d'autres propriétés utilisées sur la fonction 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');
});

Le code de test précédent doit définir la forme de l'événement, car vous utilisez un rendu peu profond. Si vous souhaitez plutôt vérifier que la valeur d'entrée réelle est utilisée sur votre fonction onSearch, vous devez essayer un rendu complet avec 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');
});
11
Carloluis

J'ai trouvé la solution.

Ainsi, au lieu de transmettre la valeur dans InputBox, nous devons la passer dans le deuxième paramètre de simulate comme indiqué ci-dessous. Ensuite, nous vérifions simplement l’égalité avec le premier argument du premier appel à la variable mockFn. De plus, nous pouvons nous débarrasser de la 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');
});
0
ZeroDarkThirty