Using $templateCache to compile a custom directive in a jasmine test

1,591 views
Skip to first unread message

Brian Colwell

unread,
Sep 25, 2013, 11:57:59 AM9/25/13
to ang...@googlegroups.com

I am new to Angular and asking for help here so please bear with me.

I am trying to test a custom directive that uses a templateUrl. I am using Jasmine, Grunt, and the html2js Grunt plugin. I do not want to mock http request/response or use Karma.

My goal is to preload the template cache before my test and have angular resolve the directive html from the cache. I have extracted the js template from the file created by html2js to simplify my test temporarily. I cannot figure out why $compile does not inject the template into my test html. Here is my code:

beforeEach(inject(function($rootScope, $controller, $compile, $templateCache) {
    isolatedScope = $rootScope.$new();
    testCtrl = $controller('valueGaugeCtrl', {
        $scope: isolatedScope
    });
    $templateCache.put("App/Common/Widgets/ValueGauge.html",
  "<div ng-controller=\"valueGaugeCtrl\">\n" +
  " <div class=\"valueGauge\">\n" +
  "     <h4>{{gaugetype}}:</h4>\n" +
  "     <h2>{{technique[gaugetype]}}</h2>\n" +
  "     <div>\n" +
  "         <button ng-click=\"onPlusClick()\" class=\"btn-default glyphicon glyphicon-plus plusMinusButton\"></button>\n" +
  "         <button ng-click=\"onMinusClick()\" class=\"btn-default glyphicon glyphicon-minus plusMinusButton\"></button>\n" +
  "     </div>\n" +
  " </div>\n" +
  "</div>");
    html = '<value-gauge gaugetype="someType"></value-gauge>';
    vg = angular.element(html);
    linkFn = $compile(vg);

At this point I would expect vg to have been injected with my template html. Instead, only 'class="ng-isolate-scope ng-scope' has been injected into the original vg.

If I specify the template html inline in the custom directive (rather than using templateUrl), the $compile works as expected and injects the html into vg.

I know the template cache is being hit because I don't get any errors related to an unexpected http request when executing $compile.

Thanks very much in advance!

Brian Colwell

unread,
Sep 25, 2013, 9:33:13 PM9/25/13
to ang...@googlegroups.com
Sorry for directly quoting code in my first post.
Here is a fiddle that works but declares the directive template inline (which I do not want to do): http://jsfiddle.net/bstr72/c6nNU/
Here is a fiddle that does not work.  However, I'm not sure it has the same problem as my jasmine test since I had to adapt it a bit for fiddle: http://jsfiddle.net/bstr72/w2NQx/1/

umi

unread,
Sep 25, 2013, 11:11:02 PM9/25/13
to ang...@googlegroups.com
You're populating the template cache in the controller, which means it won't happen until it's instantiated and your directive will try to retrieve the template before that.
A better approach would be to populate the cache in the run phase. 

Another problem is you've declared a controller in your directive's template to refer to functions/properties in your directive's controller. This is not possible and not needed. The compiled template will have access to the directive's scope.

See this modified fiddle:
http://jsfiddle.net/aKtHA/I

Hope that helps.

umi

unread,
Sep 25, 2013, 11:21:41 PM9/25/13
to ang...@googlegroups.com
Just one more comment: I may be wrong on this but I believe angular populates $templateCache on it's own after retrieving a new partial. If that's true then there's no inherent benefit to pre-populating $templateCache.

Brian Colwell

unread,
Sep 26, 2013, 9:06:34 AM9/26/13
to ang...@googlegroups.com
Hi Umi,
   Thanks for your help!  The reason for pre-populating the template cache is for unit testing.  When manually compiling the template in my unit test, angular will try to fetch the templateUrl using an http request.  This request will fail because the http service is not available.  Pre-populating the template cache will allow angular to fetch the template html from the cache and avoid the http request.  Hope this helps, Brian
Reply all
Reply to author
Forward
0 new messages