2015-10-02 31 views
6

Po wielu badaniach nie byłem w stanie poprawnie przetestować dyrektywy Angular, ponieważ nie mam dostępu do funkcji wewnątrz jej kontrolera.Jak testować dyrektywy kontrolerów w AngularJS

Oto kod dyrektywa:

angular.module('app'). 
    directive("accordionItem", function() { 
     return{ 
      restrict: 'E', 
      replace: true, 
      templateUrl: function (elem, attr) { 
       return 'partials/invoice/' + attr.temp + '.html'; 
      }, 
      scope: { 
       invoice: '=', 
       temp: '@' 
      }, 
      controller: function ($scope, listSelectionService, $state) { 

      $scope.selectItem = function() { 
       if ($scope.isOpen()) { 
        listSelectionService.selectedItem = -1; 
       } 
       else { 
        listSelectionService.selectedItem = $scope.invoice; 
       } 
      }; 
      $scope.isOpen = function() { 
       return listSelectionService.selectedItem === $scope.invoice; 
      }; 
      $scope.showFaturasSubscription = function() { 
       $state.go('app.ultimasFaturasSubscription', {subscriptionId: $scope.invoice.subscriptionId}); 
      }; 
     } 
    }; 
}); 

A moja próba:

describe('Invoice', function() { 
    var $scope = {}, controller, $httpBackend, $controller, form, element; 
    beforeEach(module('app')); 

    describe('Directives', function() { 
     beforeEach(inject(function($compile, $rootScope, _$httpBackend_, _$controller_) { 
      $httpBackend = _$httpBackend_; 
      $httpBackend.expect('GET', 'data/translation/?lang=pt').respond(200, []); 
      $httpBackend.when('GET', 'partials/invoice/undefined.html').respond(200, []); 
      $httpBackend.when('GET', 'partials/templates/loading.html').respond(200, []); 
      $httpBackend.when('GET', 'partials/invoice/invoiceContent.html').respond(200, []); 
      $scope = $rootScope.$new(); 
      $controller = _$controller_; 

      form = $compile("<accordion-item temp='invoiceContent'></accordion-item>")($scope); 
      $scope.$digest(); 

     })); 
     it('should submitButtonDisabled', inject(function($injector) { 
      var listSelectionService = $injector.get("listSelectionService"); 
      $scope.selectItem(); 
      expect(listSelectionService.selectedItem).toBe(-1); 
     })); 
    }); 
}); 

Według wielu dokumentów czytałem, po trawienia funkcji $() możemy mieć dostęp do kontroler dyrektywy. To się nie dzieje, ponieważ daje mi następujący błąd:

TypeError: $scope.selectItem is not a function 
at null.<anonymous> (http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:27:20) 
at Object.invoke (http://localhost:8234/src/main/webapp/vendor/angular/angular.js:4452:17) 
at workFn (http://localhost:8234/src/main/webapp/vendor/angular-mocks/angular-mocks.js:2420:20) 
at jasmine.Block.execute (http://localhost:8234/?:1164:19) 
at jasmine.Queue.next_ (http://localhost:8234/?:2196:33) 
at jasmine.Queue.start (http://localhost:8234/?:2149:10) 
at jasmine.Spec.execute (http://localhost:8234/?:2476:16) 
at jasmine.Queue.next_ (http://localhost:8234/?:2196:33) 
at jasmine.Queue.start (http://localhost:8234/?:2149:10) 
at jasmine.Suite.execute (http://localhost:8234/?:2621:16) 
Error: Declaration Location 
    at window.inject.angular.mock.inject (http://localhost:8234/src/main/webapp/vendor/angular-mocks/angular-mocks.js:2391:25) 
    at null.<anonymous> (http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:25:43) 
    at jasmine.Env.describe (http://localhost:8234/?:919:23) 
    at describe (http://localhost:8234/?:703:29) 
    at null.<anonymous> (http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:10:5) 
    at jasmine.Env.describe (http://localhost:8234/?:919:23) 
    at describe (http://localhost:8234/?:703:29) 
    at http://localhost:8234/spec/invoice/invoiceDirectivesSpec.js:5:1 

Każda pomoc będzie naprawdę doceniana.

Odpowiedz

5

Zwykle testuję kontrolery dyrektyw w ten sam sposób, w jaki robię zwykły kontroler.

W swojej dyrektywie zdefiniowano kontroler w linii jako część dyrektywy. Zamiast definiować go jak chcesz dla kontrolera, który jest używany w celu:

zarejestruj kontrolera na module:

angular.module('app').controller('DirectiveController', function($scope) { ... }); 

Reference sterownik w konfiguracji dyrektywy:

controller: 'DirectiveController' 

Przetestuj sterownik:

Może to zastąpić lub uzupełnić rzeczywiste testy dyrektywy. Testowanie kontrolera spoza dyrektywy jest znacznie prostsze, nie musisz martwić się o tworzenie instancji dyrektywy lub radzenie sobie z elementami DOM. Często, jeśli szablon dyrektywy jest wystarczająco prosty, nawet nie zawracam sobie głowy testami dyrektywy i po prostu testuję kontroler. Prosty przykład:

var controller, scope; 

beforeEach(inject(function($rootScope, $controller) { 
    scope = $rootScope.$new(); 
    controller = $controller('DirectiveController', {$scope: scope}); 
})); 

describe('controller', function() { 
    it('exists', function() { 
    expect(controller).toBeDefined(); 
    expect(controller).not.toBeNull(); 
    }); 
});