AngularJS + CanvasJS:如何进行单元测试?

塞尔吉奥·里纳多(Sergio Rinaudo)

我正在尝试在使用Yeoman搭建的AngularJS应用程序中运行单元测试。我尝试运行的唯一测试只是检查and数组的长度是否正确,但由于与CanvasJS相关的原因而失败

这里的日志

LOG: 'CanvasJS Error: Chart Container with id "chartContainer" was not found'
PhantomJS 1.9.7 (Windows 7) Controller: MainCtrl should attach a list of inputs to the scope  FAILED
        TypeError: 'undefined' is not an object (evaluating 'this._toolBar.appendChild')
            at /path/to/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:1799
            at /path/to/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:1919
            at /path/to/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:2093
            at /path/to/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:12551
            at /path/to/Chart/app/scripts/controllers/main.js:101
            at invoke (/path/to/Chart/app/bower_components/angular/angular.js:3869)
            at instantiate (/path/to/Chart/app/bower_components/angular/angular.js:3880)
            at /path/to/Chart/app/bower_components/angular/angular.js:7134
            at /path/to/Chart/test/spec/controllers/main.js:15
            at invoke (/path/to/Chart/app/bower_components/angular/angular.js:3869)
            at workFn (/path/to/Chart/app/bower_components/angular-mocks/angular-mocks.js:2147)
        undefined
        Expected 0 to be 3.
PhantomJS 1.9.7 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.025 secs / 0.021 secs)
Warning: Task "karma:unit" failed. Use --force to continue.

该应用程序可以在这里找到https://github.com/kaiohken1982/Chart

我不确定我是否已在AngularJS应用程序中正确实现了该库,建议将不胜感激。

谢谢

---编辑#1 --------------------

在下面的一些代码中,可以使您更好地理解场景,因为您可以看到CanvasJS用作全局而不是作为服务注入,因此问题之一是,如果没有Bower存储库,以这种方式使用第三方库是否正确。

我认为这是导致问题的原因

