1

I'm having trouble using isolated scope with templateUrl.

My directive test:

beforeEach(ngModule('app.directives'));
  var scope, compile
  beforeEach(inject(function($rootScope, $compile){
    scope = $rootScope.$new();
    compile = $compile;
  }));

  it('Replaces the element with the appropriate content', function(){
    var element = compile('<download-detail-header></download-detail-header>')(scope);
    expect(element.html()).to.equal('<p>Hello World!</p>');
  });

My directive:

function downloadDetailHeader() {
  return {
    restrict: 'EA',
    scope: {},
    template: '<p>Hello World!</p>'
    // templateUrl: 'download_detail_header/views/downloadHeader.html'
  }
}

downloadHeader.html

<p>Hello World!</p>

The test passes with template, seemingly because ng-isolate-scope is added to a class on the directive element. The test does not pass with the templateUrl provided, and no ng-isolate-scope is placed on the directive element.

Can anyone shed some light on this issue?

twsmith
  • 401
  • 4
  • 15
  • 1
    Is the template being loaded at least? It seems like a common issue, see http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates or http://stackoverflow.com/questions/15214760/unit-testing-angularjs-directive-with-templateurl – floribon Feb 19 '15 at 22:59
  • 2
    this isn't an issue with isolate scope, it's an issue with the `$templateCache`. The only solution is to load the templates manually in your test setup. – Claies Feb 19 '15 at 23:03

1 Answers1

1

@Claies comment is correct. When you reference a template file in a directive, angular has to fetch it. It defers compilation and linking until after it loads the template. Your test is evaluating the outcome before the template has been fetched.

You can include the template in a script tag or use the $templateCache.put() method to put the template in the cache manually before you run your test.

beforeEach(ngModule('app.directives'));
  var scope, compile
  beforeEach(inject(function($rootScope, $compile, $templateCache){
    scope = $rootScope.$new();
    compile = $compile;
    $templateCache.put('downloadHeader.html', '<p>Hello World!</p>');
  }));

  it('Replaces the element with the appropriate content', function(){
    var element = compile('<download-detail-header></download-detail-header>')(scope);
    expect(element.html()).to.equal('<p>Hello World!</p>');
  });
Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75
  • I don't think you need to put the template in the template cache. I usually just use a beforeEach() that calls the module() function and passes in the template path: `beforeEach(module('app.directives', 'download_detail_header/views/downloadHeader.html')); Although on second thought, you also need to use [karma-ng-html2js](https://github.com/karma-runner/karma-ng-html2js-preprocessor) for this to work. – Sunil D. Feb 20 '15 at 02:18