wake-up-neo.com

Jasmine testet AngularJS-Direktiven mit templateUrl

Ich schreibe Direktiventests für AngularJS mit Jasmine und verwende dabei templateUrl: https://Gist.github.com/tanepiper/62bd10125e8408def5cc

Wenn ich jedoch den Test durchführe, wird der Fehler im Gist angezeigt:

Error: Unexpected request: GET views/currency-select.html

Nach dem, was ich in den Dokumenten gelesen habe, dachte ich, ich mache das richtig, aber es scheint nicht so - was fehle ich hier?

Vielen Dank

70
Tane Piper

Wenn Sie ngMockE2E oder ngMock verwenden:

Alle HTTP-Anforderungen werden lokal nach von Ihnen festgelegten Regeln verarbeitet, und es werden keine übergeben zum Server. Da Vorlagen über HTTP angefordert werden, werden auch diese lokal verarbeitet. Da Sie bei dem Versuch, eine Verbindung zu views/currency-select.html Herzustellen, nichts angegeben haben, wird Ihnen mitgeteilt, dass Sie nicht wissen, wie Sie damit umgehen sollen. Sie können ngMockE2E ganz einfach anweisen, Ihre Vorlagenanfrage weiterzuleiten:

$httpBackend.whenGET('views/currency-select.html').passThrough();

Denken Sie daran, dass Sie auch reguläre Ausdrücke in Ihren Routing-Pfaden verwenden können, um alle Vorlagen zu durchlaufen, wenn Sie möchten.

In den Dokumenten wird dies genauer erläutert: http://docs.angularjs.org/api/ngMockE2E.$httpBackend

Ansonsten benutze dies:

Sie müssen den $injector Benutzen, um auf das neue Backend zuzugreifen. Aus den verlinkten Dokumenten:

var $httpBackend;
beforeEach(inject(function($injector) {
  $httpBackend = $injector.get('$httpBackend');
  $httpBackend.whenGET('views/currency-select.html').respond(200, '');
}));
70

die Karma-Methode besteht darin, die HTML-Vorlage dynamisch in $ templateCache zu laden. Sie könnten einfach den html2js-Karma-Pre-Prozessor verwenden, wie erklärt hier

dies läuft darauf hinaus, Vorlagen '. html' zu Ihren Dateien in der Datei conf.js sowie Präprozessoren = {'. html': 'html2js' hinzuzufügen. };

und verwenden

beforeEach(module('..'));

beforeEach(module('...html', '...html'));

in deine js testing datei

20
Lior

Wenn dies ein Unit-Test ist, haben Sie keinen Zugriff auf $httpBackend.passthrough(). Dies ist nur in ngMock2E2 für End-to-End-Tests verfügbar. Ich stimme den Antworten mit ng-html2js (Früher als html2js bezeichnet) zu, möchte sie aber gerne erweitern, um hier eine vollständige Lösung bereitzustellen.

Zum Rendern Ihrer Direktive verwendet Angular $http.get(), um Ihre Vorlage aus templateUrl abzurufen. Dies ist ein Unit-Test, und angular-mocks Wird geladen , angular-mocks Fängt den Aufruf von $http.get() ab und gibt den Fehler Unexpected request: GET Aus. Sie können versuchen, Wege zu finden, um dies zu umgehen, aber es ist viel einfacher, nur winklige $templateCache, Um Ihre Vorlagen vorab zu laden. Auf diese Weise wird $http.get() nicht einmal ein Problem sein.

Das ist, was der Präprozessor ng-html2js für Sie tut. Um es zum Laufen zu bringen, installieren Sie es zuerst:

$ npm install karma-ng-html2js-preprocessor --save-dev

Dann konfigurieren Sie es durch Hinzufügen/Aktualisieren der folgenden Felder in Ihrem 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',
    }
}

Verwenden Sie schließlich in Ihrem Testcode das soeben erstellte Modul test-templates. Fügen Sie einfach test-templates Zu dem Modulaufruf hinzu, den Sie normalerweise in beforeEach ausführen:

beforeEach(module('myapp', 'test-templates'));

Von hier aus sollte es ruhig laufen. Weitere Informationen zu diesem und anderen Direktiventestszenarien finden Sie in diesem Beitrag

6

Sie könnten vielleicht den $templatecache Vom Injektor abrufen und dann so etwas tun

$templateCache.put("views/currency-select.html","<div.....>");

wo würden Sie anstelle von <div.....> Ihre Vorlage einfügen?.

Danach richten Sie Ihre Direktive ein und es sollte gut funktionieren!

5
ganaraj

Wie gewünscht, einen Kommentar in eine Antwort umwandeln.


Für die Leute, die die Antwort von @ Lior in Yeoman Apps nutzen möchten:

Manchmal wird in der Karma-Konfiguration auf die Art und Weise verwiesen, wie auf die Vorlagen verwiesen wird, und folglich auf die Namen der Module, die von ng-html2js stimmen nicht mit den Werten überein, die in den Richtliniendefinitionen als templateUrls angegeben sind.
Sie müssen die generierten Modulnamen so anpassen, dass sie mit templateUrls übereinstimmen.
Diese könnten hilfreich sein:

4
vucalur

Wenn dies immer noch nicht funktioniert, verwenden Sie fiddler, um den Inhalt der von htmltojs processor dynamisch generierten js-Datei anzuzeigen und den Pfad der Vorlagendatei zu überprüfen.

Es sollte so etwas sein

angular.module('app/templates/yourtemplate.html', []).run(function($templateCache) {
  $templateCache.put('app/templates/yourtemplate.html', 

In meinem Fall war es nicht dasselbe wie in meiner eigentlichen Richtlinie, was das Problem verursachte.

Die templateURL an allen Stellen exakt gleich zu haben, hat mich durchgebracht.

4
akshayswaroop

dies ist ein Beispiel zum Testen einer Direktive, die partial als templateUrl verwendet

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();
  })
});
2
a8m

Wenn Sie das jasmine-maven-plugin zusammen mit RequireJS verwenden, können Sie das text plugin verwenden, um den Vorlageninhalt in eine Variable zu laden und ihn dann in den Vorlagencache zu legen.


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);
        }));

    });
});
0