@@ -144,32 +144,103 @@ test("Should unobserve when triggerOnce comes into view", () => {
144144 expect ( instance . unobserve ) . toHaveBeenCalled ( ) ;
145145} ) ;
146146
147- test ( "Should resume observing when triggerOnce is disabled" , ( ) => {
147+ test ( "Should resume observing when triggerOnce is disabled while in view " , ( ) => {
148148 const callback = vi . fn ( ) ;
149- const { rerender } = render (
149+ const { container , rerender } = render (
150150 < InView triggerOnce onChange = { callback } >
151151 Inner
152152 </ InView > ,
153153 ) ;
154+ const element = container . children [ 0 ] ;
155+ const initialObserver = intersectionMockInstance ( element ) ;
156+ vi . spyOn ( initialObserver , "unobserve" ) ;
154157
155158 mockAllIsIntersecting ( true ) ;
156- expect ( callback ) . toHaveBeenLastCalledWith (
159+ expect ( callback ) . toHaveBeenCalledTimes ( 1 ) ;
160+ expect ( callback ) . toHaveBeenNthCalledWith (
161+ 1 ,
157162 true ,
158163 expect . objectContaining ( { isIntersecting : true } ) ,
159164 ) ;
165+ expect ( initialObserver . unobserve ) . toHaveBeenCalledWith ( element ) ;
160166
167+ callback . mockClear ( ) ;
161168 rerender (
162169 < InView triggerOnce = { false } onChange = { callback } >
163170 Inner
164171 </ InView > ,
165172 ) ;
166- callback . mockClear ( ) ;
167- mockAllIsIntersecting ( false ) ;
173+ const resumedObserver = intersectionMockInstance ( element ) ;
174+ expect ( resumedObserver ) . not . toBe ( initialObserver ) ;
168175
169- expect ( callback ) . toHaveBeenLastCalledWith (
176+ // A fresh observer reports the element's current state.
177+ mockAllIsIntersecting ( true ) ;
178+ expect ( callback ) . toHaveBeenNthCalledWith (
179+ 1 ,
180+ true ,
181+ expect . objectContaining ( { isIntersecting : true } ) ,
182+ ) ;
183+
184+ mockAllIsIntersecting ( false ) ;
185+ expect ( callback ) . toHaveBeenNthCalledWith (
186+ 2 ,
170187 false ,
171188 expect . objectContaining ( { isIntersecting : false } ) ,
172189 ) ;
190+
191+ mockAllIsIntersecting ( true ) ;
192+ expect ( callback ) . toHaveBeenNthCalledWith (
193+ 3 ,
194+ true ,
195+ expect . objectContaining ( { isIntersecting : true } ) ,
196+ ) ;
197+ expect ( callback ) . toHaveBeenCalledTimes ( 3 ) ;
198+ } ) ;
199+
200+ test ( "Should stop observing when triggerOnce is enabled while in view" , ( ) => {
201+ const callback = vi . fn ( ) ;
202+ const { container, rerender } = render (
203+ < InView triggerOnce = { false } onChange = { callback } >
204+ Inner
205+ </ InView > ,
206+ ) ;
207+ const element = container . children [ 0 ] ;
208+ const initialObserver = intersectionMockInstance ( element ) ;
209+ vi . spyOn ( initialObserver , "unobserve" ) ;
210+
211+ mockAllIsIntersecting ( true ) ;
212+ expect ( callback ) . toHaveBeenCalledTimes ( 1 ) ;
213+ expect ( callback ) . toHaveBeenNthCalledWith (
214+ 1 ,
215+ true ,
216+ expect . objectContaining ( { isIntersecting : true } ) ,
217+ ) ;
218+
219+ callback . mockClear ( ) ;
220+ rerender (
221+ < InView triggerOnce onChange = { callback } >
222+ Inner
223+ </ InView > ,
224+ ) ;
225+ expect ( initialObserver . unobserve ) . toHaveBeenCalledWith ( element ) ;
226+
227+ const triggerOnceObserver = intersectionMockInstance ( element ) ;
228+ expect ( triggerOnceObserver ) . not . toBe ( initialObserver ) ;
229+ vi . spyOn ( triggerOnceObserver , "unobserve" ) ;
230+
231+ // A fresh observer reports the element's current state before triggerOnce stops it.
232+ mockAllIsIntersecting ( true ) ;
233+ expect ( callback ) . toHaveBeenCalledTimes ( 1 ) ;
234+ expect ( callback ) . toHaveBeenNthCalledWith (
235+ 1 ,
236+ true ,
237+ expect . objectContaining ( { isIntersecting : true } ) ,
238+ ) ;
239+ expect ( triggerOnceObserver . unobserve ) . toHaveBeenCalledWith ( element ) ;
240+
241+ mockAllIsIntersecting ( false ) ;
242+ mockAllIsIntersecting ( true ) ;
243+ expect ( callback ) . toHaveBeenCalledTimes ( 1 ) ;
173244} ) ;
174245
175246test ( "Should unobserve when unmounted" , ( ) => {
0 commit comments