2013-11-23 4 views
1

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

Проблема показывает себя, когда для вызова $httpBackend.expectPOST() я указываю ожидаемые данные.

$httpBackend.expectPOST('/notes/'+scope.note.id+'/replies', { 
    content: 'This is the reply'  /*** TEST PASSES IF EXPECTED POST DATA IS NOT SET ***/ 
}).respond(200, { 
    id: 11, 
    noteId: 199, 
    content: 'This is the reply' 
}); 

Когда я звоню elem.find('[ng-click="saveReply()"]').click(), область saveReply() является называется, но ни один из данных, который был установлен получает представлен таким образом, если указать ожидаемые данные, которые он терпит неудачу, но если я не указываю ожидаемые данные, которые он передает. Очевидно, чтобы иметь более полные тесты, я бы хотел выполнить первое.

Как уже упоминалось выше, метод saveReply() вызывается после вызова метода click(). Это заставило бы думать, что надлежащее связывание областей на месте, но если я непосредственно установил переменную области видимости, она все еще не видна в методе области видимости. Возможно, именно здесь проблема/решение ...

Я бы подумал, что требуемая ссылка на сферу может быть получена через elem.scope(), но когда я делаю это, elem.scope() совпадает с $ rootScope.

// FAILS 
expect(elem.scope().$id).not.toEqual($rootScope.$id); 

Любые идеи?

'use strict'; 

describe('Note directive', function() { 

    var scope, elem; 

    var compile = function($compile, $rootScope, PhotoService) { 
    spyOn(PhotoService, 'profilePhotoUrl').andReturn('mypic.jpg'); 
    scope = $rootScope; 
    scope.note = { 
     id: 199, 
     content: 'This is the note', 
     author: { 
     firstName: 'Jim', 
     lastName: 'Smith', 
     name: 'Jim Smith', 
     profilePhotoName: 'mypic.jpg' 
     }, 
     replies: [ 
     {id: 99, content: 'you should not see this on initial load', author: { 
      firstName: 'Jim', lastName: 'Smith', name: 'Jim Smith', profilePhotoName: 'mypic.jpg'} 
     }, 
     {id: 99, content: 'but you should see this one', author: { 
      firstName: 'Jim', lastName: 'Smith', name: 'Jim Smith', profilePhotoName: 'mypic.jpg'} 
     } 
     ] 
    }; 
    elem = $compile('<note data="note"></note>')(scope); 
    scope.$digest(); 
    }; 

    var stubCurrentUser = function ($httpBackend) { 
    $httpBackend.expectGET('/users/me').respond({id: 99, name: 'Jim Smith', role: 'owner'}); 
    }; 

    beforeEach(module('woddy')); 
    beforeEach(module('directive_templates')); 
    beforeEach(inject(stubCurrentUser, compile)); 

    iit('allows the user to reply to a note', inject(function ($httpBackend) { 
    $httpBackend.expectPOST('/notes/'+scope.note.id+'/replies', { 
     content: 'This is the reply'  /*** TEST PASSES IF EXPECTED POST DATA IS NOT SET ***/ 
    }).respond(200, { 
     id: 11, 
     noteId: 199, 
     content: 'This is the reply' 
    }); 

    expect(elem.find('[ng-repeat="reply in note.replies"]').length).toBe(2); 
    elem.find('[ng-click="reply()"]').click(); 
    scope.$digest(); 
    elem.find('[ng-model="content"]').text("This is the reply"); 
    scope.$digest(); 
    elem.find('[ng-click="saveReply()"]').click(); 

    $httpBackend.flush(); 
    $httpBackend.verifyNoOutstandingExpectation(); 
    $httpBackend.verifyNoOutstandingRequest(); 

    scope.$digest(); 
    expect(elem.find('[ng-repeat="reply in note.replies"]').length).toBe(3); 
    })); 

}); 

Директива

'use strict'; 

