5

ディレクティブ付きの通常の角度アプリがあります。このディレクティブには、呼び出しを持つ要素が含まれていng-click="clickFunction()"ます。その要素をクリックすると、すべてうまくいきます。このクリックのテストを作成し、要素がクリックされたときにこの関数が実際に実行されたことを確認する必要があります。これが問題です。

これが私の問題を説明するためのjsfiddleです: http://jsfiddle.net/miphe/v0ged3vb/

コントローラーには、clickFunction()クリック時に呼び出される関数が含まれています。単体テストは、ディレクティブの要素のクリックを模倣して、その関数の呼び出しをトリガーする必要があります。

clickFunction呼び出されたかどうかを確認できるように、sinonjs でモックされています。そのテストは失敗しました。つまり、クリックがありませんでした。

ここで何が間違っていますか?

Testing JavaScript Click Event with Sinonのような同様の質問に対する回答を見てきましたが、完全な jQuery を使用したくありません。正しい関数をモック (スパイ) していると思います。


上記のフィドルの js は次のとおりです (ここで確認したい場合)。

angular.jsangular-mocks.js同様に読み込まれます。

// App
var myApp = angular.module('myApp',[]);

myApp.controller('MyCtrl', function($scope) {
    $scope.person = 'Mr';
    $scope.clickFunction = function() {
        // Some important functionality
    };
});

myApp.directive('pers', function() {
    return {
        restrict: 'E',
        template: '<h2 ng-click="clickFunction()" ng-model="person">Person</h2>',
    };
});

// Test suite
describe('Pers directive', function() {
    var $scope, $controller, template = '<pers></pers>', compiled;
    beforeEach(module('myApp'));

    beforeEach(inject(function($rootScope, $controller, $compile) {
        $scope = $rootScope.$new();
        ctrl = $controller('MyCtrl', {$scope: $scope});
        compiled = $compile(template)($scope);

        // Do I need to run a $scope.$apply() here?
        console.log($scope.$apply); // This is a function, apparently.
        //$scope.$apply();            // But running it breaks this function.
    })); 

    it('should render directive', function() {
        el = compiled.find('h2');
        expect(el.length).to.equal(1);
    });

    it('should run clickFunction() when clicked', function() {
        el = compiled.find('h2');
        sinon.spy($scope, 'clickFunction');

        // Here's the problem! How can I trigger a click?
        //el.trigger('click');
        //el.triggerHandler('click');
        expect($scope.clickFunction.calledOnce).to.be.true
    });
});

// Run tests
mocha.run();
4

1 に答える 1

7

問題はかなり隠されていました。

まず、関数$scope.$digest$scope.$apply関数が関数を壊し、beforeEach最終的にソリューション全体につながりました。

解決

角度のあるバージョンを混在させないでください。

  • 最初のフィドル
    • angular.jsバージョン 1.3.0
    • angular-mocks.jsバージョン 1.1.5
  • 解決されたフィドルで
    • angular.jsバージョン 1.3.0
    • angular-mocks.jsバージョン 1.3.0

それが全体の問題であり、非常にあいまいなエラーが発生しました。

freenode の #AngularJS IRC チャンネルの Foxandxss に感謝します。


jQlite を使用してディレクティブでイベントをトリガーする方法は次のとおりです。

someElement.triggerHandler('click');

于 2014-11-03T14:26:54.320 に答える