【问题标题】:Unit testing AngularJS directive wrapping Snap.svg单元测试包装 Snap.svg 的 AngularJS 指令
【发布时间】:2015-09-15 07:30:54
【问题描述】:

我正在尝试创建一个 Angular 指令来包装 Snap.svg 功能,但我在对其进行单元测试时遇到了问题。到目前为止,我有一个如下所示的指令:

'use strict';

angular.module('rpApp')
  .directive('rpSvgMap', function () {
    return {
      template: '<svg id="" width="" height=""></svg>',
      restrict: 'E',
      replace: true,
      // Don't isolate scope because we want to attach rpMap to parent scope
      link: function postLink(scope, element, attrs) {
        // Set up Snap.svg wrapper
        scope.rpMap = Snap('#' + attrs.id);
      }
    };
  });

我的 Karma/Jasmine 测试如下所示:

'use strict';

describe('Directive: rpSvgMap', function () {

  // load the directive's module
  beforeEach(module('rpApp'));

  var element,
    scope;

    beforeEach(inject(function($rootScope,$compile) {
        scope = $rootScope.$new();
        element =
      '<rp-svg-map id="anyOldID" width="800" height="400" src="../../assets/testmap.svg"></rp-svg-map>';

        element = $compile(element)(scope);
        scope.$digest();
  }));

  describe('on initialization', function() {
    it('should create an SVG element with the provided dimensions and id', function() {
      expect(element.attr('id')).toBe('anyOldID');
      expect(element.attr('height')).toBe('400');
      expect(element.attr('width')).toBe('800');
    });
    it('should provide a working Snap.svg drawing surface', function() {
      var testCircle = scope.rpMap.circle(100,150,200);
      expect(testCircle.attr(cx)).toBe(100);
    });

});

第一个测试通过,第二个测试失败,因为 scope.rpMap 总是返回为“null”。

在浏览器中,这工作得很好——如果我将 $scope 附加到我的控制器中的窗口,rpMap 会被 Snap.svg 正确包装,并且 rpMap.circle() 会正确地绘制一个圆。

据我所知,测试环境正在正确加载 snap.svg 作为依赖项,并且我正在从指令中正确读取范围。例如,如果我添加:

scope.hasSnap = angular.isFunction(Snap);

到指令的链接函数,则此测试通过:

it('should tell us when Snap.svg is available', function() {
      expect(scope.hasSnap).toBe(true);
    });

Snap() 不是异步的,将 beforeAll/it 更改为异步模式也无济于事。

有什么想法我在这里做错了吗?

【问题讨论】:

  • 理想情况下,您应该模拟 Snap,因为您不需要测试它是否有效,只需您的指令调用它即可。我会把它变成间谍和expect(Snap).toHaveBeenCalledWith('#anyOldID')。见stackoverflow.com/questions/9510148/…
  • 也许我在这里遗漏了一些关于设计指令的最佳方式的信息。最终目标是该指令将加载 SVG,根据内容创建/修改一些模型,将元素绑定到范围内的其他数据等。如果测试套件看不到 Snap 允许我做的任何事情在指令内部很难测试。
  • 你不需要测试Snap。如果您正在测试您的指令和 Snap,那么它不是单元测试。
  • 我终于解决了这个问题。你想写你的第一条评论作为答案吗? (我下面的回答希望能帮助遇到同样 Snap.svg 问题的人,但你的回答是我实际测试问题的正确答案)

标签: javascript angularjs unit-testing snap.svg


【解决方案1】:

我找到的这个jsfiddle(对不起,不记得出处)包含解决方案http://jsfiddle.net/hRy4A/2/

具体来说,我们可以像这样直接将元素传递给 Snap:

scope.rpMap = Snap(element[0]);

当以这种方式创建rpMap时,以下测试通过:

it('should provide a working Snap.svg drawing surface', function() {
        var testCircle = scope.rpMap.circle(100,150,200);
        expect(testCircle.attr('cx')).toBe('100');
        expect(testCircle.attr('cy')).toBe('150');
        expect(testCircle.attr('r')).toBe('200');
    });

我想这种方法的一个潜在问题是我不一定需要或希望在 $scope 中公开所有 Snap.svg 方法——我想理想情况下,图形内容都将在指令中自包含.

请注意,我原来的测试中还有一个小错字,应该是

expect(testCircle.attr('cx')).toBe('100');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 2014-02-06
    • 2014-07-12
    相关资源
    最近更新 更多