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