OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 * THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 (function () { | |
27 | |
28 module("base"); | |
29 | |
30 test("bind", 3, function() { | |
31 function func(a, b) { | |
32 equals(this.prop, 5); | |
33 equals(a, "banana"); | |
34 deepEqual(b, [2, 3, 4]); | |
35 } | |
36 | |
37 var thisObject = { | |
38 "prop": 5 | |
39 }; | |
40 | |
41 var bound = func.bind(thisObject, "banana"); | |
42 bound([2, 3, 4]); | |
43 }); | |
44 | |
45 | |
46 test("joinPath", 1, function() { | |
47 var value = base.joinPath("path/to", "test.html"); | |
48 equals(value, "path/to/test.html"); | |
49 }); | |
50 | |
51 test("endsWith", 9, function() { | |
52 ok(base.endsWith("xyz", "")); | |
53 ok(base.endsWith("xyz", "z")); | |
54 ok(base.endsWith("xyz", "yz")); | |
55 ok(base.endsWith("xyz", "xyz")); | |
56 ok(!base.endsWith("xyz", "wxyz")); | |
57 ok(!base.endsWith("xyz", "gwxyz")); | |
58 ok(base.endsWith("", "")); | |
59 ok(!base.endsWith("", "z")); | |
60 ok(!base.endsWith("xyxy", "yx")); | |
61 }); | |
62 | |
63 test("trimExtension", 6, function() { | |
64 equals(base.trimExtension("xyz"), "xyz"); | |
65 equals(base.trimExtension("xy.z"), "xy"); | |
66 equals(base.trimExtension("x.yz"), "x"); | |
67 equals(base.trimExtension("x.y.z"), "x.y"); | |
68 equals(base.trimExtension(".xyz"), ""); | |
69 equals(base.trimExtension(""), ""); | |
70 }); | |
71 | |
72 test("joinPath with empty parent", 1, function() { | |
73 var value = base.joinPath("", "test.html"); | |
74 equals(value, "test.html"); | |
75 }); | |
76 | |
77 test("dirName", 3, function() { | |
78 equals(base.dirName("foo.html"), "foo.html"); | |
79 equals(base.dirName("foo/bar.html"), "foo"); | |
80 equals(base.dirName("foo/bar/baz.html"), "foo/bar"); | |
81 }); | |
82 | |
83 test("uniquifyArray", 5, function() { | |
84 deepEqual(base.uniquifyArray([]), []); | |
85 deepEqual(base.uniquifyArray(["a"]), ["a"]); | |
86 deepEqual(base.uniquifyArray(["a", "b"]), ["a", "b"]); | |
87 deepEqual(base.uniquifyArray(["a", "b", "b"]), ["a", "b"]); | |
88 deepEqual(base.uniquifyArray(["a", "b", "b", "a"]), ["a", "b"]); | |
89 }); | |
90 | |
91 test("flattenArray", 5, function() { | |
92 deepEqual(base.flattenArray([]), []); | |
93 deepEqual(base.flattenArray([["a"]]), ["a"]); | |
94 deepEqual(base.flattenArray([["a"], ["b"]]), ["a", "b"]); | |
95 deepEqual(base.flattenArray([["a"], ["b", "c"]]), ["a", "b", "c"]); | |
96 deepEqual(base.flattenArray([["a"], [], ["b"]]), ["a", "b"]); | |
97 }); | |
98 | |
99 test("callInParallel", 4, function() { | |
100 var expectedCall = [true, true, true]; | |
101 var expectCompletionCallback = true; | |
102 | |
103 base.callInParallel([ | |
104 function(callback) { | |
105 ok(expectedCall[0]); | |
106 expectedCall[0] = false; | |
107 callback(); | |
108 }, | |
109 function(callback) { | |
110 ok(expectedCall[1]); | |
111 expectedCall[1] = false; | |
112 callback(); | |
113 }, | |
114 function(callback) { | |
115 ok(expectedCall[2]); | |
116 expectedCall[2] = false; | |
117 callback(); | |
118 }, | |
119 ], function() { | |
120 ok(expectCompletionCallback); | |
121 expectCompletionCallback = false; | |
122 }) | |
123 }); | |
124 | |
125 test("callInSequence", 7, function() { | |
126 var expectedArg = 42; | |
127 var expectCompletionCallback = true; | |
128 | |
129 base.callInSequence(function(arg, callback) { | |
130 ok(arg < 45); | |
131 equals(arg, expectedArg++); | |
132 callback(); | |
133 }, [42, 43, 44], function() { | |
134 ok(expectCompletionCallback); | |
135 expectCompletionCallback = false; | |
136 }) | |
137 }); | |
138 | |
139 test("RequestTracker", 5, function() { | |
140 var ready = false; | |
141 var tracker = new base.RequestTracker(1, function() { | |
142 ok(ready); | |
143 }); | |
144 ready = true; | |
145 tracker.requestComplete(); | |
146 ready = false; | |
147 | |
148 tracker = new base.RequestTracker(2, function(parameter) { | |
149 ok(ready); | |
150 equals(parameter, 'argument'); | |
151 }, ['argument']); | |
152 tracker.requestComplete(); | |
153 ready = true; | |
154 tracker.requestComplete(); | |
155 ready = false; | |
156 | |
157 tracker = new base.RequestTracker(0, function() { | |
158 ok(true); | |
159 }); | |
160 tracker.requestComplete(); | |
161 | |
162 tracker = new base.RequestTracker(0); | |
163 tracker.requestComplete(); | |
164 // Should not barf. | |
165 ok(true); | |
166 }); | |
167 | |
168 test("CallbackIterator", 22, function() { | |
169 var expected = 0; | |
170 var iterator = new base.CallbackIterator(function(a, b) { | |
171 equals(a, 'ArgA' + expected); | |
172 equals(b, 'ArgB' + expected); | |
173 ++expected; | |
174 }, [ | |
175 ['ArgA0', 'ArgB0'], | |
176 ['ArgA1', 'ArgB1'], | |
177 ['ArgA2', 'ArgB2'], | |
178 ]); | |
179 ok(iterator.hasNext()) | |
180 ok(!iterator.hasPrevious()) | |
181 iterator.callNext(); | |
182 ok(iterator.hasNext()) | |
183 ok(!iterator.hasPrevious()) | |
184 iterator.callNext(); | |
185 ok(iterator.hasNext()) | |
186 ok(iterator.hasPrevious()) | |
187 iterator.callNext(); | |
188 ok(!iterator.hasNext()) | |
189 ok(iterator.hasPrevious()) | |
190 expected = 1; | |
191 iterator.callPrevious(); | |
192 ok(iterator.hasNext()) | |
193 ok(iterator.hasPrevious()) | |
194 expected = 0; | |
195 iterator.callPrevious(); | |
196 ok(iterator.hasNext()) | |
197 ok(!iterator.hasPrevious()) | |
198 }); | |
199 | |
200 test("filterDictionary", 3, function() { | |
201 var dictionary = { | |
202 'foo': 43, | |
203 'bar': 11 | |
204 }; | |
205 deepEqual(base.filterDictionary(dictionary, function() { return true; }), { | |
206 "foo": 43, | |
207 "bar": 11 | |
208 }); | |
209 deepEqual(base.filterDictionary(dictionary, function() { return false; }), {
}); | |
210 deepEqual(base.filterDictionary(dictionary, function(key) { return key == 'f
oo'; }), { | |
211 "foo": 43 | |
212 }); | |
213 }); | |
214 | |
215 test("mapDictionary", 3, function() { | |
216 deepEqual(base.mapDictionary({}, function(value) { return value - 10; }), {}
); | |
217 var dictionary = { | |
218 'foo': 43, | |
219 'bar': 11 | |
220 }; | |
221 deepEqual(base.mapDictionary(dictionary, function(value) { return value - 10
; }), { | |
222 "foo": 33, | |
223 "bar": 1 | |
224 }); | |
225 deepEqual(base.mapDictionary(dictionary, function(value) { | |
226 if (value > 20) | |
227 return value - 20; | |
228 }), { | |
229 "foo": 23, | |
230 }); | |
231 }); | |
232 | |
233 test("filterTree", 2, function() { | |
234 var tree = { | |
235 'path': { | |
236 'to': { | |
237 'test.html': { | |
238 'actual': 'PASS', | |
239 'expected': 'FAIL' | |
240 } | |
241 }, | |
242 'another.html': { | |
243 'actual': 'TEXT', | |
244 'expected': 'PASS' | |
245 } | |
246 } | |
247 } | |
248 | |
249 function isLeaf(node) | |
250 { | |
251 return !!node.actual; | |
252 } | |
253 | |
254 function actualIsText(node) | |
255 { | |
256 return node.actual == 'TEXT'; | |
257 } | |
258 | |
259 var all = base.filterTree(tree, isLeaf, function() { return true }); | |
260 deepEqual(all, { | |
261 'path/to/test.html': { | |
262 'actual': 'PASS', | |
263 'expected': 'FAIL' | |
264 }, | |
265 'path/another.html': { | |
266 'actual': 'TEXT', | |
267 'expected': 'PASS' | |
268 } | |
269 }); | |
270 | |
271 var text = base.filterTree(tree, isLeaf, actualIsText); | |
272 deepEqual(text, { | |
273 'path/another.html': { | |
274 'actual': 'TEXT', | |
275 'expected': 'PASS' | |
276 } | |
277 }); | |
278 }); | |
279 | |
280 test("UpdateTracker", 20, function() { | |
281 var dict; | |
282 | |
283 function dumpKeys() | |
284 { | |
285 var updates = [] | |
286 dict.forEach(function(item, key, updated) { | |
287 updates.push(key); | |
288 }); | |
289 return updates; | |
290 } | |
291 | |
292 function dumpUpdatedKeys() | |
293 { | |
294 var updates = [] | |
295 dict.forEach(function(item, key, updated) { | |
296 updated && updates.push(key); | |
297 }); | |
298 return updates; | |
299 } | |
300 | |
301 | |
302 dict = new base.UpdateTracker(); | |
303 dict.update("5", {}); | |
304 deepEqual(dumpUpdatedKeys(), ["5"]); | |
305 dict.update("6", {}); | |
306 dict.update("7", {}); | |
307 deepEqual(dumpUpdatedKeys(), ["5", "6", "7"]); | |
308 deepEqual(dict.get("6"), {}); | |
309 ok(dict.exists("7")); | |
310 dict.purge(); | |
311 deepEqual(dumpUpdatedKeys(), []); | |
312 deepEqual(dumpKeys(), ["5", "6", "7"]); | |
313 dict.update("5", {}); | |
314 deepEqual(dumpUpdatedKeys(), ["5"]); | |
315 dict.update("4", {}); | |
316 deepEqual(dumpUpdatedKeys(), ["4", "5"]); | |
317 deepEqual(dumpKeys(), ["4", "5", "6", "7"]); | |
318 dict.purge(); | |
319 deepEqual(dumpKeys(), ["4", "5"]); | |
320 deepEqual(dumpUpdatedKeys(), []); | |
321 dict.purge(); | |
322 deepEqual(dumpKeys(), []); | |
323 | |
324 var removeCount = 0; | |
325 dict.update("one"); | |
326 deepEqual(dumpUpdatedKeys(), ["one"]); | |
327 dict.update("two"); | |
328 deepEqual(dumpUpdatedKeys(), ["one", "two"]); | |
329 dict.update("three"); | |
330 dict.purge(); | |
331 deepEqual(dumpKeys(), ["one", "three", "two"]); | |
332 dict.update("two"); | |
333 dict.purge(function() { | |
334 removeCount++; | |
335 }); | |
336 deepEqual(dumpKeys(), ["two"]); | |
337 equal(removeCount, 2); | |
338 dict.update("four"); | |
339 var removeCounter = { count: 0 }; | |
340 dict.purge(function() { | |
341 this.count++; | |
342 }, removeCounter); | |
343 equal(removeCounter.count, 1); | |
344 dict.purge(function() { | |
345 equal(String(this), "four"); | |
346 }); | |
347 | |
348 dict = new base.UpdateTracker(); | |
349 dict.update("one"); | |
350 var thisObject = {} | |
351 dict.forEach(function(item) { | |
352 equal(this, thisObject); | |
353 }, thisObject); | |
354 | |
355 }); | |
356 | |
357 test("extends", 14, function() { | |
358 | |
359 var LikeDiv = base.extends("div", { | |
360 init: function() { | |
361 this.textContent = "awesome"; | |
362 }, | |
363 method: function(msg) { | |
364 return 42; | |
365 } | |
366 }); | |
367 | |
368 var LikeLikeDiv = base.extends(LikeDiv, { | |
369 init: function() { | |
370 this.className = "like"; | |
371 } | |
372 }); | |
373 | |
374 var LikeP = base.extends("p", { | |
375 init: function(content) { | |
376 this.textContent = content | |
377 } | |
378 }); | |
379 | |
380 var LikeProgress = base.extends("progress", { | |
381 init: function() { | |
382 this.max = 100; | |
383 this.value = 10; | |
384 } | |
385 }); | |
386 | |
387 var LikeLikeProgress = base.extends(LikeProgress, { | |
388 completed: function() { | |
389 this.value = 100; | |
390 } | |
391 }); | |
392 | |
393 document.body.appendChild(new LikeDiv()); | |
394 equals(document.body.lastChild.tagName, "DIV"); | |
395 equals(document.body.lastChild.innerHTML, "awesome"); | |
396 equals(document.body.lastChild.method(), 42); | |
397 document.body.removeChild(document.body.lastChild); | |
398 | |
399 document.body.appendChild(new LikeLikeDiv()); | |
400 equals(document.body.lastChild.tagName, "DIV"); | |
401 equals(document.body.lastChild.innerHTML, "awesome"); | |
402 equals(document.body.lastChild.method(), 42); | |
403 equals(document.body.lastChild.className, "like"); | |
404 document.body.removeChild(document.body.lastChild); | |
405 | |
406 document.body.appendChild(new LikeP("super")); | |
407 equals(document.body.lastChild.tagName, "P"); | |
408 equals(document.body.lastChild.innerHTML, "super"); | |
409 raises(function() { | |
410 document.body.lastChild.method(); | |
411 }); | |
412 document.body.removeChild(document.body.lastChild); | |
413 | |
414 document.body.appendChild(new LikeProgress()); | |
415 equals(document.body.lastChild.tagName, "PROGRESS"); | |
416 // Safari 5.1 lacks the <progress> element. | |
417 // equals(document.body.lastChild.position, 0.1); | |
418 equals(document.body.lastChild.innerHTML, ""); | |
419 raises(function() { | |
420 document.body.lastChild.method(); | |
421 }); | |
422 document.body.removeChild(document.body.lastChild); | |
423 | |
424 document.body.appendChild(new LikeLikeProgress()); | |
425 equals(document.body.lastChild.tagName, "PROGRESS"); | |
426 // Safari 5.1 lacks the <progress> element. | |
427 // equals(document.body.lastChild.position, 0.1); | |
428 document.body.lastChild.completed(); | |
429 // Safari 5.1 lacks the <progress> element. | |
430 // equals(document.body.lastChild.position, 1); | |
431 document.body.removeChild(document.body.lastChild); | |
432 }); | |
433 | |
434 test("relativizeTime", 14, function() { | |
435 var time = new Date(); | |
436 equals(base.relativizeTime(time), "Just now"); | |
437 time.setMinutes(time.getMinutes() - 1); | |
438 equals(base.relativizeTime(time), "1 minute ago"); | |
439 time.setMinutes(time.getMinutes() - 1); | |
440 equals(base.relativizeTime(time), "2 minutes ago"); | |
441 time.setMinutes(time.getMinutes() - 1); | |
442 equals(base.relativizeTime(time), "3 minutes ago"); | |
443 time.setMinutes(time.getMinutes() - 56); | |
444 equals(base.relativizeTime(time), "59 minutes ago"); | |
445 time.setMinutes(time.getMinutes() - 1); | |
446 equals(base.relativizeTime(time), "1 hour ago"); | |
447 time.setMinutes(time.getMinutes() - 29); | |
448 equals(base.relativizeTime(time), "1 hour ago"); | |
449 time.setMinutes(time.getMinutes() - 2); | |
450 equals(base.relativizeTime(time), "2 hours ago"); | |
451 time.setMinutes(time.getMinutes() - 29); | |
452 equals(base.relativizeTime(time), "2 hours ago"); | |
453 time.setHours(time.getHours() - 1); | |
454 equals(base.relativizeTime(time), "3 hours ago"); | |
455 time.setHours(time.getHours() - 20); | |
456 equals(base.relativizeTime(time), "23 hours ago"); | |
457 time.setHours(time.getHours() - 1); | |
458 equals(base.relativizeTime(time), "1 day ago"); | |
459 time.setDate(time.getDate() - 1); | |
460 equals(base.relativizeTime(time), "2 days ago"); | |
461 time.setDate(time.getDate() - 998); | |
462 equals(base.relativizeTime(time), "1000 days ago"); | |
463 }); | |
464 | |
465 test("getURLParameter", 1, function() { | |
466 ok(!base.getURLParameter('non-existant')); | |
467 }); | |
468 | |
469 test("parseJSONP", 2, function() { | |
470 deepEqual(base.parseJSONP(""), {}); | |
471 deepEqual(base.parseJSONP('p({"key": "value"})'), {"key": "value"}); | |
472 }); | |
473 | |
474 })(); | |
OLD | NEW |