reactjs 将画布模拟为DataUrl而不添加其他库

atmip9wb  于 2023-02-03  发布在  React
关注(0)|答案(1)|浏览(107)

我有一个HTML <canvas>元素,它使用onTouchEnd属性获取画布内容并转换为dataUrl,但Jest不支持这个属性。
大多数文章都建议添加jest-canvas-mock库来模拟所有HTMLCanvasElement的内容,但这似乎有些多余,因为我只需要模拟toDataURL方法,所以我想检查一下如何使用jest.mock或jest.spyOn来模拟toDataURL()并返回一个固定的字符串。
为了说明清楚,我需要这个函数是因为onChange函数设置了一个状态值(useState),该值控制按钮是否启用。
Component.js

export default function MyComponent() {

  const setTouchPosition = e => {
    const canvas = document.getElementById('canvas');

    const rect = canvas.getBoundingClientRect();
    // .. a few lines omitted for readability
  };

  const draw = e => {
    const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d');
    // .. a few lines omitted for readability
  };

  return (
    <canvas
        onTouchEnd={e => {
              onChange(e.target.toDataURL());
              onTouchMove={e => draw(e)}
              onTouchStart={e => {
                setTouchPosition(e);
              }}
            }}
        />
  );
}

View.js

export default function MyView() {

  const [data, setData] = useState('');
  const onChange = image => {
    setData(image);
  };

  return (
    <Button disabled={data === ''}>Button label</Button>
  );
}

如果Component.js不调用onChange函数,我就无法启用此Button并在其上使用fireEvent。

k2arahey

k2arahey1#

您应该能够使用jest.spyOn来模拟HTMLCanvasElement.prototype.toDataURL的实现:
我不确定要对mock toDataURL方法运行哪种Assert,但我假设您至少要检查它是否被正确调用。

const dummyDataURL = 'data:image/png;base64,<...>';
const toDataURLStub = jest
  .spyOn(HTMLCanvasElement.prototype, 'toDataURL')
  .mockImplementationOnce(() => {
    return dummyDataURL;
  });
// Create your canvas and trigger your touchend event
expect(toDataURLStub).toHaveBeenCalledWith('image/png');

您可能还需要确保有一个afterEach块来恢复所有模拟,因为如果Assert失败,它将阻止函数的其余部分运行(这就是为什么我选择不在上面代码的末尾恢复存根)。

afterEach(() => {
  // This is effectively guaranteed to run even if
  // your test assertions fail
  jest.restoreAllMocks();
});

相关问题