Search code examples
javascriptangularjsunit-testingjasmineangularjs-watch

Angular unit testing watcher with parent variable


How can watcher be tested if it watches $parent scope variable? For example I have got in childs scope:

$scope.$parent.$watch('activeId', function (hotelId) {
    $scope.select(activeId);
});

Currently how test look like:

...

    beforeEach(inject(function (_$controller_, _$rootScope_) {

       $scope = _$rootScope_.$new();
       $parentScope = _$rootScope_.$new();

       $controller = _$controller_('ChildCtrl', {'$scope': $scope});
       $parentController = _$controller_('ParentCtrl', {'$scope': $parentScope});
    }));

    describe('select', function () {
        beforeEach(function () {
           spyOn($scope, 'select');
        });
        it('should call select', function () {
           $parentScope.setActiveId(1);
           $parentScope.$digest();

           expect($scope.select).toHaveBeenCalled();
        });
    });
});

But unfortunetly this test fails.


Solution

  • Seems I was able to handle this issue and passing test by adding $parent to $scope by providing parent controller like so:

    describe('Controller: TestController', function () {
    
        beforeEach(module('App'));
    
        var $controller, $scope, $parentController, $parentScope;
    
        beforeEach(inject(function (_$controller_, _$rootScope_) {
    
            $scope = _$rootScope_.$new();
            $parentScope = _$rootScope_.$new();
            $scope.$parent = $parentScope;
    
            $parentController = _$controller_('ParentController', {'$scope': $parentScope});
            $controller = _$controller_('ChildCtrl', {'$scope': $scope});
        }));
        it('should get $parent variable', function () {
            var userId=$scope.$parent.vm.userId;
            var simId=$scope.$parent.vm.simId;
        })
           describe('select', function () {
            beforeEach(function () {
               spyOn($scope, 'select');
            });
            it('should call select', function () {
               $scope.$parent.setActiveId(1);
               $scope.$parent.$digest();
    
               expect($scope.select).toHaveBeenCalled();
            });
        });
    });