使用templateUrl和隔离作用域测试Angular指令

3
刚接触angular.js,不知道如何为具有templateUrl和隔离作用域的指令编写测试。
这是我的控制器。
(function(){
angular.module('buttons')
    .controller('buttonController', ['$scope', function($scope){

        //primary button
        $scope.primaryButton = { name: 'Submit'};
})();

这是我的views index.html &。
<div class="layoutLeft">
        <p>Primary Button</p>
        <primary-button info="primaryButton"></primary-button>
    </div>

primary-button.html

<button class="{{buttonInfo.class}}">{{buttonInfo.name}}</button>

这是我的指示。
(function(){
    angular.module('buttons')
        .directive('primaryButton', function() {
            return {
                restrict: 'EA',
                scope: {
                    buttonInfo: '=info'
                },
                templateUrl: 'scripts/local/views/primary-button.html'
            }
        })
    })();

这是我的测试。
(function(){
    beforeEach(angular.mock.module('buttons'));
describe('Buttons Directive Test', function(){

    var $compile, $scope, $httpBackend;

    beforeEach(module('templates'));

    beforeEach(inject(function(_$compile_, _$rootScope_) {
        $compile = _$compile_;
        $scope = _$rootScope_.$new();

        $scope.primaryButton = {name: 'Save'};

        elm = angular.element("<primary-button info='buttonInfo'></primary-button>");
        e = $compile(elm)($scope);
        e.digest();
    }));

    it('should do something', function(){
        expect(e.html()).toContain($scope.primaryButton);
    });
});

我正在使用Jasmine和Karma进行测试,有人能指导一下我做错了什么吗?

我的解决方案解决了你的问题吗?请告诉我。 - Peter Ashwell
2个回答

6

编辑:这里有一个plunkr演示了你的代码几乎做了什么。你在问题中提供的代码存在多个问题,我已经进行了修复:

http://plnkr.co/edit/QXprEUof2Ps0Vivg4L34?p=preview

  1. 在你的测试中,你调用了e.digest(),但这是行不通的,因为你无法摘要一个元素...你应该调用$scope.$digest。
  2. e.html()将不会包含那个JSON块。我理解为希望它包含名称标签...
  3. info='buttonInfo'将info绑定到外部作用域中的buttonInfo属性,但你称其为'primaryButton'。将$scope.primaryButton重命名为$scope.buttonInfo。
  4. 你使用了一些并不完全必要的下划线,但这不是一个大问题,在注入compile、rootscope时。
  5. 我使用了内联模板来代替加载模板,只是为了plunkr而已,但加载模板也没有任何问题。
  6. 由于你的指令是一个元素,我添加了'replace',将该元素替换为直接的按钮。考虑将其改为属性。

我的plunkr拥有通过的茉莉花测试一个工作的按钮演示。如果需要更多帮助,请告诉我。祝你在AngularJS中好运。

(旧答案)

==============

你需要使用类似nghtml2js的东西来加载模板,并使用模板缓存使其可用。

使用nghtml2js

这是你的第一个问题。你的第二个问题是通过在编译后调用元素上的isolateScope()来获取隔离作用域。记录一下在elem上调用它的结果,你会找到你想要的属性。

e.isolateScope()

我正在使用karma配置加载HTML文件,并使用nghtml2js,我将尝试使用isolateScope()。 - Varun Sheth
它起作用了吗?这是将您的隔离范围取出的方法。https://dev59.com/iWQm5IYBdhLWcg3wuhHS - Peter Ashwell
嘿,我为你创建了一个 Plunkr,请看一下。 - Peter Ashwell

3

不理解为什么上面的答案被标记为已接受。问题要求使用templateUrl实现,而@PeterAshwell的答案提供了一个内联HTML的解决方案,但在使用templateUrl时无法正常工作

当使用templateUrl时,为了访问隔离作用域,必须将isolateScope调用包装在$timeout中,以允许$http调用(由templateUrl发起)完成。

代码应该类似于:

element = $compile("<myHTML />")($scope)

$timeout(function() {
     expect(element.isolateScope().myProp).toEqual(12);

}), 0 , false);

$timeout.flush();

好的回答!我认为添加 $apply() 以确保解决任何未完成的 promises 也是一个不错的主意。 - TheChrisONeil

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