使用 Jest 的 canvas 元素的简单测试示例

Posted

技术标签:

【中文标题】使用 Jest 的 canvas 元素的简单测试示例【英文标题】:Simple testing example of canvas element using Jest 【发布时间】:2021-06-20 23:48:57 【问题描述】:

我正在尝试为此沙箱中的示例创建一个笑话测试: https://codesandbox.io/s/r3f-basic-demo-forked-297k3?file=/src/App.js

基本上我想在每个盒子上测试 onClick 功能。我已经遇到了开玩笑测试不在真正的浏览器中运行的事实。 Jest 使用 jsdom 来模拟 DOM 的必要部分。因此,我可能需要 jsdom 的 canvas 支持,但我不太确定该怎么做。

App.js

import React,  useRef, useState  from 'react'
import  Canvas, useFrame  from 'react-three-fiber'

function Box(props) 
  // This reference will give us direct access to the mesh
  const mesh = useRef()
  // Set up state for the hovered and active state
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  // Rotate mesh every frame, this is outside of React without overhead
  useFrame(() => 
    mesh.current.rotation.x = mesh.current.rotation.y += 0.01
  )
  return (
    <mesh
      ...props
      ref=mesh
      scale=active ? [1.5, 1.5, 1.5] : [1, 1, 1]
      onClick=(e) => setActive(!active)
      onPointerOver=(e) => setHover(true)
      onPointerOut=(e) => setHover(false)>
      <boxBufferGeometry args=[1, 1, 1] />
      <meshStandardMaterial color=hovered ? 'hotpink' : 'orange' />
    </mesh>
  )


export const App = () => 
  return (
    <>
      <Canvas>
        <ambientLight intensity=0.5 />
        <spotLight position=[10, 10, 10] angle=0.15 penumbra=1 />
        <pointLight position=[-10, -10, -10] />
        <Box position=[-1.2, 0, 0] />
        <Box position=[1.2, 0, 0] />
      </Canvas>
    </>
  )

【问题讨论】:

一个经典的 *** 时刻,我找到了与我相同的问题,但没有答案。你能得到答案吗? 【参考方案1】:

这不是一个很好的答案,但我发现这篇文章很有用:https://www.valentinog.com/blog/canvas/。

建议是为了正确测试 canvas 元素,不应该使用 Jest(或任何单元测试),而是使用某种 e2e 测试,以便它可以实际呈现 canvas

我能够通过以下方式进行一些较小的测试:

首先使用 jest 正常渲染您的页面。你可以给你的画布一个 test-id 或者(在我的例子中)在你的画布周围放一个 div 并给 div 一个 test-id。

我最终得到了以下结果:

let canvasContainer = getByTestId("canvas-container");
let canvas = canvasContainer.getElementsByTagName("canvas")[0];
let canvasContext = canvas.getContext("2d");

无论哪种情况,您的目标都是获取 canvas' 元素上下文。

从那里你可以用canvasContext.__getDrawCalls()检查它

这将为您提供有关迄今为止已完成的所有“drawCalls”的一些信息(例如绘制线条或矩形或您有什么)。

需要对__getDrawCalls 进行一些检查,但您应该会发现到目前为止的每个呼叫都包含在内。

我写了一些函数来帮助我得到我想要的确切细节:

const getLineInfo = (lineInfo) => 
    if (lineInfo.type !== "stroke") 
        return "not a line";
    

    let lineInfoDetail = lineInfo.props.path[3];

    return 
        lineStart: 
            x: lineInfoDetail.transform[4],
            y: lineInfoDetail.transform[5],
        ,
        lineEnd: 
            x: lineInfoDetail.transform[4] + lineInfoDetail.props.x,
            y: lineInfoDetail.transform[5] + lineInfoDetail.props.y,
        ,
    ;
;

const getRectInfo = (rectInfo) => 
    if (rectInfo.type !== "fill") 
        return "not a rect";
    

    let rectInfoDetail = rectInfo.props.path[1];

    return 
        rectStart: 
            x: rectInfoDetail.transform[4],
            y: rectInfoDetail.transform[5],
        ,
        rectEnd: 
            x: rectInfoDetail.transform[4] + rectInfoDetail.props.width,
            y: rectInfoDetail.transform[5] + rectInfoDetail.props.height,
        ,
    ;
;

例如,如果我知道第二次绘制是一条线,我可以执行以下操作:

    expect(getLineInfo(canvasContext.__getDrawCalls()[1])).toStrictEqual(
        lineStart:  x: 150, y: 250 ,
        lineEnd:  x: 150, y: 350 ,
    );

这是测试该元素是否为起点为 x: 150, y: 250 和终点为 x: 150, y: 350 的线

但问题在于 您无法在 jest 中触发画布元素的单击和拖动事件,因此使用 jest 测试画布似乎非常有限。

编辑: 看来https://yonatankra.com/how-to-test-html5-canvas-with-jest/给出了另一种解释。

【讨论】:

以上是关于使用 Jest 的 canvas 元素的简单测试示例的主要内容,如果未能解决你的问题,请参考以下文章

错误:当我在 React 中尝试使用 Jest 进行测试时,无法找到带有文本的元素

Jest/Storyshots 测试我的组件中的响应式元素

使用 Jest 运行测试时,为啥 Trix 编辑器不会安装在 Vue 组件中?

Jest / Storyshots测试组件中的响应元素

如何使用 Jest 和/或 Enzyme 获取嵌套在 React 组件中的元素的属性?

如何在 Jest (/JQuery) 测试中定位测试 html 元素?