| 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 |