atlassian / pragmatic-drag-and-drop

Fast drag and drop for any experience on any tech stack
https://atlassian.design/components/pragmatic-drag-and-drop
Other
9.32k stars 208 forks source link

DOMRect polyfill needed for Jest and jsdom #82

Closed joshkel closed 1 month ago

joshkel commented 3 months ago

The new "honey pot fix" in @atlaskit/pragmatic-drag-drop version 1.2.0 has added usage of DOMRect, which isn't provided by jsdom. This resulted in our Jest tests failing with errors similar to the following:

    ReferenceError: DOMRect is not defined
      36 |
      37 |   fireEvent.dragStart(dragItem);
    > 38 |   fireEvent.dragEnter(document.body);
         |             ^
      39 | }
      40 |
      41 | export function fireDrop(dropTarget: HTMLElement) {
      at getHoneyPotRectFor (../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/cjs/honey-pot-fix/make-honey-pot-fix.js:75:3)
      at mountHoneyPot (../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/cjs/honey-pot-fix/make-honey-pot-fix.js:140:20)
      at onPostEvent (../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/cjs/honey-pot-fix/make-honey-pot-fix.js:291:18)
      at dispatchEvent (../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/cjs/make-adapter/make-adapter.js:33:61)

To fix it, test code can polyfill DOMRect. I'm currently using the implementation from jarek-foksa/geometry-polyfill, and it seems to work.

Pragmatic Drag and Drop's very helpful testing guide should be updated with this information.

alexreardon commented 3 months ago

You are totally right @joshkel!

Plan:

  1. Expose our DOMRect polyfill through our @atlaskit/pragmatic-drag-and-drop-unit-testing package
  2. Update our testing guidelines to callout the need to polyfill DOMRect

Here is the polyfill that we are currently using for JSDOM

// This file polyfills DOMRect
// DOMRect is currently not polyfilled by jsdom

(() => {
    if (typeof window === 'undefined') {
        return;
    }
    if (window.DOMRect) {
        return;
    }

    class DOMRect {
        constructor(x = 0, y = 0, width = 0, height = 0) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;

            // Computed values.
            // See https://developer.mozilla.org/en-US/docs/Web/API/DOMRect
            this.top = height < 0 ? y + height : y;
            this.right = width < 0 ? x : x + width;
            this.bottom = height < 0 ? y : y + height;
            this.left = width < 0 ? x + width : x;
        }

        static fromRect(rectangle) {
            return new DOMRect(rectangle?.x, rectangle?.y, rectangle?.width, rectangle?.height);
        }

        toJSON() {
            return JSON.stringify(this);
        }
    }

    window.DOMRect = DOMRect;
})();
alexreardon commented 2 months ago

We are about to ship a polyfill package and updated test guidance

alexreardon commented 1 month ago

Thank you @joshkel for raising this!