javascript - Angularjs指令单元测试问题

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

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

ng-repeat 中的每个指令都使用 ng-include 添加 html 内容。每个指令都会做一些事情,并使用 getContentUrl 函数根据类型带来不同的 html。

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

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

类型错误:未定义不是 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']
  });
};

测试文件unit/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);
  });
});

最佳答案

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

关于javascript - Angularjs指令单元测试问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24246484/

相关文章:

javascript - 从外部更改 ng-repeat 范围内的模型

angularjs - 注入(inject) $http 后,代码未在 angular.js 中显示表格

node.js - 在 Mocha 中 describe() 的作用是什么?

Javascript - 两个大写字母、小写字母和数字的正则表达式

javascript - Angular Directive(指令)事件绑定(bind)不起作用

unit-testing - 需要帮助测试 Windows Phone 8 中的绑定(bind)

javascript - 在单元测试中使用 AudioContext

javascript - jQuery .click 方法不会为列表项触发

javascript - 如何在 javascript 中查找移动 safari/iphone 中的当前 "scroll"偏移量

javascript - 去抖动功能不适用于输入事件