使用Jasmine测试隔离范围时出现意外的变量类型

时间:2015-05-26 17:04:54

标签: javascript angularjs jasmine

我正在使用isolate scope(angular)和Jasmine测试框架测试一个指令。一切都工作正常,有一个奇怪的地方:如果我将$ scope上的变量类型从字符串更改为数字,Jasmine继续将其视为字符串,即使指令代码本身正确地将其视为数字。

我理解为什么这可能具有直观意义 - parm最初作为字符串插入,也许Angular有一些机制来确保它保持字符串。如果是的话,我不知道它在Angular源中的实现方式和位置(甚至可能是它)。

总之:为什么Jasmine会看到一个字符串而指令会看到一个数字?

这是我的代码:

标记

<pane id={{myId}}></pane>

指令

.directive('testPane', function () {

    function thisController($scope) {

       //$scope.id is string '1'
       $scope.id = parseInt($scope.id);

       //now it is number 1 (as expected)
       console.log($scope.id);


    };


    return {
        restrict: 'E',
        transclude: true,
        scope: { id: '@'},
        controller: thisController,
        link: function (scope, element, attrs, tabsController) {


        },
        templateUrl: 'test/test.html',
        replace: true
    };
})

Jasmine Spec

it("changes id from string to number", function () {

    var element,
        elementScope;

    $rootScope.myId = 1;

    element = $compile(html)($rootScope);

    $timeout(function () {
        businessTabScope = element.isolateScope();
        $rootScope.$digest();


        expect(elementScope.id).toBeDefined();

        //id is text '1' instead of number 1. Why?
        expect(elementScope.id).toEqual($rootScope.myId);
    }, 0, false);



   $timeout.flush();


});

1 个答案:

答案 0 :(得分:1)

<强>问题

当您定义@绑定时,Angular会为该属性创建一个观察者,以便在该属性稍后更改时更新本地属性的值。您可以在第7676行(Angular 1.3.15)找到该特定代码:

case '@':
  attrs.$observe(attrName, function(value) {
    isolateBindingContext[scopeName] = value;
  });  
  ...

现在让我们看看$observeid所说的内容(强调我的):

  

观察插值属性。

     

观察者函数将在下一个$摘要期间调用一次   编译后。然后每当调用观察者时   插值变化。

在编译指令之后,即在执行控制器和链接函数之后,观察者保证被调用一次。并且由于您要为控制器函数中的id属性分配一个新值,它会被覆盖回原始值 - 这是一个字符串,因为它是一个DOM属性。

<强>解决方案

根据您发布的代码,您似乎只关心.directive('testPane', function () { return { ... scope: {}, controller: function($scope, $attrs) { $scope.id = parseInt($attrs.id, '10'); } }; }); 第一个值。要抓住它,您只需执行以下操作:

@

如果需要,您可以继续使用/recommendation/thetitle绑定,但要确保转换后的值存储在作用域的另一个属性中,以便在编译指令或稍后编译时不会覆盖它。