加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angularjs – 在指令测试中模拟所需的控制器

发布时间:2020-12-17 17:17:11 所属栏目:安全 来源:网络整理
导读:我正在努力弄清楚如何模仿我所写的指令所需的控制器,这是另一个人的孩子. 首先让我分享我的指令: 家长 angular .module('app.components') .directive('myTable',myTable);function myTable() { var myTable = { restrict: 'E',transclude: { actions: 'act
我正在努力弄清楚如何模仿我所写的指令所需的控制器,这是另一个人的孩子.

首先让我分享我的指令:

家长

angular
    .module('app.components')
    .directive('myTable',myTable);

function myTable() {
    var myTable = {
        restrict: 'E',transclude: {
            actions: 'actionsContainer',table: 'tableContainer'
        },scope: {
            selected: '='
        },templateUrl: 'app/components/table/myTable.html',controller: controller,controllerAs: 'vm',bindToController: true
    };

    return myTable;

    function controller($attrs,$scope,$element) {
        var vm = this;
        vm.enableMultiSelect = $attrs.multiple === '';
    }
}

儿童

angular
    .module('app.components')
    .directive('myTableRow',myTableRow);

myTableRow.$inject = ['$compile'];

function myTableRow($compile) {
    var myTableRow = {
        restrict: 'A',require: ['myTableRow','^^myTable'],scope: {
            model: '=myTableRow'
        },bindToController: true,link: link
    };

    return myTableRow;

    function link(scope,element,attrs,ctrls) {

        var self = ctrls.shift(),tableCtrl = ctrls.shift();

        if(tableCtrl.enableMultiSelect){
            element.prepend(createCheckbox());
        }

        self.isSelected = function () {
            if(!tableCtrl.enableMultiSelect) {
                return false;
            }
            return tableCtrl.selected.indexOf(self.model) !== -1;
        };

        self.select = function () {
            tableCtrl.selected.push(self.model);
        };

        self.deselect = function () {
            tableCtrl.selected.splice(tableCtrl.selected.indexOf(self.model),1);
        };

        self.toggle = function (event) {
            if(event && event.stopPropagation) {
                event.stopPropagation();
            }

            return self.isSelected() ? self.deselect() : self.select();
        };

        function createCheckbox() {
            var checkbox = angular.element('<md-checkbox>').attr({
                'aria-label': 'Select Row','ng-click': 'vm.toggle($event)','ng-checked': 'vm.isSelected()'
            });

            return angular.element('<td class="md-cell md-checkbox-cell">').append($compile(checkbox)(scope));
        }
    }

    function controller() {

    }
}

正如您可能看到的那样,它的一个表行指令预先设置了复选框单元格,并且在切换时用于填充绑定到父表指令范围的所选项目数组.

当谈到单元测试表行指令时,我遇到了可以使用元素上的data属性模拟所需控制器的解决方案.

我试过这个,现在我正在尝试测试我的表行指令中的toggle函数来检查它是否将一个项添加到父表指令的scope selected属性:

describe('myTableRow Directive',function() {
  var $compile,scope,compiledElement,tableCtrl = {
      enableMultiSelect: true,selected: []
    },controller;

  beforeEach(function() {
    module('app.components');
    inject(function(_$rootScope_,_$compile_) {
      scope = _$rootScope_.$new();
      $compile = _$compile_;
    });

    var element = angular.element('<table><tbody><tr my-table-row="data"><td></td></tr></tbody></table>');

    element.data('$myTableController',tableCtrl);
    scope.data = {foo: 'bar'};
    compiledElement = $compile(element)(scope);
        scope.$digest();
    controller = compiledElement.controller('myTableRow');

  });

  describe('select',function(){
    it('should work',function(){
      controller.toggle();
      expect(tableCtrl.selected.length).toEqual(1);
    });
  });
});

但我收到一个错误:

undefined is not an object (evaluating ‘controller.toggle’)

如果我在我的测试中控制台注销控制器的值,它显示为未定义.

我在这方面毫无疑问做错了什么,有人可以赐教吗?

谢谢

UPDATE

我已经遇到过这些帖子:

Unit testing a directive that defines a controller in AngularJS

How to access controllerAs namespace in unit test with compiled element?

鉴于我正在使用controllerAs语法,我尝试了以下内容:

var element = angular.element('<table><tr act-table-row="data"><td></td></tr></table>');
  element.data('$actTableController',tableCtrl);
  $scope.data = {foo: 'bar'};
  $compile(element)($scope);
  $scope.$digest();
  console.log(element.controller('vm'));

但控制器仍然在控制台日志中未定义.

更新2

我遇到过这篇文章 – isolateScope() returning undefined when testing angular directive

认为它可以帮助我,所以我尝试了以下代替

console.log(compiledElement.children().scope().vm);

但它仍然以未定义的形式返回. compiledElement.children().scope()确实返回一个带有大量有角度的$$前缀范围相关属性的大对象,我可以看到我想要进入的vm控制器深埋在内部,但不确定这是否正确途径

更新3

我遇到过这个article,它涵盖了我正在努力实现的那种东西.

当我尝试在我的测试中实现这种方法时,我可以获得子指令的元素,但我仍然无法检索它的范围:

beforeEach(function(){
    var element = angular.element('<table><tr act-table-row="data"><td></td></tr></table>');
    element.data('$actTableController',tableCtrl);
    $scope.data = {foo: 'bar'};
    compiledElement = $compile(element)($scope);
    $scope.$digest();
    element = element.find('act-table-row');
    console.log(element);
    console.log(element.scope()); //returns undefined
});

我只是想知道这是不是使用链接函数和controllerAs语法?

解决方法

您与发布的原始代码非常接近.我认为你只是在错误的元素上使用 .controller('myTableRow'),因为此时你的compileElement是整个表元素.您需要获取实际的tr子元素才能使myTableRow控制器脱离它.

见下文,具体如下:

controller = compiledElement.find('tr').controller('myTableRow');
/* Angular App */
(function() {
  "use strict";

  angular
    .module('app.components',[])
    .directive('myTableRow',myTableRow);

  function myTableRow() {
    return {
      restrict: 'A',scope: {
        model: '=myTableRow'
      },link: link
    };

    function link($scope,$element,$attrs,$ctrls) {
      var self = $ctrls.shift(),tableCtrl = $ctrls.shift();

      self.toggle = function() {
        // keeping it simple for the unit test...
        tableCtrl.selected[0] = self.model;
      };
    }

    function controller() {}
  }

})();

/* Unit Test */
(function() {
  "use strict";

  describe('myTableRow Directive',function() {
    var $compile,tableCtrl = {},controller;

    beforeEach(function() {
      module('app.components');
      inject(function(_$rootScope_,_$compile_) {
        $scope = _$rootScope_.$new();
        $compile = _$compile_;
      });

      tableCtrl.enableMultiSelect = true;
      tableCtrl.selected = [];

      var element = angular.element('<table><tbody><tr my-table-row="data"><td></td></tr></tbody></table>');

      element.data('$myTableController',tableCtrl);
      $scope.data = {
        foo: 'bar'
      };
      compiledElement = $compile(element)($scope);
      $scope.$digest();
      controller = compiledElement.find('tr').controller('myTableRow');
      //console.log(controller); // without the above .find('tr'),this is undefined
    });

    describe('select',function() {
      it('should work',function() {
        controller.toggle();
        expect(tableCtrl.selected.length).toEqual(1);
      });
    });

  });

})();
<link rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.css" />
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine-html.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/boot.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-mocks.js"></script>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读