2015-04-23 41 views
5

我有一個基於另一個服務的值顯示/隱藏元素的自定義指令。我試圖創建一個測試,看看指令是否應該做什麼。在開始時,我再次測試了「:可見」選擇器,但即使當我知道該元素實際上正在顯示時,它總是返回錯誤。測試自定義角度指令是否顯示/隱藏元素

it('Should show element if logged', function() { 
    element = angular.element('<p hc-auth>Some Text</p>'); 
    AuthService.Logged = true; 
    scope = $rootScope.$new(); 
    scope.$apply(function() { 
     $compile(element)(scope); 
    }); 
    expect(element.is(":visible")).toBeTruthy(); 
}); 

一些調試之後,我意識到,測試執行期間,該元件具有0寬度和高度即使顯示器設置爲阻斷的,因此在「:可見」選擇器總是返回false。我改變它來檢查顯示選擇器,而現在它正確地測試元素,但這似乎太依賴於如何顯示元素的實現。

it('Should show element if logged', function() { 
    element = angular.element('<p hc-auth>Some Text</p>'); 
    AuthService.Logged = true; 
    scope = $rootScope.$new(); 
    scope.$apply(function() { 
     $compile(element)(scope); 
    }); 
    expect(element.css('display')).toBe('block'); 
}); 

這種情況的最佳方法是什麼?

回答

6

你的問題讓我想測試ngHidengShow如何角,這裏是他們的規範文件中的一個片段:

it('should show if the expression is a function with a no arguments', function() { 
    element = jqLite('<div ng-show="exp"></div>'); 
    element = $compile(element)($scope); 
    $scope.exp = function() {}; 
    $scope.$digest(); 
    expect(element).toBeShown(); 
}); 

看起來整潔。起初我還以爲他們必須使用jquery-jasmine這確實暴露出toBeHidden匹配(雖然不是toBeShown事實證明),實際上他們自己寫了custom matcher確定可視性:

// [jtrussell] Custom Jasmine Matcher 
toBeShown: function() { 
    this.message = valueFn(
     "Expected element " + (this.isNot ? "" : "not ") + "to have 'ng-hide' class"); 
    return !isNgElementHidden(this.actual); 
} 

// [jtrussell] ... 

// [jtrussell] The helper from elsewhere in same file 
function isNgElementHidden(element) { 
    // we need to check element.getAttribute for SVG nodes 
    var hidden = true; 
    forEach(angular.element(element), function(element) { 
    if ((' ' + (element.getAttribute('class') || '') + ' ').indexOf(' ng-hide ') === -1) { 
     hidden = false; 
    } 
    }); 
    return hidden; 
} 

所以我猜他們是作弊稍微...檢查.ng-hide類的存在以確定可見性。但我想他們曾經在你的鞋子裏,並認爲這是最好的路線,因爲角度已經支持這個類名。

由於我們已經在使用角度,所以您可以考慮使用.ng-hide類設置可見性並編寫一個類似的幫助程序。

編輯:

作爲一個方面說明,我會說,添加/刪除.ng-hide設置的知名度將免費獲得任何ngAnimations你的模塊的用戶的利益已經到位,爲類。

+0

我會說這是正確的方法。從Angular 1.2開始,'ngShow'和'ngHide'指令都應用'ng-hide'類,而不是將'display'屬性改爲'none'或'block'。所以我認爲在測試'ngHide'或'ngShow'時檢查這個類是安全的。 –

+0

是的,實際上我最終改變了我的實現,以添加/刪除ng-hide類並在測試中檢查它,就像你說的那樣,我想這是最好的方法。謝謝! –

1

由於可見的元素是一個加載項,而:visible不是真正的CSS選擇器,因此沒有銀色子彈。

這裏有茉莉花使用not幾種可能性

  1. 。 ('display'))。not.toBe('hidden');

但是,這不會涵蓋該元素顯示的情況,但不會顯示,因爲它沒有不透明或它位於另一個元素的後面。

  1. 獲取元素的getBoundingClientRect()。然後檢查每個角落的document.elementFromPoint是否不會返回您期望隱藏的元素。