如何测试可调整大小的圆形 SVG 元素?

How can I test a resizable circle SVG element?

试图找出如何正确测试可调整大小的 <circle> svg 元素。 我是 React 测试库的新手,所以我不确定这是否可以使用 RTL(使用 Mocha 测试框架)或者我是否应该使用 Cypress。

假设我有一个圆形元素:

<circle data-testid='circle-element' cx="100" cy="100" r="50"/>

注意:0,0 原点在左上角。

圆心位于x=100,y=100,半径为50。

位于圆的边缘 x=150,y=100 是一个 Draghandle 用户可以点击并拖动以调整圆的大小。

<DragHandle
  data-testid='circle-draghandle'
  x={handleX}
  y={handleY}
  dragMove={onHandleDrag}
/>

如果用户在其原始位置 x=150、y=100 处单击 Draghandle 并拖动到 x=200、y=100,我们预计圆半径现在为 100。

注意:圆心不变;仍然在 x=100,y=100。

我该如何测试?

我确实弄清楚了如何使用具有给定坐标和半径的 React Testing Library 来测试圆是否正确渲染:

it('should render a Circle with the coordinates provided', function () {
    render(<Circle mark={{ cx: 100, cy: 100, r: 50}} />)

    expect(screen.getByTestId('circle-element'))
      .to.have.attr('r')
      .to.equal('50')
  })

注意:<Circle> 是实际 <circle> svg 元素所在的组件。

任何帮助测试调整大小的部分真是太棒了!

谢谢。

拖动测试可能难以实现,如果使用 Cypress,我建议添加 cypress-real-events 库。

cy.get('[data-testid="circle-draghandle"]')
  .realClick()
  .realMouseMove(200, 100)  // drag 100 right
  .realMouseUp()

cy.getByTestId('circle-element')   // from cypress-testing-library add-on
  .should('have.attr', 'r', '50')

结果可能接近但不准确(例如 49),在这种情况下,测试日志会告诉您。

如果是这样,您可以使用 closeTo 断言

cy.getByTestId('circle-element')
  .should('have.attr', 'r')
  .and(radius => {
    expect(radius).to.be.closeTo(50, 1)
  })

备注

以上内容仅在您的图形为 <svg> 时有效,但不能用于 <canvas>

尝试以下 library-free 拖放解决方案:

cy.get('[data-testid="circle-draghandle"]')
.trigger('mousedown', { //simulating hold click
    button: 0
}).wait(700)
.trigger('mousemove', { //simulating drag
    pageX: 200, 
    pageY: 100,
    force: true
}).wait(250)
.trigger('mouseup', {  //simulating drop
    force: true
});

然后你可以使用 Fody 建议的 closeTo 解决方案来检查结果

好的 - 终于有了使用 React 测试库和 user-events@14!

的解决方案

希望这对其他人有所帮助。

user-events 必须为 14.0 或更高版本。

在测试文件中导入 userEvent:

import userEvent from '@testing-library/user-event'

测试:

describe('Circle tool', function () {
  let mark
  beforeEach(function () {
    mark = CircleMark.create({
      id: 'circle1',
      toolType: 'circle',
      x_center: 200,
      y_center: 200,
      r: 50
    })
  })

  it('should change the radius when drag handle is moved', async () => {
    const user = userEvent.setup()

    render(<Circle mark={mark} />)

    expect(mark.x_center).to.equal(200)
    expect(mark.y_center).to.equal(200)
    expect(mark.r).to.equal(50)

    // click on dragHandle
    // move dragHandle
    // release mouse button
    const circleDragHandle = screen.getByTestId('draghandle')
    await user.pointer([
      { keys: '[MouseLeft>]', target: circleDragHandle },
      { coords: { x: 300, y: 200 } },
      { keys: '[/MouseLeft]' }
    ])

    expect(mark.x_center).to.equal(200)
    expect(mark.y_center).to.equal(200)
    expect(mark.r).to.equal(100)
  })
})