Question

I wrote a directive 'xxx' and it has different behavior on a browser and Jasmine testing framework:

someapp.directive('xxx', function () {
    return {
      restrict: 'AE',
      replace: true,
      scope: {
        x: '=xxx'
      },
      template: '<div>Hello World {{x}}</div>',
      link: function (scope, element, attrs) {
      }
    };
  });

For browser:

<body ng-controller="MainCtrl">
  <div xxx="name"></div>
</body>

someapp.controller('MainCtrl', function($scope) {
  $scope.name = 'Test';
});

It will show "Hello World Test" on the screen in a browser. If in the link function, I add one line:

global_var = element;

and add one line of HTML

<button onclick="javascript:alert(global_var.text());">Test</button>

It will also pop up the alert dialog to show the text "Hello World Test".

However, for Jasmine testing framework:

beforeEach(module('someapp'));

var element,
  scope;

beforeEach(inject(function ($rootScope) {
  scope = $rootScope.$new();
  scope.name = 'Test';
}));

it('should expand "x"', inject(function ($compile) {
  element = angular.element('<div xxx="name"></div>');
  element = $compile(element)(scope); 
  expect(element.text()).toBe('Hello World Test');
}));

It will report the error: expected "Hello World {{x}}" to be "Hello World Test"

Does anyone know why? Thanks.

Was it helpful?

Solution

For the changes to take effect (i.e. for Angular to do its thing) you need to call scope.$apply() or scope.$digest().
($digest() would suffice for this scenario, but in a more complex situation (involving parent scopes etc) you might need to call (the more expensive) $apply() method.)

See, also, this short demo.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top