webentwicklung-frage-antwort-db.com.de

So testen Sie eine benutzerdefinierte Validierungs-AngularJS-Direktive

Diese benutzerdefinierte Validierungsanweisung ist ein Beispiel, das auf der offiziellen angular site. http://docs.angularjs.org/guide/forms angegeben ist Zahlenformat oder nicht.

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

Um diesen Code zu testen, habe ich Folgendes geschrieben:

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

Dann bekomme ich diesen Fehler:

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

Ich setze überall print-Anweisungen ein, um zu sehen, was los ist, und es sieht so aus, als würde die Direktive niemals aufgerufen. Was ist ein geeigneter Weg, um eine einfache Anweisung wie diese zu testen?

75
ghiden

Die Tests der anderen Antwort sollten wie folgt geschrieben werden:

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

Beachten Sie, dass $scope.$digest() jetzt nach $setViewValue Aufgerufen wird. Dies versetzt das Formular in einen "schmutzigen" Zustand, andernfalls würde es "makellos" bleiben, was wahrscheinlich nicht das ist, was Sie wollen.

85
jrief

Ich habe es durch Lesen des Angular-App-Codes herausgefunden https://github.com/angular-app/angular-app Dieses Video hilft auch http://youtu.be/ZhfUv0spHCY) t = 31m17s

Zwei Fehler, die ich gemacht habe:

  • Binden Sie sich nicht direkt an das Zielfernrohr, wenn Sie ng-model ausführen
  • Verwenden Sie den Formular-Controller, um direkt zu ändern, was als Direktiven übergeben werden soll

Hier ist die aktualisierte Version. Die Direktive ist die gleiche, nur der Test, den ich geändert habe.

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);
    });
  });
});
67
ghiden

Ich teste meine benutzerdefinierten Anweisungen und suche im Objekt "$ error" den Namen der benutzerdefinierten Überprüfung. Beispiel:

  '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)
  }));
});

Ich hoffe ich kann dir helfen!

2
EricdRose Lotso