Comment former les angulaires de forme unitaire?

J'ai appris AngularJS et les choses se sont passées assez bien en ce qui concerne les tests unitaires, mais j'ai atteint un point délicat.

Supposons que j'ai une forme 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 j'écrirais quelque chose comme ça (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 de chance de trouver des documents sur les tests unitaires dans le guide des forms ou dans la documentation ng-form .

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

Je ne suis pas convaincu que ce soit la meilleure façon de tester quelque chose comme ça, mais avec une aide de cette réponse pour tester des directives angulaires personnalisées et des expérimentations, j'ai trouvé un moyen de tester le formulaire.

Après avoir installé karma-ng-html2js-preprocessor et configuré, j'ai réussi à obtenir une unité de travail comme ceci:

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

Je suppose que je peux ajouter des détails à la réponse acceptée: karma-ng-html2js-preprocessor doit ê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" ] 

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

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

Sinon, si vous utilisez WebPack avec karma-webpack – vous pouvez inclure le modèle avec le 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>