Подтвердить что ты не робот

Модуль тестирования директивы, которая определяет контроллер в AngularJS

Я пытаюсь проверить директиву с помощью Karma и Jasmine, которые делают пару вещей. Во-первых, он использует templateUrl, а во-вторых, определяет контроллер. Это может быть не правильная терминология, но она создает контроллер в его объявлении. Приложение Angular настроено таким образом, чтобы каждый блок содержался в его собственном модуле. Например, все директивы включены в модуль app.directive, все контроллеры содержатся в app.controller, а все службы содержатся в app.service и т.д.

Чтобы усложнить ситуацию, контроллер, определенный в этой директиве, имеет одну зависимость и содержит функцию, которая делает запрос $http устанавливать значение в области $scope. Я знаю, что я могу издеваться над этой зависимостью, используя $httpBackend mock для имитации вызова $http и возврата соответствующего объекта в вызов этой функции. Я делал это много раз на других модульных тестах, которые я создал, и очень хорошо понимаю эту концепцию.

Нижеприведенный код написан на CoffeeScript.

Вот моя директива:

    angular.module('app.directive')
      .directive 'exampleDirective', [() ->
        restrict: 'A'
        templateUrl: 'partials/view.html'
        scope: true
        controller: ['$scope', 'Service', ($scope, Service) ->
          $scope.model = {}
          $scope.model.value_one = 1

          # Call the dependency
          Service.getValue()
            .success (data) ->
              $scope.model.value_two = data
            .error ->
              $scope.model.value_two = 0
        ]
      ]

Вот служба зависимостей:

    angular.module("app.service")
      .factory 'Service', ['$http', ($http) ->

      getValue: () ->
        options.method = "GET"
        options.url = "example/fetch"

        $http _.defaults(options)

Вот представление:

    <div>
      {{model.value_one}} {{model.value_two}}
    </div>

Я упростил это совсем немного, так как моя цель - понять, как это сделать, я могу взять его оттуда. Причина, по которой я это структурирую, заключается в том, что я изначально не создал это. Я работаю над написанием тестов для существующего проекта, и у меня нет возможности настроить его каким-либо другим способом. Я попытался написать тест, но не могу заставить его делать то, что я хочу.

Я хочу проверить, привязаны ли значения к представлению, и, если возможно, также проверить, правильно ли контроллер создает значения.

Вот что у меня есть:

    'use strict'

    describe "the exampleDirective Directive", ->

      beforeEach module("app.directive")
      beforeEach module("app/partials/view.html")

      ServiceMock = {
        getValue : () ->

        options.method = "GET"
        options.url = "example/fetch"

        $http _.defaults(options)
      }

     #use the mock instead of the service
     beforeEach module ($provide) ->
       $provide.value "Service", ServiceMock
       return

     $httpBackend = null
     scope = null
     elem = null

     beforeEach inject ($compile, $rootScope, $injector) ->

     # get httpBackend object
     $httpBackend = $injector.get("$httpBackend")
     $httpBackend.whenGET("example/fetch").respond(200, "it works")

     #set up the scope
     scope = $rootScope

     #create and compile directive
     elem = angular.element('<example-directive></example-directive>')
     $compile(elem)(scope)
     scope.$digest()

Я не знаю, насколько я близка, или если это даже правильно. Я хочу уметь утверждать, что значения привязаны к представлению правильно. Я использовал пример Vojtajina для настройки html2js в моем файле karma.js, чтобы позволить мне захватить представления. Я нашел много исследований, чтобы найти ответ, но мне нужна помощь. Надеюсь, программист мудрее, чем я могу указать мне в правильном направлении. Спасибо.

4b9b3361

Ответ 1

Создайте элемент в карме, затем используйте функцию .controller() с именем вашей директивы, чтобы захватить контроллер. В качестве примера замените последнюю пару строк следующим образом:

elem = angular.element('<div example-directive></div>');
$compile(elem)($rootScope);
var controller = elem.controller('exampleDirective');

Обратите внимание, что, учитывая, как вы определили свою директиву, она должна быть по атрибуту, а не как элемент. Я тоже не уверен на 100%, но я не думаю, что вам нужен scope.$digest;, как правило, я просто помещаю все, что нужно применить в блок scope.$apply(function() {}).