3

I am trying to unit test an html template that has variables in paragraph, anchor tags, and {{header.title || translate}} however no matter what posts I have tried it does not seem to work. I get the retrieved HTML template and when it is compiled it is still the same. In the template I still see {{user}} for example. It seems none of them are actually being compiled.

Current Template Output:

<h1>{{header.title | translate}}</h1>
<h2>{{homeCtrl.name}}</h2>

Expected Output:

<h1>Cake Blogger</h1>
<h2>Alexandria</h2>

Test Suite:

(function() {
  'use strict';

  describe('home.tpl.html', function() {
    var scope, controller, createController, template, element, rootScope;

    beforeEach(module('Templates'));
    beforeEach(module('mainApp'));

    /**
      @name: home.tpl.html
      @description: Inject and set test related objects
      @param {Service} rootScope - Used to get the language
      @param {Compiler} $templateCache - Holding the compiled template
      @param {Injector} $compile - Compiles an HTML string or DOM
    */
    beforeEach(inject(
      function(_$controller_, _$rootScope_, $templateCache, $compile) {
        scope = _$rootScope_.$new();
        createController = function() {
          return _$controller_('homeCtrl', {
            '$scope': scope
         });
      };

      controller = createController();

      rootScope = _$rootScope_;
      template = $templateCache.get('home.tpl.html');
      element = $compile(template)(rootScope);

      // var ctrl = element.controller('homeCtrl');
      rootScope.$digest();
      console.log("home page", element);
  }));

  /**
    @name: Describe Block - home.tpl.html
    @description: Test cases related to home.tpl.html
  */
  describe('home.tpl.html tests', function() {
    fit('should have "Alexandria"', function() {
      expect(element.html()).toContain("Alexandria");
    });
  });
});
})();

Karma File:

files: ['list of files'],

port: 8080,

browsers: [
  'PhantomJS'
],

plugins: [
  'karma-phantomjs-launcher',
  'karma-jasmine',
  'karma-ng-html2js-preprocessor',
],

preprocessors: {
  'app/**/*.tpl.html': 'html2js'
},

ngHtml2JsPreprocessor: {
  'moduleName': 'Templates',
  'stripPrefix': 'app/'
}

package.json

{
  "name": "",
  "private": true,
  "devDependencies": {
    "autoprefixer-core": "^5.2.1",
    "grunt": "^0.4.5",
    "grunt-angular-templates": "^0.5.7",
    "grunt-concurrent": "^1.0.0",
    "grunt-contrib-clean": "^0.6.0",
    "grunt-contrib-compass": "^1.0.0",
    "grunt-contrib-concat": "^0.5.0",
    "grunt-contrib-connect": "^0.9.0",
    "grunt-contrib-copy": "^0.7.0",
    "grunt-contrib-cssmin": "^0.12.0",
    "grunt-contrib-htmlmin": "^0.4.0",
    "grunt-contrib-imagemin": "^1.0.0",
    "grunt-contrib-jshint": "^0.11.0",
    "grunt-contrib-uglify": "^0.7.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-filerev": "^2.1.2",
    "grunt-google-cdn": "^0.4.3",
    "grunt-jscs": "^1.8.0",
    "grunt-karma": "*",
    "grunt-modernizr": "^1.0.2",
    "grunt-newer": "^1.1.0",
    "grunt-ng-annotate": "^0.9.2",
    "grunt-ng-constant": "^2.0.1",
    "grunt-postcss": "^0.5.5",
    "grunt-svgmin": "^2.0.0",
    "grunt-usemin": "^3.0.0",
    "grunt-wiredep": "^2.0.0",
    "jasmine-core": "^2.4.1",
    "jit-grunt": "^0.9.1",
    "jshint-stylish": "^1.0.0",
    "karma": "^0.13.22",
    "karma-coverage": "^0.5.5",
    "karma-fixture": "^0.2.6",
    "karma-jasmine": "*",
    "karma-json-fixtures-preprocessor": "0.0.6",
    "karma-json-preprocessor": "^0.3.3",
    "karma-junit-reporter": "^1.2.0",
    "karma-ng-html2js-preprocessor": "~0.1.0",
    "karma-phantomjs-launcher": "*",
    "phantomjs": "^2.1.7",
    "time-grunt": "^1.0.0"
  },
  "engines": {
    "node": ">=0.10.0"
  },
  "scripts": {
    "test": "grunt test"
  },
  "dependencies": {}
}

According to posts I have read such as this plunker from a post plunker example, this should be working correctly. I am thinking perhaps the controller is not binding to the scope so that when $digest runs the template cannot find the controller maybe.

Helpful Information:

  • Where it says rootscope.$digest() I also tried it as scope.$digest(), I also tried using $apply().
  • I am using ngHtml2JsPreprocessor
  • I am using TemplateCache
  • I am using $compile

Links viewed:

The template returns but the angular in the template is never compiled. Always seeing {{homeCtrl.name}} instead of Alexandria.

Update 1.1

I am thinking perhaps since the translate {{header.title | translate}} is not working that maybe angular-translate (module: pascalprecht.translate) is not actually working correctly and is then causing the controller to also fail binding. Will continue investigation.

halfer
  • 19,824
  • 17
  • 99
  • 186
L1ghtk3ira
  • 3,021
  • 6
  • 31
  • 70

1 Answers1

1

After injecting angular-translate the | translate filter just works and yields expected translated value after $compile. See this plunker as an example:

http://plnkr.co/edit/j8rbnMI067YntllwTcGi?p=preview

One possible reason that leads to your issue is timing - suppose you have big translate array / json and it takes a while to load, but Jasmine testing already starts and finishes before they are fully loaded and ready. Then Jasmine will see un-translated string during tests.


Updated 2017-06-30

After a few experiments, I can confirm that any async json loader, whether it's .useStaticFilesLoader or $.getJSON(), will not be executed before jasmine. See http://plnkr.co/edit/nreUd52iqOVvwLPMNtJA?p=preview as an example, the static loader works fine for page view but fails unit test.

One possible way to go is to ditch .useStaticFilesLoader completely. Instead, we can use grunt-replace to inject the translations during the build process. Example grunt task:

// replace string with json
replace: {
  dist: {
    options: {
      patterns: [
        {
          match: /\"JSONEN\"/,
          replacement: '<%= grunt.file.read("app/resources/en.json") %>'
        }
      ]
    },
    files: [
      {expand: true, flatten: true, src: ['app/scripts/app.js'], dest: 'public/'}
    ]
  }
}
Linker
  • 56
  • 4
  • I had jasmine timeout in the test suite as well karma timeout in the karma.conf set to 10 seconds. Did not seem to make a difference. – L1ghtk3ira Jun 29 '17 at 13:24
  • So I added 500 lines to plunker and it still runs perfectly fine. I am thinking the error is project specific perhaps. – L1ghtk3ira Jun 29 '17 at 13:35
  • I don't see a bug really, you just have to know about that static files loader is asynchronous and $translate.instant is synchronous. So mixing these two is not a good idea with this setup. – L1ghtk3ira Jun 30 '17 at 15:04
  • english json file is: locale-en_US.json. Where are getting this 'public folder'? – L1ghtk3ira Jun 30 '17 at 15:46
  • tried switching to this: replacement: '<%= grunt.file.read("app/resources/locale-en_US.json") %>' – L1ghtk3ira Jun 30 '17 at 15:49