在单元测试中获取控制器的编译模板

Get compiled template for controller in unit test

本文关键字:编译 控制器 单元测试 获取      更新时间:2023-09-26

我有以下控制器:

angular.module('app').controller('userList'
 , ['$scope','appRules',function ($scope,appRules) {
  $scope.isUserInRole=function(user,role){
    console.log("exucuting userIsInRole:",user,role);//never happens
    return  appRules.userIsInRole(user,role);
  }
  window.sscope=$scope;
  console.log($scope.menu);
}]); 

用于以下路由:

angular.module('app', [,'ui.bootstrap','ngRoute'])
.config(['$routeProvider','$locationProvider'
,function($routeProvider,$locationProvider){
  $locationProvider.html5Mode(true);
  $locationProvider.hashPrefix('!');
  $routeProvider
          .when('/admin/users',{
            templateUrl:'app/js/partials/admin/users/list.html',
            controller:'userList'
          });
}]);

模板将有一些东西,将检查用户是否可以看到这个页面或不(即使有人破解javascript没关系,因为当数据被获取或提交服务器检查)。

<div data-ng-if="!isUserInRole(login.user,'Administrator')" class="red">
  Please log in or log in as another user.
</div>
<div data-ng-if="isUserInRole(login.user,'Administrator')" class="green">
  Page to edit users.
</div>

现在我想在我的测试中创建一个控制器,看看它何时呈现,如果它正确呈现:

  var controller,scope,element;
  beforeEach(inject(function($controller
   ,$rootScope,$compile,appRules) {
    scope=$rootScope;
    scope.login={};
    scope.isUserInRole=appRules.userIsInRole;
    controller = $controller('userList',{
      $scope:scope
    });
    //here I have the controller but how to get the html it generates
    //  when rendering the template?
    element = $compile("<div ng-controller='userList'>"
      +"<div data-ng-view=''></div></div>")(scope);
    //here element isn't rendered at all, works on directives but how
    //  to do this with controllers?
    console.log("element is:",element);
  }));
我想写一个像 这样的测试
  it('Check page won''t show if user is not set or is not Administrator.'
  , function() {
    expect($(element).text().trim()
      .indexOf("Please log in or log in as another user."))
      .toBe(0,'Show login message when login.user is not set.');
  });

不知道如何获取元素。

(更新)

我实际上是在测试一个模板,因为这是由一个控制器使用的,我想用一个控制器测试它,但正如Jon建议的那样,它可以只是作为模板加载。

如何使它编译和操纵作用域并再次编译我不知道。如下:

var el = angular.element(
  $templateCache
  .get('app/js/partials/admin/users/list.html'));
$rootScope = _$rootScope_;
$rootScope.menu={login:{}};
el.scope($rootScope);
$rootScope.$apply();
console.log(el.text());

这给了我Please log in or log in as another user.Page to edit users.的输出,看起来元素只是原始元素而不是编译的元素。

尝试这样做也没有多大作用:

  beforeEach(inject(function(_$compile_
   , _$rootScope_,appSettings,$templateCache){
    console.log("before each");
    var el = angular.element($templateCache
      .get('app/js/partials/admin/users/list.html'));
    var compile=_$compile_;
    var $rootScope=_$rootScope_;
    $rootScope.login:{};
    $rootScope.isUserInRole=appSettings.userIsInRole;
    //I would think that compile would invoke the ng-if and appSettings.userIsInRole
    //  but no console log in that function is shown.
    var element = compile($templateCache
      .get('app/js/partials/admin/users/list.html'))($rootScope);
    console.log("element is:",element.html());//=undefined    
  }));

使用ng-templates或ng-html2js将模板添加到缓存中,以便在Karma运行时可用。然后这样做:

var scope = null;
beforeEach(inject(function($templateCache,_$compile_,_$rootScope_, _$controller_) {
    //get the template from the cache
    template = $templateCache.get('src/main/app/components/someController/widget-search.tpl.html');
    $compile = _$compile_;
    $rootScope = _$rootScope_;
    $controller = _$controller_;
    scope = $rootScope.new();
    //compile it
    element = $compile(template)(scope);
}));
 //then shove your compiled element into your controller instance

it( 'should be instantiated since it does not do much yet', function(){
            ctrl = $controller('SomeController',
                {
                    $scope: scope,
                    $element: element
                });
             scope.$digest();
            // my controller should set a variable called hasInstance to true when it initializes. Here i'm testing that it does.
            expect( ctrl.hasInstance).toBeTruthy();
        });

更多信息请参见http://angular-tips.com/blog/2014/06/introduction-to-unit-test-directives/

如果你正在使用Karma,你可以使用ng-html2js Karma预处理器,它基本上运行你的模板,并把它们变成模块,你可以包括在你的测试中,填充$templateCache,所以你的模板是可用的。