isolateScope () возвращает undefined при использовании templateUrl

17

У меня есть директива, которую я хочу удалить, но я столкнулся с проблемой, что я не могу получить доступ к моей изолированной области. Вот директива:

<my-directive></my-directive>

И код позади него:

angular.module('demoApp.directives').directive('myDirective', function($log) {
    return {
        restrict: 'E',
        templateUrl: 'views/directives/my-directive.html',
        scope: {},
        link: function($scope, iElement, iAttrs) {
            $scope.save = function() {
                $log.log('Save data');
            };

        }

    };
});

И вот мой unittest:

describe('Directive: myDirective', function() {
    var $compile, $scope, $log;

    beforeEach(function() {
        // Load template using a Karma preprocessor (http://tylerhenkel.com/how-to-test-directives-that-use-templateurl/)
        module('views/directives/my-directive.html');
        module('demoApp.directives');
        inject(function(_$compile_, _$rootScope_, _$log_) {
            $compile = _$compile_;
            $scope = _$rootScope_.$new();
            $log = _$log_;
            spyOn($log, 'log');
        });
    });

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

Но когда я распечатываю изолированную область, это приводит к undefined . Что меня действительно смущает, если вместо templateUrl я просто использую template в моей директиве, тогда все работает: isolateScope() имеет полностью scope объект в качестве возвращаемого значения, и все отлично. Тем не менее, при использовании templateUrl он ломается. Это ошибка в ng-mocks или в препроцессоре Karma?

Спасибо заранее.

    
задан J.P. ten Berge 05.02.2014 в 14:30
источник

5 ответов

17

У меня была та же проблема. Похоже, что при вызове $compile(element)($scope) в сочетании с использованием templateUrl цикл дайджеста не запускается автоматически. Итак, вам нужно установить его вручную:

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();
});

Я не уверен, почему функция $compile не делает этого для вас, но это должно быть какая-то идиосинкразия с тем, как работает templateUrl , так как вам не нужно делать вызов $scope.$digest() , если вы используете встроенный шаблон.

    
ответ дан fiznool 29.04.2014 в 22:37
источник
11

Мне нужно было высмеять и сбросить $httpBackend до того, как isolateScope() стало определено. Обратите внимание, что $scope.$digest() не имеет значения.

Директива

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

Тест:

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});
}));

Я использую Angular 1.3.

    
ответ дан Jeff Fairley 12.02.2015 в 19:44
источник
11

С Angularjs 1.3, если вы отключите debugInfoEnabled в конфигурации приложения:

$compileProvider.debugInfoEnabled(false);

isolateScope () также возвращает undefined !!!

    
ответ дан asicfr 09.09.2015 в 15:43
источник
1

Вы можете настроить плагин karma-ng-html2js-preprocessor . Он преобразует HTML-шаблоны в строку javascript и помещает их в службу $templateCache от Angular.

После установки moduleName в конфигурации вы можете объявить модуль в своих тестах, а затем все ваши шаблоны выпуска будут доступны без необходимости издеваться над ними с $httpBackend везде.

beforeEach(module('partials'));

Вы можете найти, как настроить плагин здесь: Ссылка     

ответ дан leonardoborges 28.08.2017 в 22:59
источник
0

В моем случае я продолжал сталкиваться с этим в тех случаях, когда я пытался изолировать область действия в директиве без свойства изоляции.

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();
  });
});
    
ответ дан Gus Crawford 05.01.2017 в 16:22
источник