Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do unit test with angular-translate

I have uses angular translate from here (http://pascalprecht.github.io/angular-translate/) and it's just work fine, but it break my controller's unit test whith Error:

Unexpected request: GET scripts/i18n/locale-en.json 

I don't understant why?

I use yeoman and test with karma.

app.js:

'use strict';  (function() {    angular.module('wbApp', ['authService', 'authUserService', 'checkUserDirective', 'ui.bootstrap', 'pascalprecht.translate'])     .config(function($routeProvider) {       $routeProvider         .when('/', {           templateUrl: 'views/login.html',           controller: 'LoginCtrl',           access: {             isFree: true           }         })         .when('/main', {           templateUrl: 'views/main.html',           controller: 'MainCtrl',           access: {             isFree: false           }         })         .otherwise({           redirectTo: '/'         });     });  })(); 

configTranslate.js:

'use strict';  (function() {    angular.module('wbApp')     .config(['$translateProvider',       function($translateProvider) {          $translateProvider.useStaticFilesLoader({             prefix: 'scripts/i18n/locale-',             suffix: '.json'         });          $translateProvider.preferredLanguage('en');        }]);  })(); 

karma.conf.js:

files = [    ...    'app/bower_components/angular-translate/angular-translate.js',   'app/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',    ...  ]; 

controller test:

'use strict';  describe('Controller: LoginCtrl', function() {    // load the controller's module   beforeEach(module('wbApp'));    var LoginCtrl, scope, location, httpMock, authUser;    // Initialize the controller and a mock scope   beforeEach(inject(function($controller, $rootScope, $location, $httpBackend, AuthUser) {     authUser = AuthUser;     location = $location;     httpMock = $httpBackend;     scope = $rootScope.$new();      LoginCtrl = $controller('LoginCtrl', {       $scope: scope     });       httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();    }));    it(...);    ...  }); 

if i add this in test controller, product same error:

httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(200); httpMock.flush(); 

or

httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough(); httpMock.flush(); 

i find this post How do I test controllers with Angular Translate initialized in App Config? but not helped me :/

I extensively use $httpBackend in my tests and it works fine, but in this case it is ineffective. If I comment the line:

$translateProvider.preferredLanguage('en'); 

obviously an error, if I add on the runtime (in my controllers)

$translate.uses(local); 

I end up with the same error?

So I turn to the translation configuration (configTranslate.js) or at runtime is the same result:

Unexpected request: GET scripts/i18n/locale-en.json 

Here is the syntax that I tested, either in a "beforeEach(inject(function(...});"

or in a test "it('...', function() {...});"

httpMock.expectGET('scripts/i18n/locale-en.json'); httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough(); httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(data); 

with at end

httpMock.flush(); 

I also tried a $ apply

httpMock.expectGET('scripts/i18n/locale-fr.json'); scope.$apply(function(){   $translate.uses('fr'); }); httpMock.flush(); 

nothing happens, Still this error is driving me crazy ..

If you have any suggestion

like image 257
bin Avatar asked Sep 18 '13 15:09

bin


People also ask

How is Angular unit testing done?

To run the test, you will only need to run the command ng test . This command will also open Chrome and run the test in watch mode, which means your test will get automatically compiled whenever you save your file. In your Angular project, you create a component with the command ng generate component doctor .

What is the best unit testing framework for Angular?

When it comes to the Angular world, Jasmine is the recommended testing framework. Angular CLI comes by default with Jasmine and Karma as the test runner. It generates test files at component creation, collects unit tests, runs karma, and displays results on a web page.

What is used to run unit tests in Angular?

You can execute the unit tests for your app via the CLI by running ng test from within the root, project directory. Upon running ng test , two things happen. First, Angular uses the Karma test runner to open up a new browser window that contains the reporting mechanism for your unit tests.

Can you conduct automated testing on Angular?

The Angular framework is a mature and comprehensive solution for enterprise-ready applications based on web technologies. At Angular's core lies the ability to test all application parts in an automated way.


2 Answers

it's a known issue, please follow the documentation here: unit testing angular

The solution

Unfortunately, this issue is caused by the design of angular-translate. To get around these errors, all we can do is to overwrite our module configuration in our test suite, that it doesn't use asynchronous loader at all. When there's no asynchronous loader, there's no XHR and therefore no error.

So how do we overwrite our module configuration at runtime for our test suite? When instantiating an angular module, we can always apply a inline function which is executed as configuration function. This configuration function can be used to overwrite the modules configuration since we have access to all providers.

Using the $provide provider, we can build a custom loader factory, which should then be used instead of the static files loader.

beforeEach(module('myApp', function ($provide, $translateProvider) {    $provide.factory('customLoader', function () {     // loader logic goes here   });    $translateProvider.useLoader('customLoader');  })); 

Please read more in the above link provided.

like image 173
nolimit Avatar answered Sep 19 '22 15:09

nolimit


We took the approach of ignoring the translation loader in unit tests, rather than being forced to modify each of the spec files.

One way to do it could be by separating the loader configuration to a separate file and then exclude it in karma.

So for example you can create a file app-i18n-loader.js (all other module configurations takes place in a different file):

    angular     .module('myApp')     .config(loaderConfig);  loaderConfig.$inject = ['$translateProvider', '$translatePartialLoaderProvider'];  function loaderConfig($translateProvider, $translatePartialLoaderProvider) {      $translateProvider.useLoader('$translatePartialLoader', {         urlTemplate: 'assets/i18n/{part}/{lang}.json'     });      $translatePartialLoaderProvider.addPart('myApp'); } 

And in your karma.conf.js exclude the file:

        files: [         'bower_components/angular/angular.js',         'bower_components/angular-mocks/angular-mocks.js',         //...         'bower_components/angular-translate/angular-translate.js',         'bower_components/angular-translate-loader-partial/angular-translate-loader-partial.js',         'app/**/*.mdl.js',         'app/**/*.js'     ],      exclude: [         'app/app-i18n-loader.js'     ], 

(Note: Answer edited to a solution that does not require grunt/gulp).

like image 24
Erez Cohen Avatar answered Sep 16 '22 15:09

Erez Cohen