Ich habe Winkelübersetzen von hier verwendet ( http://pascalprecht.github.io/angular-translate/ ) und es funktioniert einfach, aber es bricht den Unit-Test meines Controllers mit Fehler:
Unexpected request: GET scripts/i18n/locale-en.json
Ich verstehe nicht warum?
Ich benutze Yeoman und teste mit 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(...);
...
});
wenn ich dies in Test Controller hinzufüge, wird der gleiche Fehler angezeigt:
httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(200);
httpMock.flush();
oder
httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
httpMock.flush();
ich finde diesen Beitrag Wie teste ich Controller mit Angular Translate, die in App Config initialisiert wurden? aber mir hat nicht geholfen: /
Ich benutze $ httpBackend ausgiebig in meinen Tests und es funktioniert gut, aber in diesem Fall ist es unwirksam. Wenn ich die Zeile kommentiere:
$translateProvider.preferredLanguage('en');
natürlich ein Fehler, wenn ich zur Laufzeit (in meinen Controllern) hinzufüge
$translate.uses(local);
Ich ende mit dem gleichen Fehler?
Also wende ich mich an die Übersetzungskonfiguration (configTranslate.js) oder zur Laufzeit ist das gleiche Ergebnis:
Unexpected request: GET scripts/i18n/locale-en.json
Hier ist die Syntax, die ich getestet habe, entweder in "beforeEach (inject (function (...));"
oder in einem 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);
mit am Ende
httpMock.flush();
Ich habe auch versucht ein $ bewerben
httpMock.expectGET('scripts/i18n/locale-fr.json');
scope.$apply(function(){
$translate.uses('fr');
});
httpMock.flush();
nichts passiert, immer noch dieser Fehler macht mich verrückt ..
Wenn Sie einen Vorschlag haben
es ist ein bekanntes Problem, bitte folgen Sie der Dokumentation hier: Einheitstestwinkel
Die Lösung
Leider wird dieses Problem durch das Design von .__ verursacht. Winkelübersetzen. Um diese Fehler zu umgehen, können wir nur Überschreiben Sie unsere Modulkonfiguration in unserer Testsuite. Verwenden Sie asynchronen Lader überhaupt. Wenn kein asynchroner Lader vorhanden ist, Es gibt kein XHR und daher keinen Fehler.
Wie überschreiben wir unsere Modulkonfiguration zur Laufzeit für unser Testsuite? Wenn Sie ein Winkelmodul instanziieren, können Sie immer eine Inline-Funktion, die als Konfigurationsfunktion ausgeführt wird. Diese Konfigurationsfunktion kann zum Überschreiben der Module verwendet werden Konfiguration, da wir Zugriff auf alle Anbieter haben.
Mit dem Provider $ Provider können wir eine benutzerdefinierte Loader-Factory erstellen, Diese sollte dann anstelle des statischen Dateiladers verwendet werden.
beforeEach(module('myApp', function ($provide, $translateProvider) {
$provide.factory('customLoader', function () {
// loader logic goes here
});
$translateProvider.useLoader('customLoader');
}));
Bitte lesen Sie mehr im obigen Link.
Wir haben den Ansatz verfolgt, das Übersetzungsladeprogramm in Komponententests zu ignorieren, anstatt jede Spezifikationsdatei zu ändern.
Eine Möglichkeit, dies zu tun, besteht darin, die Loader-Konfiguration in eine separate Datei zu trennen und sie dann in Karma auszuschließen.
So können Sie beispielsweise eine Datei app-i18n-loader.js erstellen (alle anderen Modulkonfigurationen finden in einer anderen Datei statt):
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');
}
Und in Ihrer karma.conf.js schließen Sie die Datei aus:
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'
],
(Hinweis: Beantworten Sie die Antwort auf eine Lösung, für die kein Grunzen/Schlucken erforderlich ist).
Ich wollte eine Lösung
Dies ist, was ich endete mit:
// you need to load the 3rd party module first
beforeEach(module('pascalprecht.translate'));
// overwrite useStaticFilesLoader to get rid of request to translation file
beforeEach(module(function ($translateProvider) {
$translateProvider.useStaticFilesLoader = function () {
};
}));
Vorausgesetzt, Sie benötigen nicht die eigentlichen Übersetzungen für Ihre Komponententests, funktioniert dies hervorragend. Legen Sie das beforeEach einfach auf eine globale Ebene, vorzugsweise in eine eigene Datei im Testordner. Sie wird dann vor jedem zweiten Test ausgeführt.
Dieses Problem ist bei Winkelstücktests aufgetreten. Meine Lösung bestand darin, Übersetzungen wie folgt zu simulieren:
angular.module('app')
.config(function ($translateProvider) {
$translateProvider.translations('en', {});
$translateProvider.preferredLanguage('en');
})
Jetzt werden keine Sprachdateien heruntergeladen, keine Zeichenketten werden übersetzt und ich teste nur anhand der Zeichenfolgenschlüssel in den Spezifikationen:
expect(element(by.css('#title')).getText()).toEqual('TITLE_TEXT');
Bitte schauen Sie als Referenz nach https://github.com/PascalPrecht/angular-translate/blob/master/test/unit/service/loader-static-files.spec.js .
Im Allgemeinen würde ich die Verwendung eines Standard-Übersetzungsladeprogramms für Komponententests (ohne den Aufwand von http-Ladungen) empfehlen, was bedeutet, dass Sie die Beschriftungen mit $translateProvider.translations()
versehen können. Warum? Weil Sie die Fernladefunktionalität, die Teil des Projektes für die Winkelübersetzung ist, nicht testen müssen.
Versuchen Sie, die Methode zu testen:
it('should ...', function() {
httpMock.when('GET', 'scripts/i18n/locale-en.json').respond({});
httpMock.expectGET('scripts/i18n/locale-en.json');
scope.resetForm(); // Action which fires a http request
httpMock.flush(); // Flush must be called after the http request
}
Siehe Beispiele aus Angular docs
Keine der Lösungen funktionierte für mich, aber ich kam mit diesen Lösungen:
1) Wenn Sie scope.$apply()
verwenden müssen oder sich in Ihrem Test mit Status befassen sollten (nach $apply()
funktioniert der 2. Ansatz nicht), überschreiben Sie die Übersetzungen Ihrer App mit $translateProvider.translations()
-Methode, die ein Plugin verwendet, um JSON-Dateien zu laden
beforeEach(module(function ($translateProvider) {
$translateProvider.translations('en', readJSON('scripts/i18n/locale-en.json'));
}));
2) Wenn Ihr getesteter Controller vom Dienst $translate
Abhängt, können Sie ein Plugin verwenden, um JSON-Dateien laden und es mit $httpBackend
Zu kombinieren, um Ihre Gebietsschemadatei zu laden, wenn winklig- übersetze Anfragen dazu.
beforeEach(inject(function (_$httpBackend_) {
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('scripts/i18n/locale-en.json').respond(readJSON('scripts/i18n/locale-en.json'));
$httpBackend.flush();
})));
Beachten Sie, dass dies unter Ihrem beforeEach(module('myApp'));
liegen sollte, da sonst ein $injector
- Fehler angezeigt wird.
Ich habe einen einfachen Mock-Service für $ translate gemacht
$translate=function (translation) {
return {
then: function (callback) {
var translated={};
translation.map(function (transl) {
translated[transl]=transl;
});
return callback(translated);
}
}
};
Nutzungsbeispiel hier: https://Gist.github.com/dam1/5858bdcabb89effca457
Die Antwort darauf lautet 2016, Ihren Json in Ihre Tests vorzubereiten und die Übersetzungsarbeit Ihrer Richtlinien entsprechend zu testen.
Ich verwende karma-ng-json2js-Präprozessor. Befolgen Sie alle Schritte, um Ihre karma.conf in Ihrer Testdatei einzurichten, stellen Sie die entsprechende Datei als Modul voran und stellen Sie diese Informationen in $ translateProvider ein.
beforeEach(module('myApp', '/l10n/english-translation.json'));
// Mock translations for this template
beforeEach(module(function($translateProvider, englishTranslation) {
$translateProvider.translations('en_us', englishTranslation);
$translateProvider.useSanitizeValueStrategy(null);
$translateProvider.preferredLanguage('en_us');
}));
Beachten Sie entsprechend dem Plugin, dass es Ihren Dateinamen verwendet, um einen Kamelennamen zu generieren. Sie können mit der Funktion in/lib des Moduls spielen, im Grunde werden jedoch alle Bindestriche entfernt, aber KEEPS unterstrichen in einem camelCase. So wird en_us zu En_us.
Sie müssen Ihrem Test auch mitteilen, dass er diese Datei als GEt erwartet.
$httpBackend.expect('GET', '/l10n/english-translation.json').respond(200);
Ich benutze dieses Muster.
// application module .js
(function() {
'use strict';
angular
.module('applicationModule', [
'ngAnimate',
'ngResource',
'ui.router',
'pascalprecht.translate'
])
.config(['$stateProvider', '$urlRouterProvider', '$translateProvider', '$translatePartialLoaderProvider', config]);
function config($stateProvider, $urlRouterProvider, $translateProvider, $translatePartialLoaderProvider) {
// set routing ...
$translateProvider.useStaticFilesLoader({
prefix: 'i18n/locale-',
suffix: '.json'
});
$translateProvider.useMessageFormatInterpolation();
$translateProvider.fallbackLanguage(['en']);
$translateProvider
.registerAvailableLanguageKeys(['en', 'ko'], {
'en_US': 'en',
'ko_KR': 'ko'
})
.determinePreferredLanguage(navigator.browserLanguage);
$translateProvider.addInterpolation('$translateMessageFormatInterpolation');
$translateProvider.useSanitizeValueStrategy('escaped');
}
})();
// test.module.js
(function() {
'use strict';
angular
.module('testModule', ['applicationModule'])
.config(['$translateProvider', '$translatePartialLoaderProvider', config])
.run(['$httpBackend', run]);
function config($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'i18n/locale-en.json'
});
$translatePartialLoaderProvider.addPart('applicationModule');
}
function run($httpBackend) {
$httpBackend.when('GET', 'i18n/locale-en.json').respond(200);
}
})();
// someDirective.spec.js
describe("a3Dashboard", function() {
beforeEach(module("testModule"))
var element, $scope;
beforeEach(inject(function($compile, $rootScope) {
$scope = $rootScope;
element = angular.element("<div>{{2 + 2}}</div>");
$compile(element)($rootScope)
}))
it('should equal 4', function() {
$scope.$digest();
expect(element.html()).toBe("4");
})
})
Spät am Tisch damit, aber ich bin damit umgekommen, indem ich angab, dass Karma die Dateien einfach gemäß diesem Eintrag in karma.conf.js
bereitstellt:
files: [
...
{pattern: 'scripts/i18n/*.json', included: false, served: true},
...
]