9

問題

ディレクティブをテストしています。ディレクティブにはスコープ変数の監視がありますが、監視は呼び出されません。呼び出しを単体テスト$watch内に直接配置すると機能します。$watchディレクティブの が呼び出されないのはなぜですか?

ありがとう!

詳細

これが私のオリジナルのテストです。ディレクティブには、 を見て、時計が含まれてい'reEvalCreateDate'ます。呼び出されることはなく、日付文字列は常に空です。

ウォッチステートメントを含まないテスト

it('should inject a date string', function()
    {


        scope.reEvalCreateDate = reEvalCreateDateAsNumber;

        expect(elm.text()).toBe('');

        scope.$digest();

        expect(elm.text()).toBe(new Date(reEvalCreateDateAsNumber).toUTCString());


    });

テストとして、時計を単体テストに入れました。正しく呼び出され、テストに合格します。

ソース (時計自体をテストに入れるように変更)

it('should inject a date string', function()
    {

        scope.$watch('reEvalCreateDate', function(newValue, oldValue)
        {
            var date = new Date(newValue);
            scope.dateString = date.toUTCString();

            dump(scope.dateString)
        });

        scope.reEvalCreateDate = reEvalCreateDateAsNumber;

        expect(elm.text()).toBe('');

        scope.$digest();

        expect(elm.text()).toBe(new Date(reEvalCreateDateAsNumber).toUTCString()); //This passes!


    });

ディレクティブ ソース コード

これは、watch ステートメントを含むディレクティブ コードです。

link: function(scope, element, attrs)
            {
                scope.$watch('show',function(shouldShow){

                    console.log('should show reeval timer? ' + shouldShow);
                    if(shouldShow) {
                        $(element).fadeIn('slow');
                    }
                    else if(shouldShow === false){
                        $(element).fadeOut('slow');
                    }

                });

//this statement's never called when testing!!
                scope.$watch('reEvalCreateDate', function(newValue, oldValue)
                {
                    var date = new Date(newValue);
                    scope.dateString = date.toUTCString();
                });

            }

セットアップコード

テスト用のすべての初期化コードは次のとおりです。

var elm, scope;

var reEvalCreateDateAsNumber = 1359487598000;

beforeEach(inject(function($rootScope, $compile)
{
    // we might move this tpl into an html file as well...
    elm = angular.element(
        '<reeval-timer show="showTimePopup" re-eval-create-date="reEvalCreateDate" class="re-eval-timer" ng-cloak >' +
            '{{dateString}}' +
            '</reeval-timer>');

    scope = $rootScope.$new();

    $compile(elm)(scope);
    scope.$digest();
}));

アップデート

コメントによると、ディレクティブにスコープを設定しているとは思いません。それを可能にするAPIは何も見当たりません。$compileスコープを設定しようとして、呼び出しのいくつかの順列を試しました。

html から要素を作成し、それをコンパイルに渡します。運がない。

elm = angular.element(
  '<div>' +
    '<tabs>' +
      '<pane title="First Tab">' +
        'first content is {{first}}' +
      '</pane>' +
      '<pane title="Second Tab">' +
        'second content is {{second}}' +
      '</pane>' +
    '</tabs>' +
  '</div>');

scope = $rootScope;
$compile(elm)(scope);

最初に要素を作成することによって

var element = $compile('<p>{{total}}</p>')(scope);

問題がディレクティブにスコープを設定していないということである場合、エラーは mybeforeEachにある可能性が高いと思います。ここにあります:

describe('Reeval Timer', function()
{
    var elm, scope,element;

    var reEvalCreateDateAsNumber = 1359487598000;

    beforeEach(inject(function($rootScope, $compile)
    {
        // we might move this tpl into an html file as well...
        elm = angular.element(
            '<reeval-timer show="showTimePopup" re-eval-create-date="reEvalCreateDate" class="re-eval-timer" ng-cloak >' +
                '</reeval-timer>');

        scope = $rootScope.$new();

        element = $compile(elm.contents())(scope);
        scope.$digest();
    }));

....
4

2 に答える 2

1

私は同じ問題のように見えるものを経験していました。私の場合、ディレクティブにはtemplateUrlハードコードされた ではなくセットがtemplate含まれていたため、単体テストでは、次のように呼び出してモックされた http リクエストも設定する必要がありました。

$httpBackend.expectGET('/template.html').respond('<div></div>');

他のすべてはあなたの例と同じように見え、私の時計は呼び出されていませんでした.

$httpBackend次に、リクエストをモックするために使用するときに思い出しました。次の$httpBackend.flush()ように呼び出す必要があります。

$compile(elem)(scope);
$httpBackend.flush();

フラッシュ コールがヒットするとすぐに、私の時計が呼び出されました。

お役に立てれば....

ジェイソン

于 2013-02-13T17:43:27.213 に答える