Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock DataTransfer with Jest

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?

like image 604
jackdbd Avatar asked Feb 25 '19 10:02

jackdbd


People also ask

How do you mock data in Jest?

Note: In order to mock properly, Jest needs jest. mock('moduleName') to be in the same scope as the require/import statement. Here's a contrived example where we have a module that provides a summary of all the files in a given directory. In this case, we use the core (built in) fs module.

How do you mock an NPM Jest module?

To mock a Node module with Jest, we can use the jest. createMockFromModule method. const utils = jest. createMockFromModule('../utils').


2 Answers

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');

like image 123
Kacpers Avatar answered Oct 05 '22 17:10

Kacpers


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.

like image 44
Younes Henni Avatar answered Oct 05 '22 17:10

Younes Henni