J'écris des tests de directives pour AngularJS avec Jasmine et j'utilise templateUrl avec eux: https://Gist.github.com/tanepiper/62bd10125e8408def5cc
Cependant, lorsque j'exécute le test, j'obtiens l'erreur incluse dans le Gist:
Error: Unexpected request: GET views/currency-select.html
D'après ce que j'ai lu dans les documents, je pensais que je faisais cela correctement, mais il ne semble pas que ce soit - qu'est-ce qui me manque ici?
Merci
toutes les requêtes HTTP sont traitées localement à l'aide des règles que vous spécifiez et aucune n'est transmise au serveur. Étant donné que les modèles sont demandés via HTTP, ils sont également traités localement. Étant donné que vous n'avez rien spécifié à faire lorsque votre application tente de se connecter à views/currency-select.html
, il vous indique qu'il ne sait pas comment le gérer. Vous pouvez facilement dire à ngMockE2E de transmettre votre demande de modèle:
$httpBackend.whenGET('views/currency-select.html').passThrough();
N'oubliez pas que vous pouvez également utiliser des expressions régulières dans vos chemins de routage pour parcourir tous les modèles si vous le souhaitez.
Les docs en discutent plus en détail: http://docs.angularjs.org/api/ngMockE2E.$httpBackend
Vous devrez utiliser le $injector
pour accéder au nouveau backend. À partir des documents liés:
var $httpBackend;
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('views/currency-select.html').respond(200, '');
}));
la manière Karma est de charger dynamiquement le modèle html dans $ templateCache. vous pouvez simplement utiliser le pré-processeur html2js karma, comme expliqué ici
cela revient à ajouter des modèles '. html' à vos fichiers dans le fichier conf.js ainsi que des préprocesseurs = {'. html': 'html2js' };
et utilise
beforeEach(module('..'));
beforeEach(module('...html', '...html'));
dans votre fichier de test js
S'il s'agit d'un test unitaire, vous n'aurez pas accès à $httpBackend.passthrough()
. Cela n'est disponible que dans ngMock2E2, pour des tests de bout en bout. Je suis d'accord avec les réponses impliquant ng-html2js
(Anciennement nommé html2js) mais je voudrais les développer pour fournir une solution complète ici.
Pour rendre votre directive, Angular utilise $http.get()
pour récupérer votre modèle à partir de templateUrl
. Parce que c'est un test unitaire et que angular-mocks
Est chargé , angular-mocks
Intercepte l'appel à $http.get()
et vous donne l'erreur Unexpected request: GET
. Vous pouvez essayer de trouver des moyens de contourner cela, mais il est beaucoup plus simple d'utiliser simplement les angulaires $templateCache
Pour précharger vos modèles. De cette façon, $http.get()
ne sera même pas un problème.
C'est ce que le préprocesseur ng-html2js fait pour vous. Pour le faire fonctionner, installez-le d'abord:
$ npm install karma-ng-html2js-preprocessor --save-dev
Configurez-le ensuite en ajoutant/mettant à jour les champs suivants dans votre karma.conf.js
{
files: [
//
// all your other files
//
//your htmp templates, assuming they're all under the templates dir
'templates/**/*.html'
],
preprocessors: {
//
// your other preprocessors
//
//
// tell karma to use the ng-html2js preprocessor
"templates/**/*.html": "ng-html2js"
},
ngHtml2JsPreprocessor: {
//
// Make up a module name to contain your templates.
// We will use this name in the jasmine test code.
// For advanced configs, see https://github.com/karma-runner/karma-ng-html2js-preprocessor
moduleName: 'test-templates',
}
}
Enfin, dans votre code de test, utilisez le module test-templates
Que vous venez de créer. Ajoutez simplement test-templates
À l'appel de module que vous effectuez généralement dans beforeEach
, comme ceci:
beforeEach(module('myapp', 'test-templates'));
La navigation devrait être fluide à partir de maintenant. Pour un examen plus approfondi de ce scénario et d'autres scénarios de test de directive, consultez cet article
Vous pourriez peut-être obtenir le $templatecache
de l'injecteur, puis faites quelque chose comme
$templateCache.put("views/currency-select.html","<div.....>");
où à la place de <div.....>
vous mettriez votre modèle.
Après cela, vous configurez votre directive et cela devrait très bien fonctionner!
Comme demandé, convertir un commentaire en réponse.
Pour les personnes qui souhaitent utiliser la réponse de @ Lior dans les applications Yeoman :
Parfois, la façon dont les modèles sont référencés dans karma config et par conséquent - les noms des modules produits par ng-html2js
ne correspond pas aux valeurs spécifiées comme templateUrl
s dans les définitions de directive.
Vous devrez ajuster les noms des modules générés pour qu'ils correspondent à templateUrl
s.
Ceux-ci pourraient être utiles:
Si cela ne fonctionne toujours pas, utilisez fiddler pour voir le contenu du fichier js généré dynamiquement par le processeur htmltojs et vérifiez le chemin du fichier modèle.
Ça devrait être quelque chose comme ça
angular.module('app/templates/yourtemplate.html', []).run(function($templateCache) {
$templateCache.put('app/templates/yourtemplate.html',
Dans mon cas, ce n'était pas la même chose que j'avais dans ma directive actuelle qui était à l'origine du problème.
Avoir le templateURL exactement le même dans tous les endroits m'a aidé.
c'est par exemple comment tester une directive qui utilise partial comme templateUrl
describe('with directive', function(){
var scope,
compile,
element;
beforeEach(module('myApp'));//myApp module
beforeEach(inject(function($rootScope, $compile, $templateCache){
scope = $rootScope.$new();
compile = $compile;
$templateCache.put('view/url.html',
'<ul><li>{{ foo }}</li>' +
'<li>{{ bar }}</li>' +
'<li>{{ baz }}</li>' +
'</ul>');
scope.template = {
url: 'view/url.html'
};
scope.foo = 'foo';
scope.bar = 'bar';
scope.baz = 'baz';
scope.$digest();
element = compile(angular.element(
'<section>' +
'<div ng-include="template.url" with="{foo : foo, bar : bar, baz : baz}"></div>' +
'<div ng-include="template.url" with=""></div>' +
'</section>'
))(scope);
scope.$digest();
}));
it('should copy scope parameters to ngInclude partial', function(){
var isolateScope = element.find('div').eq(0).scope();
expect(isolateScope.foo).toBeDefined();
expect(isolateScope.bar).toBeDefined();
expect(isolateScope.baz).toBeDefined();
})
});
Si vous utilisez jasmine-maven-plugin avec RequireJS, vous pouvez utiliser plugin texte pour charger le contenu du modèle dans une variable, puis le placer dans le cache du modèle.
define(['angular', 'text!path/to/template.html', 'angular-route', 'angular-mocks'], function(ng, directiveTemplate) {
"use strict";
describe('Directive TestSuite', function () {
beforeEach(inject(function( $templateCache) {
$templateCache.put("path/to/template.html", directiveTemplate);
}));
});
});