2014-07-25 3 views
11

Ich habe Probleme beim Schreiben von Komponententests für einige meiner Angular-Anweisungen. Insbesondere diejenigen, die jQuery in der Direktive verwenden. Ich habe unten ein minimales Beispiel erstellt, das mein Problem illustriert.Testen Sie eine Angular-Anweisung, die jQuery verwendet

Diese alberne Direktive bindet das click -Ereignis an das Element. Wenn Sie darauf klicken, wird das Element ausgeblendet. According to Angular, Elemente, die an Anweisungen übergeben werden, werden als jQuery-Elemente umschlossen. Wenn jQuery verfügbar ist, wird jQuery verwendet, andernfalls wird Angulars jQuery Lite verwendet. Wenn ich diese Anweisung in einem Browser verwende, in dem jQuery enthalten ist, funktioniert die Anweisung tatsächlich und versteckt das angeklickte Element.

angular.module('myApp').directive('clickhide', function() { return { 
    link: function(scope, element, attrs) { 
     element.bind('click', function(e) { 
      element.hide(); 
      scope.$digest(); 
     }); 
    } 
}}); 

Hier ist der Test Karma Einheit spec für diese Richtlinie:

describe('clickhide', function() { 
    var scope, elm; 

    beforeEach(module('MyApp')); 

    beforeEach(inject(function($rootScope, $compile) { 
     scope = $rootScope; 
     elm = angular.element('<div clickhide></div>'); 
     $compile(elm)(scope); 
     scope.$digest(); 
    })); 

    it('should do a click', function() { 
     elm[0].click(); 
     //OOPS: undefined is not a function error 
     expect($(elm).find(":hidden").length).toBe(1); 
    }); 
}); 

Wenn ich diesen Test ausführen, es mit einem Fehler von fehlschlägt „undefiniert ist keine Funktion“, was bedeutet, dass jQuery nicht geladen war und Angular verwendet stattdessen jQuery Lite, das hide() nicht definiert.

Ich habe zwei Möglichkeiten gefunden, um dies zu umgehen.

  1. Verwenden Sie nicht jQuery. Erfordert das Umschreiben meiner Direktiven, die ich nicht machen möchte.

  2. Explizit Zeilenumbruch Elemente in meine Anweisungen, um sie zu jQuery-Elementen: $(element).hide(). Außerdem müssen meine Richtlinien geändert werden, was ich lieber nicht tun würde. Wenn es keine Alternative gibt, kann ich das sicher tun.

Ich fühle mich wie soll es möglich sein Eckige zu bekommen automatisch innerhalb einer Richtlinie jQuery zu verwenden, wenn Unit-Tests, wie es ist, wenn sie in einem Web-Browser. Ich glaube, der entscheidende Punkt ist diese Zeile aus Angulars Dokumentation:

Um jQuery zu verwenden, laden Sie es einfach, bevor das DOMContentLoaded-Ereignis ausgelöst wird.

Es ist mir nicht klar, wenn DOMContentLoaded beim Ausführen von Komponententests passiert. Mein Karma-Konfigurationsdatei enthält jQuery als die erste Datei, bevor Winkel:

module.exports = function(config) { 
    config.set({ 
    basePath: '../../', 
    frameworks: ['jasmine', 'ng-scenario'], 
    files: [ 
     'app/bower_components/jquery/dist/jquery.min.js', 
     'app/bower_components/angular/angular.js', 
     'app/bower_components/angular-route/angular-route.js', 
     'app/bower_components/angular-sanitize/angular-sanitize.js', 
     'app/bower_components/angular-mocks/angular-mocks.js', 
     ... 
    ], 
    exclude: [], 
    reporters: ['progress'], 
    port: 9876, 
    runnerPort: 9100, 
    colors: true, 
    logLevel: config.LOG_INFO, 
    autoWatch: true, 
    browsers: ['Chrome'], 
    captureTimeout: 60000, 
    singleRun: false 
    }); 
}; 

Muss ich jQuery in den Test injizieren? Vielleicht ist das eine Einschränkung von Karma? Weiß jemand?

+0

Könnten Sie versuchen 'expect (elm.find (": hidden "). Length) .toBe (1);'? – glepretre

+0

Es kommt nicht einmal zu dieser Zeile, weil es einen Fehler in der Zeile oben wegen der Sache, die ich beschrieben habe. – Jake

+0

oh ok. Wie hast du versucht, jQuery in deine App zu laden? – glepretre

Antwort

2

Versuchen Sie, $ vor jedem Block des Tests zu überschreiben.

beforeEach(function() { 
    $.fn.hide = function() { 
    this.css("display", "none") 
    }; 
}); 
+1

Ich habe jquery in meiner Karma Conf-Datei an der Spitze geladen, aber bekomme $ undefiniert. Müssen wir noch weitere Schritte unternehmen, um auf $ for jQuery zuzugreifen? – Winnemucca

Verwandte Themen