Here's Plunker Link
Updated Plunker Updated Plunker
I have written a directive which hide and shows the div based on ajax call.
How i can i test a behaviour of Directive written ?Its shows the spinner on Ajax Call.
Spec
describe('loader directive', function() {
var $compile, scope;
beforeEach(module('plunker'));
beforeEach(inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
scope = _$rootScope_.$new();
}));
it('check if div shows on', function() {
var element = $compile('<div loading>Something</div>')(scope);
scope.$apply();
});
});
Directive
app.directive('loading', ['$http' ,function ($http)
{
return {
restrict: 'A',
link: function (scope, elm, attrs)
{
scope.isLoading = function () {
return $http.pendingRequests.length > 0;
};
scope.$watch(scope.isLoading, function (v) {
if(v) {
elm.show();
} else {
elm.hide();
}
});
}
};
}]);
You can just check for an .is(':visible').
describe('loader directive', function() {
var $compile, scope, $httpBackend, $http, element;
beforeEach(module('plunker'));
beforeEach(inject(function(_$compile_, _$rootScope_, _$httpBackend_, _$http_) {
$compile = _$compile_;
scope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', '/test').respond(200, {
test: true
});
$http = _$http_;
}));
afterEach(function() {
$httpBackend.flush();
if (element && element.length) {
element.remove();
}
});
it('check if div shows on http call', function() {
element = $compile('<div class="loading-bar" loading>Something</div>')(scope);
element.appendTo('body');
$http.get('/test');
scope.$apply();
expect(element.is(':visible')).toBe(true);
});
});
To mock out the $http calls you will need to use $httpBackend service.
Plunker Demo
Related
how to check attribute is present in HTML and match its value. this is a test spec.js I wrote,
define(['angular',
'angularMocks',
'site-config',
'ng_detector',
],
function(angular,
mock,
$app,
ng_detector) {
describe('ng-detector controller', function() {
beforeEach(angular.mock.module("webapp"));
var $compile, $rootScope, tpl, $scope, elm, templateAsHtml;
beforeEach(angular.mock.inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
// $scope = _$rootScope_.$new();
}));
it('should initialize the ng-detector directive', inject(function() {
var tpl = $compile("<div ng-detector ></div>")($rootScope);
$rootScope.$digest();
console.log(tpl) // Log: r{0: <div ng-detector="" class="ng-scope" ng-verison="1.6.4"></div>, length: 1}
templateAsHtml = tpl[0].outerHTML;
expect(templateAsHtml.attr('ng-version')).toEqual(angular.version.full);
}));
});
});
directive. that adds angular version to attribute ng-version
'use strict';
define(['app-module'], function(ng) {
$app.info('ng detector initialized. {file: directives/ng-detector.js}');
ng.directive('ngDetector', function() {
return {
restrict: "A",
link: function(scope, elm, attr) {
elm.attr('ng-version', angular.version.full);
}
};
});
return ng;
});
I want to get a ng-version attribute set by the directive and match the attribute value.
I figured out myself. I was looking at the different place.
it('should check the angular version number', angular.mock.inject(function() {
expect(tpl.attr('ng-version')).toEqual(angular.version.full);
}));
Directive:
angular
.module('tdsapp')
.directive('focus', focus);
focus.$inject = ['$timeout'];
// Used to set focus on element
function focus($timeout) {
return {
scope: { focus: '#'},
link: function (scope, element) {
scope.$watch('focus',
function (value) {
if (value) {
$timeout(function () {
element[0].focus();
console.log('focus called');
});
}
}
);
}
};
Test Spec:
describe('directive: focus', function () {
var $timeout, element, $scope, $compile;
beforeEach(function () {
module('tdsapp');
inject(function (_$timeout_, $rootScope, _$compile_) {
$timeout = _$timeout_;
$compile = _$compile_;
$scope = $rootScope.$new();
});
});
it('should call focus on element', function () {
var elm = angular.element('<input type="text" name="second" focus="true" />');
spyOn(elm[0], 'focus');
$timeout.flush();
expect(elm[0].focus).toHaveBeenCalled();
});
});
I have looked at AngularJS: how to test directive which gives focus to element? and at How do I check if my element has been focussed in a unit test and neither works. I either get the expect failing or $timeout.flush() - No deferred tasks to be flushed.
EDIT:
As I stated in the text - the above two examples do not work.
I am using isolate scope in custom directive. I have updated plunker link. http://plnkr.co/edit/NBQqjxW8xvqMgfW9AVek?p=preview
Can someone help me in writing unit test case for script.js file.
script.js
var app = angular.module('app', [])
app.directive('myDirective', function($timeout) {
return {
restrict: 'A',
scope: {
content: '='
},
templateUrl: 'my-directive.html',
link: function(scope, element, attr) {
$timeout(function() {
element = element[0].querySelectorAll('div.outerDiv div.innerDiv3 p.myClass');
var height = element[0].offsetHeight;
if (height > 40) {
angular.element(element).addClass('expandable');
scope.isShowMore = true;
}
})
scope.showMore = function() {
angular.element(element).removeClass('expandable');
scope.isShowMore = false;
};
scope.showLess = function() {
angular.element(element).addClass('expandable');
scope.isShowMore = true;
};
}
}
})
(function() {
'use strict';
describe('Unit testing directive', function() {
var $compile, scope, element, compiledDirective, $rootScope, $timeout;
beforeEach(module("app"));
beforeEach(inject(function(_$compile_, _$rootScope_, _$timeout_) {
$compile = _$compile_;
scope = _$rootScope_.$new();
$timeout = _$timeout_;
element = angular.element(' <div my-directive content="content"></div>');
compiledDirective = $compile(element)(scope);
scope.$digest();
}));
it('should apply template', function() {
expect(compiledDirective.html()).toBe('');
});
it('check for timeout', function() {
$timeout.flush();
});
});
})();
Use $timeout.flush() function for writing testcase for $timeout
it('check for timeout', function() {
scope.digest();
// flush timeout(s) for all code under test.
$timeout.flush();
// this will throw an exception if there are any pending timeouts.
$timeout.verifyNoPendingTasks();
expect(scope.isShowMore).toBeTruthy();
});
Check this article for better understanding.
I have a simple directive, and in the link function is a $broadcast receiver $on. Once received, a scope function is called:
return {
restrict: 'E',
link: function($scope, element, attrs) {
$scope.createCart = function () {
// Create cart
}
function getProductList() {
// get products lists
}
$scope.$on('create-shopping-cart', function() {
$scope.createCart();
getProductList();
});
}
};
I have tried:
describe('<-- myDirective Spec ------>', function () {
var scope, $compile, element, $httpBackend;
beforeEach(angular.mock.module('myApp'));
beforeEach(inject(function (_$rootScope_, _$compile_, _$httpBackend_) {
scope = _$rootScope_.$new();
$compile = _$compile_;
$httpBackend = _$httpBackend_;
var html = '<my-directive"></my-directive>';
element = $compile(angular.element(html))(scope);
spyOn(scope, '$on').and.callThrough();
scope.$digest();
}));
it('should be defined', function () {
expect(element).toBeDefined();
});
it('should broadcast ', function () {
scope.$broadcast('create-shopping-cart');
scope.$digest();
expect(element.isolateScope().createCart()).toHaveBeenCalled();
});
});
With the above, i see error:
TypeError: 'undefined' is not an object (evaluating 'element.isolateScope().createCart')
How can i test $scope.createCart(); AND getProductList(); are called?
I am doing an AngularJS unit test and use Karma - Coverage to see the result. Here is my code.
todomvc.directive('todoBlur', function () {
return function (scope, elem, attrs) {
elem.bind('blur', function () {
scope.$apply(attrs.todoBlur);
});
scope.$on('$destroy', function () {
elem.unbind('blur');
});
};
});
I have written the following test case.
describe('TodoBlur', function() {
var $compile,
$rootScope;
beforeEach(module('todomvc'));
beforeEach(inject(function(_$compile_, _$rootScope_){
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
it('T', function() {
var element = $compile("<todoBlur></todoBlur>")($rootScope);
$rootScope.$digest();
element.blur();
var e = $.Event('keydown');
e.which = 27;
$rootScope.trigger(e);
element.triggerHandler('keydown', 27);
element.triggerHandler('keydown', 28);
});
});
As you see, I tried many codes to try to test the keydown but none of them work. The result in Code coverage report remains unchanged. How can I test it? I am new to AngularJS and its unit test and I google and still cannot find any solutions.
Edit: I tried Unit testing Angular directive click handler and modified my code. But it still not work.
beforeEach(module('todomvc'));
describe('myCtrl', function () {
var $scope, $rootScope;
beforeEach(inject(function ($controller, _$rootScope_) {
$scope = $rootScope.$new();
$controller('myCtrl', { $scope: $scope });
$rootScope = _$rootScope_;
}));
describe('T', function () {
var element;
beforeEach(function () {
element = angular.element('<todoBlur/>');
$compile(element)(scope);
$scope.$digest();
});
});
});