4

私は数週間前に JavaScript の世界に飛び込みました。私は Angular を使用しており、Karma と Jasmine でコードをテストしています。テストに問題がある角度ディレクティブがあります。

ボックスで使用するための角度ディレクティブがあり<input>ます。このディレクティブは入力ボックスを変更して、数値のみを入力として受け入れるようにします。コードの簡略版は次のとおりです。

var testDirective = angular.module('testDirectiveApp', []);

testDirective.directive('numberOnly', function() {
    return {
      restrict: 'A',
      link: function (scope, element) {
        element.on('keydown', function (event) {
          var k = event.keyCode;
          if (48 <= k && k <= 57) {
            return true;
          }
          event.preventDefault();
          return false;
        });
      }
    };
  });

次のようにhtmlで使用します。

<div>
    Numbers only: <input number-only ng-required="true" 
                  ng-model="myNumber" type="text" maxlength="3" 
                  placeholder="NNN">
</div>

ディレクティブが正しく配線され、数値以外の入力が正常に除外されることをテストしたいと思います。「a1b2c3」と入力すると、入力ボックスには「123」が表示されます。

入力ボックスに文字列を入力し、その後(入力ボックス、角度モデルなどの)値をチェックするさまざまな方法を試しましたが、これまでのところどれもうまくいきませんでした。

次のテストは、私の多くの試行の例です。

describe('numberOnly', function() {
  'use strict';
  var scope, element;

  beforeEach(module('testDirectiveApp'));

  beforeEach(inject(function($compile, $rootScope) {
    scope = $rootScope.$new();
    scope.testInput = "";
    element = angular.element('<input number-only ng-model="testInput" type="text">');
    $compile(element)(scope);
    scope.$digest();
  }));

  it('should accept number input', function() {

    triggerKeyDown(element, 49);

    expect(scope.testInput).toBe("1");
  });

  var triggerKeyDown = function (element, keyCode) {
    var e = $.Event("keydown");
    e.which = keyCode;
    e.keyCode = keyCode;

    $(element).trigger(e);
  };
});

ユーザー入力をシミュレートするために e2e テストを作成することさえ試みました。また、HTML 要素からイベント ハンドラー関数を抽出して、関数の単体テストも試みました。これまでのところ、どれも機能しませんでした。

angularディレクティブをどのようにテストするのが最適ですか?

4

1 に答える 1

0

テストでは、実際にディレクティブ定義オブジェクト (DDO) を挿入し、実際に要素を作成しなくてもリンク関数を直接呼び出すことができます。

Angular では、同じ名前で優先度が異なるディレクティブを追加できます。Angular は、ディレクティブのインジェクタブルを配列の形式で作成します (優先度が複数あるため)。ディレクティブを 1 回だけ宣言すると仮定すると、DDO が配列の最初の DDO であると想定できます。

このコードはテストされていませんが、ほとんどの方法で取得できるはずです。

describe('numberOnly', function() {
  var scope, linkFunction;

  beforeEach(module('testDirectiveApp'));

  beforeEach(inject(function($compile, $rootScope, numberOnlyDirective) {
    scope = $rootScope.$new();
     //get the link function
     linkFunction = numberOnlyDirective[0].link;
   });

it('calls the event', function(){
    //make a mock element that has the 'on' function. 
    var onCallback;
    var mockElement = {
        on: function(eventName, cb){
          expect(eventName).toEqual("keydown");
           //save the callback so we can call it in our test
           onCallback = cb;
        }
    };

    linkFunction(scope, mockElement);
    var preventDefaultWasCalled = false;

    var mockEvent = {
        which: 1,
        keyCode: 1,
        preventDefault: function(){
           preventDefaultWasCalled = true;
        }
    };
    //trigger the 'keydown' event by calling the callback
    onCallback(mockEvent);
    expect(preventDefaultWasCalled).toEqual(true);
});
于 2016-05-20T13:04:23.037 に答える