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
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 .
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.
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.
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.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With