2016-09-20 48 views
0

我有一個我試圖測試的鍵盤快捷鍵指令。它的目的是用事件數據觸發$rootScope.$broadcast()。在應用程序中它沒有任何問題,但我無法得到這個測試測試通過儘可能徹底,因爲我想。

(function(){ 
    'use strict'; 

    angular 
     .module('app.common') 
     .directive('keyboardShortcuts', keyboardShortcuts); 

    // @ngInject 
    function keyboardShortcuts($document, $rootScope){ 
     return { 
      restrict: 'A', 
      link 
     } 

     function link(scope, el, attrs){ 
      $document.bind('keypress', event => { 
       console.log('detected keypress'); 
       $rootScope.$broadcast('keyboardShortcut', event); 

       scope.$digest(); // seems to make no difference 
      }); 
     } 
    } 

})(); 

對於單元測試,我添加了一個$scope.$on處理程序來表明廣播實際上是被製成,聽了,但由於某種原因間諜沒有做它的工作。

describe('KeyboardShortcuts Directive', function(){ 
    'use strict'; 

    let $element; 
    let $scope; 
    let vm; 
    let $document; 
    let $rootScope; 

    const mockKeyboardEvent = { 
     type: 'keypress', 
     bubbles: true, 
     altKey: false, 
     ctrlKey: false, 
     shiftKey: false, 
     which: 106 
    } 

    beforeEach(module('app.common')); 

    beforeEach(inject(function(_$rootScope_, $compile, _$document_){ 
     $element = angular.element('<div keyboard-shortcuts></div>'); 
     $rootScope = _$rootScope_.$new(); 
     $document = _$document_; 

     $scope = $rootScope.$new(); 
     $compile($element)($scope); 
     $scope.$digest(); 

     spyOn($rootScope, '$broadcast'); 
    })); 

    //////////// 

    it('should broadcast when a key is pressed', function(){ 
     $scope.$on('keyboardShortcut', (event, data) => { 
      console.log('wtf!?'); 
      expect(data.which).toBe(106); 
     }); 

     $document.triggerHandler(mockKeyboardEvent); 

     $scope.$digest(); // seems to make no difference 

     expect($rootScope.$broadcast).toHaveBeenCalled(); 
    }); 
}); 

這裏是控制檯輸出。你可以看到代碼看起來在工作。

[15:33:57] Starting 'build:common:js'... 
[15:33:58] Finished 'build:common:js' after 227 ms 
[15:33:58] Starting 'test:common'... 
20 09 2016 15:33:58.250:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/ 
20 09 2016 15:33:58.250:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency 
20 09 2016 15:33:58.253:INFO [launcher]: Starting browser PhantomJS 
20 09 2016 15:33:58.797:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#37Fv2zndO5Z6XAZ8AAAg with id 3035140 
.. 
LOG: 'detected keypress' 
LOG: 'wtf!?' 
PhantomJS 2.1.1 (Mac OS X 0.0.0) KeyboardShortcuts Directive should broadcast when a key is pressed FAILED 
    Expected spy $broadcast to have been called. 

以前在單元測試控制器的時候,我也遇到過這樣的麻煩。我試圖監視在activate()方法中運行的方法,該方法立即運行(Papa樣式),通過將spyOn(...)方法放在控制器實例化的以上,我能夠讓我的間諜工作。在這種情況下,我試圖把我的spyOn放在'beforeEach'之前的各種地方,沒有任何東西似乎有所作爲。

我也試圖把expect..broadcast..beenCalled()東西$on處理器內的明顯的解決方案,但沒有任何工作,即使是主張通過和佔總證明一個作出廣播。

我有種感覺,被窺探的$ rootScope與被注入和工作的$ rootScope是不一樣的,但我不知道這是怎麼回事。

回答

0

正確的變量命名很重要。

$rootScope = _$rootScope_.$new(); 

是在角單元測試廣泛傳播的錯誤之一。

問題是,被稱爲$rootScope的東西只是子作用域,而不是根作用域。看來,很容易忘記這一點,所以

spyOn($rootScope, '$broadcast'); 

存根$broadcast方法在某些範圍。

應該

$rootScope = _$rootScope_; 
    $scope = $rootScope.$new(); 

而且

$scope.$digest(); // seems to make no difference 

應該不會有因爲jQuery/jqLit​​e事件是不依賴於消化週期。

+0

更改'$ rootScope = _ $ rootScope_.new()'似乎已經成功了。我在另一項測試中遇到了一些問題,但沒有這樣做,所以這就是爲什麼我保持這種模式。看來我必須再次檢查那些測試。謝謝! – coblr

+0

當然,不客氣。 – estus

相關問題