web-dev-qa-db-ja.com

angularjsフォームの単体テスト方法は?

私はAngularJSを学んでおり、ユニットテストに関しては順調に進んでいますが、少し注意が必要な点に到達しました。

たとえば、単純なフォームがあるとします。

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

私がコントローラーのようなものをテストしていた場合、私はそれを次のように書くことを知っています(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();
});

しかし、どのサービスを投入する必要があるのか​​分かりません。また、 formsガイド または the ng-formドキュメント

1つのユニットは、Angularでフォームをどのようにテストしますか?

19
NT3RP

私はこれがこのようなものを単体テストする最良の方法であるとは確信していませんが、 カスタムカスタムangularディレクティブ およびいくつかの実験のテストに関するこの回答で、私は考えましたフォームを単体テストする方法を探します。

インストール後 karma-ng-html2js-preprocessor そしてそれを設定すると、次のように動作する単体テストを取得できました。

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

私は受け入れられた答えにいくつかの詳細を追加できると思います:karma-ng-html2js-preprocessorは同様の方法でkarma.conf.jsファイルで設定する必要があります:

//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.

コントローラのテンプレートをコンパイルせずにangularフォームで単体テストを行う方法を以下に示します。私の限られた使用法でうまく機能します。

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

または、karma-webpackWebPack を使用している場合は、karma-ng-html2js-preprocessorパッケージを必要とせずに、requireでテンプレートを含めることができます。

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