Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

chore(datepicker): Unregister parent watchers on $destroy #5260

Closed
wants to merge 3 commits into from

Conversation

deeg
Copy link
Contributor

@deeg deeg commented Jan 15, 2016

Closes #5242

@wesleycho, looking for advice on how to test.

I basically want to spy on the $parent.$watch function and return a spy and see how many times the spy is called. I had this

    describe('clean parent watchers', function(){
        it("should clean watchers in controller", function(){
          var scope;
          var clearSpy;
          inject(function($controller, $rootScope, $parse, $interpolate, $log, dateFilter, uibDatepickerConfig, $datepickerSuppressError, uibDateParser) {
            scope = $rootScope.$new();
            scope.$parent = jasmine.createSpyObj("scope.$parent", ["$watch"]);
            clearSpy = jasmine.createSpy("clearSpy");
            scope.$parent.$watch.and.returnValue(clearSpy);
            $controller('UibDatepickerController', {
              $scope: scope,
              $attrs: {},
              $parse: $parse,
              $interpolate: $interpolate,
              $log: $log,
              dateFilter: dateFilter,
              datepickerConfig: uibDatepickerConfig,
              $datepickerSuppressError: $datepickerSuppressError,
              dateParser: uibDateParser
            });
          });

          $templateCache.put('uib/template/datepicker/datepicker.html', '<div>{{datepicker.text}}</div>');
          $rootScope.date = new Date('September 12, 2010');
          $rootScope.mode = 'month';
          element = $compile('<uib-datepicker ng-model="date" min-date="date" max-date="date" min-mode="mode" max-mode="mode" init-date="date" ng-disabled="true"></uib-datepicker>')($rootScope);
          $rootScope.$digest();

          var ctrl = element.controller('uib-datepicker');
          ctrl.$destroy();

          expect(clearSpy.calls.count()).toBe(6);
        });

but was getting this error when running

TypeError: Cannot read property 'uib:datepicker.focus' of undefined
        at Scope.$on (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular/angular.js:16231:39)
        at new <anonymous> (/Users/dgornstein/Workspace/ui-bootstrap-fork/src/datepicker/datepicker.js:9:15478)
        at invoke (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular/angular.js:4523:17)
        at Object.instantiate (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular/angular.js:4531:27)
        at /Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular/angular.js:9197:28
        at /Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular-mocks/angular-mocks.js:1882:12
        at Object.<anonymous> (/Users/dgornstein/Workspace/ui-bootstrap-fork/src/datepicker/test/datepicker.spec.js:3036:13)
        at Object.invoke (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular/angular.js:4523:17)
        at Object.workFn (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular-mocks/angular-mocks.js:2439:20)
        at window.inject.angular.mock.inject (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular-mocks/angular-mocks.js:2411:37)
    Error: Declaration Location
        at window.inject.angular.mock.inject (/Users/dgornstein/Workspace/ui-bootstrap-fork/node_modules/angular-mocks/angular-mocks.js:2410:25)
        at Object.<anonymous> (/Users/dgornstein/Workspace/ui-bootstrap-fork/src/datepicker/test/datepicker.spec.js:3031:11)

Sorry if I'm missing something trivial.

if (!dateFormat) {
throw new Error('uibDatepickerPopup must have a date format specified.');
}
if (!dateFormat) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix spacing, damn ide

@@ -990,3 +997,9 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
}
};
});

function clearWatchListeners(watchListeners) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should not be outside the controllers of relevance - this will leak as a global function.

In this case, the functionality is simple enough to not require a helper function. Something like

while (watchListeners.length) {
  watchListeners.shift()();
}

in all relevant areas should be enough

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, will fix.

@wesleycho
Copy link
Contributor

You may need to do a $timeout.flush() before executing scope.$destroy().

@deeg
Copy link
Contributor Author

deeg commented Jan 15, 2016

That still gives the same error even after adding the flush.

@wesleycho wesleycho closed this in c4171a2 Jan 16, 2016
@deeg deeg deleted the clean-datepicker-watch branch April 12, 2016 13:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants