测试元素指令 - 在测试期间无法访问隔离的范围方法

时间:2013-09-10 08:21:14

标签: angularjs angularjs-directive angularjs-scope

我有以下指令。

directivesModule.directive('wikis', function() {
var urlRegex = new RegExp('^(https?)://.+$');

return {
    restrict: 'E', 
    templateUrl: 'templates/wiki-list.html',
    scope: {
        wikis: '='
    },
    link: function(scope, element, attrs) {
        scope.newWikiURL = '';

        scope.$watch('wikis', function() {
            if (scope.wikis == undefined || scope.wikis.length === 0) {
                scope.class = 'hide';
            } else {
                scope.class = 'show';
            }
        }, false);

        scope.addWiki = function() {
            if (scope.wikis == undefined) {
                scope.wikis = [];
            }

            var nw = scope.newWikiURL;
            if (nw != undefined && nw.trim() != '' && urlRegex.exec(nw)) { 
                scope.wikis.push(nw);
                scope.newWikiURL = '';
            }
        }

    }
};

});

当我测试时:

describe('Wikis Directive Test Suite', function() {
    var scope, elem, directive, linkFn, html;

    beforeEach(function() {
        html = '<wikis wikis=''></wikis>';

        inject(function($compile, $rootScope) {
            scope = $rootScope.$new();
            scope.wikis = [];

            elem = angular.element(html);

            $compile(elem)(scope);

            scope.$digest();
        });

    });

    it('add Wiki should add a valid wiki URL to artist', function() {
        var url = 'http://www.foo.com';
        scope.newWikiURL = url;
        scope.addWiki();

        expect(scope.wikis.length).toBe(1);
        expect(scope.wikis[0]).toBe(url);
        expect(scope.newWikiURL).toBe('');
    });
});

我收到一条错误消息,指出Object没有addWiki方法。我尝试调试它,并且在测试期间不调用链接函数。我怀疑这就是为什么addWiki方法不是范围的一部分。有谁知道我为什么会收到这个错误?

顺便说一下,将一些逻辑添加到指令的链接函数中是否正常,因为它本身就是一个控制器本身?因为查看代码我知道这就是为什么我实际上在做什么。

2 个答案:

答案 0 :(得分:40)

根据角度1.2.0文档,获取隔离范围的方法是通过isolateScope方法

  • scope() - 检索当前元素或其父元素的范围。

  • isolateScope() - 如果一个直接连接到当前元素,则检索隔离范围。此getter应仅用于包含启动新隔离范围的指令的元素。在此元素上调用scope()始终返回原始的非隔离范围。

Angular doc - section jQuery/jqLite Extras

BREAKING CHANGE: jqLite#scope()

答案 1 :(得分:39)

  1. 您需要加载包含指令的模块,否则angular不知道<wikis>是什么

  2. 您的指令会创建一个隔离范围,因此一旦编译完毕,您需要使用elem.isolateScope()

  3. 获取新范围

    所以这些变化:

    describe('Wikis Directive Test Suite', function() {
        var $scope, scope, elem, directive, linkFn, html;
    
        beforeEach(module('app'));
    
        beforeEach(function() {
            html = '<wikis></wikis>';
    
            inject(function($compile, $rootScope, $templateCache) {
                $templateCache.put('templates/wiki-list.html', '<div>wiki template</div>');
    
                $scope = $rootScope.$new();
                $scope.wikis = [];
    
                elem = angular.element(html);
    
                $compile(elem)($scope);
    
                scope = elem.isolateScope();
                scope.$apply();
            });
    
        });
    
        it('add Wiki should add a valid wiki URL to artist', function() {
            var url = 'http://www.foo.com';
            scope.newWikiURL = url;
            scope.addWiki();
    
            expect(scope.wikis.length).toBe(1);
            expect(scope.wikis[0]).toBe(url);
            expect(scope.newWikiURL).toBe('');
        });
    });
    

    http://jsfiddle.net/QGmCF/1/