From 1997cbba889660fcafcd8002e0fb10c3c12122b7 Mon Sep 17 00:00:00 2001 From: alfeedrips Date: Sat, 25 Jul 2026 23:50:54 +0100 Subject: [PATCH] implemented --- .../__tests__/useInfiniteScroll.test.tsx | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/hooks/__tests__/useInfiniteScroll.test.tsx diff --git a/src/hooks/__tests__/useInfiniteScroll.test.tsx b/src/hooks/__tests__/useInfiniteScroll.test.tsx new file mode 100644 index 00000000..38b5cdeb --- /dev/null +++ b/src/hooks/__tests__/useInfiniteScroll.test.tsx @@ -0,0 +1,99 @@ +import { act, render } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { useInfiniteScroll } from '@/hooks/useInfiniteScroll'; + +const observers: { + callback: IntersectionObserverCallback; + observe: ReturnType; + disconnect: ReturnType; +}[] = []; + +beforeEach(() => { + observers.length = 0; + + class MockIntersectionObserver { + callback: IntersectionObserverCallback; + observe = vi.fn(); + disconnect = vi.fn(); + unobserve = vi.fn(); + constructor(cb: IntersectionObserverCallback) { + this.callback = cb; + observers.push({ + callback: cb, + observe: this.observe, + disconnect: this.disconnect, + }); + } + } + + vi.stubGlobal('IntersectionObserver', MockIntersectionObserver); +}); + +afterEach(() => { + vi.restoreAllMocks(); +}); + +function simulateIntersection(isIntersecting: boolean) { + const obs = observers[observers.length - 1]; + act(() => { + obs.callback( + [{ isIntersecting } as IntersectionObserverEntry], + {} as IntersectionObserver, + ); + }); +} + +function TestComponent({ + enabled, + hasMore, + onLoadMore, +}: { + enabled: boolean; + hasMore: boolean; + onLoadMore: () => void; +}) { + const sentinelRef = useInfiniteScroll({ enabled, hasMore, onLoadMore }); + return
; +} + +describe('useInfiniteScroll', () => { + it('calls onLoadMore when the observed element intersects', () => { + const onLoadMore = vi.fn(); + render(); + + simulateIntersection(true); + + expect(onLoadMore).toHaveBeenCalledTimes(1); + }); + + it('does not call onLoadMore when the element is not intersecting', () => { + const onLoadMore = vi.fn(); + render(); + + simulateIntersection(false); + + expect(onLoadMore).not.toHaveBeenCalled(); + }); + + it('disconnects the observer on unmount', () => { + const { unmount } = render( + , + ); + + unmount(); + + expect(observers[0].disconnect).toHaveBeenCalledTimes(1); + }); + + it('does not create an observer when enabled is false', () => { + render(); + + expect(observers).toHaveLength(0); + }); + + it('does not create an observer when hasMore is false', () => { + render(); + + expect(observers).toHaveLength(0); + }); +});