3

I'm using Node.js with Express and Jade in my web application, with AngularJS on top. Usually, when I build directives, I include Html in the template of the directive definition, and then I test the directive writing the Html snippet I need. But now I have to write a directive that includes a very long HTML, so I'm using the templateUrl: moreover I want to do it using Jade. So the code looks like this:

[...]
.directive('myDirective', function () {
    return {
        restrict: 'E',
        templateUrl: '/snippet',
        link: function (scope, element, attrs) {
            // some code
        }
    };
});

Where the server handle the call to /snippet with this:

app.get('/snippet', function (req, res) {
    res.render('templates/mySnippet', {}, 
        function (err, rendered) {
            if (!err)
                res.status(200).send(rendered);
        });
});

So my problem is: how can I test this directive? I usually make unit test with Karma and Mocha/Chai: does it exist any plugin for karma that can take the jade file, process it and serve it as a fake server when my directive will search for /snippet?

napcoder
  • 465
  • 1
  • 4
  • 14
  • 1
    if your jade templates are stateless (aka not depending on server data) , which I hope, you should precompilate them instead of serving them from your server, using grunt, gulp, or any js project manager. This would greatly facilitate the testing steps ( which can also be launching from grunt / glup / other) If they (the templates) are not stateless - well, make them, because they should. – Pierre Gayvallet Nov 06 '14 at 17:35
  • @PierreGayvallet do you mean it is bettere to precompile only for tests or do you mean to precompile also for normal page serving by server? Of course my template page is stateless. – napcoder Nov 07 '14 at 09:06
  • It's better to precompilate also for 'normal' page, this way, you handle the tpl compilation the same way for test phase and run / production phase ( also you avoid compilate you jade template each time a request is sent for this template ) – Pierre Gayvallet Nov 07 '14 at 09:10
  • [connect-jade-static](https://github.com/runk/connect-jade-static) might come in handy. – laggingreflex Nov 09 '14 at 07:10
  • @PierreGayvallet you are right, now I have my partial views preprocessed with grunt-contrib-jade and I can test them through karma-ng-html2js-preprocessor. If you rewrite your comment as an answer I can set this question as answered. – napcoder Nov 10 '14 at 14:56
  • @laggingreflex it can be a valid solution for runtime optimization, but considering I'm developing using TTD, a task that will generate the html file every time I launch the tests without start the web server is a better choice imho – napcoder Nov 10 '14 at 14:58

1 Answers1

2

I am using gulp (not grunt) with Jade templates in a project bootstrapped with yeoman gulp-angular generator. In order to make the Jasmine unit tests work properly, I needed to make the following changes:

In gulp/unit-tests.js:

     var htmlFiles = [
-      options.src + '/**/*.html'
+      options.src + '/**/*.html',
+      options.tmp + '/serve/**/*.html' // jade files are converted to HTML and dropped here
     ];
...
-  gulp.task('test', ['scripts'], function(done) {
+  gulp.task('test', ['markups','scripts'], function(done) {
     runTests(true, done);
   });

In karma.conf.js:

     ngHtml2JsPreprocessor: {
-      stripPrefix: 'src/',
-      moduleName: 'gulpAngular'
+      cacheIdFromPath: function(filepath) {
+                         // jade files come from .tmp/serve so we need to strip that prefix
+                         return filepath.substr(".tmp/serve/".length);
+                       },
+      moduleName: 'myAppTemplates'
     },
...
 preprocessors: {
-      'src/**/*.html': ['ng-html2js']
+      // jade templates are converted to HTML and dropped here
+      '.tmp/serve/**/*.html': ['ng-html2js']
 }

Here is a unit test file for a footer directive:

'use strict';

describe('Unit testing footer', function() {
  var $compile,
      $rootScope;

  // Load the myApp module, which contains the directive
  beforeEach(module('myApp'));
  beforeEach(module('myAppTemplates')); // generated in karma.conf

  // 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('<footer/>')($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('Copyright');
  });
});
zsteinkamp
  • 130
  • 9