How to test a directive's controller using angularJS-karma-jasmine?

angularjs, angularjs-directive, jasmine, javascript, karma-jasmine

Solution

Compile the element, and after calling `$digest()`, you will have access to the scope which contains `carousel` object with `awesomeThings` array:

describe('waCarousel Unit', function() {
    var scope;

    beforeEach(module('carouselApp'));
    beforeEach(inject(function($rootScope, $compile) {
        var element = '<test></test>';

        scope = $rootScope.$new();

        element = $compile(element)(scope);
        scope.$digest();
    }));

    it('should have a list of awesomeThings', function() {    
        expect(scope.carousel.awesomeThings.length).toBe(3);
    });
});

Also, here are some useful links to testing directives in angular:

- Testing Directives

- Testing AngularJS directive controllers with Jasmine and Karma

- Introduction to Unit Test: Directives

Problem

Goal: Write a passing test for the `waCarousel` directive scope variable: `self.awesomeThings`. Expect this test pass when `self.awsomeThings.length.toBe(3)` to is true? Question: How can I properly write this test? rather how do I inject a directives controller? Directive: ``` angular.module('carouselApp') .directive('waCarousel', function() { return { templateUrl: '../../../views/carousel/wa.carousel.html', controller: function($scope) { var self = this; self.awesomeThings = [1, 2, 3]; return $scope.carousel = self; } } }); ``` Unit Test: ``` describe('waCarousel Unit', function() { // am I missing a $controller & namespace variable init? var $compile, $rootScope; // Load the myApp module, which contains the directive beforeEach(module('carouselApp')); // Store references to $rootScope and $compile and $controller // so they are available to all tests in this describe block beforeEach(inject(function(_$compile_, _$rootScope_, _$controller_){ // The injector unwraps the underscores (_) from around the parameter names when matching $compile = _$compile_; $rootScope = _$rootScope_; $controller = _$controller_; // WaCarouselCtrl = $controller('WaCarouselCtrl', { // $scope: scope // }); })); it('should have a list of awesomeThings', function() { // This wont pass expect(scope.awesomeThings.length).toBe(3); }); }); ``` This is how I would do it for a typical view and not directive: ``` describe('Controller: MainCtrl', function() { // load the controller's module beforeEach(module('carouselApp')); var MainCtrl, scope; // Initialize the controller and a mock scope beforeEach(inject(function($controller, $rootScope) { scope = $rootScope.$new(); // !!*** this is how I would inject the typical controller of a view **!! // MainCtrl = $controller('MainCtrl', { $scope: scope }); })); it('should attach a list of awesomeThings to the scope', function() { expect(scope.awesomeThings.length).toBe(3); }); }); ``` How do I merge these two concepts so that I can expect `self.awesomeThings.length).toBe(3)`? UPDATE:

Original source