Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React / Jest - Testing a drag and drop component

Tags:

reactjs

I have created a simplified script which demonstrates my issue.

I have a blue component which can be dragged over the grey component.

I have mocked the dataTransfer obejct but the drop event does not contain the data.

The test fails:

expect(received).toBe(expected) // Object.is equality

Expected: "test" Received: undefined

codesandbox: https://codesandbox.io/s/dazzling-wood-dn63kx

How can I get the test to pass?

App.js

import DraggableComponent from "./DraggableComponent";
import "./App.css";

function App() {
  function dragOver(ev) {
    ev.preventDefault();
  }

  function drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
  }
  return (
    <div className="container-fluid h-100">
      <div className="row h-100">
        <div
          draggable={true}
          id="drop-zone"
          data-testid={"drop-zone"}
          className="col-6 center-vh"
          onDrop={(e) => drop(e)}
          onDragOver={(e) => dragOver(e)}
        ></div>
        <div className="col-6">
          <DraggableComponent />
        </div>
      </div>
    </div>
  );
}

export default App;

DraggableComponent.js

function DraggableComponent() {
  function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
  }

  return (
    <div
      id="draggable-component"
      className="center-vh"
      draggable={true}
      onDragStart={(e) => drag(e)}
      data-testid="draggable-component"
    >
      Drag Me to the grey component
    </div>
  );
}
export default DraggableComponent;

App.test.js

import { render, screen, fireEvent } from "@testing-library/react";
import App from "./App";

    test("Tests drag and drop of first component", () => {
      render(<App />);
    
  const data = "test";
  const draggableElement = screen.getByTestId("draggable-component");
  const droppableElement = screen.getByTestId("drop-zone");

  // Simulate drag and drop action
  fireEvent.dragStart(draggableElement, {
    dataTransfer: { setData: data },
  });
  fireEvent.drop(droppableElement);

  // Assert that the dataTransfer property of the drop event has the expected data
  expect(droppableElement.dataTransfer).toBe(data);

  // Assert that the droppable element has received the dropped data
  expect(droppableElement).toHaveTextContent(data);
});
like image 753
MattBlack Avatar asked Feb 04 '26 00:02

MattBlack


1 Answers

import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import Draggable from 'react-draggable';

describe('Draggable component', () => {
  it('should move the element when dragged', () => {
    const { getByTestId } = render(
      <Draggable>
        <div data-testid="test-element" />
      </Draggable>
    );

    const element = getByTestId('test-element');

    const initialPosition = element.style.transform;
    expect(initialPosition).toBeFalsy();

    const handle = getByTestId('test-element').querySelector('.react-draggable-handle');
    const initialX = handle.style.left;
    const initialY = handle.style.top;

    // simulate dragging
    fireEvent.mouseDown(handle, { clientX: 0, clientY: 0 });
    fireEvent.mouseMove(handle, { clientX: 100, clientY: 100 });
    fireEvent.mouseUp(handle);

    const newPosition = element.style.transform;
    expect(newPosition).toBeTruthy();

    const newX = handle.style.left;
    const newY = handle.style.top;
    expect(newX).not.toBe(initialX);
    expect(newY).not.toBe(initialY);
  });
});

In this example, we use the render, getByTestId, fireEvent.mouseDown, fireEvent.mouseMove, and fireEvent.mouseUp methods from the @testing-library/react library to simulate dragging. We also use the data-testid attribute to find the element in the DOM. The final assertion remains the same.

like image 150
Roman Slisarenko Avatar answered Feb 06 '26 14:02

Roman Slisarenko