1

I'm attempting to write unit tests for an AngularJS directive that uses a separate controller from the one on the page. However, I can't find any way to access that controller from within my tests.

Here's my directive:

'use strict';
angular.module('myapp.directives')
  .directive('searchButton', function () {
    function SearchButtonCtrl ($scope, $location) {
      $scope.search = function () {
        $location.path('/search');
        $location.search(q, $scope.query.w);
      };
    }
    return {
      template: '<input type="text" ng-model="query.q">',
      controller: SearchButtonCtrl,
      restrict: 'E'
    };
  });

Is it possible to access SearchButtonCtrl? Or is there a better way to structure my code such that it can be accessed?

1 Answer 1

2

The way you'll end up accessing the controller in this case is by using the function the controller is placing in its scope from the HTML snippets that will form your test inputs.

Note: The use of a jasmine spy may be overkill here, and I didn't take the time to look up the right methods for matching the arguments to $location.path() and/or $location.search(), but this should be enough to help you find the hook into a place for observation that you're looking for.

'use strict';

describe('Directive: Search', function() {

    var element, $location;

    // Load your directive module with $location replaced by a test mock.
    beforeEach( function() {
        module('myapp.directives'), function() {
            $provide.decorator('$location', function($delegate) {
                $delegate.path = jasmine.createSpy();
                $delegate.search = jasmine.createSpy();

                return $delegate;
            });
        });

        inject(function(_$location_) {
            $location = _$location_;
        });
    });

    it('changes the path', function() {
        // Arrange to trigger your directive code
        element = $element.html('<span ng-init="query.q = 'xyz'"><search><span ng-init="search()"></span></search></span>' );

        // Express your directive's intended behavior
        expect($location.path).toHaveBeenCalled();
    });

    it('changes a search param', function() {
        // Arrange to trigger your directive code
        element = $element.html('<span ng-init="query.q = 'xyz'"><search><span ng-init="search()"></span></search></span>' );

        // Express your directive's intended behavior
        expect($location.search).toHaveBeenCalled();
    });
});
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.