1 | {MockWindow, MockDocument} = require('../lib/karen')
|
2 |
|
3 | describe 'MockWindow', ->
|
4 | def 'window', -> new MockWindow
|
5 |
|
6 | describe '#pageXOffset', ->
|
7 | it 'returns zero', ->
|
8 | @window.pageXOffset.should.equal(0)
|
9 |
|
10 | describe '#pageYOffset', ->
|
11 | it 'returns zero', ->
|
12 | @window.pageYOffset.should.equal(0)
|
13 |
|
14 | describe '#innerWidth', ->
|
15 | it 'returns width', ->
|
16 | @window.innerWidth.should.equal(1280)
|
17 |
|
18 | describe '#innerHeight', ->
|
19 | it 'returns height', ->
|
20 | @window.innerHeight.should.equal(1086)
|
21 |
|
22 | describe '#top', ->
|
23 | it 'is itself', ->
|
24 | @window.top.should.equal(@window)
|
25 |
|
26 | describe '#console', ->
|
27 | describe '#log', ->
|
28 | it 'emits console-log event', (done) ->
|
29 | @window.on 'console-log', (argument1, argument2) ->
|
30 | done() if argument1 == 'log-1' &&
|
31 | argument2 == 'log-2'
|
32 |
|
33 | @window.console.log('log-1', 'log-2')
|
34 |
|
35 | describe '#postMessage', ->
|
36 | it 'emits message event', ->
|
37 | origin = {}
|
38 | @window.on 'message', (event) ->
|
39 | event.data.should.equal('message')
|
40 | event.origin.should.equal(origin)
|
41 | event.source.should.be.an('object')
|
42 | @window.postMessage('message', origin)
|
43 |
|
44 | describe '#document', ->
|
45 | it 'is a MockDocument', ->
|
46 | @window.document.should.be.an('object')
|
47 |
|
48 | it 'returns same object every time', ->
|
49 | @window.document.should.equal(@window.document)
|
50 |
|
51 | describe '#location', ->
|
52 | it 'returns a MockLocation', ->
|
53 | @window.location.should.be.an('object')
|
54 |
|
55 | it 'returns same object every time', ->
|
56 | @window.location.should.equal(@window.location)
|
57 |
|
58 | describe '#screen', ->
|
59 | it 'returns a MockScreen', ->
|
60 | @window.screen.should.be.an('object')
|
61 |
|
62 | it 'returns same object every time', ->
|
63 | @window.screen.should.equal(@window.screen)
|
64 |
|
65 | describe '#navigator', ->
|
66 | it 'returns a MockNavigator', ->
|
67 | @window.navigator.should.be.an('object')
|
68 |
|
69 | it 'returns same object every time', ->
|
70 | @window.navigator.should.equal(@window.navigator)
|
71 |
|
72 | describe 'encodeURIComponent', ->
|
73 | it 'returns encoded string', ->
|
74 | @window.encodeURIComponent('foo/bar').should.equal('foo%2Fbar')
|
75 |
|
76 | describe 'decodeURIComponent', ->
|
77 | it 'returns decoded string', ->
|
78 | @window.decodeURIComponent('foo%2Fbar').should.equal('foo/bar')
|
79 |
|
80 | describe '#setTimeout', ->
|
81 | it 'runs callback after delay', (done) ->
|
82 | @window.setTimeout(done, 100)
|
83 | @window.tick(100)
|
84 |
|
85 | it 'does not run callback if delay has not passed', (done) ->
|
86 | @window.setTimeout ->
|
87 | done('should not callback function, but did')
|
88 | , 100
|
89 | @window.tick(99)
|
90 | done()
|
91 |
|
92 | it 'runs multiple callbacks', (done) ->
|
93 | count = 0
|
94 | doneCheck = ->
|
95 | done() if (++count) >= 3
|
96 | @window.setTimeout(doneCheck, 50)
|
97 | @window.setTimeout(doneCheck, 100)
|
98 | @window.setTimeout(doneCheck, 150)
|
99 | @window.tick(150)
|
100 |
|
101 | it 'does not run callback when ticking half before', (done) ->
|
102 | @window.tick(50)
|
103 | @window.setTimeout ->
|
104 | done('should not callback, but did')
|
105 | , 100
|
106 | @window.tick(50)
|
107 | done()
|
108 |
|
109 | it 'handles floats', (done) ->
|
110 | @window.setTimeout(done, 123.456)
|
111 | @window.setTimeout ->
|
112 | done('should not call this, but did')
|
113 | , 125
|
114 | @window.tick(123)
|
115 | @window.tick(1.999)
|
116 |
|
117 | it 'runs timeouts in correct order', (done) ->
|
118 | order = []
|
119 |
|
120 | @window.setTimeout =>
|
121 | order.push(1)
|
122 |
|
123 | @window.setTimeout ->
|
124 | order.push(2)
|
125 | , 100
|
126 | , 100
|
127 |
|
128 | @window.setTimeout ->
|
129 | order.push(3)
|
130 | , 300
|
131 |
|
132 | @window.tick 300, ->
|
133 | expect(order).to.eql([1, 2, 3])
|
134 | done()
|
135 |
|
136 | it 'supports nested timeouts', (done) ->
|
137 | @window.setTimeout =>
|
138 | @window.setTimeout(done, 100)
|
139 | , 100
|
140 | @window.tick(200)
|
141 |
|
142 | it 'is called async if callback', (done) ->
|
143 | called = false
|
144 | @window.setTimeout ->
|
145 | called = true
|
146 | done()
|
147 | , 100
|
148 | @window.tick 50, ->
|
149 | @window.tick 50, ->
|
150 | expect(called).to.be.false
|
151 |
|
152 | it 'is not called async unless callback', (done) ->
|
153 | called = false
|
154 | @window.setTimeout ->
|
155 | called = true
|
156 | done()
|
157 | , 100
|
158 | @window.tick(50)
|
159 | @window.tick(50)
|
160 | expect(called).to.be.true
|
161 |
|
162 | describe '#clearTimeout', ->
|
163 | it 'does nothing when given a non timeout object', ->
|
164 | @window.clearTimeout({})
|
165 |
|
166 | it 'does not run timeout if cleared', (done) ->
|
167 | timeout = @window.setTimeout ->
|
168 | done('should not callback, but did')
|
169 | , 100
|
170 | @window.clearTimeout(timeout)
|
171 | @window.tick(100)
|
172 | done()
|
173 |
|
174 | describe '#setInterval', ->
|
175 | it 'runs callback after delay', (done) ->
|
176 | @window.setInterval(done, 100)
|
177 | @window.tick(100)
|
178 |
|
179 | it 'runs callback after every delay', (done) ->
|
180 | count = 0
|
181 | doneCheck = -> done() if (++count) >= 3
|
182 | @window.setInterval(doneCheck, 100)
|
183 | @window.tick(300)
|
184 |
|
185 | it 'does not run callback if delay has not passed', (done) ->
|
186 | @window.setInterval ->
|
187 | done('should not callback function, but did')
|
188 | , 100
|
189 | @window.tick(99)
|
190 | done()
|
191 |
|
192 | it 'runs multiple callbacks', (done) ->
|
193 | count = 0
|
194 | doneCheck = ->
|
195 | done() if (++count) >= 3
|
196 | @window.setInterval(doneCheck, 50)
|
197 | @window.setInterval(doneCheck, 100)
|
198 | @window.tick(100)
|
199 |
|
200 | it 'does not run callback when ticking half before', (done) ->
|
201 | @window.tick(50)
|
202 | @window.setInterval ->
|
203 | done('should not callback, but did')
|
204 | , 100
|
205 | @window.tick(50)
|
206 | done()
|
207 |
|
208 | it 'handles floats', (done) ->
|
209 | count = 0
|
210 | doneCheck = -> done() if (++count) >= 2
|
211 | @window.setInterval(doneCheck, 123.456)
|
212 | @window.setInterval ->
|
213 | done('should not call this, but did')
|
214 | , 249
|
215 | @window.tick(247)
|
216 | @window.tick(1.999)
|
217 |
|
218 | it 'runs intervals in correct order', (done) ->
|
219 | order = []
|
220 |
|
221 | @window.setInterval =>
|
222 | order.push(1)
|
223 |
|
224 | @window.setInterval ->
|
225 | order.push(2)
|
226 | , 100
|
227 | , 100
|
228 |
|
229 | @window.setInterval ->
|
230 | order.push(3)
|
231 | , 300
|
232 |
|
233 | @window.tick 300, ->
|
234 | expect(order).to.eql([1, 1, 2, 1, 3, 2, 2])
|
235 | done()
|
236 |
|
237 | it 'supports nested intervals', (done) ->
|
238 | @window.setInterval =>
|
239 | @window.setInterval(done, 100)
|
240 | , 100
|
241 | @window.tick(200)
|
242 |
|
243 | describe '#clearInterval', ->
|
244 | it 'does nothing when given a non timeout object', ->
|
245 | @window.clearInterval({})
|
246 |
|
247 | it 'does not run interval once cleared', (done) ->
|
248 | count = 0
|
249 | doneCheck = -> done() if (++count) >= 2
|
250 | interval = @window.setInterval(doneCheck, 100)
|
251 | @window.tick(100)
|
252 | @window.tick(100)
|
253 | @window.clearInterval(interval)
|
254 | @window.tick(100)
|
255 |
|
256 | describe '#tick', ->
|
257 | it 'callbacks when done', (done) ->
|
258 | aDone = false
|
259 | bDone = false
|
260 | cDone = false
|
261 |
|
262 | @window.setTimeout ->
|
263 | aDone = true
|
264 | , 100
|
265 |
|
266 | @window.setTimeout ->
|
267 | bDone = true
|
268 | , 200
|
269 |
|
270 | @window.setTimeout ->
|
271 | cDone = true
|
272 | , 300
|
273 |
|
274 | @window.tick 300, ->
|
275 | done() if aDone && bDone && cDone
|
276 |
|
277 | it 'adds tick ms to current time', ->
|
278 | before = (new @window.Date).getTime()
|
279 | @window.tick(100)
|
280 | after = (new @window.Date).getTime()
|
281 | (after - before).should.equal(100)
|
282 |
|
283 | it 'has correct time in callback', ->
|
284 | D = @window.Date
|
285 | orig = (new D).getTime()
|
286 | @window.tick 3, ->
|
287 | (new D().getTime() - orig).should.equal(3)
|
288 |
|
289 | it 'does not modify clock when ticking zero', ->
|
290 | orig = new @window.Date().getTime()
|
291 | @window.tick(0)
|
292 | (new @window.Date().getTime()).should.equal(orig)
|
293 |
|
294 | it 'has a valid clock each time', ->
|
295 | D = @window.Date
|
296 |
|
297 | orig = (new @window.Date).getTime()
|
298 |
|
299 | @window.setTimeout ->
|
300 | now = (new D).getTime()
|
301 | (now - orig).should.equal(100)
|
302 | , 100
|
303 |
|
304 | count = 0
|
305 |
|
306 | @window.setInterval ->
|
307 | now = (new D).getTime()
|
308 | switch ++count
|
309 | when 1 then (now - orig).should.equal(100)
|
310 | when 2 then (now - orig).should.equal(200)
|
311 | , 100
|
312 |
|
313 | @window.tick(200)
|
314 |
|
315 | describe '#tickAsync', ->
|
316 | it 'is called async', (done) ->
|
317 | called = false
|
318 | @window.setTimeout ->
|
319 | called = true
|
320 | done()
|
321 | , 100
|
322 | @window.tickAsync(50)
|
323 | @window.tickAsync(50)
|
324 | expect(called).to.be.false
|
325 |
|
326 | it 'calls callback function', (done) ->
|
327 | fn = ->
|
328 | @window.setTimeout(fn, 100)
|
329 | @window.tickAsync(50, done)
|
330 |
|
331 | describe '#setImmediate', ->
|
332 | it 'callbacks', (done) ->
|
333 | @window.setImmediate (foo, bar) ->
|
334 | expect(foo).to.equal('foo')
|
335 | expect(bar).to.equal('bar')
|
336 | done()
|
337 | , 'foo', 'bar'
|
338 |
|
339 | describe '#scrollTo', ->
|
340 | it 'updates viewport positions', ->
|
341 | @window.pageXOffset = 0
|
342 | @window.pageYOffset = 0
|
343 | @window.document.documentElement.scrollLeft = 0
|
344 | @window.document.documentElement.scrollTop = 0
|
345 | @window.document.body.scrollLeft = 0
|
346 | @window.document.body.scrollTop = 0
|
347 | @window.scrollTo(100, 200)
|
348 | expect(@window.pageXOffset).to.equal(100)
|
349 | expect(@window.pageYOffset).to.equal(200)
|
350 | expect(@window.document.documentElement.scrollLeft).to.equal(100)
|
351 | expect(@window.document.documentElement.scrollTop).to.equal(200)
|
352 | expect(@window.document.body.scrollLeft).to.equal(100)
|
353 | expect(@window.document.body.scrollTop).to.equal(200)
|
354 |
|
355 | it 'fires scroll event', (done) ->
|
356 | @window.on 'scroll', (event) =>
|
357 | expect(event.type).to.equal('scroll')
|
358 | expect(@window.pageXOffset).to.equal(100)
|
359 | expect(@window.pageYOffset).to.equal(200)
|
360 | done()
|
361 | @window.scrollTo(100, 200)
|
362 |
|