web-dev-qa-db-fra.com

Définition de la valeur d'affichage d'un champ de saisie dans un test unitaire d'une directive de formulaire angular

J'ai une directive qui construit un formulaire:

app.directive('config', function() {
  return {
    restrict: 'E',
    scope: {
      data: '='
    },
    template: '<form name="configForm">' +
      '<input type="number" max="10" ng-model="config.item" name="configItem"/>' +
      '<div class="form-error" ng-show="configForm.$error.max">Error</div>' + 
      '</form>',
    controller: 'ConfigDirectiveController',
  };
});

Ce que je veux faire, c'est valider via un test unitaire que le message d'erreur apparaîtra en fonction de certaines entrées. Avec angular 1.2, je pouvais modifier $ scope.config.item et cela mettrait à jour la valeur de la vue et afficherait l'erreur.

Pour autant que je sache, avec angular 1.3, si le modèle ne passe pas la validation, la valeur de la vue n'est pas mise à jour ... donc je dois modifier la valeur de la vue pour m'assurer que l'erreur s'affiche.

Comment puis-je accéder à l'entrée "configItem" afin de pouvoir définir la valeur de la vue pour garantir que le message d'erreur s'affiche?

Modifié pour afficher le test unitaire

Je vois que la valeur est définie correctement, mais l'erreur a toujours un ng-hide appliqué à la balise. Lorsque je consulte la page et que je modifie manuellement la valeur d'entrée, le ng-hide sera supprimé et l'erreur s'affichera si j'entre quelque chose de plus de 10.

  beforeEach(inject(function($compile, $rootScope) {
      element = angular.element('<config data="myData"></config>');
      $scope = $rootScope.$new();
      $scope.myData = {};
      element = $compile(element)($scope);
    }));

    it('should warn that we have a large number', function() {
      var input = element.find('[name="configItem"]')[0];
      $scope.$apply(function() {
        angular.element(input).val('9000000001');
      });
      errors = element.find('[class="form-error ng-binding"]');
      expect(errors.length).toBe(1);
    })
34
nathasm

Voici comment j'ai testé unitairement mes directives basées sur les entrées (Beaucoup de code omis pour plus de clarté!) La ligne importante que vous recherchez est la suivante:

angular.element(dirElementInput).val('Some text').trigger('input');

Voici le test unitaire complet:

  it('Should show a red cross when invalid', function () {

    dirElement = angular.element('<ng-form name="dummyForm"><my-text-entry ng-model="name"></my-text-entry></ng-form>');

    compile(dirElement)(scope);
    scope.$digest();

    // Find the input control: 
    var dirElementInput = dirElement.find('input');

    // Set some text!
    angular.element(dirElementInput).val('Some text').trigger('input');
    scope.$apply();

    // Check the outcome is what you expect! (in my case, that a specific class has been applied)
    expect(dirElementInput.hasClass('ng-valid')).toEqual(true);
  });
63
Ben Heymink

La réponse précédente est correcte si vous utilisez Angular avec jQuery mais pour Angular sans jQuery (utilisant jqlite), vous pouvez utiliser triggerHandler à la place ( voir ici pour l'API complète)

it('foos to the bar', function() {
  el.val('Foo').triggerHandler('input');

  // Assuming el is bound to scope.something using ng-model ...
  expect(scope.something).toBe('Foo');
});
31
OrganicPanda