如何在指令链接函数中单元测试Angular routeChangeSuccess?

时间:2016-10-30 00:03:23

标签: javascript angularjs unit-testing jasmine

Karma在TypeError: Cannot read property 'originalPath' of undefined函数中给出了以下指令时不断抛出link

angular.module('myApp').directive('sidebar', ['$route', function ($route)
{
  return {
    restrict: 'E',
    templateUrl: 'views/sidebar.html',
    scope: {
      activeNav: '@'
    },
    link: function (scope, element, attrs) {
      scope.$on('$routeChangeSuccess', function (event, curr, prev) {
        scope.activeNav = curr.$$route.originalPath || '/about';
      });
    }
}

和单元测试:

describe('sidebar directive', function () {
  var $compile,
    $rootScope,
    scope,
    element;

  beforeEach(module('MyApp'));
  beforeEach(module('my.templates')); // ng-html2js karma template loader

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


  it('defaults to /about route', function() {
    element = $compile("<sidebar></sidebar>")(scope);
    var linkScope = element.children().scope();

    $rootScope.$broadcast('$routeChangeSuccess');
    $rootScope.$digest();
    expect(linkScope.activeNav).toBe('/about');
  });
});

从链接中记录curr路由时,我得到Object{params: Object{}, pathParams: Object{}, locals: Object{}}。我已经尝试将模拟路由传递给广播的消息,但没有任何改变。我如何获得传递给指令的预期(默认)路由?这甚至是在链接中跟踪路线变化的正确方法吗?我的猜测是我刚接触Jasmine和单元测试。

1 个答案:

答案 0 :(得分:0)

我最终想出了如何使用$route.reload()

触发路线更改

来自docs,它:

  

即使$ location没有更改,也会导致$ route服务重新加载当前路由。因此,ngView创建新范围并重新实现控制器。

因此,将其添加到我的测试中,重新启动&#39;路由,强制routeChangeSuccess发出,一旦被消化,就会进入link。这是来自spec文件的更新块,添加了$ location更改以测试其他路径:

describe('sidebar directive', function () {
  var $compile,
    $rootScope,
    $route,
    $location,
    scope,
    element;

  beforeEach(module('MyApp'));
  beforeEach(module('my.templates')); // ng-html2js karma template loader

  beforeEach(inject(function(_$compile_, _$rootScope_, _$route_, _$location_){
    $compile = _$compile_;
    $rootScope = _$rootScope_;
    $location = _$location_;
    $route = _$route_;
    scope = $rootScope.$new();
    element = $compile("<sidebar></sidebar>")(scope);
  }));


  it('defaults to /about route', function() {
    $route.reload();
    $rootScope.$digest();
    var linkScope = element.children().scope(); // Get directive's isolated scope
    expect(linkScope.activeNav).toBe('/about');
  });

  it('sets activeNave to correct route on change', function() {
    $location.path('/foo');
    $route.reload();
    $rootScope.$digest();
    var linkScope = element.children().scope();
    expect(linkScope.activeNav).toBe('/foo');
  });
});