$scope exists on browser debugger, but does not ex

2019-09-04 03:32发布

问题:

I have a directive that is depended on a controller which gets data from an api though Ajax call. It works correctly. I am trying to test it using jasmine and the strange issue is that when I debug the code and check for a value of let's say $scope.measurement it returns true, but when I run in the terminal it can't find $scope.measurement and raises an error Expected undefined to be true. no clue what can be the issue. I thought the problem might be with an isolated scope, but the element doesn't have a function isolateScope(). Is there any idea what can be the problem?

Here is the controller:

'use strict';
angular.module('myApp')
  .controller('MeasurementsTimelineCtrl', ['$scope', 'Measurements', function($scope, Measurements) {
    $scope.measurements = null;
    var userId = $scope.currentUser ? $scope.currentUser.id : null;

    if (userId) {
      var listOfMeasurements = Measurements.users(userId);
      listOfMeasurements.then(function(data){
        $scope.measurements = data;
      });
    }
  });

This is the directive:

'use strict';

angular.module('myApp')
  .directive('measurementTimeline', function() {
    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;
            }
          });
        });
      }
    };
  }]);

And this is the test:

   'use strict';

    describe('Directive: measurementTimeline', function () {

      var $rootScope, $compile, element, scope, createController, $httpBackend, apiUrl;

      beforeEach(function() {
        module('myApp');

        inject(function($injector) {
          $rootScope = $injector.get('$rootScope');
          $compile = $injector.get('$compile');
          $httpBackend = $injector.get('$httpBackend');
          apiUrl = $injector.get('apiUrl');
        });
        scope = $rootScope.$new();
        element = angular.element('<dashboard-measurement-timeline></dashboard-measurement-timeline>');
        element = $compile(element)(scope);

        scope.$digest();
        scope.measurements = [{id: 'someId', time_of_test: 'Tue, 30 Dec 2014 14:00:00 -0000'},
          {id: 'someId', time_of_test: 'Fri, 13 Jun 2014 14:00:00 -0000'}];

        scope.$broadcast('measurements-updated', scope.measurements);
        scope.$apply();
      });

      describe('PUser', function(){
        beforeEach(function(){
          scope.currentUser = null;
        });

        it('should ......', function () {
          expect(scope.measurementScroll).toBe(true);
        });
      });
    });

回答1:

how about ?

it('should ......', function () {
  expect(element.scope().measurementScroll).toBe(true);
});

UPDATE:

and I think you also need to use the andCallThrough method on the _.defer

spyOn(obj, 'method').andCallThrough()



回答2:

Edit Seems that the bellow solution is a "Perfect wrong case". However the tests passes they never fall, even if they are wrong.

Wrong solution The test passed after altering the following:

it('should ......', function () {
    scope.$evalAsync(function() {
      expect(scope.measurementScroll).toBe(true);
    });
  });

Update: Right Solution

The right solution for this problem was solved by @Michal Charemza in this question - How to test _.defer() using Jasmine, AngularJs