web-dev-qa-db-fra.com

La case à cocher n'est pas «cochée» après avoir simulé un «changement» avec une enzyme

J'ai essayé d'utiliser l'enzyme pour simuler l'événement change sur une case à cocher, et j'utilise chai-enzyme Pour vérifier s'il a été vérifié.

Voici mon Hello composant réactif:

import React from 'react';

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      checked: false
    }
  }

  render() {
    const {checked} = this.state;
    return <div>
      <input type="checkbox" defaultChecked={checked} onChange={this._toggle.bind(this)}/>
      {
        checked ? "checked" : "not checked"
      }
    </div>
  }

  _toggle() {
    const {onToggle} = this.props;
    this.setState({checked: !this.state.checked});
    onToggle();
  }
}

export default Hello;

Et mon test:

import React from "react";
import Hello from "../src/hello.jsx";
import chai from "chai";
import {mount} from "enzyme";
import chaiEnzyme from "chai-enzyme";
import jsdomGlobal from "jsdom-global";
import spies  from 'chai-spies';

function myAwesomeDebug(wrapper) {
  let html = wrapper.html();
  console.log(html);
  return html
}

jsdomGlobal();
chai.should();
chai.use(spies);
chai.use(chaiEnzyme(myAwesomeDebug));


describe('<Hello />', () => {

  it('checks the checkbox', () => {
    const onToggle = chai.spy();
    const wrapper = mount(<Hello onToggle={onToggle}/>);

    var checkbox = wrapper.find('input');
    checkbox.should.not.be.checked();
    checkbox.simulate('change', {target: {checked: true}});
    onToggle.should.have.been.called.once();

    console.log(checkbox.get(0).checked);
    checkbox.should.be.checked();
  });

});

Lorsque j'exécute ce test, la checkbox.get(0).checked est false et l'assertion checkbox.should.be.checked() signale une erreur:

AssertionError: expected the node in <Hello /> to be checked <input type="checkbox" checked="checked">

Vous pouvez voir que le message est assez étrange car il y a déjà checked="checked" Dans la sortie.

Je ne sais pas où est le problème, car cela implique trop de choses.

Vous pouvez également voir un projet de démonstration ici: https://github.com/js-demos/react-enzyme-simulate-checkbox-events-demo , remarquez ces lignes

15
Freewind

Je pense que certains détails de mon explication peuvent être un peu faux, mais ma compréhension est la suivante:

Quand tu fais

var checkbox = wrapper.find('input');

Il enregistre une référence à ce noeud Enzyme dans checkbox, mais il y a des moments où lorsque l'arborescence Enzyme est mise à jour, mais pas checkbox. Je ne sais pas si c'est parce que la référence dans l'arbre change et donc le checkbox est maintenant une référence à un nœud dans une ancienne version de l'arbre.

Faire de checkbox une fonction semble la faire fonctionner pour moi, car maintenant la valeur de checkbox() est toujours tirée de l'arborescence la plus récente.

var checkbox = () => wrapper.find('input');
checkbox().should.not.be.checked();
checkbox().simulate('change', {target: {checked: true}});
///...
14
rogeliog

Ce n'est pas un bug, mais "cela fonctionne comme prévu".

L'enzyme sous-jacente utilise les outils de test React pour interagir avec React, en particulier avec l'API de simulation.

Simuler ne met pas réellement à jour le dom, il déclenche simplement les gestionnaires d'événements de réaction attachés au composant, éventuellement avec les paramètres supplémentaires que vous transmettez.

Selon la réponse que j'ai obtenue ici ( https://github.com/facebook/react/issues/495 ) c'est parce que la mise à jour du dom nécessiterait React to réimplémenter de nombreuses fonctionnalités des navigateurs, ce qui entraîne probablement des comportements imprévus, ils ont donc décidé de simplement compter sur le navigateur pour effectuer la mise à jour.

La seule façon de tester cela est de mettre à jour manuellement le dom vous-même, puis d'appeler l'api de simulation.

6
mastrolindus