我正在尝试在我的angular指令中测试ng-show条件,该指令使用controllerAs语法并为模板加载外部html文件。
我无法弄清楚如何在条件满足时测试模板中是否出现了什么。
我的问题是 - 如何在满足条件时测试ng-show是否有效和相关数据通过ctrl.error
标签显示在<p>
中?
以下是相关文件: 模板文件:
<!-- dataDisplay.html -->
<div>
<div ng-show="!ctrl.eventsFound">
<p id="errorMessage" style="color: red;">{{ctrl.error}}</p>
</div>
<div id="result" ng-show="ctrl.eventsFound">
<section id="item-block" class="item-container">
<div class="item-timeline-block" ng-repeat="item in ctrl.items track by item.index">
<div ng-class="item.iconBackground">
<span style="color:white" ng-class="item.iconImg"></span>
</div>
<div class="item-timeline-content">
<h2>{{::item.title}}</h2>
<span ng-show="{{::item.datetime}}" class="date">
</span>
<p>{{::item.content}}</p>
<a ng-hide="{{!item.link}}" href="{{::item.link}}" target="_blank">Read more</a>
<small ng-hide="{{!item.link}}">{{::item.linkWarning}}</small>
</div>
</div>
</section>
</div>
</div>
的index.html:
<!doctype html>
<html ng-app="app" ng-cloak>
<head>
<title> Test </title>
<script src="node_modules/angular/angular.min.js"></script>
<script src="node_modules/angular-sanitize/angular-sanitize.min.js"></script>
</head>
<body>
<div>
<display-dir></display-dir>
</div>
</body>
<script src="node_modules/moment/min/moment.min.js"></script>
<script src="./path/displayDir.js"></script>
</html>
指令:
//displayDir.js
angular.module('app', [])
.directive('displayDir', function() {
return {
restrict: 'E',
transclude: true,
controllerAs: 'ctrl',
scope: {},
templateUrl: 'dataDisplay.html',
link: function() {
},
controller: 'displayCtrl'
}
})
.controller('displayCtrl', ['$window', function($window) {
let ctrl = this;
ctrl.items =
[
{ event: "a", title: "title a", index: 0, datetime: "01/02/2016", content: "content 1" },
{ event: "b", title: "title b", index: 2, datetime: "01/01/2016", content: "content 2", link: 'http://www.google.com'},
];
try {
if (!ctrl.items.length) {
ctrl.eventsFound = false;
ctrl.error = "there is no data present for the control";
} else {
ctrl.eventsFound = true;
ctrl.items.map(function(item) {
if (item.title == "title b") {
item.link = item.content;
item.linkWarning = `Warning - This link will bring you to external content!`
item.content = ""
}
if (item.datetime == "") {
item.lastUpdated = ""
} else {
item.lastUpdated = $window.moment(item.datetime).fromNow()
}
return item;
});
}
} catch (error) {
ctrl.eventsFound = false;
ctrl.error = error.message
}
}])
Karma测试规范 - 使用ngHtml2JsPreprocessor
describe('the displayDir directive', function() {
let element, scope, ctrl;
beforeEach(angular.mock.module('app'));
beforeEach(module('htmlTemplate'));
beforeEach(inject(function($rootScope, $controller) {
//define the controller
scope = $rootScope;
ctrl = $controller('displayCtrl', {
$scope: scope
})
}));
describe('after loading template url', function() {
beforeEach(inject(function($compile) {
// bring in the templateUrl file
element = angular.element('<display-dir></display-dir>');
$compile(element)(scope);
scope.$digest();
}));
it('should show the errorMessage div', function() {
let messageDiv = element[0].querySelector("#errorMessage");
expect(messageDiv).toBeDefined();
});
it('should show the errorMessage div with the text', function(){
ctrl.events =[]
ctrl.eventsFound = false;
ctrl.errorMessage = 'There is no data present for the control'
let messageDiv = element[0].querySelector("#errorMessage");
//This does not show the text error message text inside the 'p' tag
console.log("element",messageDiv)
/* something like
expect(messageDiv.innerHTML()).toEqual('There is no data
present for the control');
or
expect(ctrl.errorMessage).toEqual('There is no data present
for the control')
*/
})
})
});
修改
在与Nikolaj合作之后,我有以下测试:
// FAILS ON the second expect - messageDiv.text should equal...
it('should show the errorMessage div', function() {
ctrl.events =[];
ctrl.eventsFound= false;
ctrl.errorMessage = 'There is no data'
let messageDiv = angular.element(element[0].querySelector("#errorMessage"));
expect(messageDiv.hasClass('ng-hide')).toBeFalsy();
expect(messageDiv.text()).toEqual("There is no data")
});
// FAILS ON the first expect - messageDiv should be truthy
it('should not show the errorMessage div', function() {
ctrl.events = [{event: "test"}]
ctrl.eventsFound= true;
ctrl.errorMessage = ''
let messageDiv = angular.element(element[0].querySelector("#errorMessage"));
expect(messageDiv.hasClass('ng-hide')).toBeTruthy();
expect(messageDiv.text()).toEqual('')
});
以下是我所看到的plunker行为。 scope.$digest()
似乎没有帮助,除非我做错了。
答案 0 :(得分:0)
如果传递给指令的表达式解析为ng-show
,则所有ng-hide
基本上都会将类false
添加到元素中。如果我们忽略动画,这个css类几乎等同于:
.ng-hide {
display: none !important;
}
因此,为了测试ng-show / ng-hide指令是否有效,您可以测试该元素是否包含类ng-hide
。像这样:
it('should show the errorMessage div', function() {
const messageDiv = angular.element(element[0].querySelector("#errorMessage"));
expect(messageDiv.hasClass('ng-hide')).toBeFalse();
});
或测试错误消息是否隐藏:
it('should not show the errorMessage div', function() {
const messageDiv = angular.element(element[0].querySelector("#errorMessage"));
expect(messageDiv.hasClass('ng-hide')).toBeTrue();
});
答案 1 :(得分:0)
或者您可以使用angular-test-runner库,它可以更好,更轻松地测试AngularJS应用程序,包括html模板。
您的测试非常简单,没有任何magic class
断言:
describe('the displayDir directive', () => {
let app;
const {expectElement} = testRunner.actions;
beforeEach(() => {
app = testRunner.app(['app', 'htmlTemplate']);
});
it('should show the errorMessage div', () => {
const html = app.runHtml('<display-dir></display-dir>');
html.verify(
expectElement('#errorMessage').toExist()
);
});
});