OLD | NEW |
| (Empty) |
1 <script> | |
2 var isJsTest = true; | |
3 | |
4 var description, debug, successfullyParsed; | |
5 | |
6 var expectingError; // set by shouldHaveError() | |
7 var expectedErrorMessage; // set by onerror when expectingError is true | |
8 var unexpectedErrorMessage; // set by onerror when expectingError is not true | |
9 | |
10 (function() { | |
11 function body() { | |
12 var documentElement = document.documentElement; | |
13 for (var child = documentElement.firstChild; child; child = child.nextSi
bling) { | |
14 if (child.tagName == 'BODY') | |
15 return child; | |
16 } | |
17 return documentElement; | |
18 } | |
19 | |
20 function getOrCreate(id, tagName) { | |
21 var element = document.getElementById(id); | |
22 if (element) | |
23 return element; | |
24 | |
25 element = document.createElement(tagName); | |
26 element.id = id; | |
27 var refNode; | |
28 var parent = body(); | |
29 if (id == "description") | |
30 refNode = getOrCreate("console", "div"); | |
31 else | |
32 refNode = parent.firstChild; | |
33 | |
34 parent.insertBefore(element, refNode); | |
35 return element; | |
36 } | |
37 | |
38 description = function description(msg) { | |
39 var description = getOrCreate("description", "div"); | |
40 description.textContent = msg; | |
41 }; | |
42 | |
43 debug = function debug(msg) { | |
44 var div = document.createElement("div"); | |
45 getOrCreate("console", "div").appendChild(div); | |
46 div.textContent = msg; | |
47 }; | |
48 | |
49 if (!self.isOnErrorTest) { | |
50 self.onerror = function(message) { | |
51 if (self.expectingError) { | |
52 self.expectedErrorMessage = message; | |
53 self.expectingError = false; | |
54 return; | |
55 } | |
56 self.unexpectedErrorMessage = message; | |
57 if (self.jsTestIsAsync) { | |
58 self.testFailed("Unexpected error: " + message); | |
59 finishJSTest(); | |
60 } | |
61 }; | |
62 } | |
63 })(); | |
64 | |
65 function testPassed(msg) | |
66 { | |
67 debug('PASS: ' + msg); | |
68 } | |
69 | |
70 function testFailed(msg) | |
71 { | |
72 debug('FAIL: ' + msg); | |
73 } | |
74 | |
75 function areArraysEqual(a, b) | |
76 { | |
77 try { | |
78 if (a.length !== b.length) | |
79 return false; | |
80 for (var i = 0; i < a.length; i++) | |
81 if (a[i] !== b[i]) | |
82 return false; | |
83 } catch (ex) { | |
84 return false; | |
85 } | |
86 return true; | |
87 } | |
88 | |
89 function isMinusZero(n) | |
90 { | |
91 // the only way to tell 0 from -0 in JS is the fact that 1/-0 is | |
92 // -Infinity instead of Infinity | |
93 return n === 0 && 1/n < 0; | |
94 } | |
95 | |
96 function isResultCorrect(actual, expected) | |
97 { | |
98 if (expected === 0) | |
99 return actual === expected && (1/actual) === (1/expected); | |
100 if (actual === expected) | |
101 return true; | |
102 if (typeof(expected) == "number" && isNaN(expected)) | |
103 return typeof(actual) == "number" && isNaN(actual); | |
104 if (expected && (Object.prototype.toString.call(expected) == Object.prototyp
e.toString.call([]))) | |
105 return areArraysEqual(actual, expected); | |
106 return false; | |
107 } | |
108 | |
109 function stringify(v) | |
110 { | |
111 if (v === 0 && 1/v < 0) | |
112 return "-0"; | |
113 else return "" + v; | |
114 } | |
115 | |
116 function evalAndLog(_a, _quiet) | |
117 { | |
118 if (typeof _a != "string") | |
119 debug("WARN: tryAndLog() expects a string argument"); | |
120 | |
121 // Log first in case things go horribly wrong or this causes a sync event. | |
122 if (!_quiet) | |
123 debug(_a); | |
124 | |
125 var _av; | |
126 try { | |
127 _av = eval(_a); | |
128 } catch (e) { | |
129 testFailed(_a + " threw exception " + e); | |
130 } | |
131 return _av; | |
132 } | |
133 | |
134 function shouldBe(_a, _b, quiet, opt_tolerance) | |
135 { | |
136 if (typeof _a != "string" || typeof _b != "string") | |
137 debug("WARN: shouldBe() expects string arguments"); | |
138 var _exception; | |
139 var _av; | |
140 try { | |
141 _av = eval(_a); | |
142 } catch (e) { | |
143 _exception = e; | |
144 } | |
145 var _bv = eval(_b); | |
146 | |
147 if (_exception) | |
148 testFailed(_a + " should be " + _bv + ". Threw exception " + _exception); | |
149 else if (isResultCorrect(_av, _bv) || (typeof opt_tolerance == 'number' && typ
eof _av == 'number' && Math.abs(_av - _bv) <= opt_tolerance)) { | |
150 if (!quiet) { | |
151 testPassed(_a + " is " + _b); | |
152 } | |
153 } else if (typeof(_av) == typeof(_bv)) | |
154 testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + "."); | |
155 else | |
156 testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was "
+ _av + " (of type " + typeof _av + ")."); | |
157 } | |
158 | |
159 // Execute condition every 5 milliseconds until it succeed or failureTime is rea
ched. | |
160 // completionHandler is executed on success, failureHandler is executed on timeo
ut. | |
161 function _waitForCondition(condition, failureTime, completionHandler, failureHan
dler) | |
162 { | |
163 if (condition()) { | |
164 completionHandler(); | |
165 } else if (Date.now() > failureTime) { | |
166 failureHandler(); | |
167 } else { | |
168 setTimeout(_waitForCondition, 5, condition, failureTime, completionHandler,
failureHandler); | |
169 } | |
170 } | |
171 | |
172 function shouldBecomeEqual(_a, _b, _completionHandler, _timeout) | |
173 { | |
174 if (typeof _a != "string" || typeof _b != "string") | |
175 debug("WARN: shouldBecomeEqual() expects string arguments"); | |
176 | |
177 if (_timeout === undefined) | |
178 _timeout = 500; | |
179 | |
180 var _bv; | |
181 var _condition = function() { | |
182 var _exception; | |
183 var _av; | |
184 try { | |
185 _av = eval(_a); | |
186 } catch (e) { | |
187 _exception = e; | |
188 } | |
189 _bv = eval(_b); | |
190 if (_exception) | |
191 testFailed(_a + " should become " + _bv + ". Threw exception " + _exceptio
n); | |
192 if (isResultCorrect(_av, _bv)) { | |
193 testPassed(_a + " became " + _b); | |
194 return true; | |
195 } | |
196 return false; | |
197 }; | |
198 var _failureTime = Date.now() + _timeout; | |
199 var _failureHandler = function () { | |
200 testFailed(_a + " failed to change to " + _bv + " in " + (_timeout / 1000) +
" seconds."); | |
201 _completionHandler(); | |
202 }; | |
203 _waitForCondition(_condition, _failureTime, _completionHandler, _failureHandle
r); | |
204 } | |
205 | |
206 function shouldBecomeEqualToString(value, reference, completionHandler, timeout) | |
207 { | |
208 if (typeof value !== "string" || typeof reference !== "string") | |
209 debug("WARN: shouldBecomeEqualToString() expects string arguments"); | |
210 var unevaledString = JSON.stringify(reference); | |
211 shouldBecomeEqual(value, unevaledString, completionHandler, timeout); | |
212 } | |
213 | |
214 function shouldBeType(_a, _type) { | |
215 var _exception; | |
216 var _av; | |
217 try { | |
218 _av = eval(_a); | |
219 } catch (e) { | |
220 _exception = e; | |
221 } | |
222 | |
223 var _typev = eval(_type); | |
224 if (_av instanceof _typev) { | |
225 testPassed(_a + " is an instance of " + _type); | |
226 } else { | |
227 testFailed(_a + " is not an instance of " + _type); | |
228 } | |
229 } | |
230 | |
231 // Variant of shouldBe()--confirms that result of eval(_to_eval) is within | |
232 // numeric _tolerance of numeric _target. | |
233 function shouldBeCloseTo(_to_eval, _target, _tolerance, _quiet) | |
234 { | |
235 if (typeof _to_eval != "string") { | |
236 testFailed("shouldBeCloseTo() requires string argument _to_eval. was type "
+ typeof _to_eval); | |
237 return; | |
238 } | |
239 if (typeof _target != "number") { | |
240 testFailed("shouldBeCloseTo() requires numeric argument _target. was type "
+ typeof _target); | |
241 return; | |
242 } | |
243 if (typeof _tolerance != "number") { | |
244 testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type
" + typeof _tolerance); | |
245 return; | |
246 } | |
247 | |
248 var _result; | |
249 try { | |
250 _result = eval(_to_eval); | |
251 } catch (e) { | |
252 testFailed(_to_eval + " should be within " + _tolerance + " of " | |
253 + _target + ". Threw exception " + e); | |
254 return; | |
255 } | |
256 | |
257 if (typeof(_result) != typeof(_target)) { | |
258 testFailed(_to_eval + " should be of type " + typeof _target | |
259 + " but was of type " + typeof _result); | |
260 } else if (Math.abs(_result - _target) <= _tolerance) { | |
261 if (!_quiet) { | |
262 testPassed(_to_eval + " is within " + _tolerance + " of " + _target); | |
263 } | |
264 } else { | |
265 testFailed(_to_eval + " should be within " + _tolerance + " of " + _target | |
266 + ". Was " + _result + "."); | |
267 } | |
268 } | |
269 | |
270 function shouldNotBe(_a, _b, _quiet) | |
271 { | |
272 if (typeof _a != "string" || typeof _b != "string") | |
273 debug("WARN: shouldNotBe() expects string arguments"); | |
274 var _exception; | |
275 var _av; | |
276 try { | |
277 _av = eval(_a); | |
278 } catch (e) { | |
279 _exception = e; | |
280 } | |
281 var _bv = eval(_b); | |
282 | |
283 if (_exception) | |
284 testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception)
; | |
285 else if (!isResultCorrect(_av, _bv)) { | |
286 if (!_quiet) { | |
287 testPassed(_a + " is not " + _b); | |
288 } | |
289 } else | |
290 testFailed(_a + " should not be " + _bv + "."); | |
291 } | |
292 | |
293 function shouldBecomeDifferent(_a, _b, _completionHandler, _timeout) | |
294 { | |
295 if (typeof _a != "string" || typeof _b != "string") | |
296 debug("WARN: shouldBecomeDifferent() expects string arguments"); | |
297 if (_timeout === undefined) | |
298 _timeout = 500; | |
299 | |
300 var _bv; | |
301 var _condition = function() { | |
302 var _exception; | |
303 var _av; | |
304 try { | |
305 _av = eval(_a); | |
306 } catch (e) { | |
307 _exception = e; | |
308 } | |
309 _bv = eval(_b); | |
310 if (_exception) | |
311 testFailed(_a + " should became not equal to " + _bv + ". Threw exception
" + _exception); | |
312 if (!isResultCorrect(_av, _bv)) { | |
313 testPassed(_a + " became different from " + _b); | |
314 return true; | |
315 } | |
316 return false; | |
317 }; | |
318 var _failureTime = Date.now() + _timeout; | |
319 var _failureHandler = function () { | |
320 testFailed(_a + " did not become different from " + _bv + " in " + (_timeout
/ 1000) + " seconds."); | |
321 _completionHandler(); | |
322 }; | |
323 _waitForCondition(_condition, _failureTime, _completionHandler, _failureHandle
r); | |
324 } | |
325 | |
326 function shouldBeTrue(a, quiet) { shouldBe(a, "true", quiet); } | |
327 function shouldBeTrueQuiet(a) { shouldBe(a, "true", true); } | |
328 function shouldBeFalse(a, quiet) { shouldBe(a, "false", quiet); } | |
329 function shouldBeNaN(a, quiet) { shouldBe(a, "NaN", quiet); } | |
330 function shouldBeNull(a, quiet) { shouldBe(a, "null", quiet); } | |
331 function shouldBeZero(a, quiet) { shouldBe(a, "0", quiet); } | |
332 | |
333 function shouldBeEqualToString(a, b) | |
334 { | |
335 if (typeof a !== "string" || typeof b !== "string") | |
336 debug("WARN: shouldBeEqualToString() expects string arguments"); | |
337 var unevaledString = JSON.stringify(b); | |
338 shouldBe(a, unevaledString); | |
339 } | |
340 | |
341 function shouldBeEqualToNumber(a, b) | |
342 { | |
343 if (typeof a !== "string" || typeof b !== "number") | |
344 debug("WARN: shouldBeEqualToNumber() expects a string and a number arguments
"); | |
345 var unevaledString = JSON.stringify(b); | |
346 shouldBe(a, unevaledString); | |
347 } | |
348 | |
349 function shouldBeEmptyString(a) { shouldBeEqualToString(a, ""); } | |
350 | |
351 function shouldEvaluateTo(actual, expected, opt_tolerance) { | |
352 // A general-purpose comparator. 'actual' should be a string to be | |
353 // evaluated, as for shouldBe(). 'expected' may be any type and will be | |
354 // used without being eval'ed. | |
355 if (expected == null) { | |
356 // Do this before the object test, since null is of type 'object'. | |
357 shouldBeNull(actual); | |
358 } else if (typeof expected == "undefined") { | |
359 shouldBeUndefined(actual); | |
360 } else if (typeof expected == "function") { | |
361 // All this fuss is to avoid the string-arg warning from shouldBe(). | |
362 try { | |
363 var actualValue = eval(actual); | |
364 } catch (e) { | |
365 testFailed("Evaluating " + actual + ": Threw exception " + e); | |
366 return; | |
367 } | |
368 shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'", | |
369 "'" + expected.toString().replace(/\n/g, "") + "'"); | |
370 } else if (typeof expected == "object") { | |
371 shouldBeTrue(actual + " == '" + expected + "'"); | |
372 } else if (typeof expected == "string") { | |
373 shouldBe(actual, expected, undefined, opt_tolerance); | |
374 } else if (typeof expected == "boolean") { | |
375 shouldBe("typeof " + actual, "'boolean'"); | |
376 if (expected) | |
377 shouldBeTrue(actual); | |
378 else | |
379 shouldBeFalse(actual); | |
380 } else if (typeof expected == "number") { | |
381 if (opt_tolerance) | |
382 shouldBeCloseTo(actual, expected, opt_tolerance); | |
383 else | |
384 shouldBe(actual, stringify(expected)); | |
385 } else { | |
386 debug(expected + " is unknown type " + typeof expected); | |
387 shouldBeTrue(actual, "'" +expected.toString() + "'"); | |
388 } | |
389 } | |
390 | |
391 function shouldBeNonZero(_a) | |
392 { | |
393 var _exception; | |
394 var _av; | |
395 try { | |
396 _av = eval(_a); | |
397 } catch (e) { | |
398 _exception = e; | |
399 } | |
400 | |
401 if (_exception) | |
402 testFailed(_a + " should be non-zero. Threw exception " + _exception); | |
403 else if (_av != 0) | |
404 testPassed(_a + " is non-zero."); | |
405 else | |
406 testFailed(_a + " should be non-zero. Was " + _av); | |
407 } | |
408 | |
409 function shouldBeNonNull(_a) | |
410 { | |
411 var _exception; | |
412 var _av; | |
413 try { | |
414 _av = eval(_a); | |
415 } catch (e) { | |
416 _exception = e; | |
417 } | |
418 | |
419 if (_exception) | |
420 testFailed(_a + " should be non-null. Threw exception " + _exception); | |
421 else if (_av != null) | |
422 testPassed(_a + " is non-null."); | |
423 else | |
424 testFailed(_a + " should be non-null. Was " + _av); | |
425 } | |
426 | |
427 function shouldBeUndefined(_a) | |
428 { | |
429 var _exception; | |
430 var _av; | |
431 try { | |
432 _av = eval(_a); | |
433 } catch (e) { | |
434 _exception = e; | |
435 } | |
436 | |
437 if (_exception) | |
438 testFailed(_a + " should be undefined. Threw exception " + _exception); | |
439 else if (typeof _av == "undefined") | |
440 testPassed(_a + " is undefined."); | |
441 else | |
442 testFailed(_a + " should be undefined. Was " + _av); | |
443 } | |
444 | |
445 function shouldBeDefined(_a) | |
446 { | |
447 var _exception; | |
448 var _av; | |
449 try { | |
450 _av = eval(_a); | |
451 } catch (e) { | |
452 _exception = e; | |
453 } | |
454 | |
455 if (_exception) | |
456 testFailed(_a + " should be defined. Threw exception " + _exception); | |
457 else if (_av !== undefined) | |
458 testPassed(_a + " is defined."); | |
459 else | |
460 testFailed(_a + " should be defined. Was " + _av); | |
461 } | |
462 | |
463 function shouldBeGreaterThan(_a, _b) { | |
464 if (typeof _a != "string" || typeof _b != "string") | |
465 debug("WARN: shouldBeGreaterThan expects string arguments"); | |
466 | |
467 var _exception; | |
468 var _av; | |
469 try { | |
470 _av = eval(_a); | |
471 } catch (e) { | |
472 _exception = e; | |
473 } | |
474 var _bv = eval(_b); | |
475 | |
476 if (_exception) | |
477 testFailed(_a + " should be > " + _b + ". Threw exception " + _exception
); | |
478 else if (typeof _av == "undefined" || _av <= _bv) | |
479 testFailed(_a + " should be > " + _b + ". Was " + _av + " (of type " + t
ypeof _av + ")."); | |
480 else | |
481 testPassed(_a + " is > " + _b); | |
482 } | |
483 | |
484 function shouldBeGreaterThanOrEqual(_a, _b) { | |
485 if (typeof _a != "string" || typeof _b != "string") | |
486 debug("WARN: shouldBeGreaterThanOrEqual expects string arguments"); | |
487 | |
488 var _exception; | |
489 var _av; | |
490 try { | |
491 _av = eval(_a); | |
492 } catch (e) { | |
493 _exception = e; | |
494 } | |
495 var _bv = eval(_b); | |
496 | |
497 if (_exception) | |
498 testFailed(_a + " should be >= " + _b + ". Threw exception " + _exceptio
n); | |
499 else if (typeof _av == "undefined" || _av < _bv) | |
500 testFailed(_a + " should be >= " + _b + ". Was " + _av + " (of type " +
typeof _av + ")."); | |
501 else | |
502 testPassed(_a + " is >= " + _b); | |
503 } | |
504 | |
505 function shouldNotThrow(_a) { | |
506 try { | |
507 eval(_a); | |
508 testPassed(_a + " did not throw exception."); | |
509 } catch (e) { | |
510 testFailed(_a + " should not throw exception. Threw exception " + e + ".
"); | |
511 } | |
512 } | |
513 | |
514 function shouldThrow(_a, _e) | |
515 { | |
516 var _exception; | |
517 var _av; | |
518 try { | |
519 _av = eval(_a); | |
520 } catch (e) { | |
521 _exception = e; | |
522 } | |
523 | |
524 var _ev; | |
525 if (_e) | |
526 _ev = eval(_e); | |
527 | |
528 if (_exception) { | |
529 if (typeof _e == "undefined" || _exception == _ev) | |
530 testPassed(_a + " threw exception " + _exception + "."); | |
531 else | |
532 testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an excepti
on" : _ev) + ". Threw exception " + _exception + "."); | |
533 } else if (typeof _av == "undefined") | |
534 testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception
" : _ev) + ". Was undefined."); | |
535 else | |
536 testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception
" : _ev) + ". Was " + _av + "."); | |
537 } | |
538 | |
539 function expectError() | |
540 { | |
541 if (expectingError) { | |
542 testFailed("shouldHaveError() called twice before an error occurred!"); | |
543 } | |
544 expectingError = true; | |
545 } | |
546 | |
547 function shouldHaveHadError(message) | |
548 { | |
549 if (expectingError) { | |
550 testFailed("No error thrown between expectError() and shouldHaveHadError
()"); | |
551 return; | |
552 } | |
553 | |
554 if (expectedErrorMessage) { | |
555 if (!message) | |
556 testPassed("Got expected error"); | |
557 else if (expectedErrorMessage.indexOf(message) !== -1) | |
558 testPassed("Got expected error: '" + message + "'"); | |
559 else | |
560 testFailed("Unexpected error '" + message + "'"); | |
561 expectedErrorMessage = undefined; | |
562 return; | |
563 } | |
564 | |
565 testFailed("expectError() not called before shouldHaveHadError()"); | |
566 } | |
567 | |
568 function isSuccessfullyParsed() | |
569 { | |
570 // FIXME: Remove this and only report unexpected syntax errors. | |
571 successfullyParsed = !unexpectedErrorMessage; | |
572 shouldBeTrue("successfullyParsed"); | |
573 debug('TEST COMPLETE'); | |
574 } | |
575 | |
576 var wasFinishJSTestCalled, jsTestIsAsync; | |
577 | |
578 function finishJSTest() | |
579 { | |
580 wasFinishJSTestCalled = true; | |
581 isSuccessfullyParsed(); | |
582 if (self.internals) | |
583 internals.notifyTestComplete(internals.contentAsText()); | |
584 } | |
585 | |
586 window.addEventListener('load', function() { | |
587 if (!self.jsTestIsAsync) | |
588 finishJSTest(); | |
589 }); | |
590 </script> | |
OLD | NEW |