DOMTestCase.js (19188B)
1 /* 2 Copyright (c) 2001-2005 World Wide Web Consortium, 3 (Massachusetts Institute of Technology, Institut National de 4 Recherche en Informatique et en Automatique, Keio University). All 5 Rights Reserved. This program is distributed under the W3C's Software 6 Intellectual Property License. This program is distributed in the 7 hope that it will be useful, but WITHOUT ANY WARRANTY; without even 8 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 9 PURPOSE. 10 See W3C License http://www.w3.org/Consortium/Legal/ for more details. 11 */ 12 13 function assertNull(descr, actual) { 14 return ok(actual === null, descr); 15 } 16 17 18 function assertNotNull(descr, actual) { 19 return ok(actual !== null, descr); 20 } 21 22 function assertTrue(descr, actual) { 23 return ok(actual === true, descr); 24 } 25 26 function assertFalse(descr, actual) { 27 return ok(actual === false, descr); 28 } 29 30 function assertEquals(descr, expected, actual) { 31 return is(actual, expected, descr); 32 } 33 34 function assertSize(descr, expected, actual) { 35 ok(actual !== null, descr); 36 /* 37 // Work around too strict checks. 38 if (!actual) { 39 ok(actual, "[assertSize()] 'actual' has a value"); 40 return; 41 } 42 */ 43 44 is(actual.length, expected, descr); 45 } 46 47 function assertEqualsAutoCase(context, descr, expected, actual) { 48 if (builder.contentType == "text/html") { 49 if(context == "attribute") { 50 is(actual.toLowerCase(), expected.toLowerCase(), descr); 51 } else { 52 is(actual, expected.toUpperCase(), descr); 53 } 54 } else { 55 is(actual, expected, descr); 56 } 57 } 58 59 60 function assertEqualsCollectionAutoCase(context, descr, expected, actual) { 61 // 62 // if they aren't the same size, they aren't equal 63 is(actual.length, expected.length, descr); 64 65 // 66 // if there length is the same, then every entry in the expected list 67 // must appear once and only once in the actual list 68 var expectedLen = expected.length; 69 var expectedValue; 70 var actualLen = actual.length; 71 var i; 72 var j; 73 var matches; 74 for(i = 0; i < expectedLen; i++) { 75 matches = 0; 76 expectedValue = expected[i]; 77 for(j = 0; j < actualLen; j++) { 78 if (builder.contentType == "text/html") { 79 if (context == "attribute") { 80 if (expectedValue.toLowerCase() == actual[j].toLowerCase()) { 81 matches++; 82 } 83 } else { 84 if (expectedValue.toUpperCase() == actual[j]) { 85 matches++; 86 } 87 } 88 } else { 89 if(expectedValue == actual[j]) { 90 matches++; 91 } 92 } 93 } 94 if(matches == 0) { 95 ok(false, descr + ": No match found for " + expectedValue); 96 } 97 if(matches > 1) { 98 ok(false, descr + ": Multiple matches found for " + expectedValue); 99 } 100 } 101 } 102 103 function assertEqualsCollection(descr, expected, actual) { 104 // 105 // if they aren't the same size, they aren't equal 106 is(actual.length, expected.length, descr); 107 // 108 // if there length is the same, then every entry in the expected list 109 // must appear once and only once in the actual list 110 var expectedLen = expected.length; 111 var expectedValue; 112 var actualLen = actual.length; 113 var i; 114 var j; 115 var matches; 116 for(i = 0; i < expectedLen; i++) { 117 matches = 0; 118 expectedValue = expected[i]; 119 for(j = 0; j < actualLen; j++) { 120 if(expectedValue == actual[j]) { 121 matches++; 122 } 123 } 124 if(matches == 0) { 125 ok(false, descr + ": No match found for " + expectedValue); 126 } 127 if(matches > 1) { 128 ok(false, descr + ": Multiple matches found for " + expectedValue); 129 } 130 } 131 } 132 133 134 function assertEqualsListAutoCase(context, descr, expected, actual) { 135 var minLength = expected.length; 136 if (actual.length < minLength) { 137 minLength = actual.length; 138 } 139 // 140 for(var i = 0; i < minLength; i++) { 141 assertEqualsAutoCase(context, descr, expected[i], actual[i]); 142 } 143 // 144 // if they aren't the same size, they aren't equal 145 is(actual.length, expected.length, descr); 146 } 147 148 149 function assertEqualsList(descr, expected, actual) { 150 var minLength = expected.length; 151 if (actual.length < minLength) { 152 minLength = actual.length; 153 } 154 // 155 for(var i = 0; i < minLength; i++) { 156 if(expected[i] != actual[i]) { 157 is(actual[i], expected[i], descr); 158 } 159 } 160 // 161 // if they aren't the same size, they aren't equal 162 is(actual.length, expected.length, descr); 163 } 164 165 function assertInstanceOf(descr, type, obj) { 166 if(type == "Attr") { 167 is(2, obj.nodeType, descr); 168 var specd = obj.specified; 169 } 170 /* 171 else { 172 // Ensure at least one SimpleTest check is reported. (Bug 483992) 173 todo_is(type, "Attr", "[DOMTestCase.assertInstanceOf()] Fake default check."); 174 } 175 */ 176 } 177 178 function assertSame(descr, expected, actual) { 179 if(expected != actual) { 180 is(expected.nodeType, actual.nodeType, descr); 181 is(expected.nodeValue, actual.nodeValue, descr); 182 } 183 /* 184 else { 185 // Ensure at least one SimpleTest check is reported. (Bug 483992) 186 todo_isnot(expected, actual, "[DOMTestCase.assertSame()] Fake default check." + 187 " (Type=" + actual.nodeType + ", Value=" + actual.nodeValue + ")"); 188 } 189 */ 190 } 191 192 function assertURIEquals(assertID, scheme, path, host, file, name, query, fragment, isAbsolute, actual) { 193 // 194 // URI must be non-null 195 ok(assertID, "[assertURIEquals()] 'assertID' has a value"); 196 ok(actual, "[assertURIEquals()] 'actual' has a value"); 197 /* 198 // Add missing early return. 199 if (!actual) 200 return; 201 */ 202 203 var uri = actual; 204 205 var lastPound = actual.lastIndexOf("#"); 206 var actualFragment = ""; 207 if(lastPound != -1) { 208 // 209 // substring before pound 210 // 211 uri = actual.substring(0,lastPound); 212 actualFragment = actual.substring(lastPound+1); 213 } 214 if(fragment != null) is(actualFragment, fragment, assertID); 215 216 var lastQuestion = uri.lastIndexOf("?"); 217 var actualQuery = ""; 218 if(lastQuestion != -1) { 219 // 220 // substring before pound 221 // 222 uri = actual.substring(0,lastQuestion); 223 actualQuery = actual.substring(lastQuestion+1); 224 } 225 if(query != null) is(actualQuery, query, assertID); 226 227 var firstColon = uri.indexOf(":"); 228 var firstSlash = uri.indexOf("/"); 229 var actualPath = uri; 230 var actualScheme = ""; 231 if(firstColon != -1 && firstColon < firstSlash) { 232 actualScheme = uri.substring(0,firstColon); 233 actualPath = uri.substring(firstColon + 1); 234 } 235 236 if(scheme != null) { 237 is(scheme, actualScheme, assertID); 238 } 239 240 if(path != null) { 241 is(path, actualPath, assertID); 242 } 243 244 if(host != null) { 245 var actualHost = ""; 246 if(actualPath.substring(0,2) == "//") { 247 var termSlash = actualPath.substring(2).indexOf("/") + 2; 248 actualHost = actualPath.substring(0,termSlash); 249 } 250 is(actualHost, host, assertID); 251 } 252 253 if(file != null || name != null) { 254 var actualFile = actualPath; 255 var finalSlash = actualPath.lastIndexOf("/"); 256 if(finalSlash != -1) { 257 actualFile = actualPath.substring(finalSlash+1); 258 } 259 if (file != null) { 260 is(actualFile, file, assertID); 261 } 262 if (name != null) { 263 var actualName = actualFile; 264 var finalDot = actualFile.lastIndexOf("."); 265 if (finalDot != -1) { 266 actualName = actualName.substring(0, finalDot); 267 } 268 is(actualName, name, assertID); 269 } 270 } 271 272 if(isAbsolute != null) { 273 is(actualPath.substring(0,1) == "/", isAbsolute, assertID); 274 } 275 } 276 277 278 // size() used by assertSize element 279 function size(collection) 280 { 281 return collection.length; 282 } 283 284 function same(expected, actual) 285 { 286 return expected === actual; 287 } 288 289 function getSuffix(contentType) { 290 switch(contentType) { 291 case "text/html": 292 return ".html"; 293 294 case "text/xml": 295 return ".xml"; 296 297 case "application/xhtml+xml": 298 return ".xhtml"; 299 300 case "image/svg+xml": 301 return ".svg"; 302 303 case "text/mathml": 304 return ".mml"; 305 } 306 return ".html"; 307 } 308 309 function equalsAutoCase(context, expected, actual) { 310 if (builder.contentType == "text/html") { 311 if (context == "attribute") { 312 return expected.toLowerCase() == actual; 313 } 314 return expected.toUpperCase() == actual; 315 } 316 return expected == actual; 317 } 318 319 function catchInitializationError(blder, ex) { 320 if (blder == null) { 321 alert(ex); 322 } else { 323 blder.initializationError = ex; 324 blder.initializationFatalError = ex; 325 } 326 } 327 328 function checkInitialization(blder, testname) { 329 if (blder.initializationError != null) { 330 // Fake a "warn()" function, as it was missing :-| 331 function warn(msg) { 332 info("[checkInitialization() warning] " + msg); 333 } 334 335 if (blder.skipIncompatibleTests) { 336 warn(testname + " not run:" + blder.initializationError); 337 return blder.initializationError; 338 } else { 339 // 340 // if an exception was thrown 341 // rethrow it and do not run the test 342 if (blder.initializationFatalError != null) { 343 throw blder.initializationFatalError; 344 } else { 345 // 346 // might be recoverable, warn but continue the test 347 warn(testname + ": " + blder.initializationError); 348 } 349 } 350 } 351 return null; 352 } 353 function createTempURI(scheme) { 354 if (scheme == "http") { 355 return "http://localhost:8080/webdav/tmp" + Math.floor(Math.random() * 100000) + ".xml"; 356 } 357 return "file:///tmp/domts" + Math.floor(Math.random() * 100000) + ".xml"; 358 } 359 360 361 function EventMonitor() { 362 this.atEvents = new Array(); 363 this.bubbledEvents = new Array(); 364 this.capturedEvents = new Array(); 365 this.allEvents = new Array(); 366 } 367 368 EventMonitor.prototype.handleEvent = function(evt) { 369 switch(evt.eventPhase) { 370 case 1: 371 monitor.capturedEvents[monitor.capturedEvents.length] = evt; 372 break; 373 374 case 2: 375 monitor.atEvents[monitor.atEvents.length] = evt; 376 break; 377 378 case 3: 379 monitor.bubbledEvents[monitor.bubbledEvents.length] = evt; 380 break; 381 } 382 monitor.allEvents[monitor.allEvents.length] = evt; 383 } 384 385 function DOMErrorImpl(err) { 386 this.severity = err.severity; 387 this.message = err.message; 388 this.type = err.type; 389 this.relatedException = err.relatedException; 390 this.relatedData = err.relatedData; 391 this.location = err.location; 392 } 393 394 395 396 function DOMErrorMonitor() { 397 this.allErrors = new Array(); 398 } 399 400 DOMErrorMonitor.prototype.handleError = function(err) { 401 errorMonitor.allErrors[errorMonitor.allErrors.length] = new DOMErrorImpl(err); 402 } 403 404 DOMErrorMonitor.prototype.assertLowerSeverity = function(id, severity) { 405 var i; 406 for (i = 0; i < errorMonitor.allErrors.length; i++) { 407 if (errorMonitor.allErrors[i].severity >= severity) { 408 assertEquals(id, severity - 1, errorMonitor.allErrors[i].severity); 409 } 410 } 411 } 412 413 function UserDataNotification(operation, key, data, src, dst) { 414 this.operation = operation; 415 this.key = key; 416 this.data = data; 417 this.src = src; 418 this.dst = dst; 419 } 420 421 function UserDataMonitor() { 422 this.allNotifications = new Array(); 423 } 424 425 UserDataMonitor.prototype.handle = function(operation, key, data, src, dst) { 426 userDataMonitor.allNotifications[this.allNotifications.length] = 427 new UserDataNotification(operation, key, data, src, dst); 428 } 429 430 431 432 function IFrameBuilder() { 433 this.contentType = "text/html"; 434 this.supportedContentTypes = [ "text/html", 435 "text/xml", 436 "image/svg+xml", 437 "application/xhtml+xml" ]; 438 439 this.supportsAsyncChange = false; 440 this.async = true; 441 this.fixedAttributeNames = [ 442 "validating", "expandEntityReferences", "coalescing", 443 "signed", "hasNullString", "ignoringElementContentWhitespace", "namespaceAware", "ignoringComments", "schemaValidating"]; 444 445 this.fixedAttributeValues = [false, true, false, true, true , false, false, true, false ]; 446 this.configurableAttributeNames = [ ]; 447 this.configurableAttributeValues = [ ]; 448 this.initializationError = null; 449 this.initializationFatalError = null; 450 this.skipIncompatibleTests = false; 451 } 452 453 IFrameBuilder.prototype.hasFeature = function(feature, version) { 454 return document.implementation.hasFeature(feature, version); 455 } 456 457 IFrameBuilder.prototype.getImplementation = function() { 458 return document.implementation; 459 } 460 461 IFrameBuilder.prototype.setContentType = function(contentType) { 462 this.contentType = contentType; 463 if (contentType == "text/html") { 464 this.fixedAttributeValues[6] = false; 465 } else { 466 this.fixedAttributeValues[6] = true; 467 } 468 } 469 470 471 472 IFrameBuilder.prototype.preload = function(frame, varname, url) { 473 var suffix; 474 if (this.contentType == "text/html" || 475 this.contentType == "application/xhtml+xml") { 476 if (url.substring(0,5) == "staff" || url == "nodtdstaff" || 477 url == "datatype_normalization") { 478 suffix = ".xml"; 479 } 480 } 481 482 if (!suffix) suffix = getSuffix(this.contentType); 483 484 var iframe = document.createElement("iframe"); 485 var srcname = url + suffix; 486 iframe.setAttribute("name", srcname); 487 iframe.setAttribute("src", fileBase + srcname); 488 // 489 // HTML and XHTML have onload attributes that will invoke loadComplete 490 // 491 if (suffix.indexOf("html") < 0) { 492 iframe.addEventListener("load", loadComplete, false); 493 } 494 document.getElementsByTagName("body").item(0).appendChild(iframe); 495 return 0; 496 } 497 498 IFrameBuilder.prototype.load = function(frame, varname, url) { 499 var suffix; 500 if (url.substring(0,5) == "staff" || url == "nodtdstaff" || url == "datatype_normalization") { 501 suffix = ".xml"; 502 } 503 if (!suffix) suffix = getSuffix(this.contentType); 504 var name = url + suffix; 505 var iframes = document.getElementsByTagName("iframe"); 506 for(var i = 0; i < iframes.length; i++) { 507 if (iframes.item(i).getAttribute("name") == name) { 508 var item = iframes.item(i); 509 if (typeof(item.contentDocument) != 'undefined') { 510 return item.contentDocument; 511 } 512 if (typeof(item.document) != 'undefined') { 513 return item.document; 514 } 515 return null; 516 } 517 } 518 return null; 519 } 520 521 IFrameBuilder.prototype.getImplementationAttribute = function(attr) { 522 for (var i = 0; i < this.fixedAttributeNames.length; i++) { 523 if (this.fixedAttributeNames[i] == attr) { 524 return this.fixedAttributeValues[i]; 525 } 526 } 527 throw "Unrecognized implementation attribute: " + attr; 528 } 529 530 531 532 IFrameBuilder.prototype.setImplementationAttribute = function(attribute, value) { 533 var supported = this.getImplementationAttribute(attribute); 534 if (supported != value) { 535 this.initializationError = "IFrame loader does not support " + attribute + "=" + value; 536 } 537 } 538 539 540 IFrameBuilder.prototype.canSetImplementationAttribute = function(attribute, value) { 541 var supported = this.getImplementationAttribute(attribute); 542 return (supported == value); 543 } 544 545 546 function createBuilder(implementation) { 547 if (implementation == null) { 548 return new IFrameBuilder(); 549 } 550 switch(implementation) { 551 /* case "msxml3": 552 return new MSXMLBuilder("Msxml2.DOMDocument.3.0"); 553 554 case "msxml4": 555 return new MSXMLBuilder("Msxml2.DOMDocument.4.0");*/ 556 557 case "mozillaXML": 558 return new MozillaXMLBuilder(); 559 /* 560 case "svgplugin": 561 return new SVGPluginBuilder(); 562 563 case "dom3ls": 564 return new DOM3LSBuilder(); */ 565 566 case "iframe": 567 return new IFrameBuilder(); 568 569 case "xmlhttprequest": 570 return new XMLHttpRequestBuilder(); 571 572 default: 573 alert ("unrecognized implementation " + implementation); 574 } 575 return new IFrameBuilder(); 576 } 577 578 function checkFeature(feature, version) 579 { 580 if (!builder.hasFeature(feature, version)) 581 { 582 // 583 // don't throw exception so that users can select to ignore the precondition 584 // 585 builder.initializationError = "builder does not support feature " + feature + " version " + version; 586 } 587 } 588 589 function createConfiguredBuilder() { 590 var builder = null; 591 var contentType = null; 592 var i; 593 var contentTypeSet = false; 594 var parm = null; 595 builder = new IFrameBuilder(); 596 return builder; 597 } 598 599 600 function preload(frame, varname, url) { 601 return builder.preload(frame, varname, url); 602 } 603 604 function load(frame, varname, url) { 605 return builder.load(frame, varname, url); 606 } 607 608 function getImplementationAttribute(attr) { 609 return builder.getImplementationAttribute(attr); 610 } 611 612 613 function setImplementationAttribute(attribute, value) { 614 builder.setImplementationAttribute(attribute, value); 615 } 616 617 function setAsynchronous(value) { 618 if (builder.supportsAsyncChange) { 619 builder.async = value; 620 } else { 621 update(); 622 } 623 } 624 625 626 function createXPathEvaluator(doc) { 627 try { 628 return doc.getFeature("XPath", null); 629 } 630 catch(ex) { 631 } 632 return doc; 633 } 634 635 function toLowerArray(src) { 636 var newArray = new Array(); 637 var i; 638 for (i = 0; i < src.length; i++) { 639 newArray[i] = src[i].toLowerCase(); 640 } 641 return newArray; 642 } 643 644 function MSXMLBuilder_onreadystatechange() { 645 if (builder.parser.readyState == 4) { 646 loadComplete(); 647 } 648 } 649 650 651 652 var fileBase = location.href; 653 if (fileBase.indexOf('?') != -1) { 654 fileBase = fileBase.substring(0, fileBase.indexOf('?')); 655 } 656 fileBase = fileBase.substring(0, fileBase.lastIndexOf('/') + 1) + "files/"; 657 658 function getResourceURI(name, scheme, contentType) { 659 return fileBase + name + getSuffix(contentType); 660 } 661 662 663 function getImplementation() { 664 return builder.getImplementation(); 665 } 666 667 /* 668 // Count of failures overridden as todos. 669 var gFailuresAsTodos = 0; 670 671 // Override SimpleTest result logger. 672 var ST_logResult = SimpleTest._logResult; 673 SimpleTest._logResult = function overrideSTlR(test, passString, failString) { 674 if (todoTests[docName] && !test.result && !test.todo) { 675 test.name = "[failure as todo] " + test.name; 676 test.todo = true; 677 failString = "TEST-KNOWN-FAIL"; 678 679 ++gFailuresAsTodos; 680 } 681 682 ST_logResult(test, passString, failString); 683 } 684 */ 685 686 window.doc = window; 687 SimpleTest.waitForExplicitFinish(); 688 addLoadEvent(function(){ setUpPage(); }); 689 690 /* 691 // Actual marking code is in overrideSTlR() now. 692 function markTodos() { 693 if (todoTests[docName]) { 694 isnot(gFailuresAsTodos, 0, "test marked todo should have failed somewhere"); 695 } 696 } 697 */ 698 699 function runJSUnitTests() { 700 builder = createConfiguredBuilder(); 701 try { 702 var tests = exposeTestFunctionNames(); 703 for (var i = 0; i < tests.length; i++) { 704 window[tests[i]](); 705 } 706 } catch (ex) { 707 /* 708 if (todoTests[docName]) { 709 todo(false, "[failure as todo] Test threw exception: " + ex); 710 ++gFailuresAsTodos; 711 } else { 712 */ 713 ok(false, "Test threw exception: " + ex); 714 /* 715 } 716 */ 717 } 718 }