2014-07-25 38 views
11

Mam problemy z pisaniem testów jednostkowych dla niektórych z moich dyrektyw Angular. W szczególności te, które używają jQuery wewnątrz dyrektywy. Poniżej zilustrowałem minimalny przykład ilustrujący mój problem.Testuj dyrektywę kątową, która używa jQuery

Ta głupia dyrektywa wiąże zdarzenie kliknięcia z elementem. Po kliknięciu ukrywa element. According to Angular, elementy przekazywane do dyrektyw będą pakowane jako elementy jQuery. jeśli jQuery jest dostępny, użyje jQuery, w przeciwnym razie użyje jQuery Lite Angulara. Rzeczywiście, jeśli użyję tej dyrektywy w przeglądarce z dołączonym jQuery, dyrektywa działa i ukryje kliknięty element.

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

Oto Karma testów jednostkowych spec niniejszej dyrektywy:

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

Kiedy uruchomić ten test, nie jest on z błędem „niezdefiniowany nie jest funkcja”, co oznacza, że ​​jQuery nie został załadowany i Angular użył zamiast tego jQuery Lite, który nie definiuje hide().

Znalazłem dwa sposoby obejścia tego.

  1. Nie używaj jQuery. Wymaga przepisania moich dyrektyw, których nie chcę robić.

  2. Jawnie zawijam elementy w moich dyrektywach, aby stały się elementami jQuery: $(element).hide(). Wymaga również modyfikacji moich dyrektyw, których wolałabym nie robić. Jeśli nie ma alternatywy, z pewnością mogę to zrobić.

czuję się jak powinno być możliwe, aby uzyskać kątowa automatycznie użyć jQuery wewnątrz dyrektywy podczas testów jednostkowych jak to robi w przypadku korzystania z przeglądarki internetowej. Wierzę, że kluczową kwestią jest ta linia z dokumentacji Angular:

Aby użyć jQuery, wystarczy załadować ją przed uruchomieniem zdarzenia DOMContentLoaded.

Nie jest dla mnie jasne, kiedy DOMContentLoaded dzieje się podczas uruchamiania testów jednostkowych. Karma mój plik konfiguracyjny zawiera jQuery jako pierwszego pliku, zanim kątowa:

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

Czy muszę wstrzykiwać jQuery do testu? Może to jest ograniczenie karmy? Ktoś wie?

+0

można spróbować 'spodziewać (elm.find (": ukryte"), długość). .toBe (1);'? – glepretre

+0

Nie dociera nawet do tej linii, ponieważ ma błąd w powyższym wierszu, ponieważ opisałem to. – Jake

+0

o ok. Jak próbowałeś załadować jQuery w swojej aplikacji? – glepretre

Odpowiedz

2

Spróbuj przesłonić $ in beforeEach block testu.

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

Mam jquery załadowany w moim pliku conf karmy na górze, ale otrzymuję $ undefined. Czy musimy zrobić cokolwiek więcej, aby uzyskać dostęp do $ dla jQuery? – Winnemucca

Powiązane problemy