使用独立范围的AngularJS指令进行单元测试——如何将绑定传递到输出?

时间:2021-01-03 19:39:53

I'm really needing advice and guidance on testing AngularJS directives with Isolated Scope.

我确实需要关于测试AngularJS指令和隔离范围的建议和指导。

Say I have the following directive (which works):

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

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');
                }
             }
        };
    })
;

This is the template URL code:

这是模板URL代码:

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

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

now I have the following test

现在我有下面的测试

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');
    });

})

;

Now I don't understand why the second test fails with the first element even though I have set the $scope.title (for some reason the binding {{ title }} isn't rendered). Now if I put the $scope.title on the element as an attribute the second test will pass as the rendering works, but the first test fails? I even changed the first test to

现在我不明白为什么第二个测试用第一个元素失败了,即使我设置了$scope。title(出于某种原因,未呈现绑定{{title})。现在如果我放入$作用域。元素的标题作为属性,第二个测试将在呈现工作时通过,但是第一个测试失败了?我甚至把第一个测试改为

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

when using the I put the $scope.title on the element as an attribute however this failed too.

当使用I时,放置$scope。元素的标题作为属性,但是这也失败了。

I am finding little or no good documentation on testing AngularJS Directives with isolated scopes and I am pulling my hair out. Any guidance, info or explanations to the problems I have would be most appreciated.

我发现很少或没有很好的文档来测试使用隔离范围的AngularJS指令,我把头发拉了出来。如对我所遇到的问题有任何指导、信息或解释,我将不胜感激。

1 个解决方案

#1


3  

Problem 1: setting $scope.title (for some reason the binding {{ title }} isn't rendered)

问题1:设置美元范围。title(出于某种原因,未呈现绑定{{title})

Sure, because you're using title: '@', @ means you bind with static string.

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

Problem 2:

问题2:

You're using templateUrl, the browser has to initiate an ajax request to load the template, it means that the directive's template is not loaded yet in the current function, has to wait for the ajax request to finish => the result is unpredictable.

您正在使用templateUrl,浏览器必须发起一个ajax请求来加载模板,这意味着该指令的模板尚未在当前函数中加载,必须等待ajax请求完成=>,结果是不可预测的。

As this DEMO shows, if I check the compiled html immediately in the same function, I see that it's not compiled. In order to show you that the templateUrl is correct and will be loaded later, i added one more DEMO using console.log with an object reference to prove it

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

If I use inline template, as in this DEMO, the template is replaced (but not compiled).

如果我使用内联模板(如本示例中所示),模板将被替换(但未编译)。

Problem 3:

问题3:

Angular js compile function does not finish in the current function, you may need to use $timeout to schedule it for the next cycle. DEMO

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

#1


3  

Problem 1: setting $scope.title (for some reason the binding {{ title }} isn't rendered)

问题1:设置美元范围。title(出于某种原因,未呈现绑定{{title})

Sure, because you're using title: '@', @ means you bind with static string.

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

Problem 2:

问题2:

You're using templateUrl, the browser has to initiate an ajax request to load the template, it means that the directive's template is not loaded yet in the current function, has to wait for the ajax request to finish => the result is unpredictable.

您正在使用templateUrl,浏览器必须发起一个ajax请求来加载模板,这意味着该指令的模板尚未在当前函数中加载,必须等待ajax请求完成=>,结果是不可预测的。

As this DEMO shows, if I check the compiled html immediately in the same function, I see that it's not compiled. In order to show you that the templateUrl is correct and will be loaded later, i added one more DEMO using console.log with an object reference to prove it

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

If I use inline template, as in this DEMO, the template is replaced (but not compiled).

如果我使用内联模板(如本示例中所示),模板将被替换(但未编译)。

Problem 3:

问题3:

Angular js compile function does not finish in the current function, you may need to use $timeout to schedule it for the next cycle. DEMO

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