3
3
describe ( '$anchorScroll' , function ( ) {
4
4
5
5
var elmSpy ;
6
+ var docSpies ;
6
7
var windowSpies ;
7
8
8
9
function addElements ( ) {
@@ -69,7 +70,7 @@ describe('$anchorScroll', function() {
69
70
return function ( $window ) {
70
71
forEach ( elmSpy , function ( spy , id ) {
71
72
var count = map [ id ] || 0 ;
72
- expect ( spy . calls . length ) . toBe ( count ) ;
73
+ expect ( spy . callCount ) . toBe ( count ) ;
73
74
} ) ;
74
75
expect ( $window . scrollTo ) . not . toHaveBeenCalled ( ) ;
75
76
} ;
@@ -79,17 +80,66 @@ describe('$anchorScroll', function() {
79
80
return expectScrollingTo ( NaN ) ;
80
81
}
81
82
83
+ function mockDocumentReadyState ( ) {
84
+ var docMock = {
85
+ readyState : 'mocked' ,
86
+ updateReadyState : function ( newState ) {
87
+ this . readyState = newState ;
88
+ this . dispatchFakeReadyStateChangeEvent ( ) ;
89
+ }
90
+ } ;
91
+
92
+ docSpies = { } ;
93
+ var i = 0 ;
94
+
95
+ return function ( $rootScope , $window ) {
96
+ var propsToMock = [ 'body' , 'documentElement' ] ;
97
+ var methodsToMock = [
98
+ 'getElementById' ,
99
+ 'getElementsByName' ,
100
+ 'addEventListener' ,
101
+ 'removeEventListener'
102
+ ] ;
103
+
104
+ var document_ = $window . document ;
105
+
106
+ propsToMock . forEach ( function ( prop ) {
107
+ docMock [ prop ] = document_ [ prop ] ;
108
+ } ) ;
109
+ methodsToMock . forEach ( function ( method ) {
110
+ docMock [ method ] = document_ [ method ] . bind ( document_ ) ;
111
+ docSpies [ method ] = spyOn ( docMock , method ) . andCallThrough ( ) ;
112
+ } ) ;
113
+
114
+ docMock . dispatchFakeReadyStateChangeEvent = function ( ) {
115
+ var evt = document . createEvent ( 'Event' ) ;
116
+ evt . initEvent ( 'readystatechange' , false , false ) ;
117
+ document_ . dispatchEvent ( evt ) ;
118
+ $rootScope . $digest ( ) ;
119
+ } ;
120
+
121
+ $window . document = docMock ;
122
+ } ;
123
+ }
124
+
82
125
function resetAllSpies ( ) {
83
126
function resetSpy ( spy ) {
84
127
spy . reset ( ) ;
85
128
}
86
129
87
130
return function ( $window ) {
88
131
forEach ( elmSpy , resetSpy ) ;
132
+ forEach ( docSpies , resetSpy ) ;
89
133
forEach ( windowSpies , resetSpy ) ;
90
134
} ;
91
135
}
92
136
137
+ function updateMockReadyState ( newState ) {
138
+ return function ( $window ) {
139
+ $window . document . updateReadyState ( newState ) ;
140
+ } ;
141
+ }
142
+
93
143
94
144
beforeEach ( module ( function ( $provide ) {
95
145
elmSpy = { } ;
@@ -155,6 +205,61 @@ describe('$anchorScroll', function() {
155
205
expectScrollingTo ( 'id=top' ) ) ) ;
156
206
157
207
208
+ it ( 'should wait for `document.readyState === "complete"' , inject (
209
+ mockDocumentReadyState ( ) ,
210
+ addElements ( 'id=some1' ) ,
211
+
212
+ changeHashTo ( 'some1' ) ,
213
+ expectNoScrolling ( ) ,
214
+
215
+ updateMockReadyState ( 'some-arbitrary-state' ) ,
216
+ expectNoScrolling ( ) ,
217
+
218
+ updateMockReadyState ( 'complete' ) ,
219
+ expectScrollingTo ( 'id=some1' ) ) ) ;
220
+
221
+
222
+ it ( 'should only register one execution for when `document.readyState === "complete"' , inject (
223
+ mockDocumentReadyState ( ) ,
224
+ addElements ( 'id=some1' , 'id=some2' ) ,
225
+
226
+ changeHashTo ( 'some1' ) ,
227
+ changeHashTo ( 'some2' ) ,
228
+ updateMockReadyState ( 'some-other-arbitrary-state' ) ,
229
+ changeHashTo ( 'some1' ) ,
230
+ changeHashTo ( 'some2' ) ,
231
+ expectNoScrolling ( ) ,
232
+
233
+ updateMockReadyState ( 'complete' ) ,
234
+ expectScrollingTo ( 'id=some2' ) ) ) ;
235
+
236
+
237
+ it ( 'should properly register and unregister listeners for `readystatechange` event' , inject (
238
+ mockDocumentReadyState ( ) ,
239
+ addElements ( 'id=some1' , 'id=some2' ) ,
240
+
241
+ changeHashTo ( 'some1' ) ,
242
+ changeHashTo ( 'some2' ) ,
243
+ updateMockReadyState ( 'some-other-arbitrary-state' ) ,
244
+ changeHashTo ( 'some1' ) ,
245
+ changeHashTo ( 'some2' ) ,
246
+ updateMockReadyState ( 'complete' ) ,
247
+
248
+ function ( ) {
249
+ expect ( docSpies . addEventListener . callCount ) . toBe ( 1 ) ;
250
+ expect ( docSpies . addEventListener ) .
251
+ toHaveBeenCalledWith ( 'readystatechange' , jasmine . any ( Function ) ) ;
252
+
253
+ expect ( docSpies . removeEventListener . callCount ) . toBe ( 1 ) ;
254
+ expect ( docSpies . removeEventListener ) .
255
+ toHaveBeenCalledWith ( 'readystatechange' , jasmine . any ( Function ) ) ;
256
+
257
+ var registeredListener = docSpies . addEventListener . calls [ 0 ] . args [ 1 ] ;
258
+ var unregisteredListener = docSpies . removeEventListener . calls [ 0 ] . args [ 1 ] ;
259
+ expect ( unregisteredListener ) . toBe ( registeredListener ) ;
260
+ } ) ) ;
261
+
262
+
158
263
describe ( 'watcher' , function ( ) {
159
264
160
265
function initAnchorScroll ( ) {
@@ -270,7 +375,7 @@ describe('$anchorScroll', function() {
270
375
271
376
return function ( $window ) {
272
377
expectScrollingTo ( identifierCountMap ) ( $window ) ;
273
- expect ( $window . scrollBy . calls . length ) . toBe ( list . length ) ;
378
+ expect ( $window . scrollBy . callCount ) . toBe ( list . length ) ;
274
379
forEach ( list , function ( offset , idx ) {
275
380
// Due to sub-pixel rendering, there is a +/-1 error margin in the actual offset
276
381
var args = $window . scrollBy . calls [ idx ] . args ;
0 commit comments