J'ai une directive AngularJS qui a un templateUrl
fichier. J'essaye de le tester unitaire avec Jasmine.
Mon JavaScript Jasmine ressemble à ce qui suit, selon la recommandation de ceci :
describe('module: my.module', function () {
beforeEach(module('my.module'));
describe('my-directive directive', function () {
var scope, $compile;
beforeEach(inject(function (_$rootScope_, _$compile_, $injector) {
scope = _$rootScope_;
$compile = _$compile_;
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('path/to/template.html').passThrough();
}));
describe('test', function () {
var element;
beforeEach(function () {
element = $compile(
'<my-directive></my-directive>')(scope);
angular.element(document.body).append(element);
});
afterEach(function () {
element.remove();
});
it('test', function () {
expect(element.html()).toBe('asdf');
});
});
});
});
Lorsque je l'exécute dans mon erreur de spécification Jasmine, j'obtiens l'erreur suivante:
TypeError: Object #<Object> has no method 'passThrough'
Tout ce que je veux, c'est que le templateUrl soit chargé tel quel - je ne veux pas l'utiliser respond
. Je pense que cela peut être lié à l'utilisation de ngMock au lieu de ngMockE2E . Si c'est le coupable, comment utiliser ce dernier au lieu du premier?
Merci d'avance!
.passThrough();
de cette façon, mais à partir de la documentation, avez-vous essayé quelque chose comme:$httpBackend.expectGET('path/to/template.html'); // do action here $httpBackend.flush();
Je pense que cela correspond mieux à votre utilisation - vous ne voulez pas attraper la demande, c'estwhenGet()
-à- dire , mais vérifiez plutôt qu'elle est envoyée, puis effectivement envoie-le?expectGET
envoie des demandes ... du moins hors de la boîte. Dans la documentation, leur exemple avec/auth.py
a un$httpBackend.when
avant les appels$httpBackend.expectGET
et$httpBackend.flush
.expectGet
s'agit simplement de vérifier si une demande a été tentée.$httpBackend
maquette d'utiliser réellement l'URL fournie dans la directive ci-dessoustemplateUrl
et d'aller la chercher. Je pensais quepassThrough
je ferais ça. Connaissez-vous une autre façon de procéder?Réponses:
Vous avez raison de dire que c'est lié à ngMock. Le module ngMock est automatiquement chargé pour chaque test angulaire et initialise la maquette
$httpBackend
pour gérer toute utilisation du$http
service, qui inclut la récupération de modèle. Le système de modèles essaie de charger le modèle$http
et cela devient une «demande inattendue» pour le simulacre.Ce dont vous avez besoin, un moyen de pré-charger les modèles dans le
$templateCache
afin qu'ils soient déjà disponibles lorsque Angular les demande, sans utiliser$http
.La solution préférée: le karma
Si vous utilisez Karma pour exécuter vos tests (et vous devriez l'être), vous pouvez le configurer pour charger les modèles pour vous avec le préprocesseur ng-html2js . Ng-html2js lit les fichiers HTML que vous spécifiez et les convertit en un module angulaire qui précharge le fichier
$templateCache
.Étape 1: Activez et configurez le préprocesseur dans votre
karma.conf.js
Si vous utilisez Yeoman pour échafauder votre application, cette configuration fonctionnera
Étape 2: Utilisez le module dans vos tests
Pour un exemple complet, regardez cet exemple canonique du gourou du test angulaire Vojta Jina . Il comprend une configuration entière: configuration de karma, modèles et tests.
Une solution non-karma
Si vous n'utilisez pas Karma pour une raison quelconque (j'ai eu un processus de construction inflexible dans l'application héritée) et que vous testez simplement dans un navigateur, j'ai trouvé que vous pouvez contourner la prise de contrôle de ngMock
$httpBackend
en utilisant un XHR brut pour récupérer le modèle pour de vrai et insérez-le dans le fichier$templateCache
. Cette solution est beaucoup moins flexible, mais elle fait le travail pour le moment.Sérieusement. Utilisez Karma . La configuration demande un peu de travail, mais elle vous permet d'exécuter tous vos tests, dans plusieurs navigateurs à la fois, à partir de la ligne de commande. Vous pouvez donc l'inclure dans votre système d'intégration continue et / ou en faire une touche de raccourci depuis votre éditeur. Bien mieux que alt-tab-refresh-ad-infinitum.
la source
preprocessors
modèle de fichier (par exemple"path/to/templates/**/*.html"
) à lafiles
section danskarma.conf.js
.false
paramètre pour l'appel du XHRopen
pour le rendre synchrone. Si vous ne le faites pas, l'exécution se poursuivra joyeusement et commencera à exécuter vos tests, sans que le modèle ne soit chargé. Cela vous ramène directement au même problème: 1) La demande de modèle est envoyée. 2) Le test commence à s'exécuter. 3) Le test compile une directive et le modèle n'est toujours pas chargé. 4) Angular demande le modèle via son$http
service, qui est simulé. 5) Le$http
service simulé se plaint: "demande inattendue".npm install --save-dev karma-ng-html2js-preprocessor
) et l'ajouter à la section plugins de votrekarma.conf.js
, selon stackoverflow.com/a/19077966/859631 .Ce que j'ai fini par faire, c'est obtenir le cache du modèle et y mettre la vue. Je n'ai pas le contrôle de ne pas utiliser ngMock, il s'avère que:
la source
Ce problème initial peut être résolu en ajoutant ceci:
C'est parce qu'il essaie de trouver $ httpBackend dans le module ngMock par défaut et qu'il n'est pas plein.
la source
La solution que j'ai atteinte nécessite jasmine-jquery.js et un serveur proxy.
J'ai suivi ces étapes:
ajoutez jasmine-jquery.js à vos fichiers
ajoutez un serveur proxy qui servira vos appareils
Dans vos spécifications
describe ('MySpec', function () {var $ scope, template; jasmine.getFixtures (). fixturesPath = 'public / partials /'; // chemin personnalisé afin que vous puissiez servir le modèle réel que vous utilisez sur l'application beforeEach (function () {template = angular.element ('');
});
Exécutez un serveur sur le répertoire racine de votre application
python -m SimpleHTTPServer 3502
Exécutez le karma.
Il m'a fallu un certain temps pour comprendre cela, ayant à rechercher de nombreux messages, je pense que la documentation à ce sujet devrait être plus claire, car c'est une question très importante.
la source
localhost/base/specs
et à ajouter un serveur proxy enpython -m SimpleHTTPServer 3502
exécutant le corrigé. Vous monsieur êtes un génie!Ma solution:
test/karma-utils.js
:karma.config.js
:le test:
la source
static
, par exemplebeforeEach(preloadTemplate(static_url +'seed/partials/beChartDropdown.html'));
Merci!Si vous utilisez Grunt, vous pouvez utiliser grunt-angular-templates. Il charge vos modèles dans le templateCache et il est transparent à la configuration de vos spécifications.
Mon exemple de configuration:
la source
J'ai résolu le même problème d'une manière légèrement différente de la solution choisie.
Tout d'abord, j'ai installé et configuré le plugin ng-html2js pour le karma. Dans le fichier karma.conf.js:
Ensuite, j'ai chargé le module créé dans le fichier beforeEach. Dans votre fichier Spec.js:
Ensuite, j'ai utilisé $ templateCache.get pour le stocker dans une variable. Dans votre fichier Spec.js:
Enfin, je l'ai testé de cette façon. Dans votre fichier Spec.js:
la source
Pour charger dynamiquement le template HTML dans $ templateCache, vous pouvez simplement utiliser le pré-processeur karma html2js, comme expliqué ici
cela revient à ajouter des modèles ' .html' à vos fichiers dans le fichier conf.js ainsi que preprocessors = {' .html': 'html2js'};
et utilise
dans votre fichier de test js
la source
Uncaught SyntaxError: Unexpected token <
si vous utilisez Karma, pensez à utiliser karma-ng-html2js-preprocessor pour pré-compiler vos modèles HTML externes et éviter que Angular essaie de les obtenir par HTTP pendant l'exécution du test. J'ai eu du mal avec cela pour quelques-uns des nôtres - dans mon cas, les chemins partiels de templateUrl ont été résolus pendant l'exécution normale de l'application mais pas pendant les tests - en raison de différences dans les structures des répertoires d'application et de test.
la source
Si vous utilisez le jasmine-maven-plugin avec RequireJS, vous pouvez utiliser le plugin de texte pour charger le contenu du modèle dans une variable, puis le mettre dans le cache du modèle.
la source
Si vous utilisez requirejs dans vos tests, vous pouvez utiliser le plugin 'text' pour extraire le modèle html et le mettre dans $ templateCache.
la source
Je résous ce problème en compilant tous les modèles en templatecache. J'utilise gulp, vous pouvez également trouver une solution similaire pour grunt. Mon templateUrls dans les directives, les modaux ressemblent
Ajouter un nouveau package npm dans mon package.json
"gulp-angular-templatecache": "1.*"
Dans le fichier gulp, ajoutez templatecache et une nouvelle tâche:
var templateCache = require('gulp-angular-templatecache'); ... ... gulp.task('compileTemplates', function () { gulp.src([ './app/templates/**/*.html' ]).pipe(templateCache('templates.js', { transformUrl: function (url) { return '/templates/' + url; } })) .pipe(gulp.dest('wwwroot/assets/js')); });
Ajouter tous les fichiers js dans index.html
<script src="/assets/js/lib.js"></script> <script src="/assets/js/app.js"></script> <script src="/assets/js/templates.js"></script>
Prendre plaisir!
la source