How to mock DataTransfer with Jest
Asked Answered
R

2

20

I have some React components where I use the HTML Drag interface.

In particular, I listen to dragover events on one component and set x and y positions with the DataTransfer object. Then, I listen to dragleave events on a different component and retrieve x and y positions from the DataTransfer.

I'm using Jest and Enzyme to test my components.

If I run my tests I get this error:

Test suite failed to run
ReferenceError: DataTransfer is not defined

As far I understand, the Drag interface is not available in Jest, so I need to mock it and (maybe?) make it available via Jest globals.

For now I defined DataTransfer in my jest.config.js and made it a global, but I'm not sure if this is the best solution.

class DataTransfer {
  constructor() {
    this.data = { dragX: "", dragY: "" };
    this.dropEffect = "none";
    this.effectAllowed = "all";
    this.files = [];
    this.img = "";
    this.items = [];
    this.types = [];
    this.xOffset = 0;
    this.yOffset = 0;
  }
  clearData() {
    this.data = {};
  }
  getData(format) {
    return this.data[format];
  }
  setData(format, data) {
    this.data[format] = data;
  }
  setDragImage(img, xOffset, yOffset) {
    this.img = img;
    this.xOffset = xOffset;
    this.yOffset = yOffset;
  }
}

const baseConfig = {
  globals: {
    DataTransfer: DataTransfer,
  },
  // other config...
};

module.exports = baseConfig;

What is the best way to mock the Drag interface in Jest?

Rounding answered 25/2, 2019 at 10:37 Comment(1)
It's hard to say for sure without seeing the component that are using the drag interface but the MDN docs do state: This object is available from the dataTransfer property of all drag events. Noting that the object is called dataTransfer (with a lowercase d). Is your drag and drop component consuming the dataTransfer object or the DataTransfer object?Contribution
B
2

I am using following custom mockup:

  // Arrange

  // Map as storage place
  const testStorage = new Map();

  // Mock of the drop Event
  const testEvent = {
      dataTransfer: {
        setData: (key, value) => testStorage.set(key, value),
        getData: (key) => testStorage.get(key)
      }
    };
    // remmeber to have 'and.callTrough()' to allow go trough the method
    spyOn(testEvent.dataTransfer, 'getData').and.callThrough();

    // Act
    // Add your code here

    // Assert
    expect(testEvent.dataTransfer.getData('YOUR_CHECKED_KEY')).toEqual('EXCPECTED_VALUE');

Beverlee answered 30/3, 2021 at 6:5 Comment(0)
P
1

It's important to know that in these cases, you do not really need to follow the "best" way of mocking the API, because there just isn't one. Mocking an API is just about giving your script the environment it needs to be executed, so it would have relevant input and output. If the mock you've made serves its purpose, then there's absolutely no need to look for a better way You're creating a class definition for your DataTransfer mock. That's the way we usually make mocks. So I guess yours is a good solution.

Popularity answered 15/8, 2021 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.