2

So I can't seem to call a method in my test that is written on the internalScope of an angular directive.

Here is my test

describe('auto complete directive', function () {

var el, $scope, scope;

beforeEach(module('italic'));
beforeEach(module('stateMock'));
beforeEach(module('allTemplates'));

beforeEach(inject(function ($compile, $rootScope, UserService) {
spyOn(UserService, 'getCurrentUser').and.returnValue({});

$scope = $rootScope;

el = angular.element('<auto-complete collection="" input-value="" enter-event="" focus-on="" />');
$compile(el)($scope);

scope = el.isolateScope();
console.log(scope);
$scope.$apply();

}));

it('should', function () {
 scope.matchSelected();
 expect(scope.showPopup).toBe(false);
}); 
});

and my directive:

italic.directive('autoComplete', ['$timeout', function($timeout) {
return {
restrict: "E",
template: '',
scope: {
  collection: '=',
  inputValue: '=',
  enterEvent: '=',
  focusOn: '='
},
link: function(scope, element) {      
  scope.matchSelected = function (match) {
    scope.inputValue = match;
    scope.showPopup = false;
  };
 }
}; 
}]);

and the error:

undefined is not a function (called on scope.matchSelected in the test)

I believe that it is rooted in the fact that scope = el.isolateScope(); returns undefined.

1
  • I'm not sure if it's related but you are missing two braces on your directive Commented Feb 16, 2015 at 21:38

1 Answer 1

3

It looks like the issue must be to do with two missing braces in the directive. Intead of }]); at the end it should be }}}]);. I'd recommend to take more care when indenting and using braces. If you use indents correctly it will minimise issues such as this. If you were indenting correctly the directive would look like:

italic.directive('autoComplete', ['$timeout', function($timeout) {
  return {
    restrict: "E",
    template: '',
    scope: {
      collection: '=',
      inputValue: '=',
      enterEvent: '=',
      focusOn: '='
    },
    link: function(scope, element) {      
      scope.matchSelected = function (match) {
        scope.inputValue = match;
        scope.showPopup = false;
      };
    }
  };
}]);

It's best to create your directive in the actual it and not in before, that way you can control the scope properties set on the directive.

describe('auto complete directive', function () {
  var $rootScope, $compile;

  beforeEach(module('italic'));

  beforeEach(inject(function (_$compile_, _$rootScope_) {
    $compile = _$compile_;
    $rootScope = _$rootScope_;
  }));

  it('should', function () {
    //Arrange
    var element = $compile("<auto-complete collection=\"\" input-value=\"\" enter-event=\"\" focus-on=\"\" />")($rootScope);

    var scope = element.isolateScope();
    var match = "match";

    //Act
    $rootScope.$digest();
    scope.matchSelected(match);

    //Assert
    expect(scope.showPopup).toBe(false);
  }); 
});

Plunkr

Sign up to request clarification or add additional context in comments.

4 Comments

Its not the brackets. I just used that as a quick example from a larger directive. I'm 100% the brackets are right in my code. Webstorm is what I'm using and they all line up.
Your example gives the same error. console.log(element.html()); returns '' for me. scope is also undefined.
No it's not. It's working fine with no errors. Are you saying that my Plunkr is giving you an error? Are you running the test differently to the Plunkr?
Its working now. You were right. It was the $rootscope.$digest() as opposed to my $scope.$apply()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.