-
-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathscrollElementIntoView.test.ts
More file actions
109 lines (90 loc) · 4.12 KB
/
scrollElementIntoView.test.ts
File metadata and controls
109 lines (90 loc) · 4.12 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
import { describe, it, expect, vi, beforeEach } from 'vitest'
import scrollElementIntoView from './scrollElementIntoView.js'
describe('scrollElementIntoView', () => {
let mockElement: HTMLElement
let mockHtmlNode: HTMLElement
let mockBodyNode: HTMLElement
let mockStyleTag: HTMLStyleElement
let mockHead: HTMLElement
beforeEach(() => {
mockElement = {
getBoundingClientRect: vi.fn().mockReturnValue({ top: 100 }),
} as unknown as HTMLElement
mockHtmlNode = {
scrollTop: 0,
get scrollHeight() { return 1000 },
get clientHeight() { return 500 },
} as unknown as HTMLElement
mockBodyNode = {
scrollTop: 0,
get scrollHeight() { return 1000 },
get clientHeight() { return 500 },
} as unknown as HTMLElement
mockStyleTag = {
innerHTML: '',
} as unknown as HTMLStyleElement
mockHead = {
appendChild: vi.fn(),
removeChild: vi.fn(),
} as unknown as HTMLElement
global.document = {
documentElement: mockHtmlNode,
body: mockBodyNode,
createElement: vi.fn().mockReturnValue(mockStyleTag),
head: mockHead,
} as unknown as Document
})
it('should scroll element into view when html node is scrollable', () => {
const addressBarShadowPadding = 10
const result = scrollElementIntoView(mockElement, addressBarShadowPadding)
expect(result).toBe(0)
expect(mockHtmlNode.scrollTop).toBe(90)
expect(mockHead.appendChild).toHaveBeenCalledWith(mockStyleTag)
expect(mockHead.removeChild).toHaveBeenCalledWith(mockStyleTag)
})
it('should scroll element into view when body node is scrollable', () => {
Object.defineProperty(mockHtmlNode, 'scrollHeight', { value: 500 })
const addressBarShadowPadding = 10
const result = scrollElementIntoView(mockElement, addressBarShadowPadding)
expect(result).toBe(0)
expect(mockBodyNode.scrollTop).toBe(90)
expect(mockHead.appendChild).toHaveBeenCalledWith(mockStyleTag)
expect(mockHead.removeChild).toHaveBeenCalledWith(mockStyleTag)
})
it('should return current scroll position when html node has scroll', () => {
mockHtmlNode.scrollTop = 50
const addressBarShadowPadding = 10
const result = scrollElementIntoView(mockElement, addressBarShadowPadding)
expect(result).toBe(50)
// Document y = currentScroll(50) + BCR.top(100) - padding(10) = 140
expect(mockHtmlNode.scrollTop).toBe(140)
})
it('should return current scroll position when body node has scroll', () => {
mockHtmlNode.scrollTop = 0
mockBodyNode.scrollTop = 50
Object.defineProperty(mockHtmlNode, 'scrollHeight', { value: 500 })
const addressBarShadowPadding = 10
const result = scrollElementIntoView(mockElement, addressBarShadowPadding)
expect(result).toBe(50)
// Document y = currentScroll(50) + BCR.top(100) - padding(10) = 140
expect(mockBodyNode.scrollTop).toBe(140)
})
it('should not re-scroll when element is already at the viewport top', () => {
mockHtmlNode.scrollTop = 600
;(mockElement.getBoundingClientRect as ReturnType<typeof vi.fn>).mockReturnValue({ top: 0 })
const addressBarShadowPadding = 0
const result = scrollElementIntoView(mockElement, addressBarShadowPadding)
expect(result).toBe(600)
// Document y = currentScroll(600) + BCR.top(0) - padding(0) = 600 (stays put)
expect(mockHtmlNode.scrollTop).toBe(600)
})
it('should not scroll when neither html nor body is scrollable', () => {
Object.defineProperty(mockHtmlNode, 'scrollHeight', { value: 500 })
Object.defineProperty(mockBodyNode, 'scrollHeight', { value: 500 })
const addressBarShadowPadding = 10
const result = scrollElementIntoView(mockElement, addressBarShadowPadding)
expect(result).toBe(0)
expect(mockHtmlNode.scrollTop).toBe(0)
expect(mockBodyNode.scrollTop).toBe(0)
})
})