Search code examples
angularjsunit-testingangularjs-directivegulpbrowserify

Gulp angular unit testing directive templateUrl


I read many post on internet and SO but couldn't find any solution that works I am trying to write unit test for a directive and want the html files to be served from template cache

I am using Gulp as a build tool

The gulp task for test looks like this

gulp.task('test', function (done) {
    karma.start({
        configFile:__dirname + '/' + config.test.karmaconf,
        singleRun: false
    }, done);
});

and in karma.conf , I have defined

    browserify: {
        debug: true,
        transform: [['browserify-ng-html2js', {
            module: 'templates',
            extension: 'html'
        }]]
    } 

In unit test , I declared

beforeEach(angular.mock.module('templates'));

but receiving

Error: Unexpected request: GET path/to/some.html
No more request expected
    at $httpBackend 

I also tried to use preprocessors and ngHtml2JsPreprocessor in karma.conf but no success. Could anyone provide solution or point me how can I go about debugging why the templates are not served?


Solution

  • Solution

    There are multiple ways you could go about doing that. Here's how I do it:

    1. Use gulp-angular-templatecache:
    gulp.task('bundle-common', function() {
      return merge(
        // Store all html files in $templateCache
        gulp.src([
          appDir + '/common/**/*.html'
        ])
        .pipe($$.angularTemplatecache({
          root: 'common'
        }))
    
        // Append everything else: directives, tests, etc.
        gulp.src([
          appDir + '/common/**/*.js'
        ])
      )
      .pipe($$.concat('common.js'))
      .pipe(gulp.dest('public/js/'));
    });
    

    This will output a file named common.js with all your html templates and directives in it.

    It will look somewhat like this:

    angular.module("templates").run(["$templateCache", function($templateCache) {
    $templateCache.put("common/a-great-eye.html","<div>lidless, wreathed in flame, 2 times</div>");}]);
    
    angular.module("common")
    
    .directive('aGreatEye', function () {
        return {
            restrict: 'E',
            replace: true,
            templateUrl: 'common/a-great-eye.html'
        };
    });
    
    ...
    
    1. In karma.conf.js load common.js:
         files: [
          '../vendor/jquery/dist/jquery.js',
          '../vendor/angular/angular.js',
          '../vendor/angular-mocks/angular-mocks.js',
          '../public/js/common.js'
        ]
    
    1. In your test file reference the templates module:
    describe('Unit testing great quotes', function() {
      var $compile,
          $rootScope;
    
      // Load the common module, which contains the directive
      beforeEach(function() {
        module('templates');
        module('common');
      });
    
      // Store references to $rootScope and $compile
      // so they are available to all tests in this describe block
      beforeEach(inject(function(_$compile_, _$rootScope_){
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $compile = _$compile_;
        $rootScope = _$rootScope_;
      }));
    
      it('Replaces the element with the appropriate content', function() {
        // Compile a piece of HTML containing the directive
        var element = $compile("<a-great-eye></a-great-eye>")($rootScope);
        // fire all the watches, so the scope expression {{1 + 1}} will be evaluated
        $rootScope.$digest();
        // Check that the compiled element contains the templated content
        expect(element.html()).toContain("lidless, wreathed in flame, 2 times");
      });
    });
    

    Debugging

    Start your test in Chrome browser and hit Debug button. Then open Developer Console.

    Few tips:

    • You can add breakpoints in your tests.
    • Make sure that there are no errors in console window, especially injection errors. If you do, verify that all the js files you requested in karma.config.js (they will be listed in Developer Console) are loaded correctly and contain the code you need (angular, templates, directives, etc.).