Changes from Curt Arnold, reviewed by Vicki.
[WebKit-https.git] / LayoutTests / dom / html / level2 / events / selfhtml.js
1 /*
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. 
8
9 [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
10 */
11
12
13 //
14 //   Webkit modification:  28-July-2005
15 //
16 if (window.layoutTestController)
17     layoutTestController.dumpAsText();
18 //
19 //   End modification
20 //
21
22
23   function assertSize(descr, expected, actual) {
24     var actualSize;
25     assertNotNull(descr, actual);
26     actualSize = actual.length;
27     assertEquals(descr, expected, actualSize);
28   }
29
30   function assertEqualsAutoCase(context, descr, expected, actual) {
31         if (builder.contentType == "text/html") {
32             if(context == "attribute") {
33                 assertEquals(descr, expected.toLowerCase(), actual.toLowerCase());
34             } else {
35                 assertEquals(descr, expected.toUpperCase(), actual);
36             }
37         } else {
38                 assertEquals(descr, expected, actual); 
39         }
40   }
41   
42
43   function assertEqualsCollectionAutoCase(context, descr, expected, actual) {
44     //
45     //  if they aren't the same size, they aren't equal
46     assertEquals(descr, expected.length, actual.length);
47     
48     //
49     //  if there length is the same, then every entry in the expected list
50     //     must appear once and only once in the actual list
51     var expectedLen = expected.length;
52     var expectedValue;
53     var actualLen = actual.length;
54     var i;
55     var j;
56     var matches;
57     for(i = 0; i < expectedLen; i++) {
58         matches = 0;
59         expectedValue = expected[i];
60         for(j = 0; j < actualLen; j++) {
61                 if (builder.contentType == "text/html") {
62                         if (context == "attribute") {
63                                 if (expectedValue.toLowerCase() == actual[j].toLowerCase()) {
64                                         matches++;
65                                 }
66                         } else {
67                                 if (expectedValue.toUpperCase() == actual[j]) {
68                                         matches++;
69                                 }
70                         }
71                 } else {
72                 if(expectedValue == actual[j]) {
73                         matches++;
74                 }
75             }
76         }
77         if(matches == 0) {
78             assert(descr + ": No match found for " + expectedValue,false);
79         }
80         if(matches > 1) {
81             assert(descr + ": Multiple matches found for " + expectedValue, false);
82         }
83     }
84   }
85
86   function assertEqualsCollection(descr, expected, actual) {
87     //
88     //  if they aren't the same size, they aren't equal
89     assertEquals(descr, expected.length, actual.length);
90     //
91     //  if there length is the same, then every entry in the expected list
92     //     must appear once and only once in the actual list
93     var expectedLen = expected.length;
94     var expectedValue;
95     var actualLen = actual.length;
96     var i;
97     var j;
98     var matches;
99     for(i = 0; i < expectedLen; i++) {
100         matches = 0;
101         expectedValue = expected[i];
102         for(j = 0; j < actualLen; j++) {
103             if(expectedValue == actual[j]) {
104                 matches++;
105             }
106         }
107         if(matches == 0) {
108             assert(descr + ": No match found for " + expectedValue,false);
109         }
110         if(matches > 1) {
111             assert(descr + ": Multiple matches found for " + expectedValue, false);
112         }
113     }
114   }
115
116
117   function assertEqualsListAutoCase(context, descr, expected, actual) {
118         var minLength = expected.length;
119         if (actual.length < minLength) {
120             minLength = actual.length;
121         }
122     //
123     for(var i = 0; i < minLength; i++) {
124                 assertEqualsAutoCase(context, descr, expected[i], actual[i]);
125     }
126     //
127     //  if they aren't the same size, they aren't equal
128     assertEquals(descr, expected.length, actual.length);
129   }
130
131
132   function assertEqualsList(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         if(expected[i] != actual[i]) {
140                         assertEquals(descr, expected[i], actual[i]);
141         }
142     }
143     //
144     //  if they aren't the same size, they aren't equal
145     assertEquals(descr, expected.length, actual.length);
146   }
147
148   function assertInstanceOf(descr, type, obj) {
149     if(type == "Attr") {
150         assertEquals(descr,2,obj.nodeType);
151         var specd = obj.specified;
152     }
153   }
154
155   function assertSame(descr, expected, actual) {
156     if(expected != actual) {
157         assertEquals(descr, expected.nodeType, actual.nodeType);
158         assertEquals(descr, expected.nodeValue, actual.nodeValue);
159     }
160   }
161
162   function assertURIEquals(assertID, scheme, path, host, file, name, query, fragment, isAbsolute, actual) {
163     //
164     //  URI must be non-null
165     assertNotNull(assertID, actual);
166
167     var uri = actual;
168
169     var lastPound = actual.lastIndexOf("#");
170     var actualFragment = "";
171     if(lastPound != -1) {
172         //
173         //   substring before pound
174         //
175         uri = actual.substring(0,lastPound);
176         actualFragment = actual.substring(lastPound+1);
177     }
178     if(fragment != null) assertEquals(assertID,fragment, actualFragment);
179
180     var lastQuestion = uri.lastIndexOf("?");
181     var actualQuery = "";
182     if(lastQuestion != -1) {
183         //
184         //   substring before pound
185         //
186         uri = actual.substring(0,lastQuestion);
187         actualQuery = actual.substring(lastQuestion+1);
188     }
189     if(query != null) assertEquals(assertID, query, actualQuery);
190
191     var firstColon = uri.indexOf(":");
192     var firstSlash = uri.indexOf("/");
193     var actualPath = uri;
194     var actualScheme = "";
195     if(firstColon != -1 && firstColon < firstSlash) {
196         actualScheme = uri.substring(0,firstColon);
197         actualPath = uri.substring(firstColon + 1);
198     }
199
200     if(scheme != null) {
201         assertEquals(assertID, scheme, actualScheme);
202     }
203
204     if(path != null) {
205         assertEquals(assertID, path, actualPath);
206     }
207
208     if(host != null) {
209         var actualHost = "";
210         if(actualPath.substring(0,2) == "//") {
211             var termSlash = actualPath.substring(2).indexOf("/") + 2;
212             actualHost = actualPath.substring(0,termSlash);
213         }
214         assertEquals(assertID, host, actualHost);
215     }
216
217     if(file != null || name != null) {
218         var actualFile = actualPath;
219         var finalSlash = actualPath.lastIndexOf("/");
220         if(finalSlash != -1) {
221             actualFile = actualPath.substring(finalSlash+1);
222         }
223         if (file != null) {
224             assertEquals(assertID, file, actualFile);
225         }
226         if (name != null) {
227             var actualName = actualFile;
228             var finalDot = actualFile.lastIndexOf(".");
229             if (finalDot != -1) {
230                 actualName = actualName.substring(0, finalDot);
231             }
232             assertEquals(assertID, name, actualName);
233         }
234     }
235
236     if(isAbsolute != null) {
237         assertEquals(assertID, isAbsolute, actualPath.substring(0,1) == "/");
238     }
239   }
240
241
242 // size() used by assertSize element
243 function size(collection)
244 {
245   return collection.length;
246 }
247
248 function same(expected, actual)
249 {
250   return expected === actual;
251 }
252
253 function equalsAutoCase(context, expected, actual) {
254         if (builder.contentType == "text/html") {
255                 if (context == "attribute") {
256                         return expected.toLowerCase() == actual;
257                 }
258                 return expected.toUpperCase() == actual;
259         }
260         return expected == actual;
261 }
262
263 function createTempURI(scheme) {
264    if (scheme == "http") {
265           return "http://localhost:8080/webdav/tmp" + Math.floor(Math.random() * 100000) + ".xml";
266    }
267    return "file:///tmp/domts" + Math.floor(Math.random() * 100000) + ".xml";
268 }
269
270
271
272 function EventMonitor() {
273   this.atEvents = new Array();
274   this.bubbledEvents = new Array();
275   this.capturedEvents = new Array();
276   this.allEvents = new Array();
277 }
278
279 EventMonitor.prototype.handleEvent = function(evt) {
280     switch(evt.eventPhase) {
281        case 1:
282        monitor.capturedEvents[monitor.capturedEvents.length] = evt;
283        break;
284        
285        case 2:
286        monitor.atEvents[monitor.atEvents.length] = evt;
287        break;
288
289        case 3:
290        monitor.bubbledEvents[monitor.bubbledEvents.length] = evt;
291        break;
292     }
293     monitor.allEvents[monitor.allEvents.length] = evt;
294 }
295
296 function DOMErrorImpl(err) {
297   this.severity = err.severity;
298   this.message = err.message;
299   this.type = err.type;
300   this.relatedException = err.relatedException;
301   this.relatedData = err.relatedData;
302   this.location = err.location;
303 }
304
305
306
307 function DOMErrorMonitor() {
308   this.allErrors = new Array();
309 }
310
311 DOMErrorMonitor.prototype.handleError = function(err) {
312     errorMonitor.allErrors[errorMonitor.allErrors.length] = new DOMErrorImpl(err);
313 }
314
315 DOMErrorMonitor.prototype.assertLowerSeverity = function(id, severity) {
316     var i;
317     for (i = 0; i < this.allErrors.length; i++) {
318         if (this.allErrors[i].severity >= severity) {
319            assertEquals(id, severity - 1, this.allErrors[i].severity);
320         }
321     }
322 }
323
324 function UserDataNotification(operation, key, data, src, dst) {
325     this.operation = operation;
326     this.key = key;
327     this.data = data;
328     this.src = src;
329     this.dst = dst;
330 }
331
332 function UserDataMonitor() {
333         this.allNotifications = new Array();
334 }
335
336 UserDataMonitor.prototype.handle = function(operation, key, data, src, dst) {
337     userDataMonitor.allNotifications[userDataMonitor.allNotifications.length] =
338          new UserDataNotification(operation, key, data, src, dst);
339 }
340
341
342
343 function HTMLBuilder() {
344     this.contentType = "text/html";
345     this.supportedContentTypes = [ "text/html" ];
346
347     this.supportsAsyncChange = false;
348     this.async = false;
349     this.fixedAttributeNames = [
350         "validating",  "expandEntityReferences", "coalescing", 
351         "signed", "hasNullString", "ignoringElementContentWhitespace", "namespaceAware", "ignoringComments", "schemaValidating"];
352
353     this.fixedAttributeValues = [false,  true, false, true, true , false, false, false, false ];
354     this.configurableAttributeNames = [ ];
355     this.configurableAttributeValues = [ ];
356     this.initializationError = null;
357     this.initializationFatalError = null;
358     this.skipIncompatibleTests = true;
359     this.documentURLs = new Array();
360     this.documentVarnames = new Array();
361 }
362
363 HTMLBuilder.prototype.hasFeature = function(feature, version) {
364     return document.implementation.hasFeature(feature, version);
365 }
366
367 HTMLBuilder.prototype.getImplementation = function() {
368   return document.implementation;
369 }
370
371 HTMLBuilder.prototype.preload = function(frame, varname, url) {
372   var i;
373   this.documentVarnames[this.documentVarnames.length] = varname;
374   this.documentURLs[this.documentURLs.length] = url;
375   if (this.documentURLs.length > 1) {
376      //
377      //   if all the urls are not the same
378      //
379      for (i = 1; i < this.documentURLs.length; i++) {
380          if (this.documentURLs[i] != this.documentURLs[0]) {
381              throw "Tests with multiple loads of different documents are not currently supported";
382          }
383      }
384   }
385   return 1;
386 }
387
388 HTMLBuilder.prototype.cloneNode = function(srcNode, doc) {
389    var clone = null;
390    switch(srcNode.nodeType) {
391       //
392       //  element
393       case 1:
394       clone = doc.createElement(srcNode.nodeName.toLowerCase());
395       var attrs = srcNode.attributes;
396       for(var i = 0; i < attrs.length; i++) {
397           var srcAttr = attrs.item(i);
398           clone.setAttribute(srcAttr.nodeName, srcAttr.nodeValue);
399       }
400       var srcChild = srcNode.firstChild;
401       while(srcChild != null) {
402          var cloneChild = this.cloneNode(srcChild, doc);
403          if (cloneChild != null) {
404              clone.appendChild(cloneChild);
405          }
406          srcChild = srcChild.nextSibling;
407       }
408       break;
409       
410       case 3:
411       clone = doc.createTextNode(srcNode.nodeValue);
412       break;
413       
414       case 4:
415       clone = doc.createCDATASection(srcNode.nodeValue);
416       break;
417             
418       case 7:
419       clone = doc.createProcessingInstruction(srcNode.nodeValue);
420       break;
421       
422       case 8:
423       clone = doc.createComment(srcNode.nodeValue);
424       break;
425    }
426    return clone;
427       
428 }
429
430
431 HTMLBuilder.prototype.load = function(frame, varname, url) {
432   if (this.documentVarnames[0] == varname) {
433         return document;
434   }
435   //
436   //
437   //  not a perfect way to do this
438   //    Document.cloneNode is implementation dependent but exists in L1
439   //       and implemented in IE.  The alternative brute force copy
440   //       only works in L2 or higher implementations and can't copy
441   //       entity and notation definitions, etc.
442   var clone = null;
443   try {
444       clone = document.cloneNode(true);
445   } catch(ex) {
446   }
447   if (clone == null) {
448       clone = document.implementation.createDocument(
449           document.documentElement.namespaceURI,
450           document.documentElement.nodeName,
451           null);
452       //
453       //   Work-around since
454       //   Safari does not create document element 
455       //      create document.      
456       if (clone.documentElement == null) {
457            clone.appendChild(clone.createElement(document.documentElement.nodeName));
458       }
459       var attrs = document.documentElement.attributes;
460       for(var i = 0; i < attrs.length; i++) {
461           var srcAttr = attrs.item(i);
462           clone.documentElement.setAttribute(srcAttr.nodeName, srcAttr.nodeValue);
463       }
464
465       var srcNode = document.firstChild;
466       while(srcNode != null && srcNode.nodeType != 1) {
467           if (srcNode.nodeType != 10) {
468                  var cloneNode = this.cloneNode(srcNode, clone);
469              clone.insertBefore(cloneNode, clone.documentElement);
470            }
471            srcNode = srcNode.nextSibling; 
472       }
473       srcNode = document.documentElement.nextSibling;
474       while(srcNode != null) {
475           var cloneNode = this.cloneNode(srcNode, clone);
476           clone.appendChild(cloneNode);
477           srcNode = srcNode.nextSibling;
478       }
479       srcNode = document.documentElement.firstChild;
480       while(srcNode != null) {
481           var cloneNode = this.cloneNode(srcNode, clone);
482           if (cloneNode != null) {
483              clone.documentElement.appendChild(cloneNode);
484           }
485           srcNode = srcNode.nextSibling;
486       }
487   }
488   return clone;
489 }
490
491 HTMLBuilder.prototype.getImplementationAttribute = function(attr) {
492     for (var i = 0; i < this.fixedAttributeNames.length; i++) {
493         if (this.fixedAttributeNames[i] == attr) {
494             return this.fixedAttributeValues[i];
495         }
496     }
497     throw "Unrecognized implementation attribute: " + attr;
498 }
499
500
501 HTMLBuilder.prototype.setImplementationAttribute = function(attribute, value) {
502     var supported = this.getImplementationAttribute(attribute);
503     if (supported != value) {
504         this.initializationError = "HTML loader does not support " + attribute + "=" + value;
505     }
506 }
507
508 HTMLBuilder.prototype.canSetImplementationAttribute = function(attribute, value) {
509     var supported = this.getImplementationAttribute(attribute);
510     return (supported == value);
511 }
512
513
514
515
516 function createConfiguredBuilder() {
517     return new HTMLBuilder();
518 }
519
520 function catchInitializationError(buildr, ex) {
521    buildr.initializationError = ex;
522    buildr.initializationFatalError = ex;
523 }
524
525 function toLowerArray(src) {
526    var newArray = new Array();
527    var i;
528    for (i = 0; i < src.length; i++) {
529       newArray[i] = src[i].toLowerCase();
530    }
531    return newArray;
532 }
533
534
535 function checkFeature(feature, version)
536 {
537   if (!builder.hasFeature(feature, version))
538   {
539     //
540     //   don't throw exception so that users can select to ignore the precondition
541     //
542     builder.initializationError = "builder does not support feature " + feature + " version " + version;
543   }
544 }
545
546 function setResult(resultType, message) {
547    var testName = getTargetURI();
548    document.open();
549    document.writeln("<html><head>");
550    document.writeln("<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; CHARSET=utf-8'>");    
551    document.write("<title>");
552    document.write(testName + ":" + resultType);
553    document.write("</title></head><body><table width='100%' border='1' style='color:");
554    if (resultType == null) {
555       document.writeln("green'><tr><td>Test:</td><td>" + testName + "</td></tr><tr><td>Status:</td><td>Success</td></tr>");
556    } else {
557       if (resultType == "skip") {
558         document.writeln("blue'><tr><td>Test:</td><td>" + testName + "</td></tr><tr><td>Status:</td><td>Skipped</td></tr>");
559       } else {
560         document.writeln("red'><tr><td>Test:</td><td>" + testName + "</td><td></tr><tr><td>Status:</td><td>" + resultType + "</td></tr>");
561       }
562    }
563    if (message != null) {
564                 document.writeln("<tr><td>Detail:</td><td>" + message + "</td></tr>");
565    }
566    document.write("</table></body></html>");
567    document.close();
568    if (parent != window) {
569        parent.setResult(testName, resultType, message);
570    }
571 }
572
573 function checkInitialization(buildr, testname) {
574    return buildr.initializationError;
575 }
576
577 function preload(docRef, varname, href) {
578    return builder.preload(docRef, varname, href);
579 }
580
581
582 function load(docRef, varname, href) {
583    return builder.load(docRef, varname, href);
584 }
585
586
587 function getImplementationAttribute(attr) {
588     return builder.getImplementationAttribute(attr);
589 }
590
591
592 function setImplementationAttribute(attribute, value) {
593     builder.setImplementationAttribute(attribute, value);
594 }
595
596 function createXPathEvaluator(doc) {
597     try {
598         return doc.getFeature("XPath", null);
599     }
600     catch(ex) {
601     }
602     return doc;
603 }
604
605
606 function getImplementation() {
607     return builder.getImplementation();
608 }
609
610 function assertEquals(id, expected, actual) {
611    var myActual;
612    if (expected != actual) {
613        myActual = actual;
614        if (actual == null) {
615           myActual = "null";
616        }
617        throw "failure:" + id + ": assertEquals failed, actual " + myActual + ", expected " + expected + "."; 
618    }
619 }
620
621 function assertNull(id, actual) {
622    if (actual != null) {
623        throw "failure:" + id + ": assertNull failed, actual " + actual;
624    }
625 }
626
627
628 function assertTrue(id, actual) {
629    if (!actual) {
630        throw "failure:" + id + ": assertTrue failed";
631    }
632 }
633
634
635 function assertFalse(id, actual) {
636    if (actual) {
637        throw "failure:" + id +  ": assertTrue failed";
638    }
639 }
640
641 function assertNotNull(id, actual) {
642    if (actual == null) {
643        throw "failure:" + id + ": assertNotNull failed";
644    }
645 }
646
647 function fail(id) {
648     throw "failure:" + id +  ": fail";
649 }
650
651
652
653 function getSuffix(contentType) {
654     switch(contentType) {
655         case "text/xml":
656         return ".xml";
657
658         case "application/xhtml+xml":
659         return ".xhtml";
660
661         case "image/svg+xml":
662         return ".svg";
663
664         case "text/mathml":
665         return ".mml";
666     }
667     return ".html";
668 }
669
670
671 function getResourceURI(name, scheme, contentType) {
672     var base = document.documentURI;
673     if (base == null) {
674        base = "";
675     } else {
676            base = base.substring(0, base.lastIndexOf('/') + 1) + "files/";
677     }
678     return base + name + getSuffix(contentType);
679 }
680
681
682
683 function startTest() {
684         //
685         //   invoke test setup
686         //
687         setUpPage();
688
689         try {
690             runTest();
691             if (builder.initializationError == null) {
692                setResult(null, null);
693             } else {
694                setResult("skip", builder.initializationError);
695             }
696         } catch(ex) {
697             if (typeof(ex.substring) != 'undefined' && ex.substring(0, 8) == "failure:") {
698             setResult("failure", ex.substring(8));
699         } else {
700             setResult("error", ex);
701         }
702     }
703 }