web-dev-qa-db-fra.com

Comment tester le comportement dans la fonction de lien d'une directive

Dans certaines de mes directives, j'ajoute des fonctions à la portée afin de gérer la logique propre à la directive. Par exemple:

link: function(scope, element, attrs) {
         scope.doStuff = function() {
            //do a bunch of stuff I want to test
         }        
      }

Comment puis-je tester cette fonction? J'ai cherché sur Google comment tester une directive, mais les choses que j'ai trouvées étaient plutôt sur le test des modifications apportées à l'élément. Je peux certainement compiler ma directive avant chacun de mes tests, mais cela effacerait mon champ d'application à chaque fois. Je souhaite tester la fonction en tant que propriétés de ma portée.

Existe-t-il un moyen de récupérer l'objet renvoyé par la définition de directive? Ensuite, je pourrais simplement appeler la fonction de lien directement et tester le comportement de chacune des fonctions définies dans le scope. Y a-t-il une meilleure façon de faire tout cela?

J'utilise Jasmine pour exécuter mes tests et je souhaite configurer mon étendue dans les fonctions describe afin de pouvoir disposer de plusieurs fonctions it pour les mêmes données d'étendue.

45
dnc253

Fondamentalement, plutôt que de tester la fonction de liaison elle-même, vous testez le résultat de la directive par programmation. Ce que vous feriez, c’est d’écrire la directive en chaîne et d’utiliser $compile pour la traiter de manière angulaire. Ensuite, vous testez la sortie pour vous assurer que tout est câblé correctement.

La source d'angular regorge de bons exemples sur la façon de le faire ... par exemple Test de la directive ngRepeat par Angular

Vous pouvez voir ce qu'ils sont en train de configurer la directive, Modification de la portée (dans ce cas, $rootScope) en s'assurant que c'est $digested, puis testez le DOM qu'il génère pour vous assurer que tout est correctement câblé. Vous pouvez également tester le contenu de la portée, si la directive modifie cela.

Le test pour ngClick est également très intéressant, car il montre le test d’une interaction de navigateur et son effet sur la portée.

Par souci d'exhaustivité, voici un extrait des tests ngClick qui résume assez bien le test d'une directive:

 it('should get called on a click', inject(function($rootScope, $compile) {
   element = $compile('<div ng-click="clicked = true"></div>')($rootScope);
   $rootScope.$digest();
   expect($rootScope.clicked).toBeFalsy();

   browserTrigger(element, 'click');
   expect($rootScope.clicked).toEqual(true);
 }));

Donc, dans le cas de votre fonction scope.doStuff, je ne testerais pas ce que c'est doing, mais plutôt ce qui est affecté dans l'étendue, puis les éléments DOM affectés.

44
Ben Lesh

Si nécessaire, il est possible de tester directement la méthode de liaison d'une directive par unité. Voir le testeur d'unité du module de glace angulaire: "test d'une configuration de directive".

http://bverbist.github.io/angular-ice/#/unitTester

exemple d'utilisation: https://github.com/bverbist/angular-ice/blob/master/app/components/icebank/bank-account-number-directive_link_test.js

Dans votre cas, vous pouvez conserver une référence à l'objet de portée que vous transmettez à la méthode link de la directive, puis vous pouvez directement tester la fonction doStuff sur cette portée.

1
bverbist
 it('should get called on a click', inject(function($rootScope, $compile) {
   var scope = $rootScope.$new();
   element = $compile('<div ng-click="doIt()"></div>')(scope);
   scope.$digest();
   expect(scope.$$childHead.doIt()).toBeDefined();
 }));

Utiliser ce $$ childHead était pour moi la solution au même problème. Je pouvais ainsi couvrir des fonctions qui n'étaient pas appelées dans mes tests.

0
Leonardo Berteotti