...
$scope.chart = new CanvasJS.Chart('chartContainer', {
...

控制器视图包含“ chartContainer” ID

<div id="chartContainer"></div>

app / scripts / controllers / main.js'使用严格';

/*global CanvasJS:false */

/**
 * @ngdoc function
 * @name ngprojectApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the ngprojectApp
 */
angular.module('ChartApp')
  .controller('MainCtrl', function ($scope) {

    // Regexp to ensure that input dates are in the required format
    $scope.dateRegexp = /^(January|February|March|April|June|July|August|Semptember|October|November|December)[ ](0[1-9]|1[0-9]|2[0-9]|3[0-1])[ ](19|20)\d{2}$/i;

    // Called to remove an entry
    $scope.removeInput = function (index) {
      $scope.inputs.splice(index, 1);
    };

    // Called to add an entry
    $scope.addRow = function () {
      $scope.inputs.push($scope.value);
      $scope.value = '';
    };

     $scope.predicate = '';
     $scope.reverse = false;
     $scope.inputs = [];
     $scope.updateMyText = function() {};

     // Chart below
     var datapoints = [];

     var chartPoint = null;
     $scope.canEdit = true;
     $scope.editMode = false;
     $scope.units = 1; // increase or decrease bar value by this unit
     $scope.chart = new CanvasJS.Chart('chartContainer', {
       theme: 'theme1',
       interactivityEnabled: true,
       title:{
          text: 'Website response time'              
       },
       axisY: {
          title: 'ms',
          labelFontSize: 16,
       },
       axisX: {
          title: 'timeline',
          labelFontSize: 16,
          gridThickness: 1
       },
       data: [              
          {
            click: function() {
              $scope.$apply(function() {
                if($scope.canEdit) {
                  $scope.editMode = !$scope.editMode; 
                }
              });

              if($scope.editMode) {
                console.log('EditMode is now TRUE');
              }

              if(!$scope.editMode) {
                console.log('EditMode is now FALSE');
              }
            },
            mousemove: function(e) {
              if(!$scope.editMode) {
                chartPoint = null;
                return false;
              }

              // First point? Assign it and return
              if(null === chartPoint) {
                chartPoint = e;
                return false;
              }

              // Update inputs at the correct index will re-render graph and table data
              $scope.$apply(function() {
                var diffY = e.y - chartPoint.y; // if it is > 0 means that the mouse pointer went UP
                var time = diffY < 0 ? e.dataPoint.y+$scope.units : e.dataPoint.y-$scope.units;
                $scope.inputs[e.dataPointIndex].time = time;
                // Update chartPoint
                chartPoint = e;
              });

            },
             type: 'column',
             dataPoints: []
          }
       ]
    });

    $scope.chart.render(); //render the chart for the first time

    $scope.changeChartType = function(chartType) {
      $scope.canEdit = 'column' === chartType;
      $scope.editMode = false; // disable EditMode whatever the type is
      $scope.chart.options.data[0].dataPoints = datapoints;
      $scope.chart.options.data[0].type = chartType;
        $scope.chart.render(); //re-render the chart to display the new layout
    };

    // DEEP watch for any changes in the array
    $scope.$watch('inputs', function() {
      datapoints = [];
      for(var i in $scope.inputs) {
        var e = $scope.inputs[i];
        // update the timestamp for the value
        var d = new Date(e.date);
        e.timestamp = d.valueOf() / 1000;
        datapoints.push({
          'label': e.url,
          x: new Date(e.date),
          y: e.time
        });
      }
      // Reassign data to chart
      $scope.chart.options.data[0].dataPoints = datapoints;
      $scope.chart.render();
    }, true);


    $scope.inputs.push({
      date: 'January 02 2014',
      url: 'http://uno.it',
      time: 111
    });

    $scope.inputs.push({
      date: 'January 12 2014',
      url: 'http://due.it',
      time: 292
    });

    $scope.inputs.push({
      date: 'January 22 2014',
      url: 'http://tre.it',
      time: 333
    });

  });

测试/规范/控制器/ main.js'使用严格';

describe('Controller: MainCtrl', function () {

  // load the controller's module
  beforeEach(module('ChartApp'));

  var MainCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    MainCtrl = $controller('MainCtrl', {
      $scope: scope
    });
  }));

  it('should attach a list of inputs to the scope ', function () {
    expect(scope.inputs.length).toBe(3);
  });
});

我想Karma.conf.js具有所有必需的文件...

....
    files: [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular-mocks/angular-mocks.js',
      'app/bower_components/angular-animate/angular-animate.js',
      'app/bower_components/angular-cookies/angular-cookies.js',
      'app/bower_components/angular-resource/angular-resource.js',
      'app/bower_components/angular-route/angular-route.js',
      'app/bower_components/angular-sanitize/angular-sanitize.js',
      'app/bower_components/angular-touch/angular-touch.js',

      'app/bower_components/jquery/dist/jquery.js',
      'app/bower_components/angular-ui/build/angular-ui.js',
      'app/bower_components/jquery-ui/jquery-ui.js',
      'app/scripts/vendor/canvasjs-1.5.0-beta/canvasjs.min.js',

      'app/scripts/directives/directive.js',
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],
...

---编辑#2 --------------------

收到建议后,这就是我编辑main.js测试的方式

  beforeEach(inject(function ($controller, $rootScope, $compile) {
    var htmlString = '' +
    '<div ng-controller="MainCtrl">' +
    '    <div id="chartContainer">' +
    '</div>'
    ;
    var element = angular.element(htmlString)
    scope = $rootScope.$new();
    $compile(element)(scope);
    scope.$digest();
    MainCtrl = $controller('MainCtrl', {
      $scope: scope
    });
  }));

错误几乎相同

LOG: 'CanvasJS Error: Chart Container with id "chartContainer" was not found'
PhantomJS 1.9.7 (Windows 7) Controller: MainCtrl should attach a list of inputs to the scope  FAILED
        TypeError: 'undefined' is not an object (evaluating 'this._toolBar.appendChild')
            at /path/to/workspace/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:1799
            at /path/to/workspace/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:1919
            at /path/to/workspace/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:2093
            at /path/to/workspace/Chart/app/scripts/vendor/canvasjs-1.5.0-beta/source/canvasjs.js:12551
            at /path/to/workspace/Chart/app/scripts/controllers/main.js:101
            at invoke (/path/to/workspace/Chart/app/bower_components/angular/angular.js:3869)
            at instantiate (/path/to/workspace/Chart/app/bower_components/angular/angular.js:3880)
            at /path/to/workspace/Chart/app/bower_components/angular/angular.js:7134
            at /path/to/workspace/Chart/app/bower_components/angular/angular.js:6538
            at forEach (/path/to/workspace/Chart/app/bower_components/angular/angular.js:330)
            at nodeLinkFn (/path/to/workspace/Chart/app/bower_components/angular/angular.js:6552)
            at compositeLinkFn (/path/to/workspace/Chart/app/bower_components/angular/angular.js:5986)
            at publicLinkFn (/path/to/workspace/Chart/app/bower_components/angular/angular.js:5891)
            at /path/to/workspace/Chart/test/spec/controllers/main.js:20
            at invoke (/path/to/workspace/Chart/app/bower_components/angular/angular.js:3869)
            at workFn (/path/to/workspace/Chart/app/bower_components/angular-mocks/angular-mocks.js:2147)
        undefined
        TypeError: 'undefined' is not an object (evaluating 'scope.inputs.length')
            at /path/to/workspace/Chart/test/spec/controllers/main.js:28
PhantomJS 1.9.7 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.029 secs / 0.028 secs)
Warning: Task "karma:unit" failed. Use --force to continue.

更新测试控制器时我是否犯了错?

---编辑#3 --------------------

在Ivarni的宝贵帮助下,我得出了以下解决方案:

在应用程序控制器中

