web-dev-qa-db-fra.com

Comment tester à l'unité la forme angularjs?

J'ai appris AngularJS et les choses se passent plutôt bien pour les tests unitaires, mais j'ai atteint un point délicat.

Supposons que j'ai un formulaire simple, par exemple:

<form name="form">
    <input type="text" name="number" ng-pattern="/^d+$/">
</form>

Si je testais quelque chose comme un contrôleur, je sais que je l'écrirais comme ceci (en utilisant Jasmine + Karma):

beforeEach(module('some.module'));

beforeEach(inject(/* services */) {
    /* inject necessary services */
});

it('should be invalid when given bad input', function () {
    form.number = 'Not a number';
    expect(form.number.$valid).toBeFalsy();
    expect(form.$valid).toBeFalsy();
});

Mais je ne sais pas quels services je dois injecter et je n'ai pas eu la chance de trouver de la documentation sur les tests unitaires dans the forms guide ou the ng-form documentation .

Comment une unité teste-t-elle un formulaire en forme angulaire?

17
NT3RP

Je ne suis pas convaincu que ce soit la meilleure façon de tester un élément de ce type, mais avec l'aide de cette réponse sur le test de directives angulaires personnalisées et quelques expériences, j'ai trouvé un moyen de tester le formulaire à l'unité.

Après avoir installé karma-ng-html2js-preprocessor et l'avoir configuré, j'ai réussi à obtenir un test unitaire comme celui-ci:

var scope, form;

beforeEach(function() {
  module('my-module');
  module('templates');
});

beforeEach(inject($rootScope, $controller, $templateCache, $compile) {
    scope = $rootScope.$new()

    ctrl = $controller('MyController'), {
        "$scope": scope
    }

    templateHtml = $templateCache.get('path/to/my/template.html')
    formElem = angular.element("<div>" + templateHtml + "</div>")
    $compile(formElem)(scope)
    form = scope.form

    scope.$apply()
}

it('should not allow an invalid `width`', function() {
  expect(form.$valid).toBeTruthy();
  form.number.$setViewValue('BANANA');
  expect(form.number.$valid).toBeFalsy()
});
23
NT3RP

Je suppose que je peux ajouter quelques détails à la réponse acceptée: karma-ng-html2js-préprocessor devrait être configuré dans le fichier karma.conf.js de la même manière:

//karma.conf.js
ngHtml2JsPreprocessor: { 
    moduleName: 'templates'
},
files: [
    //... other files
    //my templates 
    'app/**/*.html'
],
preprocessors: {
    'app/**/*.html': ['ng-html2js']
}, 
plugins: [
    //... other plugins
    "karma-ng-html2js-preprocessor"
]
4
andrea.spot.

Voici un moyen de tester les unités avec une forme angulaire sans avoir à compiler le modèle d'un contrôleur Fonctionne bien pour moi dans mon utilisation limitée.

describe('Test', function() {

  var $scope, fooController;

  beforeEach(function($rootScope, $controller, formDirective) {

    $scope = $rootScope.$new();
    fooController = $controller('fooController', {$scope: $scope});

    // we manually create the form controller
    fooController.form = $controller(formDirective[0].controller, {
      $scope: $scope,
      $element: angular.element("<form></form>"),
      $attrs: {}
    });

  });

  it('should test something', function() {
    expect(fooController.form.$valid).toBeFalsy();
  });

});
1
ssmith

Si vous utilisez WebPack avec karma-webpack -, vous pouvez également inclure le modèle avec require, sans avoir besoin du package karma-ng-html2js-preprocessor:

describe("MyCtrl's form", function () {
    var $scope,
        MyCtrl;

    beforeEach(angular.mock.module("my.module"));

    beforeEach(inject(function (_$rootScope_, _$controller_, _$compile_) {
        $scope = _$rootScope_.$new();

        // Execute the controller's logic
        // Omit the ' as vm' suffix if you are not using controllerAs
        MyCtrl = _$controller_("MyCtrl as vm", { $scope: $scope });

        // Compile the template against our scope to populate form variables
        var html = require("./my.template.html"),
            template = angular.element(html);

        _$compile_(template)($scope);
    }));

    it('should be invalid when given bad input', function () {
        MyCtrl.form.number.$setViewValue('Not a number');
        expect(MyCtrl.form.number.$valid).toBeFalsy();
        expect(MyCtrl.form.$valid).toBeFalsy();
    });
});

HTML:

<form name="vm.form">
    <input type="text" name="number" ng-pattern="/^d+$/">
</form>
1
Jonas Masalskis