isolateScope() returns undefined when using templateUrl

前端 未结 5 1533
遥遥无期
遥遥无期 2021-02-07 03:41

I have a directive that I want to unittest, but I\'m running into the issue that I can\'t access my isolated scope. Here\'s the directive:

&l         


        
相关标签:
5条回答
  • 2021-02-07 04:18

    I had to mock and flush the $httpBackend before isolateScope() became defined. Note that $scope.$digest() made no difference.

    Directive:

    app.directive('deliverableList', function () {
        return {
            templateUrl: 'app/directives/deliverable-list-directive.tpl.html',
            controller: 'deliverableListDirectiveController',
            restrict = 'E',
            scope = {
                deliverables: '=',
                label: '@'
            }
        }
    })
    

    test:

    it('should be defined', inject(function ($rootScope, $compile, $httpBackend) {
        var scope = $rootScope.$new();
    
        $httpBackend.expectGET('app/directives/deliverable-list-directive.tpl.html').respond();
    
        var $element = $compile('<deliverable-list label="test" deliverables="[{id: 123}]"></deliverable-list>')(scope);
    
        $httpBackend.flush();
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    
        expect($element).toBeDefined();
        expect($element.controller).toBeDefined();
    
        scope = $element.isolateScope();
        expect(scope).toBeDefined();
        expect(scope.label).toEqual('test');
        expect(scope.deliverables instanceof Array).toEqual(true);
        expect(scope.deliverables.length).toEqual(1);
        expect(scope.deliverables[0]).toEqual({id: 123});
    }));
    

    I'm using Angular 1.3.

    0 讨论(0)
  • 2021-02-07 04:19

    You could configure karma-ng-html2js-preprocessor plugin. It will convert the HTML templates into a javascript string and put it into Angular's $templateCache service.

    After set a moduleName in the configuration you can declare the module in your tests and then all your production templates will available without need to mock them with $httpBackend everywhere.

    beforeEach(module('partials'));
    

    You can find how to setup the plugin here: http://untangled.io/how-to-unit-test-a-directive-with-templateurl/

    0 讨论(0)
  • 2021-02-07 04:31

    With Angularjs 1.3, if you disable debugInfoEnabled in the app config:

    $compileProvider.debugInfoEnabled(false);
    

    isolateScope() returns undefined also!

    0 讨论(0)
  • 2021-02-07 04:33

    In my case, I kept running into this in cases where I was trying to isolate a scope on a directive with no isolate scope property.

    function testDirective() {
      return {
        restrict:'EA',
        template:'<span>{{ message }}</span>'
        scope:{} // <-- Removing this made an obvious difference
      };
    }
    function testWithoutIsolateScopeDirective() {
      return {
        restrict:'EA',
        template:'<span>{{ message }}</span>'
      };
    }
    describe('tests pass', function(){
      var compiledElement, isolatedScope, $scope;
      beforeEach(module('test'));
      beforeEach(inject(function ($compile, $rootScope){
        $scope = $rootScope.$new();
        compiledElement = $compile(angular.element('<div test-directive></div>'))($scope);
        isolatedScope = compiledElement.isolateScope();
      }));
      it('element should compile', function () {
        expect(compiledElement).toBeDefined();
      });
      it('scope should isolate', function () {
        expect(isolatedScope).toBeDefined();
      });
    });
    describe('last test fails', function(){
      var compiledElement, isolatedScope, $scope;
      beforeEach(module('test'));
      beforeEach(inject(function ($compile, $rootScope){
        $scope = $rootScope.$new();
        compiledElement = $compile(angular.element('<div test-without-isolate-scope-directive></div>'))($scope);
        isolatedScope = compiledElement.isolateScope();
      }));
      it('element should compile', function () {
        expect(compiledElement).toBeDefined();
      });
      it('scope should isolate', function () {
        expect(isolatedScope).toBeDefined();
      });
    });
    
    0 讨论(0)
  • 2021-02-07 04:41

    I had the same problem. It seems that when calling $compile(element)($scope) in conjunction with using a templateUrl, the digest cycle isn't automatically started. So, you need to set it off manually:

    it('should work', function() {
        var el = $compile('<my-directive></my-directive>')($scope);
        $scope.$digest();    // Ensure changes are propagated
        console.log('Isolated scope:', el.isolateScope());
        el.isolateScope().save();
        expect($log.log).toHaveBeenCalled();
    });
    

    I'm not sure why the $compile function doesn't do this for you, but it must be some idiosyncracy with the way that templateUrl works, as you don't need to make the call to $scope.$digest() if you use an inline template.

    0 讨论(0)
提交回复
热议问题