我正在使用隔离范围( 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 规范
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();
});
最佳答案
问题
当您定义 @
绑定(bind)时,Angular 会为该属性创建一个观察者,以便在该属性稍后发生更改时可以更新本地属性的值。您可以在第 7676 行 ( Angular 1.3.15 ) 找到该特定代码:
case '@':
attrs.$observe(attrName, function(value) {
isolateBindingContext[scopeName] = value;
});
...
现在让我们看看 the docs $observe
上对此进行了说明(强调我的):
Observes an interpolated attribute.
The observer function will be invoked once during the next $digest following compilation. The observer is then invoked whenever the interpolated value changes.
因此,在编译指令后,即在执行 Controller 和链接函数之后,保证观察者被调用一次。由于您在 Controller 函数中为 id
属性分配了一个新值,因此它会被覆盖回其原始值 - 这是一个字符串,因为它是一个 DOM 属性。
解决方案
鉴于您发布的代码,您似乎只关心 id
第一个值。要获取它,您只需执行以下操作:
.directive('testPane', function () {
return {
...
scope: {},
controller: function($scope, $attrs) {
$scope.id = parseInt($attrs.id, '10');
}
};
});
如果需要,您可以继续使用 @
绑定(bind),但请确保转换后的值存储在作用域的另一个属性中,以便它不会被覆盖 - 无论是在编译指令之后还是稍后。
关于javascript - 使用 Jasmine 测试隔离范围时出现意外的变量类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30464764/