指令作用域变量在Jasmine测试中不可访问。

3

我有一个如下的指令:

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的值没有在指令中反映出来,因此resetButton函数从未被调用。我该如何访问指令范围内的变量并更改其值?我已尝试使用isolateScope,但问题仍然存在。
1个回答

7
请注意,您在调用resetButton函数时传递了两个参数,但该函数只接受一个参数。我已在示例代码中进行了修复。我还将类btn-primary添加到按钮元素中,以使测试结果更清晰。
您的指令正在设置外部作用域和隔离作用域之间的双向数据绑定:
scope: {
  isDirty: '=',
  isSaving: '='
}

你应该利用这个来修改 isSaving 变量。
给你的元素添加 is-saving 属性:
elem = '<save-button is-saving="isSaving"></save-button>';

然后修改编译时使用的作用域的isSaving属性(还需要触发脏检查循环以使监视器检测到更改):

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 的双向绑定:

scope: {
  isDirty: '='
}

否则,它会尝试绑定到不存在的内容,因为元素上没有 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

我曾经遇到过同样的错误,后来通过确保指令作用域定义中的可选参数带有 '=?' 来解决了它。 - Daniel Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接