Compatibility issue: Jest mock works in React / fails in Preact when using ForwardRef in a component
DanielMaczak opened this issue · comments
I am using Preact 10.19.6 (should be the latest).
The bug
Jest does not call event handler in ForwardRef component when using Preact.
This behavior does not happen in both of the following cases:
- I use React in place of Preact and I keep ForwardRef in my component.
- I use Preact and I don't use ForwardRef in my component.
It seems the onChange event does not trigger at all in tests while using forwardRef because I never reach it, even when putting a breakpoint directly inside the event:
...
<input // <-- breakpoint here does trigger
type="date"
value={value}
id="test-id"
onChange={e => {
storeValue(e); // <-- breakpoint here does not trigger
}}
ref={ref as Ref<HTMLInputElement>}
/>
...
To Reproduce
Preact repo where you can see the error: https://github.com/DanielMaczak/testing-jest-forwardref-bug
React repo where the test passes: https://github.com/DanielMaczak/testing-react-forwardref-bug
I did my best to make both as close to each other as possible:
- Using the latest version of Preact and React
- Using the same version of Jest
- Using raw Jest instead to Vitest to ensure it is not Vitest issue
- Scaling the code to minimum and using virtually identical code in both repos
Steps to verify the behavior (in both repos):
- Run
npm i
- Run
npm run test
You will see that one of the repos throws error on the mocked function not being called once while the other does not complain and the test passes.
Expected behavior
Both repos use the same code for the component and for the test, thus results in both should be the same.
Further information on this bug:
It occurs even when the forwardRef
is used in the tested module like this, e.g. not referencing the tested component and not even imported in the tests at all:
export const Test= forwardRef(() => {
return <div></div>;
});
I also pinpointed where the tests diverge between the two scenarios when forwardRef
is used and isn't in the tested module:
node_modules / jsdom / lib / jsdom / living / events / EventTarget-impl.js > innerInvokeEventListeners :
if (!listeners || !listeners[type]) {
return found; // the code exits here when using forwardRef()
}
EDIT: I found the compat
piece of code causing this. I will try to come up with a solution and submit a pull request.
This is an issue with preact-testing-library. It does not translate event names to React version when preact/compat
is imported. I will submit a fix there.