简体   繁体   English

如何使用 react-testing-library 和 framer-motion 测试 mousemove 拖放

[英]How to test mousemove drag and drop with react-testing-library and framer-motion

I am trying to test the drag and drop functionality using react-testing-libary.我正在尝试使用 react-testing-libary 测试拖放功能。 The drag and drop functionality comes from framer-motion and the code is in reacy.拖放功能来自 framer-motion,并且代码处于响应状态。 From what I understand it uses the mousedown, mousemove and mouseup events to do this.据我了解,它使用 mousedown、mousemove 和 mouseup 事件来执行此操作。 I want to test drag and drop functionality of the following basic component:我想测试以下基本组件的拖放功能:

export const Draggable: FC<DraggableInterface> = ({
  isDragging,
  setIsDragging,
  width,
  height,
  x,
  y,
  radius,
  children,
}) => {
  return (
      <motion.div
        {...{ isDragging }}
        {...{ setIsDragging }}
        drag
        dragConstraints={{
          left: Number(`${0 - x}`),
          right: Number(
            `${width - x}`,
          ),
          top: Number(`${0 - y}`),
          bottom: Number(
            `${height - y}`,
          ),
        }}
        dragElastic={0}
        dragMomentum={false}
        data-test-id='dragabble-element'
      >
        {children}
      </motion.div>
  );
};

And I have a snippet of the test as follows:我有一个测试片段如下:

