react-intersection-observer
react-intersection-observer copied to clipboard
Version >= 9.12.0 breaks automatic InteractionOberserver setup with jest
We have a test environment where we've used mockAllIsIntersecting from react-intersection-observer/test-utils together with Jest This has worked just fine until we updated to version 9.12.0 and beyond after that we've started to get type errors when running tests.
After that we got the error:
TypeError: observer.observe is not a function
at observe (node_modules/react-intersection-observer/src/observe.ts:153:12)
at node_modules/react-intersection-observer/src/useInView.tsx:66:19
at commitHookEffectListMount (node_modules/react-dom/cjs/react-dom.development.js:23189:26)
The error could be resolved by manually adding this code to our Jest tests:
beforeEach(() => {
setupIntersectionMocking(jest.fn);
});
afterEach(() => {
resetIntersectionMocking();
});
So it seems like version 9.12.0 broke the automatic setup with Jest? 🤔
To Reproduce Try and recreate the issue in a Codesandbox:
Expected behavior
If react-intersection-observer should still be possible to run together with Jest without manually using setupIntersectionMocking and resetIntersectionMocking types should be fixed.
I suspect that this error comes from this update mentioned in the release notes for version 9.12.0
"Types cleanup in test-utils, getting rid of @types/jest (replaced with vitest)"
Screenshots
**Desktop **
- OS: Mac OS Sonoma
- Browser N/A (Jest tests)
- Version >= 9.12.0
Can you verify that it's 9.12 it first happens? What if you run just one test? It could be Jest resets the observer after a run, so before All isn't working as expected. Do you have something in your code that resets it after a test?
I unfortunately won't have a chance to look into it until September.
I've now verified that the error isn't there with version 9.11 it starts with 9.12. I've also verified that the error doesn't occur if I run just one test.
The error occurs only when I have two or more tests that both contains a call to mockAllIsIntersecting(true);
I didn't have anything that resets between the test before I've added a the fix to circumvent this error (the setupIntersectionMocking/resetIntersectionMocking mentioned above)
Could be a difference between vitest and jest, and how they reset code. Might have to go back to beforeEach for Jest tests then.
I've tried installing and running the hooks.test.tsx tests using Jest instead of Vitest - Using a default Jest configuration, it correctly does the mocking, so mockAllIsIntersecting works as expected.
Is there anything special in your setup or Jest configuration?
I just want to chime in and say I'm experiencing the same issue as well using Jest and starting with 9.12, though my error looks slightly different:
TypeError: io.observe is not a function
@valleywood 's workaround solved the issue for me, but I only needed setupIntersectionMocking(jest.fn) in the beforeEach() hook. I did not need resetIntersectionMocking() in afterEach()
We're running into the same issue, updating from 9.10.3 to 9.13.1 and getting the observer.observe is not a function error.
In terms of custom setup, the only thing that comes to mind is that we add a top-level
import "intersection-observer";
at the top of our test setup file.
We experience the same issue. For us the problem is that setupIntersectionMocking(jest.fn) is called in the beforeAll step. However, since we use jest with resetMocks=true, the mocks are reset after each test, but only setup at the beginning.
Calling setupIntersectionMocking(jest.fn) in beforeEach fixes the error for us.
@julian-jambit that could explain the issue.
This change was made because of the issue in #689 - I'm thinking it might sense to just go back to beforeEach to be safe.
:tada: This issue has been resolved in version 9.15.0 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
Hi @thebuilder thank you for the quick fix. Unfortunately, the version 9.15.0 still doesn't solve the issue and even breaks our mentioned worarkound. The additional check for isMocking in setupIntersectionMocking does not work well together with resetMocks=true in jest. With resetMocks jest resets all mocks after each test, but it does not reset your isMocking variable, so the mock is never setup again.
Right. Okay. I should be able to determine the mock state without using a variable.
@julian-jambit could you try https://github.com/thebuilder/react-intersection-observer/pull/716 - You should be able to install it before it's released with the pkg-pr-new bundle:
npm i https://pkg.pr.new/thebuilder/react-intersection-observer@716
This has the same error. From the documentation of resetMocks:
This will lead to any mocks having their fake implementations removed but does not restore their initial implementation.
So isMockFunction seems to still return true, even if the mock is reset. I don't know if there is a way to check if there is no mock implementation.
Jeez, what kind of pseudo reset is that. Seems like Vitest does the same. Can't find an obvious way to determine if it has been reset. Maybe I have to skip that check then, and always create a new instance.
:tada: This issue has been resolved in version 9.15.1 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
I can confirm that it works now, thank you!