angularjs - Jasmine 测试中无法访问指令范围变量

标签 angularjs angularjs-directive angularjs-scope karma-jasmine

我有如下指令:

angular.module('buttonModule', []).directive('saveButton', [
function () {

    function resetButton(element) {
        element.removeClass('btn-primary');
    }
    return {
        restrict: 'E',
        replace: 'false',
        scope: {
            isSave: '='
        },
        template:
            '<button class="btn" href="#" style="margin-right:10px;" ng-disabled="!isSave">' +

            '</button>',
        link: function (scope, element) {               
            console.log(scope.isSave);
            scope.$watch('isSave', function () {
                if (scope.isSave) {
                    resetButton(scope, element);
                }
            });
        }
    };
}
]);

Jasmine 测试如下:

describe('Directives: saveButton', function() {

var scope, compile;

beforeEach(module('buttonModule'));

beforeEach(inject(function($compile, $rootScope) {
    scope = $rootScope.$new();
    compile = $compile;
}));

function createDirective() {
    var elem, compiledElem;
    elem = angular.element('<save-button></save-button>');
    compiledElem = compile(elem)(scope);
    scope.$digest();

    return compiledElem;    
}

it('should set button clean', function() {

    var el = createDirective();
    el.scope().isSaving = true;
    expect(el.hasClass('btn-primary')).toBeFalsy();     
});

});

问题是 isSaving 的值没有反射(reflect)在指令中,因此永远不会调用 resetButton 函数。我如何访问规范中的指令范围并更改变量值。我尝试使用 isolateScope,但同样的问题仍然存在。

最佳答案

首先请注意,您在调用 resetButton 函数时使用了两个参数,而它只接受一个参数。我在我的示例代码中修复了这个问题。我还在按钮元素中添加了 btn-primary 类,使测试的通过更加清晰。

您的指令在外部范围和隔离范围之间设置双向数据绑定(bind):

scope: {
  isDirty: '=',
  isSaving: '='
}

您应该利用它来修改 isSaving 变量。

is-saving 属性添加到您的元素:

elem = '<save-button is-saving="isSaving"></save-button>';

然后修改编译时使用的scope的isSaving属性(还需要触发digest循环让watcher检测到变化):

var el = createDirective();

scope.isSaving = true;
scope.$apply();

expect(el.hasClass('btn-primary')).toBeFalsy();

演示: http://plnkr.co/edit/Fr08guUMIxTLYTY0wTW3?p=preview

如果您不想将 is-saving 属性添加到您的元素并且仍然想修改您需要检索隔离范围的变量:

var el = createDirective();

var isolatedScope = el.isolateScope();
isolatedScope.isSaving = true;
isolatedScope.$apply();

expect(el.hasClass('btn-primary')).toBeFalsy();

然而,要使其正常工作,您需要删除与 isSaving 的双向绑定(bind):

scope: {
  isDirty: '='
}

否则它会尝试绑定(bind)到不存在的东西,因为元素上没有 is-saving 属性,您会收到以下错误:

Expression 'undefined' used with directive 'saveButton' is non-assignable! (https://docs.angularjs.org/error/$compile/nonassign?p0=undefined&p1=saveButton)

演示: http://plnkr.co/edit/Ud6nK2qYxzQMi6fXNw1t?p=preview

关于angularjs - Jasmine 测试中无法访问指令范围变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23942532/

相关文章:

angularjs - 如何使用angularjs将http POST方法中的两个不同类型的参数传递给Web API?

javascript - 遍历提供的属性

javascript - Angular js 服务值不会在 View 中更新

javascript - 隔离范围指令对更改没有反应 : angularjs

javascript - 将值从一个对象复制到另一个对象,忽略新属性

angularjs - 抑制 ngResource 中的方法

angularjs - 我如何摆脱我的 Protractor 测试这个错误 : Error while waiting for Protractor to sync with the page: {}

javascript - 当复选框值更改时,$watch 不会在 Angular 指令中被命中

javascript - 只使用一次 Angular Directive(指令)

javascript - 在 Angular 中,在两个不同的指令之间传递匹配的 $index