1
+ /* global Element */
2
+
3
+ import React from 'react'
1
4
import { findDOMNode } from 'react-dom'
2
5
import { render } from '../TestUtils'
3
6
import { IS_SCROLLING_TIMEOUT } from './utils/onScroll'
4
- import { getMarkup , simulateWindowScroll , simulateWindowResize } from './utils/TestUtils'
7
+ import WindowScroller from './WindowScroller'
8
+
9
+ function ChildComponent ( { scrollTop, isScrolling, height } ) {
10
+ return (
11
+ < div > { `scrollTop:${ scrollTop } , isScrolling:${ isScrolling } , height:${ height } ` } </ div >
12
+ )
13
+ }
14
+
15
+ function mockGetBoundingClientRectForHeader ( {
16
+ documentOffset = 0 ,
17
+ height
18
+ } ) {
19
+ // Mock the WindowScroller element and window separately
20
+ // The only way to mock the former (before its created) is globally
21
+ Element . prototype . getBoundingClientRect = jest . fn ( ( ) => ( {
22
+ top : height
23
+ } ) )
24
+ document . documentElement . getBoundingClientRect = jest . fn ( ( ) => ( {
25
+ top : documentOffset
26
+ } ) )
27
+ }
28
+
29
+ function getMarkup ( {
30
+ headerElements,
31
+ documentOffset,
32
+ ...props
33
+ } = { } ) {
34
+ const windowScroller = (
35
+ < WindowScroller { ...props } >
36
+ { ( { height, isScrolling, scrollTop } ) => (
37
+ < ChildComponent
38
+ height = { height }
39
+ isScrolling = { isScrolling }
40
+ scrollTop = { scrollTop }
41
+ />
42
+ ) }
43
+ </ WindowScroller >
44
+ )
45
+
46
+ // JSDome doesn't implement a working getBoundingClientRect()
47
+ // But WindowScroller requires it
48
+ mockGetBoundingClientRectForHeader ( {
49
+ documentOffset,
50
+ height : headerElements ? headerElements . props . style . height : 0
51
+ } )
52
+
53
+ if ( headerElements ) {
54
+ return (
55
+ < div >
56
+ { headerElements }
57
+ { windowScroller }
58
+ </ div >
59
+ )
60
+ } else {
61
+ return windowScroller
62
+ }
63
+ }
64
+
65
+ function simulateWindowScroll ( {
66
+ scrollY = 0
67
+ } ) {
68
+ document . body . style . height = '10000px'
69
+ window . scrollY = scrollY
70
+ document . dispatchEvent ( new window . Event ( 'scroll' , { bubbles : true } ) )
71
+ document . body . style . height = ''
72
+ }
73
+
74
+ function simulateWindowResize ( {
75
+ height = 0
76
+ } ) {
77
+ window . innerHeight = height
78
+ document . dispatchEvent ( new window . Event ( 'resize' , { bubbles : true } ) )
79
+ }
5
80
6
81
describe ( 'WindowScroller' , ( ) => {
7
82
// Set default window height and scroll position between tests
@@ -23,10 +98,9 @@ describe('WindowScroller', () => {
23
98
render . unmount ( )
24
99
25
100
// Simulate scrolled documentElement
26
- document . documentElement . getBoundingClientRect = ( ) => ( {
27
- top : - 100
28
- } )
29
- const component = render ( getMarkup ( ) )
101
+ const component = render ( getMarkup ( {
102
+ documentOffset : - 100
103
+ } ) )
30
104
const rendered = findDOMNode ( component )
31
105
const top = rendered . getBoundingClientRect ( ) . top
32
106
expect ( component . _positionFromTop ) . toEqual ( top + 100 )
@@ -148,4 +222,63 @@ describe('WindowScroller', () => {
148
222
expect ( rendered . textContent ) . toContain ( 'height:1000' )
149
223
} )
150
224
} )
225
+
226
+ describe ( 'updatePosition' , ( ) => {
227
+ it ( 'should calculate the initial offset from the top of the page when mounted' , ( ) => {
228
+ let windowScroller
229
+
230
+ render ( getMarkup ( {
231
+ headerElements : < div style = { { height : 100 } } > </ div > ,
232
+ ref : ( ref ) => {
233
+ windowScroller = ref
234
+ }
235
+ } ) )
236
+
237
+ expect ( windowScroller . _positionFromTop ) . toBe ( 100 )
238
+ } )
239
+
240
+ it ( 'should recalculate the offset from the top when the window resizes' , ( ) => {
241
+ let windowScroller
242
+
243
+ render ( getMarkup ( {
244
+ headerElements : < div id = 'header' style = { { height : 100 } } > </ div > ,
245
+ ref : ( ref ) => {
246
+ windowScroller = ref
247
+ }
248
+ } ) )
249
+
250
+ expect ( windowScroller . _positionFromTop ) . toBe ( 100 )
251
+
252
+ mockGetBoundingClientRectForHeader ( {
253
+ height : 200
254
+ } )
255
+
256
+ expect ( windowScroller . _positionFromTop ) . toBe ( 100 )
257
+
258
+ simulateWindowResize ( { height : 1000 } )
259
+
260
+ expect ( windowScroller . _positionFromTop ) . toBe ( 200 )
261
+ } )
262
+
263
+ it ( 'should recalculate the offset from the top if called externally' , ( ) => {
264
+ let windowScroller
265
+
266
+ render ( getMarkup ( {
267
+ headerElements : < div id = 'header' style = { { height : 100 } } > </ div > ,
268
+ ref : ( ref ) => {
269
+ windowScroller = ref
270
+ }
271
+ } ) )
272
+
273
+ expect ( windowScroller . _positionFromTop ) . toBe ( 100 )
274
+
275
+ mockGetBoundingClientRectForHeader ( {
276
+ height : 200
277
+ } )
278
+
279
+ windowScroller . updatePosition ( )
280
+
281
+ expect ( windowScroller . _positionFromTop ) . toBe ( 200 )
282
+ } )
283
+ } )
151
284
} )
0 commit comments