3

我的指令中有 d3 可视化。问题在于,有很多样板代码可以在许多其他可视化中重复使用,例如将 element[0] 设置为 d3 可视化的容器。所以我决定创建一个服务来完成指令中正在完成的所有工作,并尽量让自己保持干燥。我目前正忙于测试,这就是我希望得到帮助的地方。我的代码如下

指示


angular.module('app')
  .directive('barchart', function (Barchartservice) {
    return {
      restrict: 'E',
      link: function postLink(scope, element, attrs) {

        scope.$on('drawCharts',function(ev,attrs){
          draw();
        });

        function draw(){
          if(!scope.dataset) return;

          var svg = Barchartservice.setContainer(svg, element);
          .
          .
          .
          .

        }
      }
    };
  });


服务


angular.module('app')
  .service('Barchartservice', function Barchartservice() {
    var margin = {top: 50, right: 20, bottom: 50, left: 40},
              container,
              width = (1120 || container.width() - 20) - margin.left - margin.right,
              height = 400 - margin.top - margin.bottom;
    return{
        setContainer: function(svg, element){
            container  = angular.element(element);
            svg = d3.select(element[0]).append('svg')
                    .attr('width', width + margin.left + margin.right)
                    .attr('height', height + margin.top + margin.bottom)
                    .append('g')
                    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
        return svg;
        }
    }
  });

测试


'use strict';

describe('Service: Barchartservice', function () {

  // load the service's module
  beforeEach(module('clientApp'));

  // instantiate service
  var Barchartservice;
  beforeEach(inject(function (_Barchartservice_) {
    Barchartservice = _Barchartservice_;
  }));

  it('should insert an svg element into the barchart directive', function () {
    var svg = undefined;
    var element = [];
    element[0] = '<barchart></barchart>';
    expect(Barchartservice.setContainer()).toEqual('<barchart><svg></svg></barchart>');
  });

});

错误


PhantomJS 1.9.2 (Mac OS X) Service: Barchartservice should do something FAILED
    TypeError: 'undefined' is not an object (evaluating 'element[0]')

任何帮助深表感谢。谢谢!

4

1 回答 1

1

You need to compile the element. When testing AngularJS you have to control compiling and linking the directives to the dom tree. You also need to call scope.$apply() once this is completed as well.

So first you need to inject the $compile service and the $rootScope service in the beforeEach DI block.

Set scope = $rootScope in the beforeEach as well so you can reference a clean scope for you tests.

var element = $compile('<barchart></barchart>')(scope);
scope.$apply();
expect(Barchartservice.setContainer()).toEqual('<barchart><svg></svg></barchart>');

This should get you further, but it may not pass the test completely. It seems from your source, that you need to broadcast a drawCharts event as well to actually run the setContainer function. So this could be an issue as well.

于 2013-11-29T23:30:16.253 回答