Test d’événement Mouseover en D3 avec Sinon

J’ai du mal à faire passer mon test. Je voudrais pouvoir utiliser un espion pour vérifier si l’événement mouseover a été appelé correctement. Actuellement, le message d’erreur suivant s’affiche: “Erreur: on s’attend à ce qu’il ait été appelé au moins une fois, mais il n’a jamais été appelé”. Une partie de la confusion de ma part tient aux différences entre les sélecteurs d3 et jQuery. Je suis ravi d’utiliser ce dernier, mais je ne suis pas sûr de savoir comment utiliser correctement le premier dans un test pour obtenir le résultat souhaité.

Mes dépendances sont d3, jQuery, mocha, chai, sinon et sinon-chai.

Code pertinent de mon fichier index.html,

 
mocha.ui('bdd'); mocha.reporter('html'); var expect = chai.expect; mocha.run();

fixtures.js,

 var path = svg.selectAll("path") .data(pie(data)) .enter().append("path").attr("class", "path") .style("fill", function(d, i) { return color(i); }) .attr("d", arc) .on("mouseover", function() { d3.select(this).style("fill", "#ff0000"); }) .on("mouseout" , function() { d3.selectAll("path").style("fill", function(d, i) { return color(i); }); }); // I wanted to test my understanding of d3 selectors var path_one = d3.select('.path').attr("id", "path_one"); 

tests.js,

 describe('Donut Chart', function() { describe("Mouseover events", function() { it("should call on('mouseover')", function () { var spy = sinon.spy(path, "on"); $('path').mouseenter(); sinon.assert.called(spy); }); }); }); 

Il y a quelques problèmes ici; nous pouvons régler votre syntaxe, mais nous devons également déterminer l’intention.

Le message d’erreur “Erreur: on s’attend on qu’il ait été appelé au moins une fois mais n’a jamais été appelé” est exact. on n’est pas appelé pendant votre test . Il est uniquement appelé dans vos rencontres, pour configurer les gestionnaires d’événements. Vous déclenchez également un événement mouseenter mais vos écouteurs sont pour mouseover et mouseout . Dans le monde réel, vous obtiendrez un mouseover très rapidement après un événement mouseenter , mais cela ne se produira pas si vous le mouseenter avec jQuery. jQuery est un non-starter de toute façon; voir ci-dessous.


Vous pouvez essayer de résoudre ce problème en remplaçant les fonctions anonymes par un nom nommé, comme ceci:

 var mouseOverHandler = function() { d3.select(this).style('fill', '#ff0000'); }; 

Et liez-le ensuite à votre path avec path.on('mouseover', mouseOverHandler) . Vous pourriez penser que vous pouvez maintenant espionner mouseOverHandler , mais cela ne fonctionnera pas non plus . Votre fonction sera liée lorsque vous appelez, donc l’échanger pour un espion Sinon sinon n’aura aucun effet.

Le déclenchement de jQuery ne fonctionnera pas avec D3

Un autre problème est que vous ne pouvez pas utiliser jQuery pour déclencher des événements D3 car les événements jQuery ne sont pas des événements DOM . Vous devez donc remplacer votre appel à $('path').mouseenter() par quelque chose comme document.getElementById('path_one').dispatchEvent(new MouseEvent('mouseover')); (En notant que cela modifie le code de “déclencheur mouseenter sur tous les chemins” en “déclencheur au mouseover de la mouseover sur l’élément portant l’id path_one “).

Tester la mauvaise chose

Vous pouvez utiliser la refactorisation pour échanger votre rappel avec quelque chose que vous pouvez espionner, mais vous testez fondamentalement la mauvaise chose. Essentiellement, vous essayez d’écrire un test pour D3; “Lorsque j’ajoute un écouteur d’événement, assurez-vous que cet écouteur est appelé.” Au lieu de cela, vous devriez tester le comportement de votre code actuel: “Quand quelqu’un passe la souris sur le graphique, sa couleur devrait changer”.

Si vous voulez vraiment affirmer que votre gestionnaire d’événements est lié, vous pouvez le faire:

 expect(path.on('mouseover')).to.be.a('function') 

Mais si vous voulez vous assurer que votre couleur est modifiée, vous voulez que votre test soit comme suit:

 describe("Mouseover events", function() { it("should update the colours when a user mouses over the paths", function () { var oldColor = path.style('fill'); document.getElementById('path_one').dispatchEvent(new MouseEvent('mouseover')); expect(path.style('fill')).to.not.equal(oldColor); }); });