angular.module('woddy').directive('note', function() { 

    return { 
    restrict: 'E', 
    scope: { 
     note: '=data' 
    }, 
    templateUrl: '/dashboard/note.html', 

    controller: function($scope, PhotoService, Reply, CurrentUser) { 

     $scope.state = 'show'; 
     $scope.showAllReplies = false; 

     CurrentUser.get().then(function(user) { 
     $scope.currentUser = user; 
     }); 

     /** 
     * Reply on the note 
     */ 
     $scope.reply = function() { 
     $scope.content = ''; 
     $scope.state = 'add'; 
     }; 

     /** 
     * Revert back to the default view 
     */ 
     $scope.reset = function() { 
     $scope.content = 'Add a comment...'; 
     $scope.state = 'show'; 
     }; 

     $scope.saveReply = function() { 
     console.log("It is calling the method") 
     var reply = new Reply({ 
      noteId: $scope.note.id, 
      content: $scope.content 
     }); 

     reply.$save(function() { 
      var author = $scope.currentUser; 
      $scope.note.replies.push({ 
      content: $scope.content, 
      author: { 
       id: author.id, 
       name: author.name, 
       photoName: author.photoName, 
       gender: author.gender 
      } 
      }); 

      $scope.reset(); 
     }); 
     }; 

    } 
    }; 
}); 

Посмотреть

<div class="note box"> 
    <img class="author" ng-src="{{authorPhotoUrl()}}" alt="{{note.author.name}}"/> 
    <div class="details"> 
    <div class="name" ng-bind="note.author.name"></div> 
    <div class="timestamp" timestamp="{{note.timestamp}}"></div> 
    </div> 

    <div class="content" ng-bind-html="note.content"></div> 

    <div class="note-replies" ng-if="note.replies.length > 0"> 
    <div class="links"> 
     <span>{{note.replies.length}} {{note.replies.length == 1 ? 'Comment' : 'Comments'}}</span> 
     <a href="#" ng-show="!showAllReplies && note.replies.length > 1" ng-click="showAllReplies = true">Show Comments</a> 
     <a href="#" ng-show="showAllReplies && note.replies.length > 1" ng-click="showAllReplies = false">Hide Comments</a> 
    </div> 

    <div class="replies"> 
     <div class="reply" ng-repeat="reply in note.replies" ng-show="showAllReplies || $last"> 
     <img ng-src="{{replyAuthorPhotoUrl(reply.author)}}" alt="{{reply.author.name}}"> 
     <div class="reply-details"> 
      <span class="name" ng-bind="reply.author.name"></span> 
      <span class="timestamp" timestamp="{{reply.timestamp}}"></span> 
      <div class="content" ng-bind-html="reply.content"></div> 
     </div> 
     </div> 
    </div> 
    </div> 

    <div class="reply-form"> 
    <div class="reply-content" ng-click="reply()" contenteditable="true" ng-model="content">Add a comment...</div> 
    <form ng-show="state == 'add'"> 
     <div class="text-right"> 
     <button class="secondary" ng-click="reset()">Cancel</button> 
     <button ng-click="saveReply()">Comment</button> 
     </div> 
    </form> 
    </div> 
</div> 

ответ

0

В AngularJs 1.2 вы можете использовать elem.isolateScope() для доступа к директиве изолировать сферу.

Вот plunker пример: http://plnkr.co/edit/x0c0HYfyVMfsV8LX2bZX?p=preview

+0

Это один из ответов, которые я получил от совета IRC, но в этом случае isolateScope() возвращает нуль. Проблема в том, почему игнорируются значения значений элемента формы. ex 'elem.find ('[ng-model =" content "]'). text (" Это ответ ")' // это значение не попадает в httpBackend – chris

+0

У вас есть пользовательский '' 'contenteditable '' 'директива? Угловое не поддерживает '' 'contenteditable''' из коробки, хотя есть много примеров. Проблема документирована [здесь] (https://github.com/angular/angular.js/issues/528) – rgaskill

+0

Я делаю и хорошо работает при использовании приложения через браузер, однако это все данные, а не только контент-ориентированные связанные данные, которые не отправляются. – chris

Смежные вопросы