【问题标题】:testing an angular checkbox using in jasmin使用 jasmin 测试角度复选框
【发布时间】:2014-05-11 14:01:22
【问题描述】:

我的情况如下:

指令

scope: { foo:'=' },
template: '<input type="checkbox" ng-model="foo"/>'

父控制器

$scope.foo = false;

茉莉花测试

var cb = iElement.find('input');

$timeout(function() {  // using $timeout to ensure $digest() isn't the issue.
    cb.prop('checked',!cb.prop('checked'))
},0);

expect(cb.prop('checked')).toBe(true); // passes

expect($scope.foo).toBe(true); // doesn't pass

我的问题:为什么在我发出 prop('checked') 时 $scope.foo 没有得到更新,即使 DOM 更新了(正如我在检查后验证的那样)。

这里是一个jsbin,大致演示了问题http://jsbin.com/kapifezi/2/edit

【问题讨论】:

  • 以不同的方式询问 - 测试 ng-model 链接到其父控制器中的变量的复选框(位于指令中)的正确方法是什么?

标签: javascript angularjs checkbox jasmine karma-runner


【解决方案1】:

所以完整的答案是: 你需要改变'checked'属性,然后触发点击事件。

var input = element.find('input');
input.prop('checked',!input.prop('checked'));
// input.triggerHandler('click');
input.triggerHandler('change');

感谢凯文,这对我帮助很大!

【讨论】:

    【解决方案2】:

    经过进一步调查 - 当您将 ng-model 添加到复选框之类的东西时,Angular 似乎会添加一个 click 侦听器。

    因此,似乎正确的测试方法是在 jasmine 测试中对 DOM 对象发出 click event

    【讨论】:

    • 实际上 - 我最近遇到了一个问题(可能与在此处使用 click 相关),其中 Firefox 无法获取点击事件(或者可能更改没有执行 $digest 循环 - 不管我在 click 之后直接对 $digest() 的明确调用——尽管测试在 Chrome 和 PhantomJS 中都通过了。不知道发生了什么......
    • 感谢@Kevin,您的 cmets 拯救了我的一天在我的测试中 el.prop('checked', true) 不起作用,但一旦更改为 el.click(),模型已正确更新
    【解决方案3】:

    试试

    expect($scope.$parent.foo).toBe(true);
    

    更新答案:

    $timeout(function() {  // using $timeout to ensure $digest() isn't the issue.
          //cb.prop('checked',!cb.prop('checked'));  
          $scope.val = !cb.prop('checked');
    
    },0);
    

    您希望将所有更新保持在范围级别,并让 Angular 自行管理周期。如果更新了属性,您将不在 Angular 的雷达范围内。

    【讨论】:

    • 我猜你的意思是 $scope.$parent。无论如何, foo 在那里不存在。如果我理解正确,为了访问指令创建的隔离范围,我需要使用返回的范围,例如:ele = angular.element('&lt;directive&gt;&lt;/directive&gt;');$compile(ele)($rootScope)isolated_scope = ele.scope();
    • 抱歉错字。固定答案。模板中的新输入有自己的范围。您传递了值,但应该能够访问父值。
    • 也许我的问题不清楚 - 在这个 jsbin 示例中:link 为什么我的范围变量 $scope.val 没有更新?
    • 如果我做对了,您希望通过单击按钮来更新复选框和标签。为此,请替换行 'cb.prop('checked',!cb.prop('checked'));' with '$scope.val = !cb.prop('checked');' - 对我有用。
    • 是的,你是对的 - 这确实有效 - 但不是我需要/想要的方式。如果您注意到,$scope.val 与 checkbox 指令的 ng-model 相关联,所以在我看来,如果复选框从选中变为未选中,那么 ng-model 应该接受此更改是有道理的.或者,也许我对 MVC 交互方式的理解存在偏差。无论哪种情况,我想我现在都可以按照您上面的建议做一些事情。谢谢。
    【解决方案4】:

    @egoproxy 的回答最终帮助了我,但我在使用原始 dom 元素时遇到了问题。为了解决这个问题,我使用了angular.element(domElement)将原始 DOM 元素或 HTML 字符串包装为 jQuery 元素。

    var checkbox = angular.element(checkboxElement));
    
    // Click to check it, then Change to propate to ngModel 
    checkbox.trigger('click');
    checkbox.trigger('change');
    

    【讨论】:

      猜你喜欢
      • 2018-01-18
      • 2020-01-18
      • 2015-04-02
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 2020-10-31
      • 2023-03-22
      • 2020-08-22
      相关资源
      最近更新 更多