0

I am using angular-translate in my application and when writing unit-tests they are failing with error

  Error: Unexpected request: GET /src/app/modules/login/resources/en.json
      No more request expected

This is how my karma.config looks like:

'use strict';

var baseDir = 'client';

module.exports = {

  //This is the list of file patterns to load into the browser during testing.
  files: [
    baseDir + '/src/vendor/angular/angular.js',
    baseDir + '/src/vendor/angular-mocks/angular-mocks.js',
    baseDir + '/src/vendor/angular-ui-router/release/angular-ui-router.js',
    baseDir + '/src/vendor/angular-bootstrap/ui-bootstrap.min.js',
    baseDir + '/src/vendor/angular-bootstrap/ui-bootstrap-tpls.min.js',
    baseDir + '/src/vendor/angular-translate/angular-translate.js',
    baseDir + '/src/vendor/angular-translate-loader-partial/angular-translate-loader-partial.js',
    baseDir + '/src/app/modules/home/home.module.js',
    baseDir + '/src/app/modules/login/login.module.js',
    baseDir + '/src/app/app.js',
    baseDir + '/src/app/**/*.js',
    baseDir + '/src/app/modules/**/*.html',
    baseDir + '/test/unit/**/*.spec.js'
  ],

  //used framework
  frameworks: ['jasmine'],

  plugins: [
    'karma-chrome-launcher',
    'karma-phantomjs-launcher',
    'karma-jasmine',
    'karma-coverage',
    'karma-html-reporter',
    'karma-mocha-reporter',
    'karma-ng-html2js-preprocessor'
  ],

  preprocessors: {
    '**/client/src/**/*.js': 'coverage',
    '**/client/src/**/*.html': ['ng-html2js']
  },

  reporters: ['mocha', 'html', 'coverage'],

  coverageReporter: {
    type: 'html',
    dir: baseDir + '/test/unit-results/coverage',
    file: 'coverage.html'
  },

  htmlReporter: {
    outputDir: baseDir + '//test/unit-results/html'
  },

  ngHtml2JsPreprocessor: {
    moduleName: 'templates',
    cacheIdFromPath : function(filepath) {
      return filepath.substr(filepath.indexOf("appname")+8);
    }
  },

  logLevel: 'info',

  urlRoot: '/__test/',

  //used browsers (overriding in some gulp task)
  browsers: ['PhantomJS']
};

I already tried some solutions like adding angular-translate to new .js file instead of app.js file and then exclude that file in karma.config.js. Here is also short code of my test. Maybe I can somehow ignore this en.json file or?

/* jshint undef:false*/
(function() {
  'use strict';

  describe('LoginCtrl', function() {
    var loginController, rootScope, q, state, mockLoginService, mockSessionService, scope;
    var mockupUser = {username: 'Test', password: 'Test1'};
    var mockupBadUser = {username: 'Test', password: 'Test123'};

    beforeEach(module('app'));
    beforeEach(module('login'));
    beforeEach(inject(function($rootScope, $controller, $q, $state, _LoginService_, _SessionService_) {
      rootScope = $rootScope;
      scope = rootScope.$new();
      q = $q;
      state = $state;
      mockLoginService = _LoginService_;
      mockSessionService = _SessionService_;
      //spyOn(mockLoginService , 'userLogin').and.returnValue(q.when({}));
      loginController = $controller('LoginCtrl as loginvm', {
        $scope : scope,
        mockLoginService : _LoginService_,
        mockSessionService : _SessionService_
      });
    }));
    describe('loginUser with good credentials',function(){
      beforeEach(function(){
        spyOn(mockLoginService , 'userLogin').and.callFake(function(mockupUser) {
          var deferred = q.defer();
          if (mockupUser.username === "Test" && mockupUser.password === "Test1") {
            deferred.resolve(mockupUser);
          }
          else {
            deferred.reject();
          }
          return deferred.promise;
        });
        spyOn(state, 'go');
        spyOn(mockSessionService, 'setUser');
      });
      it("should call loginUser from LoginService with good credentials", function() {
        var expectedState = 'root.home';
        loginController.loginUser(mockupUser);

        rootScope.$digest();

        expect(mockLoginService.userLogin).toHaveBeenCalledWith(mockupUser);
        expect(mockSessionService.setUser).toHaveBeenCalled();
        expect(state.go).toHaveBeenCalledWith(expectedState);
      });
    });
    describe('loginUser with bad credentials',function(){
      beforeEach(function(){
        spyOn(mockLoginService , 'userLogin').and.callFake(function(mockupBadUser) {
          var deferred = q.defer();
            deferred.reject();

          return deferred.promise;
        });
      });
      it("should call loginUser from LoginService with bad credentials", function() {
        loginController.loginUser();

        rootScope.$digest();

        expect(mockLoginService.userLogin).toHaveBeenCalled();
      });
    });
  });
})();

