andy-dev
andy-dev

Reputation: 133

Testing Directive Angular using ControllerAs

I'm trying to test a directive. using controllerAs creates a toplevel scope where we can access its properties. however when debugging I try to access element.scope().property --I am getting undefined. Any help on why would be greatly appreciated.

--BugDirective

 (function() {
  'use strict';

  angular
    .module('debug-blog-app')
    .directive('avBug', avBug);

  function avBug() {
    return {
        restrict: 'E',
        templateUrl: 'views/directives/bug.html',
        scope: {
          bug: '='
        },
        controller: BugFormController,
        controllerAs: 'bugCtrl',
        bindToController: true
    };
  };

  BugFormController.$inject = ['$window', '$scope', 'BugService'];
  function BugFormController($window, $scope, BugService) {
    var vm = this;

    vm.updateBug = function(){
      BugService.updateBug(vm.bug);
    };

    vm.deleteBug = function(){
      if($window.confirm("Delete the Bug?!")){
        return BugService.deleteBug(vm.bug.id)
          .then(function(){
            $scope.$emit('bug.deleted', vm.bug);
          });
      }
    };
  };
})();

--Spec

'use strict'

describe('avBug Directive', function () {
    var bugCtrl,
        element,
        BugService,
        $scope,
        $rootScope;

    beforeEach(module('app'));

    beforeEach(inject(function($q, $compile, _$rootScope_, _BugService_) {
        $rootScope = _$rootScope_;


        var directiveMarkup = angular.element("<av-bug></av-Bug>");
        element = $compile(directiveMarkup)($rootScope);
        bugCtrl = element.scope().bugCtrl;


        BugService = _BugService_;


        spyOn(BugService, 'deleteBug').and.callFake(function() {
            var deferred = $q.defer();
            deferred.resolve('data');
            return deferred.promise;
        });

        spyOn($rootScope,'$emit').and.callThrough();
    }));

    it('should delete a bug', function() {
        bugCtrl.deleteBug(0);
        expect(BugService.deleteBug).toHaveBeenCalledWith(0);
        $rootScope.$digest();
        expect($rootScope.$emit).toHaveBeenCalledWith('bug.deleted');
    });
});

--index.html

<div class="container">
  <div ui-view></div>
</div>

--home.html

<av-bug bug="bug" ng-repeat="bug in homeCtrl.bugs"></av-bug>

Upvotes: 1

Views: 705

Answers (2)

Michael Jota
Michael Jota

Reputation: 138

I would also add, for unit testing purposes, that you can get the parent controllerAs with the same function that @Ramy Deeb post.

vm = element.scope().$$childTail.nameOfParentControllerAs

And for testing the element isolate scope, just get

isolateScope = element.isolateScope()

I hope this can help anyone like me ending here searching how to unit test directives and controllers calling them, all of them being using ControllerAs syntax.

Thanks you.

I would comment, but I cannot.

Upvotes: 1

Ramy Deeb
Ramy Deeb

Reputation: 593

Your controller is located at:

element.scope().$$childTail.bugCtrl

Upvotes: 0

Related Questions