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