dom-testing-library: šŸ›Passing options to a PointerEvent through createEvent doesn't work

Hey, I’m maintaining react-use-gesture and heavily rely on testing-library for tests (thanks so much btw).

I’m planning to move to PointerEvent instead of a mix of TouchEvent and MouseEvent for our drag recognizer. Our set of tests implies creating events that simulate pointer coordinates in the form of { clientX: number, clientY: number }.

  • DOM Testing Library version: 7.5.1 (from yarn.lock, I’m using @testing-library/react)
  • node version: 12.16.1
  • yarn version: 1.22.4

Relevant code or config:

// this works
const event = createEvent.mouseMove(element, { clientX: 30, clientY: 80 })
console.log(event.clientX) // <-- prints 30

// this doesn't work
const event = createEvent.pointerMove(element, { clientX: 30, clientY: 80 })
console.log(event.clientX) // <-- prints undefined

I’ll link to a repro as soon as codesandbox works properly.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (3 by maintainers)

Commits related to this issue

Most upvoted comments

I was able to hack around this by adding my own implementation of PointerEvent that allows me to pass through the properties I care about for testing on the Event object.

const pointerEventCtorProps = ['clientX', 'clientY', 'pointerType'];
export default class PointerEventFake extends Event {
  constructor(type, props) {
    super(type, props);
    pointerEventCtorProps.forEach((prop) => {
      if (props[prop] != null) {
        this[prop] = props[prop];
      }
    });
  }
}

Then in my test:

 window.PointerEvent = PointerEventFake;
 fireEvent.pointerDown(myElement, new PointerEventFake('pointerdown', {clientX: 20}));
 fireEvent.pointerMove(myElement, new PointerEventFake('pointermove', {clientX: 30}));

And they get fired and hit as I would expect in my React components.

@hatpick what I’m saying is the options are passed to the the PointerEvent constructor, just that clientX Is not a valid option for PointerEvent, as you can see here https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent. Try switching to fireEvent.mouseDown(node, { clientX: 0 }), or use pointerDown with one of the options from the mdn docs, such as fireEvent.pointerDown(node, { pressure: 0 }). Either way, you should see that those options are set on the event. This can also be confirmed by looking into the createEvent code, where you will see that the options are passed to the constructor for the Event or PointerEvent.

I was able to hack around this by adding my own implementation of PointerEvent that allows me to pass through the properties I care about for testing on the Event object.

const pointerEventCtorProps = ['clientX', 'clientY', 'pointerType'];
export default class PointerEventFake extends Event {
  constructor(type, props) {
    super(type, props);
    pointerEventCtorProps.forEach((prop) => {
      if (props[prop] != null) {
        this[prop] = props[prop];
      }
    });
  }
}

Then in my test:

 window.PointerEvent = PointerEventFake;
 fireEvent.pointerDown(myElement, new PointerEventFake('pointerdown', {clientX: 20}));
 fireEvent.pointerMove(myElement, new PointerEventFake('pointermove', {clientX: 30}));

And they get fired and hit as I would expect in my React components.

Adding that to my fireEvent didnt work but adding your class to my setupTests.js file along with

global.PointerEvent = PointerEventFake;

worked a treat! Thank you!