Jasmine tests AngularJS Directives with templateUrl

I'm writing directive tests for AngularJS with Jasmine, and using templateUrl with them: https://gist.github.com/tanepiper/62bd10125e8408def5cc

However, when I run the test I get the error included in the gist:

Error: Unexpected request: GET views/currency-select.html

From what I've read in the docs I thought I was doing this correctly, but it doesn't seem so - what am I missing here?

Thanks

When you use ngMockE2E or ngMock, all HTTP requests are processed locally using rules you specify and none are passed to the server. Since templates are requested via HTTP, they too are processed locally. Since you did not specify anything to do when your app tries to connect to views/currency-select.html, it tells you it doesn't know how to handle it. You can easily tell ngMockE2E to pass along your template request:

$httpBackend.whenGET('views/currency-select.html').passThrough();

Remember that you can also use regular expressions in your routing paths to pass through all templates if you'd like.

The docs discuss this in more detail: http://docs.angularjs.org/api/ngMockE2E.$httpBackend

Update

FYI, you'll need to use the $injector to access the new backend. From the linked docs:

var $httpBackend;
beforeEach(inject(function($injector) {
  $httpBackend = $injector.get('$httpBackend');
  $httpBackend.whenGET('views/currency-select.html').respond(200, '');
}));

the Karma way is to load the template html dynamically into $templateCache. you could just use html2js karma pre-processor, as explained here

this boils down to adding templates '.html' to your files in the conf.js file as well preprocessors = { '.html': 'html2js' };

and use

beforeEach(module('..'));

beforeEach(module('...html', '...html'));

into your js testing file

If this is still not working , use fiddler to see the content of the js file dynamically generated by htmltojs processor and check the path of template file.

It should be something like this

angular.module('app/templates/yourtemplate.html', []).run(function($templateCache) {
  $templateCache.put('app/templates/yourtemplate.html', 

In my case , it was not same as I had in my actual directive which was causing the issue.

Having the templateURL exactly same in all places got me through.

As requested, converting a comment to an answer.


For the people who want to make use of @Lior's answer in Yeoman apps:

Sometimes the way the templates are referenced in karma config and consequently - the names of modules produced by ng-html2js don't match the values specified as templateUrls in directive definitions.
You will need adjusting generated module names to match templateUrls.
These might be helpful:

You could perhaps get the $templatecache from the injector and then do something like

$templateCache.put("views/currency-select.html","<div.....>");

where in place of <div.....> you would be putting your template.

After that you setup your directive and it should work just fine!

this is example how to test directive that use partial as a templateUrl

describe('with directive', function(){
  var scope,
    compile,
    element;

  beforeEach(module('myApp'));//myApp module

  beforeEach(inject(function($rootScope, $compile, $templateCache){
   scope = $rootScope.$new();
   compile = $compile;

   $templateCache.put('view/url.html',
     '<ul><li>{{ foo }}</li>' +
     '<li>{{ bar }}</li>' +
     '<li>{{ baz }}</li>' +
     '</ul>');
   scope.template = {
     url: 'view/url.html'
    };

   scope.foo = 'foo';
   scope.bar = 'bar';
   scope.baz = 'baz';
   scope.$digest();

   element = compile(angular.element(
    '<section>' +
      '<div ng-include="template.url" with="{foo : foo, bar : bar, baz : baz}"></div>' +
      '<div ng-include="template.url" with=""></div>' +
    '</section>'
     ))(scope);
   scope.$digest();

 }));

  it('should copy scope parameters to ngInclude partial', function(){
    var isolateScope = element.find('div').eq(0).scope();
    expect(isolateScope.foo).toBeDefined();
    expect(isolateScope.bar).toBeDefined();
    expect(isolateScope.baz).toBeDefined();
  })
});

If you are using the jasmine-maven-plugin together with RequireJS you can use the text plugin to load the template content into a variable and then put it in the template cache.


define(['angular', 'text!path/to/template.html', 'angular-route', 'angular-mocks'], function(ng, directiveTemplate) {
    "use strict";

    describe('Directive TestSuite', function () {

        beforeEach(inject(function( $templateCache) {
            $templateCache.put("path/to/template.html", directiveTemplate);
        }));

    });
});