javascript - online - Cómo probar el comportamiento en la función de enlace de una directiva.
javascript online console (5)
En algunas de mis directivas, estoy agregando funciones al ámbito para manejar la lógica específica de la directiva. Por ejemplo:
link: function(scope, element, attrs) {
scope.doStuff = function() {
//do a bunch of stuff I want to test
}
}
¿Cómo hago para probar esa función? Busqué en Google para ver cómo probar una directiva, pero lo que encontré fue más sobre probar cambios en el elemento. Ciertamente puedo compilar mi directiva antes de cada una de mis pruebas, pero eso eliminaría mi alcance cada vez. Quiero probar la función ya que las propiedades en mi alcance cambian.
¿Hay alguna forma de obtener una retención del objeto que se devuelve de la definición de la directiva? Entonces podría simplemente llamar directamente a la función de enlace y probar el comportamiento de cada una de las funciones definidas en el alcance. ¿Hay una mejor manera de hacer todo esto?
Estoy usando Jasmine para ejecutar mis pruebas, y deseo que mi alcance esté configurado en las funciones de describe
, por lo que puedo tener múltiples funciones para los mismos datos de alcance.
Básicamente, en lugar de probar la función de enlace en sí, probaría los resultados de la directiva mediante programación. Lo que haría es escribir la directiva en una cadena y usar $compile
para procesarla angularmente. Luego, prueba la salida para asegurarse de que todo esté conectado correctamente.
La fuente de Angular está llena de buenos ejemplos de cómo hacer esto ... por ejemplo, la prueba de Angular de la directiva ngRepeat
Puede ver lo que están haciendo al configurar la directiva, Cambiar el alcance (en este caso $rootScope
) asegurándose de que sea $digest
ed, y luego probar el DOM que genera para asegurarse de que todo esté conectado correctamente. También puede probar lo que está en el alcance, si la directiva lo está modificando.
La prueba para ngClick también es bastante interesante, ya que muestra las pruebas de la interacción de un navegador y su efecto en el alcance.
Para completar, aquí hay un fragmento de las pruebas ngClick que creo que resume una directiva bastante bien:
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);
}));
Por lo tanto, en el caso de su función scope.doStuff
, no probaría lo que está haciendo , sino que probaría lo que sea que esté afectado en el alcance, y posteriormente se verán afectados los elementos DOM.
Como se indica en una respuesta de comentario a @sqlexception. Simplemente necesita controlar el alcance de la directiva, lo que no es difícil de hacer. Lo que no desea hacer es modificar su código para satisfacer sus pruebas, como debería ser al revés.
Para obtener el alcance de la directiva simplemente compile así:
var element = $compile(<directive''s html>).($scope)
donde $scope
se declara con $scope = $rootScrope.$new()
. Ahora podemos obtener el ámbito de aislamiento haciendo element.scope()
Hace poco escribí una breve entrada de blog sobre esto, que se encuentra aquí Probando una función de enlace con un plunker para ayudar:
Resolví este problema un poco diferente.
Si tiene una función de enlace muy simple en su directiva y no necesita el tercer argumento ( attrs ), simplemente deshágase de la función de enlace y asigne un controlador a la directiva.
app.directive(''loadIndicator'', function() {
return {
restrict: ''E'',
replace: true,
templateUrl: ''blahblah/indicator.html'',
controller: ''LoadIndicatorController''
};
});
Al igual que tiene argumentos para el alcance y el elemento en la función de enlace de una directiva, estos 2 argumentos se pueden inyectar en un controlador fácil de probar como $ scope y $ element .
Si eres capaz de crear controladores y unidades de prueba de esos controladores, entonces esto será realmente fácil de hacer.
Si es necesario, es posible probar directamente el método de enlace de una directiva. Ver el comprobador de unidades del módulo de hielo angular: "probar una configuración directiva"
http://bverbist.github.io/angular-ice/#/unitTester
ejemplo de uso: https://github.com/bverbist/angular-ice/blob/master/app/components/icebank/bank-account-number-directive_link_test.js
En su caso, puede mantener una referencia al objeto de alcance que pase al método de enlace de la directiva, y luego puede probar directamente la función doStuff en ese alcance.
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();
}));
El uso de este $$ childHead fue la solución para mí para el mismo problema, con esto puedo cubrir funciones que no estaban siendo llamadas en mis pruebas.