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.
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
“).
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); }); });