github twitter linkedin email
Testing Directives With Server-side Templates
Oct 13, 2015
2 minutes read

View code on Github


  • Project decides early on that the HTML files used by the AngularJS app will be served via the backend application (ASP.NET MVC) for use of localisation (i18n) via Razor tags.
  • While the paths generally follow convention, they do not match the file structure at all. They are organised in the project in areas (think modules) along with their respective Javascript code.

Example directive structure ~/areas/common/modules/header/header.js ~/areas/common/modules/header/templates/header.cshtml


angular.module('myapp').directive('header', function() {
   return {
      restrict: 'E',
      templateUrl: 'common/header/header',
      controller: [...]

So when it came to testing, we could only really do unit tests on the controllers, services etc as they were simple to resolve. Any time spent resolving this resulted in a dead-end as ng-html2js wants the templateUrl to mirror the file structure.

There are some configurable settings such as moduleName and cacheIdFromPath which I did get to work, rather hackily, but this is a better solution. I had to write a load of code which I felt should be in the library itself.

Example usage of the forked library in the karma config file.

// karma.conf.js
module.exports = function(config) {
    preprocessors: {
      'Areas/Common/Modules/**/*.cshtml': ['ng-html2js-custom'],

    files: [
      // if you wanna load template files in nested directories, you must use this

    // if you have defined plugins explicitly, add karma-ng-html2js-preprocessor
    // plugins: [
    //     <your plugins>
    //     'karma-ng-html2js-preprocessor',
    // ]

    ngHtml2JsPreprocessor: {
      maps: {
        'Areas/Common/Modules/**/Templates/': 'common/{0}/'
      fileNameFormatter: function(fileName) {
        if (fileName.indexOf('.cshtml') > -1) {
          // Camel to file case
          var formatted = fileName.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
          return formatted.replace('.cshtml', '').toLowerCase();

        return fileName;

Back to posts

comments powered by Disqus