-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't use MouseEvent properties that aren't supported by jsdom #268
Comments
I created a test case in https://github.com/julienw/testcase-react-testing-library, branch To test in a browser:
git clone https://github.com/julienw/testcase-react-testing-library
cd testcase-react-testing-library
git checkout testcase-2
yarn install
yarn start
Compare what you get in your browser:
with the result in tests:
|
Unfortunately yes. It does seem odd that even if you provide the values explicitly it doesn't support adding those 🤔 You could also consider testing those things in cypress (with cypress-testing-library) or karma. I don't think there's anything we can do in this project though :-( |
That's because that's not how the MouseEvent constructor is supposed to work. According to the spec it only accepts |
Yeah, that's why I say I'd typically use a real browser for situations where I need those things. I wonder if there'd be a way to mock this sufficiently to do this in jsdom though. If you figure it out please let's add an example! |
This seems to work for me (with some Flow typing on top of it): type FakeMouseEventInit = $Shape<{
bubbles: boolean,
cancelable: boolean,
composed: boolean,
altKey: boolean,
button: 0 | 1 | 2 | 3 | 4,
buttons: number,
clientX: number,
clientY: number,
ctrlKey: boolean,
metaKey: boolean,
movementX: number,
movementY: number,
offsetX: number,
offsetY: number,
pageX: number,
pageY: number,
screenX: number,
screenY: number,
shiftKey: boolean,
x: number,
y: number,
}>;
class FakeMouseEvent extends MouseEvent {
offsetX: number;
offsetY: number;
pageX: number;
pageY: number;
x: number;
y: number;
constructor(type: string, values: FakeMouseEventInit) {
const { pageX, pageY, offsetX, offsetY, x, y, ...mouseValues } = values;
super(type, (mouseValues: Object));
Object.assign(this, {
offsetX: offsetX || 0,
offsetY: offsetY || 0,
pageX: pageX || 0,
pageY: pageY || 0,
x: x || 0,
y: y || 0,
});
}
}
export function getMouseEvent(
type: string,
values: FakeMouseEventInit = {}
): FakeMouseEvent {
values = {
bubbles: true,
cancelable: true,
...values,
};
return new FakeMouseEvent(type, values);
} Then I'd use this with |
JSDom would be the main place to look for this support, but maybe our friendly neighborhood user-event helper might be willing to add in these extra properties... |
That seems like a pretty good workaround (especially considering this is not a typical necessity). Would you be willing to add an example of this workaround until we can get it built-into something like user-event as @alexkrolick mentioned? |
(note: slightly updated the workaround, I made a mistake in the I can work on adding an example, but more likely on Friday or Monday. |
Your code works for me @julienw 😄 I copied what you posted and implemented it like so // I got an alias for root, which is `@app` but the file could be anywhere.
import getMouseEvent from '@app/__tests__/helpers/getMouseEvent';
...
const mouseMove = getMouseEvent('mousemove', {
pageX: 250,
pageY: 250,
})
fireEvent(document.body, mouseMove) And now I get the correct |
just wanted to add some comments to this thread in case anyone stumbled on it. I personally wanted to simulate a mouse drag in my code. I thought I was basically limited to just fireEvent.click(container) and wasn't even aware that I could perform other events, so I thought this thread was basically my key to success but I ended up with alternate route where I just used
In jsdom clientX/Y is supported by jsdom. While possibly things like pageX/Y are not, clientX/Y is modern and very intuitive and works fine with these fireEvent react-testing-library calls :) it was also helpful to stumble on the full "events" list here https://github.com/testing-library/dom-testing-library/blob/master/src/events.js which is linked from the docs (could be useful to add that stuff directly to the docs even though the code is basically helpful in showing all the events you can use) |
Also had this issue with jest, vue-test-utils and Drag & Drop. TIL: use client instead of page!
|
If you're looking for a TS version of interface MouseEventWithOffsets extends MouseEventInit {
pageX?: number
pageY?: number
offsetX?: number
offsetY?: number
x?: number
y?: number
}
class FakeMouseEvent extends MouseEvent {
constructor(type: string, values: MouseEventWithOffsets) {
const { pageX, pageY, offsetX, offsetY, x, y, ...mouseValues } = values
super(type, mouseValues)
Object.assign(this, {
offsetX: offsetX || 0,
offsetY: offsetY || 0,
pageX: pageX || 0,
pageY: pageY || 0,
x: x || 0,
y: y || 0,
})
}
} Usage: fireEvent(
element,
new FakeMouseEvent('mouseover', {
bubbles: true,
pageX: 350,
pageY: 125,
})
) |
I'm migrating our tests from enzyme to react-testing-library and encountered a roadblock. Indeed some of our code relies on the properties
offsetX
offsetY
pageX
pageY
of a MouseEvent instance. In Enzyme we could simply pass these as part of asimulate
call.But because
fireEvent
relies on real DOM events, and we rely onjsdom
, andjsdom
'sMouseEvent
doesn't support these properties, we can't test this code anymore.There's an issue for
pageX
andpageY
at jsdom/jsdom#1911, I mentioned the other missing properties there too. But maybe the issue is broader than just for these properties.What's the best path forward in your opinion? Is it the best path to add the support to jsdom, or can we somehow pass the direct values to React's event subsystem?
The text was updated successfully, but these errors were encountered: