web-dev-qa-db-fra.com

Comment se moquer de e.preventDefault dans l'enfant du composant React

Je ne sais pas vraiment comment se moquer de la fonction en ligne dans l'enfant du composant React

Ma pile: sinon, chai, enzyme;

Utilisation des composants:

<ListItem onClick={() => someFn()} />

Rendu du composant:

render() {
    return (
      <li>
        <a href="#" onClick={e => {
            e.preventDefault();
            this.props.onClick();
          }}
        > whatever </a>
      </li>
    );
  }

Nous avons ici une fonction onClick qui appelle e.preventDefault(). Comment dire à <a href> (link) de ne pas appeler e.preventDefault()? Comment se moquer d'un onClick?

Voici ce que j'ai essayé dans les tests:

Configuration de copie superficielle

function setup() {
  const someFn = sinon.stub();

  const component = shallow(
    <ListItem
      onClick={() => {
        someFn();
      }}
    />
  );

  return {
    component: component,
    actions: someFn,
    link: component.find('a'),
    listItem: component.find('li'),
  }
}

Et le test

  it('simulates click events', () => {
    const { link, actions } = setup();
    link.simulate('click'); //Click on <a href>
    expect(actions).to.have.property('callCount', 1); //would be good if we'll remove e.preventDefault()
  });

Erreur de sortie du test:

TypeError: Cannot read property 'preventDefault' of undefined
27
Sergei Panfilov

Essaye ça

link.simulate('click', {
  preventDefault: () => {
  }
 });
70
WitVault
 test('simulates click events', () => {
    const e = { stopPropagation: jest.fn() };
    const component = shallow(<ListItem{...props} />);
    const li = component.find('li').at(0).childAt(0)
    li.props().onClick(e)

    expect();
  });
4
Anton Karpenko

Juste pour noter que c'est un problème uniquement lorsque vous utilisez le rendu d'enzyme shallow. Dans le cas d'un rendu DOM complet mount, l'objet événement contient la méthode preventDefault, vous n'avez donc pas à vous en moquer.

3
Matus Dubrava

Pour ceux qui utilisent Jest et @testing-library ou react-testing-librarys fireEvent, vous devez fournir un objet événement initialisé, sinon l'événement ne peut pas être distribué via votre élément.

On peut alors affirmer sur e.preventDefault étant appelé en affectant une propriété à cet événement initialisé:

test('prevents default on click', () => {
  const {getByText} = render(<MyComponent />);
  const button = getByText(/click me/);

  // initialise an event, and assign your own preventDefault
  const clickEvent = new MouseEvent('click');
  Object.assign(clickEvent, {preventDefault: jest.fn()});

  fireEvent(button, clickEvent);

  expect(event.preventDefault).toHaveBeenCalledTimes(1);
});

De même pour stopPropagation.

réponse d'Anton Karpenko pour Jest a été utile.

3
Larry

Je suggère de créer un nouvel objet basé sur jest.fn () avec

const event = Object.assign(jest.fn(), {preventDefault: () => {}})

puis utilisez-le:

element.simulate('click', event);
1
VonAxt

Vous pouvez définir un objet avec une fonction concernant que vous moquerez via un outil de test, par exemple regardez Jest et Enzyme

describe('Form component', () => {
  test('deos not reload page after submition', () => {
    const wrapper = shallow(<TodosForm />)
    // an object with some function
    const event = { preventDefault: () => {} }
    // mocks for this function
    jest.spyOn(event, 'preventDefault')
    wrapper.find('form').simulate('submit', event)
    // how would you know that function is called
    expect(event.preventDefault).toBeCalled()
  })
})
1
Purkhalo Alex