[英]Unit testing the output of $sce.trustAsHtml in Angular
我正在Angular中編寫一個REST應用程序,我想為它編寫單元測試(當然!)。 我有一個控制器,它從json中的REST服務獲取博客文章列表,並將摘要放入$ scope,因此我可以在視圖中顯示它們。
起初,博客文章只是顯示為文本,即<p>Blog body</p>
,而不是呈現為已解析的HTML,直到我發現您可以將ng-bind-html與$ sce服務結合使用。 這在正確顯示博客文章方面現在可以正常工作。
單元測試時會出現問題。 我試圖用一些HTML模擬一個json響應,然后測試我的控制器是否正確處理HTML。 這是我的代碼:
.controller( 'HomeCtrl', function HomeController( $scope, $http, $sce ) {
$scope.posts = {};
$http.get('../drupal/node.json').success(function (data) {
var posts;
posts = data.list;
for(var i = 0; i < posts.length; i ++) {
posts[i].previewText = $sce.trustAsHtml(posts[i].body.summary);
posts[i].created = posts[i].created + '000'; // add milliseconds so it can be properly formatted
}
$scope.posts = posts;
});
})
describe('HomeCtrl', function() {
var $httpBackend, $rootScope, $sce, createController;
beforeEach(inject(function ($injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
// The $controller service is used to create instances of controllers
var $controller = $injector.get('$controller');
$sce = $injector.get('$sce');
createController = function() {
return $controller('HomeCtrl', {
'$scope': $rootScope
});
};
}));
it('should get a list of blog posts', function() {
var rawResponse = {
"list": [
{
"body": {
"value": "\u003Cp\u003EPost body.\u003C\/p\u003E\n",
"summary": "\u003Cp\u003ESummary.\u003C\/p\u003E\n"
},
"created": "1388415860"
}
]};
var processedResponse = [{
"body": {
"value": "\u003Cp\u003EPost body.\u003C\/p\u003E\n",
"summary": "\u003Cp\u003ESummary.\u003C\/p\u003E\n"
},
"created": "1388415860000",
previewText: $sce.trustAsHtml("\u003Cp\u003ESummary.\u003C\/p\u003E\n")
}];
$httpBackend.when('GET', '../drupal/node.json').respond(rawResponse);
$httpBackend.expectGET("../drupal/node.json").respond(rawResponse);
var homeCtrl = createController();
expect(homeCtrl).toBeTruthy();
$httpBackend.flush();
expect($rootScope.posts).toEqual(processedResponse);
});
});
當我通過Karma測試運行器運行上述內容時,我收到以下響應:
Chrome 31.0.1650 (Windows) home section HomeCtrl should get a list of blog posts FAILED
Expected [ { body : { value : '<p>Post body.</p>
', summary : '<p>Summary.</p>
' }, created : '1388415860000', previewText : { $$unwrapTrustedValue : Function } } ] to equal [ { body
: { value : '<p>Post body.</p>
', summary : '<p>Summary.</p>
' }, created : '1388415860000', previewText : { $$unwrapTrustedValue : Function } } ].
我懷疑問題是因為$sce.trustAsHtml
返回一個包含函數的對象而不是字符串。
我的問題是,首先, 我是否以正確的方式處理這個問題?
其次,如果是這樣, 我應該如何測試$sce.trustAsHtml
的輸出?
由於michael-bromley給出的答案對我不起作用,我想指出另一種解決方案。 在我的情況下,我使用的是一個過濾器,它將每個字符串的出現包裝在另一個字符串中,其字符串的類別為“highlight”。 換句話說,我希望突出顯示單詞。 這是代碼:
angular.module('myModule').filter('highlight', function ($sce) {
return function (input, str) {
return $sce.trustAsHtml((input || '').replace(new RegExp(str, 'gi'), '<span class=\"highlighted\">$&</span>'));
};
});
我使用$ sce服務將結果值信任為HTML。 為了測試這個,我需要對結果值使用$$ unwrapTrustedValue函數來使我的測試工作:
it('01: should add a span with class \'highlight\' around each mathing string.', inject(function ($filter) {
// Execute
var result = $filter('highlight')('this str contains a str that will be a highlighted str.', 'str');
// Test
expect(result.$$unwrapTrustedValue()).toEqual('this <span class="highlighted">str</span> contains a <span class="highlighted">str</span> that will be a highlighted <span class="highlighted">str</span>.');
}));
更新:
正如@gugol所指出的那樣,最好不要使用像$$ unwrapTrustedValue這樣的Angular內部方法。 更好的方法是在$ sce服務上使用public getTrustedHtml方法。 像這樣:
it('01: should add a span with class \'highlight\' around each mathing string.', inject(function ($sce, $filter) {
// Execute
var result = $filter('highlight')('this str contains a str that will be a highlighted str.', 'str');
// Test
expect($sce.getTrustedHtml(result)).toEqual('this <span class="highlighted">str</span> contains a <span class="highlighted">str</span> that will be a highlighted <span class="highlighted">str</span>.');
}));
在每次測試之前,您必須使用其提供程序禁用$ sce。
當$ sce被禁用時,所有$ sce.trust *方法只返回原始值而不是包裝函數。
beforeEach(module(function ($sceProvider) {
$sceProvider.enabled(false);
}));
it('shall pass', inject(function($sce){
expect($sce.trustAsHtml('<span>text</span>')).toBe('<span>text</span>');
}));
在您的特定示例中,只需這樣做:
describe('HomeCtrl', function() {
var $httpBackend, $rootScope, $sce, createController;
beforeEach(module(function ($sceProvider) {
$sceProvider.enabled(false);
}));
// rest of the file
});
我發現你可以使用$sce.getTrusted
,它將返回最初傳遞給$sce.trustAsHtml
的值,在這種情況下是一個包含HTML的字符串,然后你可以用通常的方式測試它是否相等。
所以我的測試現在看起來像這樣:
it('should create a previewText property using $sce.trustAsHtml', function() {
// confirms that it is an object, as should be the case when
// it has been through $sce.trustAsHtml
expect(typeof result.previewText === 'object').toEqual(true);
expect($sce.getTrusted($sce.HTML, result.previewText))
.toEqual('<p>Original HTML content string</p>');
});
另一個選擇是使用getTrustedHtml()函數從$$ unwrapTrustedValue獲取html字符串值。
vm.user.bio = $sce.getTrustedHtml(vm.user.bio);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.