2013-03-05 20 views
74

Questa direttiva di convalida personalizzata è un esempio presentato al sito angolare ufficiale. http://docs.angularjs.org/guide/forms Controlla che un input di testo sia in formato numerico o meno.Per testare una direttiva angularjs di convalida personalizzata

var INTEGER_REGEXP = /^\-?\d*$/; 
app.directive('integer', function() { 
    return { 
    require: 'ngModel', 
    link: function(scope, elm, attrs, ctrl) { 
     ctrl.$parsers.unshift(function(viewValue) { 
     if (INTEGER_REGEXP.test(viewValue)) { 
      // it is valid 
      ctrl.$setValidity('integer', true); 
      return viewValue; 
     } else { 
      // it is invalid, return undefined (no model update) 
      ctrl.$setValidity('integer', false); 
      return undefined; 
     } 
     }); 
    } 
    }; 
}); 

Per unità di prova di questo codice, ho scritto questo:

describe('directives', function() { 
    beforeEach(module('exampleDirective')); 

    describe('integer', function() { 
    it('should validate an integer', function() { 
     inject(function($compile, $rootScope) { 
     var element = angular.element(
      '<form name="form">' + 
      '<input ng-model="someNum" name="someNum" integer>' + 
      '</form>' 
     ); 
     $compile(element)($rootScope); 
     $rootScope.$digest(); 
     element.find('input').val(5); 
     expect($rootScope.someNum).toEqual(5); 
     }); 
    }); 
    }); 
}); 

Allora ottengo questo errore:

Expected undefined to equal 5. 
Error: Expected undefined to equal 5. 

ho messo istruzioni di stampa in tutto il mondo per vedere cosa sta succedendo, e sembra che la direttiva non venga mai chiamata. Qual è un modo corretto per testare una direttiva semplice come questa?

+0

Grazie per aver trovato il tempo di riportare una risposta! Solo FYI, puoi estrarre la tua risposta e contrassegnarla come quella accettata per gli utenti successivi, che è accettabile da queste parti ;-) –

+0

Grazie per i tuoi suggerimenti. Ho spostato la mia risposta. – ghiden

risposta

80

test di L'altra risposta dovrebbe essere scritto come:

describe('directives', function() { 
    var $scope, form; 
    beforeEach(module('exampleDirective')); 
    beforeEach(inject(function($compile, $rootScope) { 
    $scope = $rootScope; 
    var element = angular.element(
     '<form name="form">' + 
     '<input ng-model="model.somenum" name="somenum" integer />' + 
     '</form>' 
    ); 
    $scope.model = { somenum: null } 
    $compile(element)($scope); 
    form = $scope.form; 
    })); 

    describe('integer', function() { 
    it('should pass with integer', function() { 
     form.somenum.$setViewValue('3'); 
     $scope.$digest(); 
     expect($scope.model.somenum).toEqual('3'); 
     expect(form.somenum.$valid).toBe(true); 
    }); 
    it('should not pass with string', function() { 
     form.somenum.$setViewValue('a'); 
     $scope.$digest(); 
     expect($scope.model.somenum).toBeUndefined(); 
     expect(form.somenum.$valid).toBe(false); 
    }); 
    }); 
}); 

noti che $scope.$digest() ora viene richiamato dopo $setViewValue. Questo imposta la forma in uno stato "sporco", altrimenti rimarrebbe "incontaminato", che probabilmente non è quello che desideri.

+0

Grazie mille, mi hai aiutato molto oggi! Ma sto usando direttamente il modello di scope piuttosto che '$ setViewValue()', non so se mi mancano molti casi ...? –

67

ho capito leggendo il codice angolare-app https://github.com/angular-app/angular-app Questo video aiuta anche troppo http://youtu.be/ZhfUv0spHCY?t=31m17s

Due errori che ho fatto:

  • non legano direttamente al campo di applicazione quando si sta facendo ng -model
  • Utilizza controllore modulo di manipolare direttamente quanto passare per direttive

Ecco la versione aggiornata. La direttiva è la stessa, solo il test che ho cambiato.

describe('directives', function() { 
    var $scope, form; 
    beforeEach(module('exampleDirective')); 
    beforeEach(inject(function($compile, $rootScope) { 
    $scope = $rootScope; 
    var element = angular.element(
     '<form name="form">' + 
     '<input ng-model="model.somenum" name="somenum" integer />' + 
     '</form>' 
    ); 
    $scope.model = { somenum: null } 
    $compile(element)($scope); 
    $scope.$digest(); 
    form = $scope.form; 
    })); 

    describe('integer', function() { 
    it('should pass with integer', function() { 
     form.somenum.$setViewValue('3'); 
     expect($scope.model.somenum).toEqual('3'); 
     expect(form.somenum.$valid).toBe(true); 
    }); 
    it('should not pass with string', function() { 
     form.somenum.$setViewValue('a'); 
     expect($scope.model.somenum).toBeUndefined(); 
     expect(form.somenum.$valid).toBe(false); 
    }); 
    }); 
}); 
+1

Grazie amico, questo mi ha salvato un giorno;) – luacassus

+0

@ghiden Questo mi ha davvero aiutato, tuttavia, hai mai sperimentato di incatenare più direttive e testarlo? Come se avessi fatto una direttiva per telefono o e-mail? Ricevo un sacco di errori ogni volta che provo e aggiungo una direttiva aggiuntiva. Pensieri? – thescientist

+0

Concatenamento di più direttive? Suppongo che anche se applichi più direttive a un elemento, vuoi comunque testarle separatamente, corretto? Se ognuno funziona correttamente e la priorità è impostata correttamente, suppongo che dovrebbero funzionare. A volte faccio qualcosa di simile alla validazione del modello, quindi procedo con la direttiva sugli effetti visivi con priorità molto bassa. – ghiden

2

Verifica le mie direttive personalizzate cercando nell'oggetto "$ error" il nome della convalida personalizzata. Esempio:

'use strict'; 

describe('Directive: validadorCorreo', function() { 

    // load the directive's module 
    beforeEach(module('sistemaRegistroProCivilApp')); 

    var inputCorreo, formulario, elementoFormulario, scope, $compile; 

    beforeEach(inject(function ($rootScope, _$compile_) { 
    scope = $rootScope.$new(); 
    $compile = _$compile_; 

    elementoFormulario = angular.element('<form name="formulario">' + 
     '<input type="text" name="correo" data-ng-model="correo" required data-validador-correo/>' + 
     '</form'); 
    scope.correo = ''; 
    elementoFormulario = $compile(elementoFormulario)(scope); 
    scope.$digest(); 
    inputCorreo = elementoFormulario.find('input'); 
    formulario = scope.formulario; 
    console.log(formulario.correo.$error); 
    })); 

    it('Deberia Validar si un correo ingresado en el input es correcto e incorrecto', inject(function ($compile) { 

    inputCorreo.val('[email protected]').triggerHandler('input'); 
    expect(formulario.correo.$error.email).toBe(true); //Here, the name of the custom validation appears in the $error object. 
    console.log(formulario.correo.$error); 

    inputCorreo.val('[email protected]').triggerHandler('input'); 
    expect(formulario.correo.$error.email).toBeUndefined();//Here, the name of the custom validation disappears in the $error object. Is Undefined 
    console.log(formulario.correo.$error.email) 
    })); 
}); 

Spero di poterti aiutare!

Problemi correlati