Skip to content

Commit 3bc4847

Browse files
committed
test: cover triggerOnce transitions while in view
1 parent 5163d33 commit 3bc4847

1 file changed

Lines changed: 77 additions & 6 deletions

File tree

packages/react-intersection-observer/src/__tests__/InView.test.tsx

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

175246
test("Should unobserve when unmounted", () => {

0 commit comments

Comments
 (0)