I already asked this question where the main point was scope doesn't exists in terminal but it exists in Chrome debugging tool. Despite the answers it didn't get fixed.
The question is what is the right syntax to test the bellow directive, especially the line expect(scope.measurementScroll).toBe(true);
. While digging through web i couldn't find any similar question most questions are related to $q.defer()
where in my case there is underscore method _.defer()
Controller
'use strict';
angular.module('myApp')
.controller('MeasurementsTimelineCtrl', ['$scope', '$state', 'Measurements', function($scope, $state, Measurements) {
$scope.measurements = null;
var userId = $scope.currentUser ? $scope.currentUser.id : null;
if (userId) {
var listOfMeasurements = Measurements.userIndex(userId);
listOfMeasurements.then(function(data){
$scope.measurements = data;
$scope.$broadcast('measurements-updated', $scope.measurements);
});
}
}]);
Directive:
'use strict';
angular.module('myApp')
.directive('dashboardMeasurementTimeline', ['$window', function($window) {
return {
restrict: 'E',
templateUrl: 'myView.html',
controller: 'MeasurementsTimelineCtrl',
link: function(scope, element){
scope.$on('measurements-updated', function(measurements) {
_.defer(function(){
if(measurements) {
scope.measurementScroll = true;
}
});
});
}
};
}]);
Test
'use strict';
describe('Directive: dashboardMeasurementTimeline', function () {
var $rootScope, $compile, element, scope;
beforeEach(function() {
module('myApp');
inject(function($injector) {
$rootScope = $injector.get('$rootScope');
$compile = $injector.get('$compile');
});
scope = $rootScope.$new();
element = angular.element('<dashboard-measurement-timeline></dashboard-measurement-timeline>');
element = $compile(element)(scope);
scope.currentUser = {id : 'someId'};
scope.$digest();
scope.measurements = [{id: 'someId', time_of_test: 'Tue, 30 Dec 2014 14:00:00 -0000'},
{id: 'someId', time_of_test: 'Thu, 20 Nov 2014 03:00:00 -0000'},];
scope.$broadcast('measurements-updated', scope.measurements);
scope.$apply();
});
it('should assign true value to measurementScroll', function () {
expect(scope.measurementScroll).toBe(true);
});
});
@Michal Charezma, gave a great solution for the problem that is actually a solution, but as it turned out it has some other restrictions for the rest of
_
functions. For example:raises an error that the
throttle
is undefined.Following @Michal's logic, found another solution that lets functions like
_.throttle()
to work properly. So, instead of importing_
and using:One can mock the
defer
function only, from the spec like:You can do this by injecting a mock underscore library, with a
defer
function defined in the test. A way to do this is to define your own factory,_
, which can then be mocked easily:Then in the directive, you have to use it by injecting it:
In the test, you can then mock it:
This means that instead of the real one, the directive will use the mock
_
, which saves the callback passed todefer
asdeferCallback
so you can invoke it when needed:This makes the test synchronous, which is usually a better idea than using
done()
, as it keeps test as fast as possible.You can see the above working at http://plnkr.co/edit/r7P25jKzEFgE5j10bZgE?p=preview
If you do not have lodash as a service to be injected you can just spy over the
defer
method, and if you care about the execution of the function passed then you can just set acallFake
and call the argument function passed to the realdefer
:More deeper let's say you have the following call:
then in your test you can say: