1
- import { describe , expect , it , vi } from 'vitest'
1
+ import { afterEach , describe , expect , it , vi } from 'vitest'
2
2
3
- import { renderHook } from '@testing-library/react-hooks '
3
+ import { render , renderHook , screen , fireEvent , cleanup } from '@testing-library/react'
4
4
import type React from 'react'
5
- import ReactDOM from 'react-dom'
6
5
7
6
import useBottomScrollListener from './'
8
7
@@ -37,7 +36,8 @@ describe('useBottomScrollListener', () => {
37
36
38
37
// window size is 768.
39
38
// 768 + 400 = 1168, should not scroll
40
- ; ( document . documentElement as unknown as Record < string , unknown > ) . scrollHeight = 1200
39
+ // @ts -expect-error scrollHeight is a mock property
40
+ document . documentElement . scrollHeight = 1200
41
41
document . documentElement . scrollTop = 400
42
42
43
43
window . dispatchEvent ( new Event ( 'scroll' ) )
@@ -52,7 +52,8 @@ describe('useBottomScrollListener', () => {
52
52
53
53
// window size is 768.
54
54
// 768 + 432 = 1200, should scroll
55
- ; ( document . documentElement as unknown as Record < string , unknown > ) . scrollHeight = 1200
55
+ // @ts -expect-error scrollHeight is a mock property
56
+ document . documentElement . scrollHeight = 1200
56
57
document . documentElement . scrollTop = 432
57
58
58
59
window . dispatchEvent ( new Event ( 'scroll' ) )
@@ -68,69 +69,50 @@ describe('useBottomScrollListener', () => {
68
69
} )
69
70
70
71
describe ( 'given a ref it should use the given ref and' , ( ) => {
71
- const setupFakeContainer = ( containerRef : React . RefObject < HTMLDivElement > ) => {
72
- const div = document . createElement ( 'div' )
73
-
74
- // biome-ignore lint: should be migrated to a more modern way of doing this
75
- const renderedNode : HTMLDivElement = ReactDOM . render ( < div ref = { containerRef } /> , div ) as unknown as HTMLDivElement
76
-
77
- ; ( renderedNode as unknown as Record < string , unknown > ) . clientHeight = 600
78
-
79
- let triggerScroll : ( ( ) => void ) | null = null
80
- renderedNode . addEventListener = vi . fn ( ) . mockImplementation ( ( _ , cb ) => {
81
- triggerScroll = cb
82
- } )
83
-
84
- return { renderedNode, getTriggerScroll : ( ) => triggerScroll }
72
+ const TestComponent = ( { onBottom } : { onBottom : ( ) => void } ) => {
73
+ const ref = useBottomScrollListener < HTMLDivElement > ( onBottom , { offset : 0 , debounce : 0 } )
74
+
75
+ return (
76
+ < div ref = { ref } style = { { height : '600px' } } data-testid = "container" >
77
+ < h1 > I am test</ h1 >
78
+ </ div >
79
+ )
85
80
}
86
81
82
+ afterEach ( cleanup )
83
+
87
84
it ( 'shall not invoke onBottom when container has not hit bottom' , ( ) => {
88
85
const onBottom = vi . fn ( )
86
+ render ( < TestComponent onBottom = { onBottom } /> )
89
87
90
- const hook = renderHook ( ( ) => useBottomScrollListener < HTMLDivElement > ( onBottom , { offset : 0 , debounce : 0 } ) )
91
- const containerRef : React . RefObject < HTMLDivElement > = hook . result . current
92
-
93
- const { renderedNode, getTriggerScroll } = setupFakeContainer ( containerRef )
94
-
95
- hook . rerender ( )
96
-
97
- const triggerScroll = getTriggerScroll ( )
98
- if ( triggerScroll == null ) {
99
- throw new Error ( 'Hook setup failed, callback never set' )
100
- }
88
+ const container : { clientHeight : number ; scrollHeight : number ; scrollTop : number } =
89
+ screen . getByTestId ( 'container' )
101
90
102
91
// container size is 600.
103
92
// 600 + 300 = 900, should not scroll
104
- ; ( renderedNode as unknown as Record < string , unknown > ) . scrollHeight = 1000
105
- renderedNode . scrollTop = 300
93
+ container . clientHeight = 600
94
+ container . scrollHeight = 1000
95
+ container . scrollTop = 300
106
96
107
- triggerScroll ( )
97
+ fireEvent . scroll ( container as Element , { target : { scrollY : 300 } } )
108
98
109
99
expect ( onBottom ) . not . toHaveBeenCalled ( )
110
100
} )
111
101
112
102
it ( 'shall invoke onBottom when container is exactly at bottom' , ( ) => {
113
103
const onBottom = vi . fn ( )
104
+ render ( < TestComponent onBottom = { onBottom } /> )
114
105
115
- const hook = renderHook ( ( ) => useBottomScrollListener < HTMLDivElement > ( onBottom , { offset : 0 , debounce : 0 } ) )
116
- const containerRef : React . RefObject < HTMLDivElement > = hook . result . current
117
-
118
- const { renderedNode, getTriggerScroll } = setupFakeContainer ( containerRef )
119
-
120
- hook . rerender ( )
121
-
122
- const triggerScroll = getTriggerScroll ( )
123
- if ( triggerScroll == null ) {
124
- throw new Error ( 'Hook setup failed, callback never set' )
125
- }
106
+ const container : { clientHeight : number ; scrollHeight : number ; scrollTop : number } =
107
+ screen . getByTestId ( 'container' )
126
108
127
109
// container size is 600.
128
110
// 600 + 400 = 1000, should scroll
111
+ container . clientHeight = 600
112
+ container . scrollHeight = 1000
113
+ container . scrollTop = 400
129
114
130
- ; ( renderedNode as unknown as Record < string , unknown > ) . scrollHeight = 1000
131
- renderedNode . scrollTop = 400
132
-
133
- triggerScroll ( )
115
+ fireEvent . scroll ( container as Element , { target : { scrollY : 400 } } )
134
116
135
117
expect ( onBottom ) . toHaveBeenCalledTimes ( 1 )
136
118
} )
0 commit comments