Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to implement a test that relies on a scope variable. I want to enable ng-switch-when to resolve an expression. This is what I'm trying to do (UPDATE using $rootScope):

it('should switch on array changes', inject(function($rootScope, $compile) {
  element = $compile(
    '<div ng-switch="select">' +
      '<div ng-switch-when="test[0]">test[0]:{{test[0]}}</div>' +
    '</div>')($rootScope);
  expect(element.html()).toEqual('<!-- ngSwitchWhen: test[0] -->');
  $rootScope.test = ["leog"];
  $rootScope.select = "leog";
  $rootScope.$apply();
  expect(element.text()).toEqual('test[0]:leog');
}));

My problem is that the implementation I have for this to work does not get the scope variable "test" to evaluate and work as I expect. Here is the implementation:

var ngSwitchWhenDirective = ngDirective({
  transclude: 'element',
  priority: 800,
  require: '^ngSwitch',
  compile: function(element, attrs) {
    return function(scope, element, attr, ctrl, $transclude) {
      var expr = scope.$eval(attrs.ngSwitchWhen),
          ngSwitchWhen = expr !== undefined ? expr : attrs.ngSwitchWhen;
      ctrl.cases['!' + ngSwitchWhen] = (ctrl.cases['!' + ngSwitchWhen] || []);
      ctrl.cases['!' + ngSwitchWhen].push({ transclude: $transclude, element: element });
    };
  }
});

Does anybody knows what I'm doing wrong? Any help will be appreciated.

Thanks in advance!

UPDATE

Just to clarify, this is an example of how ng-switch it's being tested from the Angular team. Just to show that I'm doing my test in a similar way but not having the expected result.

And also, I forgot to reverse my code to $rootScope, what you've been seeing up until now was one of my attempts to make this work creating a new scope to avoid relying on $rootScope for a change.

it('should switch on value change', inject(function($rootScope, $compile) {
    element = $compile(
      '<div ng-switch="select">' +
      '<div ng-switch-when="1">first:{{name}}</div>' +
      '<div ng-switch-when="2">second:{{name}}</div>' +
      '<div ng-switch-when="true">true:{{name}}</div>' +
      '</div>')($rootScope);
    expect(element.html()).toEqual(
       '<!-- ngSwitchWhen: 1 --><!-- ngSwitchWhen: 2 --><!-- ngSwitchWhen: true -->');
    $rootScope.select = 1;
    $rootScope.$apply();
    expect(element.text()).toEqual('first:');
    $rootScope.name="shyam";
    $rootScope.$apply();
    expect(element.text()).toEqual('first:shyam');
    $rootScope.select = 2;
    $rootScope.$apply();
    expect(element.text()).toEqual('second:shyam');
    $rootScope.name = 'misko';
    $rootScope.$apply();
    expect(element.text()).toEqual('second:misko');
    $rootScope.select = true;
    $rootScope.$apply();
    expect(element.text()).toEqual('true:misko');
}));
share|improve this question
    
does it work outside of the test? what does element.text() return when the test runs? –  UnicodeSnowman Dec 10 '13 at 20:07
    
Yes, it does work on a real use case. When the test runs the element.text() is '' (empty string). Debugging it I found that the scope variable on the compile inner function, does not have the "test" property as I do have on the real use case. Perhaps this has something to do with scope visibility. –  LeoG Dec 10 '13 at 23:41
    
This might reveal my ignorance, but can you confirm the aim of your test? It seems like you've posted the AngularJS source of ngSwitchWhen: are you trying to test that? –  Michal Charemza Dec 15 '13 at 22:28
    
As I described, I want to have the ng-switch-when from Angular to resolve expressions, in the case of this test, have the ng-switch value match an array value. –  LeoG Dec 16 '13 at 23:21
1  
My bad, after changing back to $rootScope and moving $rootScope.test before compiling I was able to resolve the issue, thanks a lot @Jonathan. –  LeoG Dec 22 '13 at 18:34

2 Answers 2

up vote 1 down vote accepted

So, after moving some code around I found that the variables not involved on making $rootScope change to test the feature, should be defined before compiling the element to test. Thanks @Jonathan for the hint.

Here is the working code with additional test cases:

it('should evaluate expressions to match switch value', inject(function($rootScope, $compile) {
  $rootScope.array = ["leog", ".me"];
  $rootScope.obj = {"key": "value"};
  $rootScope.$apply();
  element = $compile(
    '<div ng-switch="select">' +
      '<div ng-switch-when="obj.key">obj.key:{{obj.key}}</div>' +
      '<div ng-switch-when="array[0]">array[0]:{{array[0]}}</div>' +
      '<div ng-switch-when="array[1]">array[1]:{{array[1]}}</div>' +
    '</div>')($rootScope);
  expect(element.html()).toEqual('<!-- ngSwitchWhen: obj.key -->' +
                                 '<!-- ngSwitchWhen: array[0] -->' +
                                 '<!-- ngSwitchWhen: array[1] -->');
  $rootScope.select = "value1";
  $rootScope.$apply();
  expect(element.text()).toEqual('obj.key:value');
  $rootScope.select = "leog";
  $rootScope.$apply();
  expect(element.text()).toEqual('array[0]:leog');
  $rootScope.select = ".me";
  $rootScope.$apply();
  expect(element.text()).toEqual('array[1]:.me');
}));

Thanks you all.

share|improve this answer

$scope.$apply needs to have a function inside of the parenthesis that is to be executed, which your test code is lacking. To get things to happen while testing I use $scope.$digest() (instead of $scope.$apply(); This kicks off a manual digest cycle that would not otherwise be running in the test.

share|improve this answer
    
Already tested your two possible solutions and nothing. Thanks anyway @MBielski –  LeoG Dec 22 '13 at 17:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.