useScrollRestoration.test.js
3.32 KB
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
105
106
107
108
109
110
111
112
113
114
115
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
import { useScrollRestoration } from '../useScrollRestoration'
const create_session_storage = () => {
const store = {}
return {
store,
setItem: vi.fn((key, value) => {
store[key] = String(value)
}),
getItem: vi.fn((key) => {
if (Object.prototype.hasOwnProperty.call(store, key)) return store[key]
return null
}),
removeItem: vi.fn((key) => {
delete store[key]
}),
clear: vi.fn(() => {
Object.keys(store).forEach((key) => delete store[key])
}),
}
}
describe('useScrollRestoration', () => {
const original_window = globalThis.window
const original_session_storage = globalThis.sessionStorage
beforeEach(() => {
const session_storage = create_session_storage()
vi.stubGlobal('sessionStorage', session_storage)
const window_stub = {
scrollY: 0,
scrollTo: vi.fn(({ top }) => {
window_stub.scrollY = top
}),
}
vi.stubGlobal('window', window_stub)
})
afterEach(() => {
vi.unstubAllGlobals()
if (original_window !== undefined) vi.stubGlobal('window', original_window)
if (original_session_storage !== undefined) vi.stubGlobal('sessionStorage', original_session_storage)
vi.clearAllMocks()
})
it('restore_state 会等待 wait_for 达成后再执行滚动', async () => {
const { save_state, restore_state } = useScrollRestoration({
get_key: () => 'scroll_key',
get_scroll_el: () => window,
})
window.scrollY = 200
save_state({ extra: 1 })
window.scrollY = 0
let calls = 0
await restore_state({
wait_for: () => {
calls += 1
return calls >= 3
},
wait_for_timeout_ms: 200,
wait_for_interval_ms: 1,
settle_frames: 0,
get_scroll_top: () => 123,
})
expect(calls).toBeGreaterThanOrEqual(3)
expect(window.scrollTo).toHaveBeenCalled()
expect(window.scrollY).toBe(123)
})
it('wait_for 超时后仍会继续尝试恢复滚动', async () => {
const { save_state, restore_state } = useScrollRestoration({
get_key: () => 'scroll_key_timeout',
get_scroll_el: () => window,
})
window.scrollY = 80
save_state()
window.scrollY = 0
await restore_state({
wait_for: () => false,
wait_for_timeout_ms: 20,
wait_for_interval_ms: 5,
settle_frames: 0,
get_scroll_top: () => 50,
})
expect(window.scrollTo).toHaveBeenCalled()
expect(window.scrollY).toBe(50)
})
it('should_restore 返回 false 时不滚动且会清理状态', async () => {
const { save_state, restore_state, read_state } = useScrollRestoration({
get_key: () => 'scroll_key_should_restore',
get_scroll_el: () => window,
})
window.scrollY = 10
save_state()
await restore_state({
should_restore: () => false,
})
expect(window.scrollTo).not.toHaveBeenCalled()
expect(read_state()).toBeNull()
})
})