Update for Zakaria answer

beforeEach(function(){
    var $injector, $httpBackend;
    $injector = angular.injector (['ngMock']);
    $httpBackend = $injector.get ('$httpBackend');
    $httpBackend.whenGET("/src/app/modules/home/resources/en.json").respond({ title: 'Title' });
    $httpBackend.whenGET("/src/app/modules/login/resources/en.json").respond({ title: 'Title' });
  });

  describe('HomeCtrl', function() {
    var homeController, rootScope, q, state, mockDataService, mockSessionService, scope, modal;
    var mockupUsers = [....

I tried to add one of the test and they are still failing... Only solution that is working is as I said earlier to add these two lines:

$httpBackend.whenGET("/src/app/modules/home/resources/en.json").respond({ title: 'Title' });
    $httpBackend.whenGET("/src/app/modules/login/resources/en.json").respond({ title: 'Title' });

in every unit test.... I also tried to just add this lins in karma.config:

 baseDir + '/test/unit/**/*.spec.js',
  {
    pattern:  baseDir + '/src/app/modules/**/*.json',
    included: false,
    served: true
 ],

but no success either...

Micko
  • 431
  • 8
  • 27
  • Did you try adding your ".json" in the karma's config file (in the file pattern area) ? – Zakaria Sep 13 '16 at 15:46
  • I tried adding this lines in files:[] in karma.config but no success... same error.. { pattern: baseDir + '/src/app/modules/login/resources/en.json', watched: true, served: true, included: false }, { pattern: baseDir + '/src/app/modules/home/resources/en.json', watched: true, served: true, included: false } – Micko Sep 13 '16 at 16:12

2 Answers2

1

You can use the $httpBackend service to serve a mocked translate file :

$httpBackend.whenGET("/src/app/modules/login/resources/en.json").respond({ title: 'Title' });

Edit To avoid repeating your beforeEaches (as your $httpBackend.whenGET should appear there) you can refer to this post that solves the problem of test duplication.

Community
  • 1
  • 1
Zakaria
  • 14,892
  • 22
  • 84
  • 125
  • this is working. But one problem with this is for every .js file that i will create in futureand that is using translate in unit test for that file, I would need in beforeEach(inject(...)) to add lines like you send me for all en.json files... – Micko Sep 13 '16 at 16:04
  • for example for another home controller unit test I needed to add two lines: $httpBackend.whenGET("/src/app/modules/home/resources/en.jso‌​n").respond({ title: 'Title' }); $httpBackend.whenGET("/src/app/modules/login/resources/en.js‌​on").respond({ title: 'Title' }); – Micko Sep 13 '16 at 16:32
0

After some hours spent searching and trying for solution I found one... Just add this code in unit test when registering module:

beforeEach(module('myApp', function ($provide, $translateProvider) {

  $provide.factory('customLoader', function ($q) {
    return function () {
      var deferred = $q.defer();
      deferred.resolve({});
      return deferred.promise;
    };
  });

  $translateProvider.useLoader('customLoader');

}));

https://angular-translate.github.io/docs/#/guide/22_unit-testing-with-angular-translate

Micko
  • 431
  • 8
  • 27