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