使用隔离范围对AngularJS Directive进行单元测试 - 如何获得输出绑定?

时间:2014-01-07 13:19:05

标签: javascript unit-testing angularjs angularjs-directive karma-runner

我真的需要有关使用Isolated Scope测试AngularJS指令的建议和指导。

假设我有以下指令(有效):

angular.module('myApp')

    .directive('pageNav', function() {
        return {
            restrict: 'A',
            scope: {
                title: '@'
            },
            transclude: true,
            templateUrl: 'pageNav.html',
            link: function(scope, element, attrs) {
                if (attrs.pageNav == 'translucent') {
                    element.find('nav').addClass('newClass');
                }
             }
        };
    })
;

这是模板网址代码:

<nav class="pageNav">
    <div class="content">
        <h1 ng-if="title">{{ title }}</h1>

        <div class="contentRight" ng-transclude></div>
    </div>
</nav>

现在我有以下测试

describe('Page Nav Directive', function() {

    var $scope,
        element;

    beforeEach(module('myApp'));
    beforeEach(module('pageNav.html'));

    beforeEach(inject(function($compile, $rootScope) {
        $scope = $rootScope;
        $scope.title = "hey hey, my my";
        element = angular.element('<div page-nav></div>');
        // element = angular.element('<div page-nav title="hey hey, my my"></div>');
        $compile(element)($scope);

        $scope.$digest();
    }));

    it('should render the directive', function() {
       // this test will fail if I un-comment the element above
       expect(element.find('div').eq(1).attr('class')).toBe('contentRight');
    });

    it('should render a title', function() {
        // this test will pass if I un-comment the element above
       expect(element.find('h1').eq(0).text()).toBe('hey hey, my my');
    });

})

;

现在我不明白为什么第二个测试因第一个元素而失败,即使我已设置$scope.title(由于某种原因,未呈现绑定{{ title }})。现在,如果我将$scope.title作为属性放在元素上,第二个测试将在渲染工作时通过,但第一个测试失败了吗?我甚至将第一次测试改为

expect(element.scope().find('div').eq(1).attr('class')).toBe('contentRight');

使用时我将元素$scope.title作为属性,但这也失败了。

我发现很少或没有关于使用隔离范围测试AngularJS指令的好文档,我正在拔掉头发。我对此问题的任何指导,信息或解释都将非常感激。

1 个答案:

答案 0 :(得分:3)

问题1:设置$scope.title(由于某种原因,未呈现绑定{{ title }}

当然,因为您使用title: '@'@表示您使用静态字符串进行绑定。

问题2:

您正在使用templateUrl,浏览器必须启动 ajax请求才能加载模板,这意味着该指令的模板尚未加载在当前函数中,必须等待ajax请求才能完成=&gt;结果是不可预测的。

正如这个DEMO所示,如果我在同一个函数中立即检查已编译的html,我看到它没有被编译。为了向您展示templateUrl是正确的并且稍后会加载,我使用console.log添加了一个DEMO并使用对象引用来证明它

如果我使用内联template,就像在此DEMO中一样,模板会被替换(但不会被编译)。

问题3:

Angular js编译功能在当前函数中没有完成,您可能需要使用$ timeout来为下一个周期安排它。 DEMO