...
$scope.chart = new $window.CanvasJS.Chart('chartContainer', {
...

在控制器测试中

...
beforeEach(inject(function ($controller, $rootScope, $compile, $window) {
    $window.CanvasJS = { Chart: function(){
        this.render = function() {};
    } };
...

现在可以模拟CanvasJS,并且可以运行UnitTest了:)

伊瓦尼

我认为您对导致错误的原因的假设是正确的。您的控制器未连接到DOM,因此无法找到ID为“ chartContainer”的任何内容都是合理的。

对于单元测试,我将尝试使用与对指令进行单元测试相同的方法。这是类似的东西

beforeEach(inject(function($rootScope, $compile) {
    var htmlString = '' +
        '<div ng-controller="MainCtrl">' +
        '    <div id="chartContainer">' +
        '</div>'
        ;
    element = angular.element(htmlString)
    scope = $rootScope.$new();
    $compile(element)(scope);
    scope.$digest();
}));

这将编译一个最小的DOM,并附加您的控制器和一个具有CanvasJS所需ID的元素。您可能不得不为此花些时间。只要您确保将CanvasJS包含在业力配置中,我就不会发现将CanvasJS用作全局变量存在任何问题。

探索的另一种方法是查看Angular的e2e测试功能。有位文件的位置在测试DOM渲染时,这可能更合适。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

AngularJS + CanvasJS:如何进行单元测试?

来自分类Dev

如何对angularjs表单进行单元测试?

来自分类Dev

如何模拟$ window进行单元测试AngularJS服务?

来自分类Dev

如何对AngularJS $ promise.then进行单元测试

来自分类Dev

AngularJS:如何对提供程序进行单元测试

来自分类Dev

如何对AngularJS服务/工厂进行单元测试

来自分类Dev

使用ReSharper进行AngularJS单元测试

来自分类Dev

使用ReSharper进行AngularJS单元测试

来自分类Dev

对angularJS中的服务进行单元测试

来自分类Dev

使用ReSharper进行AngularJS单元测试

来自分类Dev

如何进行单元测试

来自分类Dev

如何使用AngularJS持有变量时进行单元测试?

来自分类Dev

如何对依赖Promise的AngularJS控制器进行单元测试?

来自分类Dev

如何对内部使用localStorage的AngularJS服务进行单元测试

来自分类Dev

如何在业力angularjs中对setInterval进行单元测试

来自分类Dev

如何在AngularJS中使用$ http.jsonp对功能进行单元测试?

来自分类Dev

如何对使用AngularJS中的另一个工厂的异步工厂进行单元测试?

来自分类Dev

如何在AngularJS中对$ location服务search()方法进行单元测试?

来自分类Dev

如何对使用AngularJS中的另一个工厂的异步工厂进行单元测试?

来自分类Dev

如何对一个全局函数(即angularJs中的$ rootScope.functionname)进行单元测试

来自分类Dev

如何在AngularJS中使用$ http.jsonp对功能进行单元测试?

来自分类Dev

使用$ window.location.pathname对angularjs进行单元测试

来自分类Dev

对使用$ translatePartialLoaderProvider的AngularJS应用进行单元测试

来自分类Dev

AngularJS覆盖(模拟)服务以进行单元测试

来自分类Dev

用“ resolve”对AngularJS路由进行单元测试

来自分类Dev

使用Jasmine进行AngularJS控制器单元测试

来自分类Dev

AngularJS覆盖(模拟)服务以进行单元测试

来自分类Dev

在AngularJS中使用Jasmine对滤镜进行单元测试

来自分类Dev

单元测试AngularJS服务

Related 相关文章

  1. 1

    AngularJS + CanvasJS:如何进行单元测试?

  2. 2

    如何对angularjs表单进行单元测试?

  3. 3

    如何模拟$ window进行单元测试AngularJS服务?

  4. 4

    如何对AngularJS $ promise.then进行单元测试

  5. 5

    AngularJS:如何对提供程序进行单元测试

  6. 6

    如何对AngularJS服务/工厂进行单元测试

  7. 7

    使用ReSharper进行AngularJS单元测试

  8. 8

    使用ReSharper进行AngularJS单元测试

  9. 9

    对angularJS中的服务进行单元测试

  10. 10

    使用ReSharper进行AngularJS单元测试

  11. 11

    如何进行单元测试

  12. 12

    如何使用AngularJS持有变量时进行单元测试?

  13. 13

    如何对依赖Promise的AngularJS控制器进行单元测试?

  14. 14

    如何对内部使用localStorage的AngularJS服务进行单元测试

  15. 15

    如何在业力angularjs中对setInterval进行单元测试

  16. 16

    如何在AngularJS中使用$ http.jsonp对功能进行单元测试?

  17. 17

    如何对使用AngularJS中的另一个工厂的异步工厂进行单元测试?

  18. 18

    如何在AngularJS中对$ location服务search()方法进行单元测试?

  19. 19

    如何对使用AngularJS中的另一个工厂的异步工厂进行单元测试?

  20. 20

    如何对一个全局函数(即angularJs中的$ rootScope.functionname)进行单元测试

  21. 21

    如何在AngularJS中使用$ http.jsonp对功能进行单元测试?

  22. 22

    使用$ window.location.pathname对angularjs进行单元测试

  23. 23

    对使用$ translatePartialLoaderProvider的AngularJS应用进行单元测试

  24. 24

    AngularJS覆盖(模拟)服务以进行单元测试

  25. 25

    用“ resolve”对AngularJS路由进行单元测试

  26. 26

    使用Jasmine进行AngularJS控制器单元测试

  27. 27

    AngularJS覆盖(模拟)服务以进行单元测试

  28. 28

    在AngularJS中使用Jasmine对滤镜进行单元测试

  29. 29

    单元测试AngularJS服务

热门标签

归档