-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
index.test.ts
104 lines (82 loc) · 3.96 KB
/
index.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
import { useElementVisibility } from '.'
describe('useElementVisibility', () => {
let el: HTMLDivElement
beforeEach(() => {
el = document.createElement('div')
})
it('should work when el is not an element', async () => {
const visible = useElementVisibility(null)
expect(visible.value).toBeFalsy()
})
it('should work when window is undefined', () => {
// @ts-expect-error set window null
const visible = useElementVisibility(el, { window: null })
expect(visible.value).toBeFalsy()
})
describe('when internally using useIntersectionObserver', async () => {
const { useIntersectionObserver } = await import('../useIntersectionObserver')
beforeAll(() => {
vi.resetAllMocks()
vi.mock('../useIntersectionObserver')
})
it('should call useIntersectionObserver internally', () => {
expect(useIntersectionObserver).toHaveBeenCalledTimes(0)
useElementVisibility(el)
expect(useIntersectionObserver).toHaveBeenCalledTimes(1)
})
it('passes the given element to useIntersectionObserver', () => {
useElementVisibility(el)
expect(vi.mocked(useIntersectionObserver).mock.lastCall?.[0]).toBe(el)
})
it('passes a callback to useIntersectionObserver that sets visibility to false only when isIntersecting is false', () => {
const isVisible = useElementVisibility(el)
const callback = vi.mocked(useIntersectionObserver).mock.lastCall?.[1]
const callMockCallbackWithIsIntersectingValue = (isIntersecting: boolean) => callback?.([{ isIntersecting, time: 1 } as IntersectionObserverEntry], {} as IntersectionObserver)
// It should be false initially
expect(isVisible.value).toBe(false)
// It should still be false if the callback doesn't get an isIntersecting = true
callMockCallbackWithIsIntersectingValue(false)
expect(isVisible.value).toBe(false)
// But it should become true if the callback gets an isIntersecting = true
callMockCallbackWithIsIntersectingValue(true)
expect(isVisible.value).toBe(true)
// And it should become false again if isIntersecting = false
callMockCallbackWithIsIntersectingValue(false)
expect(isVisible.value).toBe(false)
})
it('uses the latest version of isIntersecting when multiple intersection entries are given', () => {
const isVisible = useElementVisibility(el)
const callback = vi.mocked(useIntersectionObserver).mock.lastCall?.[1]
const callMockCallbackWithIsIntersectingValues = (...entries: { isIntersecting: boolean; time: number }[]) => {
callback?.(entries as IntersectionObserverEntry[], {} as IntersectionObserver)
}
// It should be false initially
expect(isVisible.value).toBe(false)
// It should take the latest value of isIntersecting
callMockCallbackWithIsIntersectingValues(
{ isIntersecting: false, time: 1 },
{ isIntersecting: false, time: 2 },
{ isIntersecting: true, time: 3 },
)
expect(isVisible.value).toBe(true)
// It should take the latest even when entries are out of order
callMockCallbackWithIsIntersectingValues(
{ isIntersecting: true, time: 1 },
{ isIntersecting: false, time: 3 },
{ isIntersecting: true, time: 2 },
)
expect(isVisible.value).toBe(false)
})
it('passes the given window to useIntersectionObserver', () => {
const mockWindow = {} as Window
useElementVisibility(el, { window: mockWindow })
expect(vi.mocked(useIntersectionObserver).mock.lastCall?.[2]).toContain({ window: mockWindow })
})
it('uses the given scrollTarget as the root element in useIntersectionObserver', () => {
const mockScrollTarget = document.createElement('div')
useElementVisibility(el, { scrollTarget: mockScrollTarget })
expect(vi.mocked(useIntersectionObserver).mock.lastCall?.[2]).toContain({ root: mockScrollTarget })
})
})
})