首页 > 解决方案 > 有没有办法模拟 SVGTextElement 以便能够使用 Jest 测试使用 getBBox() 来测量文本的函数?

问题描述

在决定使用什么字体大小之前,我编写了简单的函数来测量文本。

const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
svg.appendChild(text);

interface HeightAndWidth {
  width: number;
  height: number;
}

interface MeasureProps {
  label: string;
  fontFamily: string;
  size: number;
  fontWeight?: number;
  lineHeight?: number;
  letterSpacing?: string;
}

export const measureText = ({
  label,
  fontFamily,
  size,
  fontWeight = 400,
  lineHeight = 1,
  letterSpacing = '0',
}: MeasureProps): HeightAndWidth => {
  text.setAttribute('font-size', `${size}px`);
  text.setAttribute('line-height', `${lineHeight}px`);
  text.setAttribute('font-family', fontFamily);
  text.setAttribute('font-weight', `${fontWeight}`);
  text.setAttribute('letter-spacing', letterSpacing);
  text.textContent = label;
  document.body.appendChild(svg);

  const { width, height } = text.getBBox();

  return {
    width,
    height,
  };
};

它非常简单,而且效果很好,但是我在为此编写单元测试时遇到了问题。问题是在浏览器中工作时它在测试期间不起作用并引发错误

text.getBBox 不是函数。

我尝试模拟window.SVGTextElement,但它不断抛出错误,它的原型缺少 241 个属性。甚至尝试过它的类型,但错误仍然存​​在,并且缺少getBBox重复的错误。

有没有办法像这样测试代码?

import { measureText } from '../measure';

interface MockSvgTextElement {
  prototype: {
    getBBox: () => { height: number; width: number };
  };
}

describe('animateNumber', () => {
  beforeEach(() => {
    window.SVGTextElement = {
      prototype: {
        getBBox: () => ({
          height: 20,
          width: 100,
        }),
      },
    } as MockSvgTextElement;
    const p = document.createElement('p');
    document.body.appendChild(p);
    console.log('window.SVGTextElement', window.SVGTextElement);
  });

  it('should measure text', () => {
    const textSize = measureText(
      {
        label: '12345',
        fontFamily: 'Roboto',
        size: 20,

      }
    );
    expect(textSize).toEqual({});
  });
});

标签: javascripttypescriptsvgjestjs

解决方案


getBBox只能用于SVGGraphicsElement类型。

在下创建一个<svg>元素body,然后附加一个<text>svg

getBBox().width然后你可以调用text元素


推荐阅读