Meteor Blaze 单元测试获取 SVG children

Meteor Blaze Unit Test get SVG children

问题

我正在测试一些包含 <svg> 元素和各种 <g> children 的 Blaze 模板。测试使用 jQuery 检查各种输入是否呈现正确的 children。

虽然我至少可以检查 svg 是否存在,但我不能得到它的任何一个 children - 既不是通过 class 也不是通过 id.

空 child 个元素

将 svg .children 记录到控制台会显示每个 child {}。当 运行 我的应用程序时模板呈现良好,并且此行为仅在尝试访问测试中的模板的 children 时发生。

空 SVG 内容文档

我也无法检索 svg 的内容文档:

// does unfortunately not return contentDoc
const svgDom = template.find('svg').get(0).contentDoc;

代码示例

要重现,请考虑以下模板:

<template name="svgtest">
  <svg width="100%" height="100%">
    <g class="element1"></g>
    <g class="element2"></g>
  </svg>
</template>

和相应的测试:

import { _ } from 'meteor/underscore';
import { Template } from 'meteor/templating';
import { Blaze } from 'meteor/blaze';
import { Tracker } from 'meteor/tracker';
import { assert } from 'meteor/practicalmeteor:chai';

// the test helpers, you know them
// from the Meteor testing guide

const withDiv = function withDiv(callback) {
  const el = document.createElement('div');
  document.body.appendChild(el);
  try {
    callback(el);
  } finally {
    document.body.removeChild(el);
  }
};

const withRenderedTemplate = function withRenderedTemplate(template, data, callback) {
  withDiv((el) => {
    const ourTemplate = _.isString(template) ? Template[template] : template;
    Blaze.renderWithData(ourTemplate, data, el);
    Tracker.flush();
    callback(el);
  });
};

describe('svgtest', function () {

  beforeEach(function () {
    Template.registerHelper('_', key => key);
  });

  afterEach(function () {
    Template.deregisterHelper('_');
  });


  it('renders correctly with simple data', function () {

    withRenderedTemplate('svgtest', {}, (el) => {
      const template = $(el);

      // passes
      assert.equal(template.find('svg').length, 1);

      // does unfortunately not return contentDoc
      const svgDom = template.find('svg').get(0).contentDoc;

      // fails with AssertionError: expected 0 to equal 1
      assert.equal(template.find('.element1').length, 1);
      assert.equal(template.find('.element2').length, 1);
    });
  });
});

相关

我已经检查了以下 SO 资源以访问元素:

retrieve child elements of svg g

JQuery and SVG - how to find the 'g' tag

How to use jquery in SVG (Scalable Vector Graphics)?

How to access SVG elements with Javascript

但是,它们只在我的 运行 应用程序中有效,在测试中无效。我也想避免使用 jQuery svg 插件,因为这会扰乱 Meteor 内置 jQuery.

我认为这需要一个 Blaze-specific 解决方案,以便单元上下文可以访问 SVG DOM。

有人已经解决了这个问题或找到了解决方法吗?

其实我自己找到了答案,我觉得值得分享。

所以问题是 SVG 元素还没有渲染到根元素中。

为了让它们出现在 DOM 中,withRenderedTemplate 方法基本上需要在触发回调之前等待一小段时间。

const withRenderedTemplate = function withRenderedTemplate(template, data, callback) {
  withDiv((el) => {
    const ourTemplate = _.isString(template) ? Template[template] : template;
    Blaze.renderWithData(ourTemplate, data, el);
    Tracker.flush();
    setTimeout(() => {
      callback(el);
    }, 100);
  });
};

此时元素将出现在 DOM 中,并且可以像任何其他元素一样通过 id 或 class 访问。