From 7d55fc92c25b787b1feddd463e4e838a164cf717 Mon Sep 17 00:00:00 2001 From: Dmitry Belyaev Date: Mon, 19 Jan 2015 17:04:39 +1100 Subject: [PATCH 1/3] Ensure spied functions contents is executed --- test/calendar.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/calendar.spec.js b/test/calendar.spec.js index 76b4e01..4a7a2bf 100644 --- a/test/calendar.spec.js +++ b/test/calendar.spec.js @@ -367,12 +367,12 @@ describe('uiCalendar', function () { } }; - spyOn($rootScope,'$apply'); + spyOn($rootScope,'$apply').andCallThrough(); angular.forEach(scope.uiConfig.calendar, function(value,key){ if (typeof value === 'function'){ functionCount++; - spyOn(scope.uiConfig.calendar, key); + spyOn(scope.uiConfig.calendar, key).andCallThrough(); var fullCalendarConfig = calendarCtrl.getFullCalendarConfig(scope.uiConfig.calendar, {}); @@ -401,12 +401,12 @@ describe('uiCalendar', function () { } }; - spyOn($rootScope,'$apply'); + spyOn($rootScope,'$apply').andCallThrough(); angular.forEach(scope.uiConfig.calendar, function(value,key){ if (typeof value === 'function'){ functionCount++; - spyOn(scope.uiConfig.calendar, key); + spyOn(scope.uiConfig.calendar, key).andCallThrough(); var fullCalendarConfig = calendarCtrl.getFullCalendarConfig(scope.uiConfig.calendar, {}); From 6e2a52e37d736983960e7beb832f6cddef4a779e Mon Sep 17 00:00:00 2001 From: Dmitry Belyaev Date: Mon, 19 Jan 2015 17:08:44 +1100 Subject: [PATCH 2/3] Remove non-valid test --- test/calendar.spec.js | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/test/calendar.spec.js b/test/calendar.spec.js index 4a7a2bf..2dbef41 100644 --- a/test/calendar.spec.js +++ b/test/calendar.spec.js @@ -384,41 +384,6 @@ describe('uiCalendar', function () { } }); })); - - it('should make sure that any function that already has an apply in it does not break the calendar (backwards compatible)', inject(function($timeout, $rootScope){ - - var functionCount = 0; - scope.uiConfig = { - calendar:{ - height: 200, - weekends: false, - defaultView: 'month', - dayClick: function(){scope.$apply();}, - eventClick: function(){scope.$apply();}, - eventDrop: function(){scope.$apply();}, - eventResize: function(){scope.$apply();}, - eventMouseover: function(){scope.$apply();} - } - }; - - spyOn($rootScope,'$apply').andCallThrough(); - - angular.forEach(scope.uiConfig.calendar, function(value,key){ - if (typeof value === 'function'){ - functionCount++; - spyOn(scope.uiConfig.calendar, key).andCallThrough(); - - var fullCalendarConfig = calendarCtrl.getFullCalendarConfig(scope.uiConfig.calendar, {}); - - fullCalendarConfig[key](); - - scope.$apply(); - $timeout.flush(); - expect($rootScope.$apply.callCount).toBe(functionCount*2); - expect(scope.uiConfig.calendar[key]).toHaveBeenCalled(); - } - }); - })); }); -}); \ No newline at end of file +}); From bce26163b0147927a95a6f0967163d958f99c26f Mon Sep 17 00:00:00 2001 From: Dmitry Belyaev Date: Wed, 21 Jan 2015 15:14:04 +1100 Subject: [PATCH 3/3] Use $scope.$root.$apply instead of $timeout This also makes possible to return value to fullcalendar. --- src/calendar.js | 25 ++++++++----------- test/calendar.spec.js | 57 +++++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/calendar.js b/src/calendar.js index 8663967..45a318b 100644 --- a/src/calendar.js +++ b/src/calendar.js @@ -11,10 +11,8 @@ angular.module('ui.calendar', []) .constant('uiCalendarConfig', {calendars: {}}) .controller('uiCalendarCtrl', ['$scope', - '$timeout', '$locale', function( $scope, - $timeout, $locale){ var sourceSerialId = 1, @@ -23,22 +21,19 @@ angular.module('ui.calendar', []) extraEventSignature = $scope.calendarWatchEvent ? $scope.calendarWatchEvent : angular.noop, wrapFunctionWithScopeApply = function(functionToWrap){ - var wrapper; - - if (functionToWrap){ - wrapper = function(){ - // This happens outside of angular context so we need to wrap it in a timeout which has an implied apply. - // In this way the function will be safely executed on the next digest. + return function(){ + // This may happen outside of angular context, so create one if outside. + if ($scope.$root.$$phase) { + return functionToWrap.apply(this, arguments); + } else { var args = arguments; - var _this = this; - $timeout(function(){ - functionToWrap.apply(_this, args); + var self = this; + return $scope.$root.$apply(function(){ + return functionToWrap.apply(self, args); }); - }; - } - - return wrapper; + } + }; }; this.eventsFingerprint = function(e) { diff --git a/test/calendar.spec.js b/test/calendar.spec.js index 2dbef41..a39744b 100644 --- a/test/calendar.spec.js +++ b/test/calendar.spec.js @@ -352,37 +352,40 @@ describe('uiCalendar', function () { scope.$apply(); }); - it('should make sure that all config functions are called in an angular context', inject(function($timeout, $rootScope){ - var functionCount = 0; - scope.uiConfig = { - calendar:{ - height: 200, - weekends: false, - defaultView: 'month', - dayClick: function(){}, - eventClick: function(){}, - eventDrop: function(){}, - eventResize: function(){}, - eventMouseover: function(){} - } - }; + it('should make sure that all config functions are called in an angular context', inject(function($rootScope){ + scope.uiConfig = { + calendar:{ + height: 200, + weekends: false, + defaultView: 'month' + } + }; - spyOn($rootScope,'$apply').andCallThrough(); + var keys = ['dayClick', 'eventClick', 'eventDrop', 'eventResize', 'eventMouseover']; + angular.forEach(keys, function(key) { + scope.uiConfig.calendar[key] = jasmine.createSpy().andReturn(key); + }); - angular.forEach(scope.uiConfig.calendar, function(value,key){ - if (typeof value === 'function'){ - functionCount++; - spyOn(scope.uiConfig.calendar, key).andCallThrough(); + var fullCalendarConfig = calendarCtrl.getFullCalendarConfig(scope.uiConfig.calendar, {}); - var fullCalendarConfig = calendarCtrl.getFullCalendarConfig(scope.uiConfig.calendar, {}); + spyOn($rootScope,'$apply').andCallThrough(); - fullCalendarConfig[key](); - $timeout.flush(); - expect($rootScope.$apply.callCount).toBe(functionCount); - expect(scope.uiConfig.calendar[key]).toHaveBeenCalled(); - $rootScope.$apply.isSpy = false; - } - }); + angular.forEach(keys, function(key){ + $rootScope.$apply.reset(); + + var fn = fullCalendarConfig[key]; + + expect(fn()).toBe(key); + expect($rootScope.$apply.callCount).toBe(1); + expect(scope.uiConfig.calendar[key].callCount).toBe(1); + + expect($rootScope.$apply(function(){ + expect($rootScope.$apply.callCount).toBe(2); + return fn(); + })).toBe(key); + expect($rootScope.$apply.callCount).toBe(2); + expect(scope.uiConfig.calendar[key].callCount).toBe(2); + }); })); });