0
votes

I'm trying to test an directive's callback function

To be short (angular 1.x, karma and angular-mocks):

The directive points:

  • $scope.show is a function
  • $scope.show expected "message" parameter

The directive code:

angular.module('test', [])
.controller('alertCtrl', function($scope) {
    $scope.show({
        message: 'Hello'
    })
})
.directive('alert', function() {
    return {
        controller: 'alertCtrl',
        scope: {
            show: '&'
        }
    }
})

The spec:

beforeEach(function () {
  $scope.show = function (message) {
    alert(message)
  }
})

it('must execute an expression', function(){
  element = $compile(`
    <alert show="show(message)"></alert>`)($scope);

  $scope.$digest() // It makes no difference
  scope = element.isolateScope()
  scope.$digest() // It makes no difference
  console.log(angular.mock.dump(scope)) // scope.show == undefined
})

After compile is complete the directive property "show" is undefined. I miss something?

EDIT:

The full code ...

angular.module('test', [])
.controller('alertCtrl', function($scope) {
    $scope.show({
        message: 'Hello'
    })
})
.directive('alert', function() {
    return {
        controller: 'alertCtrl',
        scope: {
            show: '&',
            bind: '=',
            string: '@'
        }
    }
})

describe('test', function(){

  beforeEach(angular.mock.module('test'));

  beforeEach(angular.mock.inject(function (_$compile_, _$rootScope_) {
    $compile = _$compile_;
    $scope = _$rootScope_.$new();
  }))

  beforeEach(function () {
    $scope.show = function (message) {
      alert(message)
    }
    $scope.bind = {data: 123}
  })

  it('must execute an expression', function(){
    element = $compile(`
      <alert show="show(message)"
        bind="bind"
        string="'World'"
        ></alert>`)($scope);

    $scope.$digest() // It makes no difference
    scope = element.isolateScope()
    scope.$digest() // It makes no difference
    console.log(angular.mock.dump(scope)) // scope.show == undefined
  })

})

The output of karma... ALERT: 'Hello' LOG: ' Scope(3): { show: undefined bind: {"data":123} string: "'World'" }' Chrome 59.0.3071 (Linux 0.0.0): Executed 1 of 1 SUCCESS (0.01 secs / 0.036 secs)

1
I believe what you did is right, only the testing part looks wrong. try replace $scope.$digest() // It makes no difference scope = element.isolateScope() scope.$digest() // It makes no difference console.log(angular.mock.dump(scope)) // scope.show == undefined by $scope.$digest(); expect(element.isolateScope().show).toBeDefined(); I advised you to use a spy to test function binding instead. - Julon Lou
Jasmine' spyOn function worked great! Thanks @JulonLou! - saulsluz

1 Answers

0
votes

It looks like you declare the show function in the wrong shared scope var. Did you declare the scope var right under your declare statement and init it in a beforeeach with a $rootScope.$new() then add your function to it then pass it to your directive instanciation?