2 Copyright (c) 2001-2005 World Wide Web Consortium,
3 (Massachusetts Institute of Technology, European Research Consortium
4 for Informatics and Mathematics, Keio University). All
5 Rights Reserved. This work is distributed under the W3C(r) Software License [1] in the
6 hope that it will be useful, but WITHOUT ANY WARRANTY; without even
7 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
12 function assertSize(descr, expected, actual) {
14 assertNotNull(descr, actual);
15 actualSize = actual.length;
16 assertEquals(descr, expected, actualSize);
19 function assertEqualsAutoCase(context, descr, expected, actual) {
20 if (builder.contentType == "text/html") {
21 if(context == "attribute") {
22 assertEquals(descr, expected.toLowerCase(), actual.toLowerCase());
24 assertEquals(descr, expected.toUpperCase(), actual);
27 assertEquals(descr, expected, actual);
31 function assertEqualsCollectionAutoCase(context, descr, expected, actual) {
33 // if they aren't the same size, they aren't equal
34 assertEquals(descr, expected.length, actual.length);
37 // if there length is the same, then every entry in the expected list
38 // must appear once and only once in the actual list
39 var expectedLen = expected.length;
41 var actualLen = actual.length;
45 for(i = 0; i < expectedLen; i++) {
47 expectedValue = expected[i];
48 for(j = 0; j < actualLen; j++) {
49 if (builder.contentType == "text/html") {
50 if (context == "attribute") {
51 if (expectedValue.toLowerCase() == actual[j].toLowerCase()) {
55 if (expectedValue.toUpperCase() == actual[j]) {
60 if(expectedValue == actual[j]) {
66 assert(descr + ": No match found for " + expectedValue,false);
69 assert(descr + ": Multiple matches found for " + expectedValue, false);
74 function assertEqualsCollection(descr, expected, actual) {
76 // if they aren't the same size, they aren't equal
77 assertEquals(descr, expected.length, actual.length);
79 // if there length is the same, then every entry in the expected list
80 // must appear once and only once in the actual list
81 var expectedLen = expected.length;
83 var actualLen = actual.length;
87 for(i = 0; i < expectedLen; i++) {
89 expectedValue = expected[i];
90 for(j = 0; j < actualLen; j++) {
91 if(expectedValue == actual[j]) {
96 assert(descr + ": No match found for " + expectedValue,false);
99 assert(descr + ": Multiple matches found for " + expectedValue, false);
104 function assertEqualsListAutoCase(context, descr, expected, actual) {
105 var minLength = expected.length;
106 if (actual.length < minLength) {
107 minLength = actual.length;
110 for(var i = 0; i < minLength; i++) {
111 assertEqualsAutoCase(context, descr, expected[i], actual[i]);
114 // if they aren't the same size, they aren't equal
115 assertEquals(descr, expected.length, actual.length);
118 function assertEqualsList(descr, expected, actual) {
119 var minLength = expected.length;
120 if (actual.length < minLength) {
121 minLength = actual.length;
124 for(var i = 0; i < minLength; i++) {
125 if(expected[i] != actual[i]) {
126 assertEquals(descr, expected[i], actual[i]);
130 // if they aren't the same size, they aren't equal
131 assertEquals(descr, expected.length, actual.length);
134 function assertInstanceOf(descr, type, obj) {
136 assertEquals(descr,2,obj.nodeType);
137 var specd = obj.specified;
141 function assertSame(descr, expected, actual) {
142 if(expected != actual) {
143 assertEquals(descr, expected.nodeType, actual.nodeType);
144 assertEquals(descr, expected.nodeValue, actual.nodeValue);
148 function assertURIEquals(assertID, scheme, path, host, file, name, query, fragment, isAbsolute, actual) {
150 // URI must be non-null
151 assertNotNull(assertID, actual);
155 var lastPound = actual.lastIndexOf("#");
156 var actualFragment = "";
157 if(lastPound != -1) {
159 // substring before pound
161 uri = actual.substring(0,lastPound);
162 actualFragment = actual.substring(lastPound+1);
164 if(fragment != null) assertEquals(assertID,fragment, actualFragment);
166 var lastQuestion = uri.lastIndexOf("?");
167 var actualQuery = "";
168 if(lastQuestion != -1) {
170 // substring before pound
172 uri = actual.substring(0,lastQuestion);
173 actualQuery = actual.substring(lastQuestion+1);
175 if(query != null) assertEquals(assertID, query, actualQuery);
177 var firstColon = uri.indexOf(":");
178 var firstSlash = uri.indexOf("/");
179 var actualPath = uri;
180 var actualScheme = "";
181 if(firstColon != -1 && firstColon < firstSlash) {
182 actualScheme = uri.substring(0,firstColon);
183 actualPath = uri.substring(firstColon + 1);
187 assertEquals(assertID, scheme, actualScheme);
191 assertEquals(assertID, path, actualPath);
196 if(actualPath.substring(0,2) == "//") {
197 var termSlash = actualPath.substring(2).indexOf("/") + 2;
198 actualHost = actualPath.substring(0,termSlash);
200 assertEquals(assertID, host, actualHost);
203 if(file != null || name != null) {
204 var actualFile = actualPath;
205 var finalSlash = actualPath.lastIndexOf("/");
206 if(finalSlash != -1) {
207 actualFile = actualPath.substring(finalSlash+1);
210 assertEquals(assertID, file, actualFile);
213 var actualName = actualFile;
214 var finalDot = actualFile.lastIndexOf(".");
215 if (finalDot != -1) {
216 actualName = actualName.substring(0, finalDot);
218 assertEquals(assertID, name, actualName);
222 if(isAbsolute != null) {
223 assertEquals(assertID, isAbsolute, actualPath.substring(0,1) == "/");
227 // size() used by assertSize element
228 function size(collection)
230 return collection.length;
233 function same(expected, actual)
235 return expected === actual;
238 function equalsAutoCase(context, expected, actual) {
239 if (builder.contentType == "text/html") {
240 if (context == "attribute") {
241 return expected.toLowerCase() == actual;
243 return expected.toUpperCase() == actual;
245 return expected == actual;
248 function createTempURI(scheme) {
249 if (scheme == "http") {
250 return "http://localhost:8080/webdav/tmp" + Math.floor(Math.random() * 100000) + ".xml";
252 return "file:///tmp/domts" + Math.floor(Math.random() * 100000) + ".xml";
255 function EventMonitor() {
256 this.atEvents = new Array();
257 this.bubbledEvents = new Array();
258 this.capturedEvents = new Array();
259 this.allEvents = new Array();
262 EventMonitor.prototype.handleEvent = function(evt) {
263 switch(evt.eventPhase) {
265 monitor.capturedEvents[monitor.capturedEvents.length] = evt;
269 monitor.atEvents[monitor.atEvents.length] = evt;
273 monitor.bubbledEvents[monitor.bubbledEvents.length] = evt;
276 monitor.allEvents[monitor.allEvents.length] = evt;
279 function DOMErrorImpl(err) {
280 this.severity = err.severity;
281 this.message = err.message;
282 this.type = err.type;
283 this.relatedException = err.relatedException;
284 this.relatedData = err.relatedData;
285 this.location = err.location;
288 function DOMErrorMonitor() {
289 this.allErrors = new Array();
292 DOMErrorMonitor.prototype.handleError = function(err) {
293 errorMonitor.allErrors[errorMonitor.allErrors.length] = new DOMErrorImpl(err);
296 DOMErrorMonitor.prototype.assertLowerSeverity = function(id, severity) {
298 for (i = 0; i < this.allErrors.length; i++) {
299 if (this.allErrors[i].severity >= severity) {
300 assertEquals(id, severity - 1, this.allErrors[i].severity);
305 function UserDataNotification(operation, key, data, src, dst) {
306 this.operation = operation;
313 function UserDataMonitor() {
314 this.allNotifications = new Array();
317 UserDataMonitor.prototype.handle = function(operation, key, data, src, dst) {
318 userDataMonitor.allNotifications[userDataMonitor.allNotifications.length] =
319 new UserDataNotification(operation, key, data, src, dst);
322 function HTMLBuilder() {
323 this.contentType = "text/html";
324 this.supportedContentTypes = [ "text/html" ];
326 this.supportsAsyncChange = false;
328 this.fixedAttributeNames = [
329 "validating", "expandEntityReferences", "coalescing",
330 "signed", "hasNullString", "ignoringElementContentWhitespace", "namespaceAware", "ignoringComments", "schemaValidating"];
332 this.fixedAttributeValues = [false, true, false, true, true , false, false, false, false ];
333 this.configurableAttributeNames = [ ];
334 this.configurableAttributeValues = [ ];
335 this.initializationError = null;
336 this.initializationFatalError = null;
337 this.skipIncompatibleTests = true;
338 this.documentURLs = new Array();
339 this.documentVarnames = new Array();
342 HTMLBuilder.prototype.hasFeature = function(feature, version) {
343 return document.implementation.hasFeature(feature, version);
346 HTMLBuilder.prototype.getImplementation = function() {
347 return document.implementation;
350 HTMLBuilder.prototype.preload = function(frame, varname, url) {
352 this.documentVarnames[this.documentVarnames.length] = varname;
353 this.documentURLs[this.documentURLs.length] = url;
354 if (this.documentURLs.length > 1) {
356 // if all the urls are not the same
358 for (i = 1; i < this.documentURLs.length; i++) {
359 if (this.documentURLs[i] != this.documentURLs[0]) {
360 throw "Tests with multiple loads of different documents are not currently supported";
367 HTMLBuilder.prototype.cloneNode = function(srcNode, doc) {
369 switch(srcNode.nodeType) {
373 clone = doc.createElement(srcNode.nodeName.toLowerCase());
374 var attrs = srcNode.attributes;
375 for(var i = 0; i < attrs.length; i++) {
376 var srcAttr = attrs.item(i);
377 clone.setAttribute(srcAttr.nodeName, srcAttr.nodeValue);
379 var srcChild = srcNode.firstChild;
380 while(srcChild != null) {
381 var cloneChild = this.cloneNode(srcChild, doc);
382 if (cloneChild != null) {
383 clone.appendChild(cloneChild);
385 srcChild = srcChild.nextSibling;
390 clone = doc.createTextNode(srcNode.nodeValue);
394 clone = doc.createCDATASection(srcNode.nodeValue);
398 clone = doc.createProcessingInstruction(srcNode.nodeValue);
402 clone = doc.createComment(srcNode.nodeValue);
409 HTMLBuilder.prototype.load = function(frame, varname, url) {
410 if (this.documentVarnames[0] == varname) {
415 // not a perfect way to do this
416 // Document.cloneNode is implementation dependent but exists in L1
417 // and implemented in IE. The alternative brute force copy
418 // only works in L2 or higher implementations and can't copy
419 // entity and notation definitions, etc.
422 clone = document.cloneNode(true);
426 clone = document.implementation.createDocument(
427 document.documentElement.namespaceURI,
428 document.documentElement.nodeName,
432 // Safari does not create document element
434 if (clone.documentElement == null) {
435 clone.appendChild(clone.createElement(document.documentElement.nodeName));
437 var attrs = document.documentElement.attributes;
438 for(var i = 0; i < attrs.length; i++) {
439 var srcAttr = attrs.item(i);
440 clone.documentElement.setAttribute(srcAttr.nodeName, srcAttr.nodeValue);
443 var srcNode = document.firstChild;
444 while(srcNode != null && srcNode.nodeType != 1) {
445 if (srcNode.nodeType != 10) {
446 var cloneNode = this.cloneNode(srcNode, clone);
447 clone.insertBefore(cloneNode, clone.documentElement);
449 srcNode = srcNode.nextSibling;
451 srcNode = document.documentElement.nextSibling;
452 while(srcNode != null) {
453 var cloneNode = this.cloneNode(srcNode, clone);
454 clone.appendChild(cloneNode);
455 srcNode = srcNode.nextSibling;
457 srcNode = document.documentElement.firstChild;
458 while(srcNode != null) {
459 var cloneNode = this.cloneNode(srcNode, clone);
460 if (cloneNode != null) {
461 clone.documentElement.appendChild(cloneNode);
463 srcNode = srcNode.nextSibling;
469 HTMLBuilder.prototype.getImplementationAttribute = function(attr) {
470 for (var i = 0; i < this.fixedAttributeNames.length; i++) {
471 if (this.fixedAttributeNames[i] == attr) {
472 return this.fixedAttributeValues[i];
475 throw "Unrecognized implementation attribute: " + attr;
478 HTMLBuilder.prototype.setImplementationAttribute = function(attribute, value) {
479 var supported = this.getImplementationAttribute(attribute);
480 if (supported != value) {
481 this.initializationError = "HTML loader does not support " + attribute + "=" + value;
485 HTMLBuilder.prototype.canSetImplementationAttribute = function(attribute, value) {
486 var supported = this.getImplementationAttribute(attribute);
487 return (supported == value);
490 function createConfiguredBuilder() {
491 return new HTMLBuilder();
494 function catchInitializationError(buildr, ex) {
495 buildr.initializationError = ex;
496 buildr.initializationFatalError = ex;
499 function toLowerArray(src) {
500 var newArray = new Array();
502 for (i = 0; i < src.length; i++) {
503 newArray[i] = src[i].toLowerCase();
508 function checkFeature(feature, version)
510 if (!builder.hasFeature(feature, version))
513 // don't throw exception so that users can select to ignore the precondition
515 builder.initializationError = "builder does not support feature " + feature + " version " + version;
519 function setResult(resultType, message) {
520 var testName = getTargetURI();
522 document.writeln("<html><head>");
523 document.writeln("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; CHARSET=utf-8'>");
524 document.write("<title>");
525 document.write(testName + ":" + resultType);
526 document.write("</title></head><body><table width='100%' border='1' style='color:");
527 if (resultType == null) {
528 document.writeln("green'><tr><td>Test:</td><td>" + testName + "</td></tr><tr><td>Status:</td><td>Success</td></tr>");
530 if (resultType == "skip") {
531 document.writeln("blue'><tr><td>Test:</td><td>" + testName + "</td></tr><tr><td>Status:</td><td>Skipped</td></tr>");
533 document.writeln("red'><tr><td>Test:</td><td>" + testName + "</td><td></tr><tr><td>Status:</td><td>" + resultType + "</td></tr>");
536 if (message != null) {
537 document.writeln("<tr><td>Detail:</td><td>" + message + "</td></tr>");
539 document.write("</table></body></html>");
541 if (parent != window) {
542 parent.setResult(testName, resultType, message);
546 function checkInitialization(buildr, testname) {
547 return buildr.initializationError;
550 function preload(docRef, varname, href) {
551 return builder.preload(docRef, varname, href);
554 function load(docRef, varname, href) {
555 return builder.load(docRef, varname, href);
558 function getImplementationAttribute(attr) {
559 return builder.getImplementationAttribute(attr);
562 function setImplementationAttribute(attribute, value) {
563 builder.setImplementationAttribute(attribute, value);
566 function createXPathEvaluator(doc) {
568 return doc.getFeature("XPath", null);
575 function getImplementation() {
576 return builder.getImplementation();
579 function assertEquals(id, expected, actual) {
581 if (expected != actual) {
583 if (actual == null) {
586 throw "failure:" + id + ": assertEquals failed, actual " + myActual + ", expected " + expected + ".";
590 function assertNull(id, actual) {
591 if (actual != null) {
592 throw "failure:" + id + ": assertNull failed, actual " + actual;
596 function assertTrue(id, actual) {
598 throw "failure:" + id + ": assertTrue failed";
602 function assertFalse(id, actual) {
604 throw "failure:" + id + ": assertTrue failed";
608 function assertNotNull(id, actual) {
609 if (actual == null) {
610 throw "failure:" + id + ": assertNotNull failed";
615 throw "failure:" + id + ": fail";
618 function getSuffix(contentType) {
619 switch(contentType) {
623 case "application/xhtml+xml":
626 case "image/svg+xml":
635 function getResourceURI(name, scheme, contentType) {
636 var base = document.documentURI;
640 base = base.substring(0, base.lastIndexOf('/') + 1) + "files/";
642 return base + name + getSuffix(contentType);
645 function startTest() {
648 // WebKit modification: 18-August-2005
650 // Inform the test controller that this test has a text-format result and so should
651 // be dumped as text, and also that the dump should not occur automatically.
653 if (window.testRunner) {
654 testRunner.dumpAsText();
655 testRunner.waitUntilDone();
658 // End WebKit modification
668 if (builder.initializationError == null) {
669 setResult(null, null);
671 setResult("skip", builder.initializationError);
674 if (typeof(ex.substring) != 'undefined' && ex.substring(0, 8) == "failure:") {
675 setResult("failure", ex.substring(8));
677 setResult("error", ex);
682 // WebKit modification: 18-August-2005
684 // Inform the test controller that this test is complete, so it's time to dump.
686 if (window.testRunner) {
687 testRunner.notifyDone();
690 // End WebKit modification