Angularjs指令单元测试问题

时间:2014-06-16 14:54:12

标签: javascript angularjs unit-testing angularjs-directive angularjs-ng-repeat

我正在尝试用名为'card'的指令填充ng-repeat(home.html),如下所示。 CardProvider是使用$ http加载内容的promise对象。

ng-repeat中的每个指令都使用ng-include添加html内容。并且每个指令执行一些操作并使用getContentUrl函数根据类型带来不同的html。

我使用karma,mocha,chai进行单元测试和AngularJS v1.2.18。

我的问题是,当我创建单元测试时,如下所示。我的测试错误如下:

TypeError:undefined不是Scope.scope.getContentUrl中的函数(/Users/me/projects/web/src/app.js:161:31)

它接缝我无法访问ng-repeat中每个孤立的指令范围。

home.html的

<ul id="container" ng-controller="CardCtrl">
  <li card index="{{$index}}" type="{{item.in.Collection}}" ng-repeat="item in cards"></li>
</ul>

app.js

angular.module('App', ['ngRoute'])

  .config(function($routeProvider){
    $routeProvider
      .when("/",{
        templateUrl: "view/home.html",
        controller: "CardCtrl",
        resolve: {
          load: function ($route, CardProvider) {
            return CardProvider.load();
          }
        }
      })
      .otherwise({
        redirectTo: "/!"
      });
  })

  .controller('CardCtrl', ['$scope', 'CardProvider', function($scope, CardProvider) {
    $scope.cards = CardProvider.data;
  }])

  .directive('card', ['$window', 'CardProvider', function($window, CardProvider) {
    return {
      scope: {
        index: '@',
        type: '@'
      },

      template: '<div class="card-wrapper" ng-include="getContentUrl()"></div>',
      link: function(scope) {

        // Find which card processing
        scope.card = CardProvider.data[scope.index];

        scope.getContentUrl = function() {
          // When reached last card activate packery library to designate screen
          if (parseInt(scope.index) + 1 == CardProvider.data.length) {
            var container = angular.element('#container');

            // Activate packery
            var packery = new $window.Packery(container[0], {
              itemSelector: '.card',
              gutter: 10
            });
          }

          // If we have a type specifier return it otherwise null
          return scope.type ? 'public/js/directives/' + scope.type + '.html' : '';
        }
      }
    };
  }]);

Karma.conf.js:

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha','jquery-chai'],

    // list of files / patterns to load in the browser
    files: [
      'public/components/angular/angular.js',
      'public/components/angular-route/angular-route.js',
      'public/components/angular-mocks/angular-mocks.js',
      'src/app.js',
      'test/unit/*.spec.js'
    ],

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome']
  });
};

测试文件单元/ cards.spec.js:

var assert = chai.assert,
    expect = chai.expect,
    should = chai.should();

describe('Cards Unit Tests', function() {
  var scope, cardsElement, httpBackend, controller;
  var discussions = [{
    "title": "\"The Incubation Period: Why Stanford’s Startup Culture is Only\"",
    "on": "2014-06-01T17:56:59.301+03:00",
    "tags": [
      "startup"
    ],
    "in": {
      "Collection": "communities",
      "Id": "538ccd41062a2a0fafbae507",
      "Database": ""
    },
    "posts": [
      {
        "on": "2014-06-01T17:56:59.301+03:00",
        "author": {
          "Collection": "profiles",
          "Id": "538cc882062a2a0fafbae4fa",
          "Database": ""
        },
        "content": "The article below is a product of the Harvard Political Review. Review articles and viewpoints expressed are written and edited exclusively by Review undergraduate students.",
        "popularity": 4.7
      }
    ]
  }];
  var cardContent = '<ul id="container" ng-controller="CardCtrl"><li card index="{{$index}}" type="{{item.in.Collection}}" ng-repeat="item in cards"></li></ul>';

  beforeEach(module('App'));

  beforeEach(inject(function($rootScope, $controller, $httpBackend, CardProvider) {
    scope = $rootScope.$new();
    controller = $controller;
    httpBackend = $httpBackend;
    CardProvider.data = discussions;
    //httpBackend.whenGET('http://localhost:8080/explore/discussions').respond(discussions);
  }));

  beforeEach(inject(function($compile, $rootScope) {
    var el = angular.element(cardContent);
    cardsElement = $compile(el)(scope);
    scope.$digest();
  }));

  it('should show load cards to the page', function() {
    expect(cardsElement.find('li').length).to.be.above(0);
  });
});

1 个答案:

答案 0 :(得分:0)

基于错误消息以及scope.getContentUrl()中唯一用作函数的事实是$window.Packery,似乎Packery未正确加载。