1. ホーム
  2. javascript

[解決済み] AngularJSで孤立したスコープディレクティブをユニットテストする方法

2023-07-07 01:47:28

質問

AngularJSで孤立したスコープをユニットテストする良い方法は何でしょうか?

ユニットテストを示すJSFiddle

ディレクティブのスニペット

    scope: {name: '=myGreet'},
    link: function (scope, element, attrs) {
        //show the initial state
        greet(element, scope[attrs.myGreet]);

        //listen for changes in the model
        scope.$watch(attrs.myGreet, function (name) {
            greet(element, name);
        });
    }

ディレクティブが変更に対してリスニングしていることを確認したい - これは ではなく で動作しません。

    it('should watch for changes in the model', function () {
        var elm;
        //arrange
        spyOn(scope, '$watch');
        //act
        elm = compile(validHTML)(scope);
        //assert
        expect(scope.$watch.callCount).toBe(1);
        expect(scope.$watch).toHaveBeenCalledWith('name', jasmine.any(Function));
    });

UPDATEです。 期待されるウォッチャーが子スコープに追加されているかどうかをチェックすることで動作するようになりましたが、非常にもろく、おそらく文書化されていない方法でアクセサを使用しています(別名、予告なしに変更される可能性があります!)。

//this is super brittle, is there a better way!?
elm = compile(validHTML)(scope);
expect(elm.scope().$$watchers[0].exp).toBe('name');

アップデイト2です。 私が言及したように、これは脆いです! このアイデアはまだ動作しますが、AngularJSの新しいバージョンでは、アクセッサが scope() から isolateScope() :

//this is STILL super brittle, is there a better way!?
elm = compile(validHTML)(scope);                       
expect(elm.isolateScope().$$watchers[0].exp).toBe('name');

どのように解決するのですか?

参照 angular要素apiドキュメント . もし 要素.scope() を使うと、ディレクティブの scope プロパティで定義した要素のスコープを取得します。もし 要素.isolateScope() を使用すると、分離されたスコープ全体を取得します。 例えば、あなたのディレクティブが次のようなものであったとします。

scope : {
 myScopeThingy : '='
},
controller : function($scope){
 $scope.myIsolatedThingy = 'some value';
}

そうすると、テストの中でelement.scope()を呼び出すと、以下のようになります。

{ myScopeThingy : 'whatever value this is bound to' }

しかし、element.isolateScope()を呼ぶと、次のようになります。

{ 
  myScopeThingy : 'whatever value this is bound to', 
  myIsolatedThingy : 'some value'
}

これはangular 1.2.2か1.2.3時点のもので、正確にはわかりません。 以前のバージョンでは、element.scope()しかありませんでした。