it('should drag the node to the new position', async () => {

    const DraggableItem = () => {
      const [isDragging, setIsDragging] = useState<boolean>(true);
      return (
          <Draggable
            isDragging={isDragging}
            setIsDragging={() => setIsDragging}
            x={0}
            y={0}
            onUpdateNodePosition={() => undefined}
            width={500}
            height={200}
          >
            <div
            style={{
                height: '32px',
                width: '32px'
            }}
            />
          </Draggable>
      );
    };

    const { rerender, getByTestId } = render(<DraggableItem />);
    rerender(<DraggableItem />);
    const draggableElement = getByTestId('dragabble-element');

    const { getByTestId, container } = render(
      <DraggableItem />
    );
    fireEvent.mouseDown(draggableElement);
    fireEvent.mouseMove(container, {
      clientX: 16,
      clientY: 16,
    })

    fireEvent.mouseUp(draggableElement)

    await waitFor(() =>
      expect(draggableElement).toHaveStyle(
        'transform: translateX(16px) translateY(16px) translateZ(0)',
      ),
    );

However, I cannot get the test to pass successfully as the transform value I test for is set to none .但是,我无法让测试成功通过,因为我测试的transform值设置为none It does not update it the value with the updated CSS.它不会使用更新的 CSS 更新它的值。 I think there is some sort of async issue or animation delay so the mousemove is not detected and the value of the transform does not change.我认为存在某种异步问题或 animation 延迟,因此未检测到 mousemove 并且转换的值不会改变。 Would anyone know how to get the test to work or a way to test the mousemove changes?有人知道如何让测试工作或测试 mousemove 更改的方法吗?

Any advice or guidance on how I can solve this would be greatly appreciated!任何有关如何解决此问题的建议或指导将不胜感激!

It looks like you are invoking mouseMove() on the container instead of your draggable item.看起来您正在容器上调用 mouseMove() 而不是您的可拖动项目。 The container here refers to a root div containing your DraggableItem but is not the item itself ( API ).此处的容器指的是包含 DraggableItem 但不是项目本身的根 div ( API )。 Therefore, events are being fired on the root div and not the item.因此,事件是在根 div 而不是项目上触发的。


Here is a simple working example for testing draggable elements (for passers-by looking to test mouse down, move, and up events on draggable elements) :这是一个用于测试可拖动元素的简单工作示例(对于希望测试可拖动元素上的鼠标向下、移动和向上事件的路人)

//
// file: draggable-widget.tsx
//
import $ from 'jquery'
import * as React from 'react'

type WidgetProps = { children?: React.ReactNode }

export default class DraggableWidget extends React.Component<WidgetProps> {
    private element: React.RefObject<HTMLDivElement>

    constructor(props: WidgetProps) {
        super(props)
        this.element = React.createRef()
    }

    show() { if (this.element.current) $(this.element.current).show() }
    hide() { if (this.element.current) $(this.element.current).hide() }

    getLocation() {
        if (!this.element.current) return { x: 0, y: 0 }
        return {
            x: parseInt(this.element.current.style.left),
            y: parseInt(this.element.current.style.top)
        }
    }

    private onDraggingMouse(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
        let location = this.getLocation()
        let offsetX  = e.clientX - location.x
        let offsetY  = e.clientY - location.y
        let mouseMoveHandler = (e: MouseEvent) => {
            if (!this.element.current) return
            this.element.current.style.left = `${e.clientX - offsetX}px`
            this.element.current.style.top  = `${e.clientY - offsetY}px`
        }
        let reset = () => {
            window.removeEventListener('mousemove', mouseMoveHandler)
            window.removeEventListener('mouseup', reset)
        }
        window.addEventListener('mousemove', mouseMoveHandler)
        window.addEventListener('mouseup', reset)
    }

    render() {
        return (
            <div ref={this.element} className="draggable-widget">
                <div className="widget-header"
                    onMouseDown={e => this.onDraggingMouse(e)}>
                    <button className="widget-close" onClick={() => this.hide()}
                        onMouseDown={e => e.stopPropagation()}></button>
                </div>
            </div>
        )
    }
}

Then for the test logic:然后对于测试逻辑:

//
// file: draggable-widget.spec.tsx
//
import 'mocha'
import $ from 'jquery'
import * as React from 'react'
import { assert, expect } from 'chai'
import { render, fireEvent } from '@testing-library/react'
import Widget from './draggable-widget'

describe('draggable widget', () => {
    it('should move the widget by mouse delta-xy', () => {
        const mouse = [
            { clientX: 10, clientY: 20 },
            { clientX: 15, clientY: 30 }
        ]

        let ref = React.createRef<Widget>()
        let { container } = render(<Widget ref={ref} />)
        let element = $(container).find('.widget-header')
        assert(ref.current)
        expect(ref.current.getLocation()).to.deep.equal({ x: 0, y: 0 })

        fireEvent.mouseDown(element[0], mouse[0])
        fireEvent.mouseMove(element[0], mouse[1])
        fireEvent.mouseUp(element[0])

        expect(ref.current.getLocation()).to.deep.equal({
            x: mouse[1].clientX - mouse[0].clientX,
            y: mouse[1].clientY - mouse[0].clientY
        })
    })
})

Found this section in the react-testing-library docs在 react-testing-library 文档中找到此部分

https://testing-library.com/docs/dom-testing-library/api-events/#fireeventeventname https://testing-library.com/docs/dom-testing-library/api-events/#fireeventeventname

Scroll down to the dataTransfer property section - apparently this is what we should be using to test drag-and-drop interactions向下滚动到dataTransfer属性部分 - 显然这是我们应该用来测试拖放交互的内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用拖动道具时,如何让 React Framer-motion 为手机触发 onClick 事件? - How do you get React Framer-motion to fire onClick events for mobiles when using the drag prop? 应用运动来反应组件 Framer-Motion - Apply motion to react component Framer-Motion react framer-motion中的退出动画没有出现 - Exit animations in react framer-motion not appearing Framer-motion 覆盖 react-bootstrap - Framer-motion overriding react-bootstrap 在退出时对 framer-motion "AnimatePresence" animation 做出反应,试图让它工作..noob framer-motion 用户 - react framer-motion "AnimatePresence" animation on exiting, trying to get it working..noob framer-motion user 如何使用 Jest 和 react-testing-library 测试 react-dropzone? - How to test react-dropzone with Jest and react-testing-library? 如何使用 react-testing-library 测试 react-select - how to test react-select with react-testing-library 如何用 jest 和 react-testing-library 测试 react-toastify - How to test react-toastify with jest and react-testing-library 如何测试用 div(react-testing-library)渲染的组件数量? - How to test the number of components that are rendered with a div (react-testing-library)? 如何在反应测试库中测试父子关系? - How to test parent child relationship in react-testing-library?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM