Bug 416553 - option to run accessibility tests, r=rcampbell
authorsurkov.alexander@gmail.com
Thu, 14 Feb 2008 02:32:21 -0800
changeset 11713 d1d0847a66a5890a8225aa961b6ac1244afd6301
parent 11712 e18651c2f2709d445078180d4e3b399a6845a516
child 11714 680f1692d750c38fd7127d8ac210892d050a2cf7
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrcampbell
bugs416553
milestone1.9b4pre
Bug 416553 - option to run accessibility tests, r=rcampbell
accessible/Makefile.in
accessible/tests/Makefile.in
accessible/tests/mochitest/Makefile.in
accessible/tests/mochitest/test_bug368835.xul
testing/mochitest/Makefile.in
testing/mochitest/harness-a11y.xul
testing/mochitest/harness-overlay.xul
testing/mochitest/harness.xul
testing/mochitest/redirect-a11y.html
testing/mochitest/redirect.html
testing/mochitest/redirect.js
testing/mochitest/runtests.pl.in
testing/mochitest/runtests.py.in
--- a/accessible/Makefile.in
+++ b/accessible/Makefile.in
@@ -38,12 +38,12 @@
 DEPTH   = ..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH   = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE	= accessibility
-DIRS    = public src build
+DIRS    = public src build tests
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH   = ../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH   = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE	= test_accessibility
+
+ifdef MOZ_MOCHITEST
+DIRS		+= mochitest
+endif
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES =\
+		test_bug368835.xul \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_bug368835.xul
@@ -0,0 +1,253 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<!--
+  Bug 368835 - fire TreeViewChanged/TreeRowCountChanged events.
+-->
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Mozilla Bug 368835">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript">
+  <![CDATA[
+    function inTreeView() { }
+
+    inTreeView.prototype =
+    {
+      mRowCount: 0,
+      mTree: null,
+      mData: {},
+
+      get rowCount() { return this.mRowCount; },
+      setTree: function(aTree) { this.mTree = aTree; },
+      getCellText: function(aRow, aCol)
+      {
+        var key = String(aRow)  + aCol.id;
+        if (key in this.mData)
+          return this.mData[key];
+
+        return "hello";
+      },
+      getRowProperties: function(aIndex, aProperties) {},
+      getCellProperties: function(aIndex, aCol, aProperties) {},
+      getColumnProperties: function(aCol, aProperties) {},
+      getParentIndex: function(aRowIndex) { },
+      hasNextSibling: function(aRowIndex, aAfterIndex) { },
+      getLevel: function(aIndex) {},
+      getImageSrc: function(aRow, aCol) {},
+      getProgressMode: function(aRow, aCol) {},
+      getCellValue: function(aRow, aCol) {},
+      isContainer: function(aIndex) {},
+      isContainerOpen: function(aIndex) {},
+      isContainerEmpty: function(aIndex) {},
+      isSeparator: function(aIndex) {},
+      isSorted: function() {},
+      toggleOpenState: function(aIndex) {},
+      selectionChanged: function() {},
+      cycleHeader: function(aCol) {},
+      cycleCell: function(aRow, aCol) {},
+      isEditable: function(aRow, aCol) {},
+      isSelectable: function(aRow, aCol) {},
+      setCellValue: function(aRow, aCol, aValue) {},
+      setCellText: function(aRow, aCol, aValue) { },
+      performAction: function(aAction) {},
+      performActionOnRow: function(aAction, aRow) {},
+      performActionOnCell: function(aAction, aRow, aCol) {}
+    };
+
+    var gTreeViewChanged = false;
+    function TreeViewChangedHandler(aEvent)
+    {
+      gTreeViewChanged = true;
+    }
+
+    var gTreeRowCountChanged = false;
+    function TreeRowCountChangedHandler(aEvent)
+    {
+      gTreeRowCountChanged = true;
+
+      var index = aEvent.getData("index");
+      is(index, 0, "Wrong 'index' data of 'treeRowCountChanged' event.");
+
+      var count = aEvent.getData("count");
+      is(count, 1, "Wrong 'count' data of 'treeRowCountChanged' event.");
+    }
+
+    var gTreeInvalidatedCount = 0;
+    function TreeInvalidatedHandler(aEvent)
+    {
+      gTreeInvalidatedCount++;
+      switch (gTreeInvalidatedCount) {
+        case 2:
+          TreeColumnInvalidatedHandler(aEvent);
+          break;
+        case 3:
+          TreeRowInvalidatedHandler(aEvent);
+          break;
+      }
+    }
+
+    var gTreeColumnInvalidated = false;
+    function TreeColumnInvalidatedHandler(aEvent)
+    {
+      var startRow = aEvent.getData("startrow");
+      is(startRow, null,
+         "Wrong 'startrow' of 'treeInvalidated' event on InvalidateColumn().");
+
+      var endRow = aEvent.getData("endrow");
+      is(endRow, null,
+         "Wrong 'endrow' of 'treeInvalidated' event on InvalidateColumn().");
+
+      var startCol = aEvent.getData("startcolumn");
+      is(startCol, 0,
+         "Wrong 'startcolumn' of 'treeInvalidated' event on InvalidateColumn().");
+
+      var endCol = aEvent.getData("endcolumn");
+      is(endCol, 0,
+         "Wrong 'endcolumn' of 'treeInvalidated' event on InvalidateColumn().");
+
+      gTreeColumnInvalidated = true;
+    }
+
+    var gTreeRowInvalidated = false;
+    function TreeRowInvalidatedHandler(aEvent)
+    {
+      var startRow = aEvent.getData("startrow");
+      is(startRow, 1,
+         "Wrong 'startrow' of 'treeInvalidated' event on InvalidateColumn().");
+
+      var endRow = aEvent.getData("endrow");
+      is(endRow, 1,
+         "Wrong 'endrow' of 'treeInvalidated' event on InvalidateColumn().");
+
+      var startCol = aEvent.getData("startcolumn");
+      is(startCol, null,
+         "Wrong 'startcolumn' of 'treeInvalidated' event on InvalidateColumn().");
+
+      var endCol = aEvent.getData("endcolumn");
+      is(endCol, null,
+         "Wrong 'endcolumn' of 'treeInvalidated' event on InvalidateColumn().");
+
+      gTreeRowInvalidated = true;
+    }
+
+    function CheckEvents()
+    {
+      // If these fail then it doesn't mean actually events are not fired,
+      // possibly setTimeout was executed earlier than events have beenS fired.
+
+      ok(gTreeViewChanged,
+         "TreeViewChanged event should have been fired.");
+      ok(gTreeRowCountChanged,
+         "TreeRowCountChanged event should have been fired.");
+      ok(gTreeColumnInvalidated,
+         "TreeInvalidated event should have been fired for InvalidateColumn().");
+      ok(gTreeRowInvalidated,
+         "TreeInvalidated event should have been fired for InvalidateRow().");
+
+      document.removeEventListener("TreeViewChanged",
+                                   TreeViewChangedHandler, true);
+
+      document.removeEventListener("TreeRowCountChanged",
+                                   TreeRowCountChangedHandler, true);
+
+      document.removeEventListener("TreeInvalidated",
+                                   TreeInvalidatedHandler, true);
+
+      SimpleTest.finish();
+    }
+
+    var gAccService = null;
+
+    function doTest()
+    {
+      // Check whether accessbility support is enabled.
+      if (!("@mozilla.org/accessibleRetrieval;1" in Components.classes)) {
+        SimpleTest.finish();
+        return;
+      }
+
+      // Activate accessibility, otherwise events aren't fired.
+      gAccService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                    getService(Components.interfaces.nsIAccessibleRetrieval);
+
+      // Add event listeners
+      document.addEventListener("TreeViewChanged",
+                                TreeViewChangedHandler, true);
+      document.addEventListener("TreeRowCountChanged",
+                                TreeRowCountChangedHandler, true);
+      document.addEventListener("TreeInvalidated",
+                                TreeInvalidatedHandler, true);
+
+      // Initialize the tree
+      var tree = document.getElementById("tree");
+      var treeBox = tree.treeBoxObject;
+
+      var view = new inTreeView();
+      view.mRowCount = 5;
+
+      // Fire 'TreeViewChanged' event
+      treeBox.view = view;
+
+      // Fire 'TreeRowCountChanged' changed
+      ++view.mRowCount;
+      treeBox.rowCountChanged(0, 1);
+
+      // Fire 'TreeInvalidated' event by InvalidateColumn()
+      var firstCol = treeBox.columns.getFirstColumn();
+      for (var i = 0; i < view.mRowCount; i++) {
+        var key = String(i) + firstCol.id;
+        view.mData[key] = key + "_col";
+      }
+
+      treeBox.invalidateColumn(firstCol);
+
+      // Fire 'TreeInvalidated' event by InvalidateRow()
+      var colCount = tree.columns.count;
+      for (var i = 0; i < colCount; i++) {
+        var key = "1" + tree.columns.getColumnAt(i).id;
+        view.mData[key] = key + "_row";
+      }
+
+      treeBox.invalidateRow(1);
+
+      // Wait for events.
+      if (gTreeViewChanged && gTreeRowCountChanged &&
+          gTreeColumnInvalidated)
+        CheckEvents();
+      else
+        window.setTimeout(CheckEvents, 1000);
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=368835">
+      Mozilla Bug 368835
+    </a>
+    <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <pre id="test">
+    </pre>
+  </body>
+
+  <tree id="tree" flex="1">
+    <treecols>
+      <treecol id="col" flex="1" primary="true" label="column"/>
+      <treecol id="scol" flex="1" label="column 2"/>
+    </treecols>
+    <treechildren id="treechildren"/>
+  </tree>
+</window>
+
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -52,21 +52,25 @@ DIRS =	MochiKit \
 include $(topsrcdir)/config/rules.mk
 
 # files that get copied into $objdir/_tests/
 _SERV_FILES = 	\
 		runtests.pl \
 		runtests.py \
 		gen_template.pl \
 		server.js \
+		harness-a11y.xul \
+		harness-overlay.xul \
 		harness.xul \
 		browser-test-overlay.xul \
 		browser-test.js \
 		browser-harness.xul \
+		redirect-a11y.html \
 		redirect.html \
+		redirect.js \
 		$(topsrcdir)/netwerk/test/httpserver/httpd.js \
 		$(NULL)	
 
 
 _DEST_DIR = $(DEPTH)/_tests/$(relativesrcdir)
 
 ifeq ($(USE_SHORT_LIBNAME), 1)
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/harness-a11y.xul
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/static/harness.css" 
+                 type="text/css"?>
+                 
+<?xul-overlay href="chrome://mochikit/content/harness-overlay.xul"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessibility Chrome Test Harness"
+        id="browserTestOverlay"
+        aonload="loadTests('chrome');">
+  <script type="text/javascript">
+    gDir = "a11y";
+  </script>
+</window>
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/harness-overlay.xul
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<overlay id="browserTestOverlay"
+         xmlns:html="http://www.w3.org/1999/xhtml"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+         xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<window>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="text/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/>
+  <script type="text/javascript"
+   src="chrome://mochikit/content/tests/SimpleTest/MozillaFileLogger.js"/>
+  <script type="text/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/quit.js" />
+  <script type="text/javascript" 
+          src="chrome://mochikit/content/tests/SimpleTest/setup.js" />
+  <script type="application/javascript;version=1.7"><![CDATA[
+    function loadTests(aDir)
+    {
+      // Find our chrome dir
+      var ios = Cc["@mozilla.org/network/io-service;1"].
+                  getService(Ci.nsIIOService);
+      var chromeURI = ios.newURI("chrome://mochikit/content/",
+                                 null, null);
+      var resolvedURI = Cc["@mozilla.org/chrome/chrome-registry;1"].
+                          getService(Ci.nsIChromeRegistry).
+                          convertChromeURL(chromeURI);
+      var fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
+                          getService(Ci.nsIFileProtocolHandler);
+      var chromeDir = fileHandler.getFileFromURLSpec(resolvedURI.spec);
+      chromeDir = chromeDir.parent.QueryInterface(Ci.nsILocalFile);
+      chromeDir.appendRelativePath(aDir);
+
+      // load server.js in so we can share template functions
+      var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+                           getService(Ci.mozIJSSubScriptLoader);
+      var srvScope = {};
+      scriptLoader.loadSubScript("chrome://mochikit/content/server.js",
+                                 srvScope);
+
+      // generate our test list
+      srvScope.makeTags();
+      var url = "chrome://mochikit/content/" + aDir + "/";
+      var [links, count] = srvScope.list(url, chromeDir, true);
+      var listContent = srvScope.linksToListItems(links);
+      var tableContent = srvScope.linksToTableRows(links);
+      function populate() {
+        $("list-holder").setAttribute("rowspan", 1 + count);
+        $("test-list").innerHTML += listContent;
+        $("test-table").innerHTML += tableContent;
+        $("wrapper").innerHTML += " "; // redraw the table
+      }
+      gTestList = eval(srvScope.jsonArrayOfTestFiles(links));
+      connect(window, 'onload', populate);
+      connect(window, 'onload', hookup);
+    }
+
+    loadTests(gDir);
+  ]]>
+  </script>
+
+  <vbox>   
+    <button label="Run Chrome Tests" id="runtests" flex="1"/>
+
+    <body xmlns="http://www.w3.org/1999/xhtml" id="xulharness">
+      <div class="container">
+        <p style="float:right;">
+          <small>Based on the MochiKit unit tests.</small>
+        </p>
+        <div class="status">
+          <h1 id="indicator">Status</h1>
+          <h2 id="pass">Passed: <span id="pass-count">0</span></h2>
+          <h2 id="fail">Failed: <span id="fail-count">0</span></h2>
+          <h2 id="fail">Todo: <span id="todo-count">0</span></h2>
+        </div>
+        <div class="clear"></div>
+        <div id="current-test">
+          <b>Currently Executing: <span id="current-test-path">_</span></b>
+        </div>
+        <div class="clear"></div>
+        <div class="frameholder">
+          <iframe scrolling="no" id="testframe" width="500"></iframe>
+        </div>
+        <div class="clear"></div>
+        <div class="toggle">
+          <a href="#" id="toggleNonTests">Show Non-Tests</a>
+          <br />
+        </div>
+        <div id="wrapper">
+          <table cellpadding="0" cellspacing="0" id="test-table">
+            <tr>
+              <td>Passed</td>
+              <td>Failed</td>
+              <td>Todo</td>
+              <td id="list-holder">
+                <ul class="top" id="test-list"><li><b>Test Files</b></li></ul>
+              </td>
+            </tr>
+          </table>
+        </div>
+      </div>
+    </body>
+  </vbox>
+</window>
+
+</overlay>
--- a/testing/mochitest/harness.xul
+++ b/testing/mochitest/harness.xul
@@ -1,97 +1,15 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="chrome://mochikit/content/static/harness.css" 
                  type="text/css"?>
-<window title="Chrome Test Harness"
-  xmlns:html="http://www.w3.org/1999/xhtml"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <script type="application/javascript"
-          src="chrome://mochikit/content/MochiKit/packed.js" />
-  <script type="text/javascript"
-	  src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/>
-  <script type="text/javascript"
-   src="chrome://mochikit/content/tests/SimpleTest/MozillaFileLogger.js"/>
-  <script type="text/javascript"
-	  src="chrome://mochikit/content/tests/SimpleTest/quit.js" />
-  <script type="text/javascript" 
-	  src="chrome://mochikit/content/tests/SimpleTest/setup.js" />
-  <script type="application/javascript;version=1.7"><![CDATA[
-    /** Find our chrome dir **/
-    var ios = Cc["@mozilla.org/network/io-service;1"].
-                getService(Ci.nsIIOService);
-    var chromeURI = ios.newURI("chrome://mochikit/content/",
-                               null, null);
-    var resolvedURI = Cc["@mozilla.org/chrome/chrome-registry;1"].
-                        getService(Ci.nsIChromeRegistry).
-                        convertChromeURL(chromeURI);
-    var fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
-                        getService(Ci.nsIFileProtocolHandler);
-    var chromeDir = fileHandler.getFileFromURLSpec(resolvedURI.spec);
-    chromeDir = chromeDir.parent.QueryInterface(Ci.nsILocalFile);
-    chromeDir.appendRelativePath("chrome");
-
-    /** load server.js in so we can share template functions **/
-    var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
-                         getService(Ci.mozIJSSubScriptLoader);
-    var srvScope = {};
-    scriptLoader.loadSubScript("chrome://mochikit/content/server.js", srvScope);
+                 
+<?xul-overlay href="chrome://mochikit/content/harness-overlay.xul"?>
 
-    /** generate our test list **/
-    srvScope.makeTags();
-    var [links, count] = srvScope.list("chrome://mochikit/content/chrome/",
-                                       chromeDir, true);
-    var listContent = srvScope.linksToListItems(links);
-    var tableContent = srvScope.linksToTableRows(links);
-    function populate() {
-      $("list-holder").setAttribute("rowspan", 1 + count);
-      $("test-list").innerHTML += listContent;
-      $("test-table").innerHTML += tableContent;
-      $("wrapper").innerHTML += " "; // redraw the table
-    }
-    gTestList = eval(srvScope.jsonArrayOfTestFiles(links));
-    connect(window, 'onload', populate);
-    connect(window, 'onload', hookup);
-  ]]>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Chrome Test Harness"
+        id="browserTestOverlay"
+        aonload="loadTests('chrome');">
+  <script type="text/javascript">
+    gDir = "chrome";
   </script>
-  <vbox>   
-    <button label="Run Chrome Tests" id="runtests" />
-    <body xmlns="http://www.w3.org/1999/xhtml" id="xulharness">
-      <div class="container">
-	<p style="float:right;">
-	  <small>Based on the MochiKit unit tests.</small>
-	</p>
-	<div class="status">
-	  <h1 id="indicator">Status</h1>
-	  <h2 id="pass">Passed: <span id="pass-count">0</span></h2>
-	  <h2 id="fail">Failed: <span id="fail-count">0</span></h2>
-	  <h2 id="fail">Todo: <span id="todo-count">0</span></h2>
-	</div>
-	<div class="clear"></div>
-	<div id="current-test">
-	  <b>Currently Executing: <span id="current-test-path">_</span></b>
-	</div>
-	<div class="clear"></div>
-	<div class="frameholder">
-	  <iframe
-           scrolling="no" id="testframe" width="500"></iframe>
-	</div>
-	<div class="clear"></div>
-	<div class="toggle">
-	  <a href="#" id="toggleNonTests">Show Non-Tests</a>
-          <br />
-	</div>
-        <div id="wrapper">
-	  <table cellpadding="0" cellspacing="0" id="test-table">
-	    <tr>
-	      <td>Passed</td>
-	      <td>Failed</td>
-	      <td>Todo</td>
-	      <td id="list-holder"><ul class="top" id="test-list"><li><b>Test Files</b></li></ul></td>
-	    </tr>
-	  </table>
-        </div>
-      </div>
-    </body>
-  </vbox>
 </window>
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/redirect-a11y.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+  <title>redirecting...</title>
+
+  <script type="text/javascript" src="redirect.js"></script>
+
+  <script type="text/javascript">
+    redirect("chrome://mochikit/content/harness-a11y.xul");
+  </script>
+</head>
+<body>
+redirecting...
+</body>
+</html>
--- a/testing/mochitest/redirect.html
+++ b/testing/mochitest/redirect.html
@@ -1,22 +1,14 @@
 <html>
 <head>
   <title>redirecting...</title>
 
-  <script type="text/javascript">
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  <script type="text/javascript" src="redirect.js"></script>
 
-  const Cc = Components.classes;
-  const Ci = Components.interfaces;
-    
-  var windowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].
-                         getService(Ci.nsIWindowMediator);
-  var win = windowMediator.getMostRecentWindow("navigator:browser");
-  win.getWebNavigation().loadURI("chrome://mochikit/content/harness.xul" +
-                                 location.search,
-                                 null, null, null, null);
+  <script type="text/javascript">
+    redirect("chrome://mochikit/content/harness.xul");
   </script>
 </head>
 <body>
 redirecting...
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/redirect.js
@@ -0,0 +1,53 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MozJSHTTP code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert Sayre <sayrer@gmail.com>
+ *   Alexander Surkov <surkov.alexander@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function redirect(aURL)
+{
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  
+  const Cc = Components.classes;
+  const Ci = Components.interfaces;
+  
+  var windowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].
+  getService(Ci.nsIWindowMediator);
+  var win = windowMediator.getMostRecentWindow("navigator:browser");
+  win.getWebNavigation().loadURI(aURL + location.search,
+                                 null, null, null, null);
+}
--- a/testing/mochitest/runtests.pl.in
+++ b/testing/mochitest/runtests.pl.in
@@ -86,18 +86,20 @@ use strict;
  # consoleLevel, fileLevel: set the logging level of the console and
  # file logs, if activated.
  # <http://mochikit.com/doc/html/MochiKit/Logging.html>
 
  # Path to the test script on the server
 use constant TEST_SERVER_HOST => "localhost:8888";
 use constant TEST_PATH => "/tests/";
 use constant CHROME_PATH => "/redirect.html";
+use constant A11Y_PATH => "/redirect-a11y.html";
 use constant TESTS_URL => "http://" . TEST_SERVER_HOST . TEST_PATH;
 use constant CHROMETESTS_URL => "http://" . TEST_SERVER_HOST . CHROME_PATH;
+use constant A11YTESTS_URL => "http://" . TEST_SERVER_HOST . A11Y_PATH;
 
  # Max time in seconds to wait for server startup before tests will fail -- if
  # this seems big, it's mostly for debug machines where cold startup
  # (particularly after a build) takes forever.
 use constant SERVER_STARTUP_TIMEOUT => 45;
 
 
  # Since some tests require cross-domain support in Mochitest, across ports,
@@ -159,26 +161,27 @@ my $unixish = (!($is_win32) && !($is_mac
 
  #################
  # MAIN FUNCTION #
  #################
 
 sub main {
   my ($close_when_done, $appoverride, $log_path, $autorun,
       $console_level, $file_level, $help, $do_chrome, $test_path,
-      $do_browser_chrome, %browser_env, %browser_args);
+      $do_browser_chrome, $do_a11y, %browser_env, %browser_args);
   GetOptions("close-when-done!"=> \$close_when_done,
              "appname:s"=> \$appoverride,
              "log-file:s" => \$log_path,
              "autorun!" => \$autorun,
              "console-level:s" => \$console_level,
              "file-level:s" => \$file_level,
              "chrome!" => \$do_chrome,
              "test-path:s" => \$test_path,
              "browser-chrome!" => \$do_browser_chrome,
+             "a11y!" => \$do_a11y,
              "setenv=s%" => \%browser_env,
              "browser-arg=s%" => \%browser_args,
              "help!" => \$help);
 
   # if the switches include --help, exit and print directions
   if ($help) {
     usage_and_exit();
   }
@@ -208,16 +211,18 @@ sub main {
 
   my $url;
   if ($do_chrome) {
    $url = CHROMETESTS_URL . ($test_path ? $test_path : "") . "?";
   } elsif ($do_browser_chrome) {
    # Tests will run from an overlay, no need to load any URL.  We'll include
    # the test path in the config file so the browser chrome harness can use it.
    $url = "about:blank";
+  } elsif ($do_a11y) {
+   $url = A11YTESTS_URL . ($test_path ? $test_path : "") . "?";
   } else {
    $url = TESTS_URL . ($test_path ? $test_path : "") . "?";
   }
 
   if ($do_browser_chrome) {
     generate_test_config($autorun, $close_when_done, $log_path, $test_path);
   } else {
     if ($autorun) {
@@ -254,24 +259,26 @@ sub main {
  #######################
  # COMMANDLINE USAGE   #
  #######################
 
 sub usage_and_exit {
   print "\n";
   print "Usage instructons for runtests.pl.\n";
   print "If --log-file is specified, --file-level must be specified as well.\n";
-  print "If --chrome is specified, chrome tests will be run instead of web content tests";
-  print "If --browser-chrome is specified, browser-chrome tests will be run instead of web content tests";
+  print "If --chrome is specified, chrome tests will be run instead of web content tests.\n";
+  print "If --browser-chrome is specified, browser-chrome tests will be run instead of web content tests.\n";
+  print "If --a11y is specified, a11y tests will be run instead of web content tests.";
   print "\n\n";
   print "Syntax:\n";
   print "  runtests.pl \\\n";
   print "   [--autorun] \\\n";
   print "   [--chrome] \\\n";
   print "   [--browser-chrome] \\\n";
+  print "   [--a11y] \\\n";
   print "   [--close-when-done] \\\n";
   print "   [--appname=/path/to/app] \\\n";
   print "   [--log-file=/path/to/logfile] \\\n";
   print "   [--test-path=relative/path/to/tests] \\\n";
   print "   [--setenv=VAR=value] \\\n";  
   print "   [--browser-arg=VAR=value] \\\n";
   print "   [--file-level=DEBUG|INFO|ERROR|FATAL|WARNING] \\\n";  
   print "   [--console-level=DEBUG|INFO|ERROR|FATAL|WARNING] \n\n";  
--- a/testing/mochitest/runtests.py.in
+++ b/testing/mochitest/runtests.py.in
@@ -54,18 +54,20 @@ from urllib import quote_plus as encodeU
 import urllib2
 import commands
 
 
 # Path to the test script on the server
 TEST_SERVER_HOST = "localhost:8888"
 TEST_PATH = "/tests/"
 CHROME_PATH = "/redirect.html";
+A11Y_PATH = "/redirect-a11y.html"
 TESTS_URL = "http://" + TEST_SERVER_HOST + TEST_PATH
 CHROMETESTS_URL = "http://" + TEST_SERVER_HOST + CHROME_PATH
+A11YTESTS_URL = "http://" + TEST_SERVER_HOST + A11Y_PATH
 SERVER_SHUTDOWN_URL = "http://" + TEST_SERVER_HOST + "/server/shutdown"
 
 # Max time in seconds to wait for server startup before tests will fail -- if
 # this seems big, it's mostly for debug machines where cold startup
 # (particularly after a build) takes forever.
 SERVER_STARTUP_TIMEOUT = 45
 
 # Since some tests require cross-domain support in Mochitest, across ports,
@@ -189,16 +191,20 @@ class MochitestOptions(optparse.OptionPa
                     help = "start in the given directory's tests")
     defaults["testPath"] = ""
 
     self.add_option("--browser-chrome",
                     action = "store_true", dest = "browserChrome",
                     help = "run browser chrome Mochitests")
     defaults["browserChrome"] = False
 
+    self.add_option("--a11y",
+                    action = "store_true", dest = "a11y",
+                    help = "run accessibility Mochitests");
+
     self.add_option("--setenv",
                     action = "append", type = "string", dest = "environment",
                     help = "given a VAR=value pair, sets that in the "
                            "browser's environment")
     defaults["environment"] = []
     
     self.add_option("--browser-arg",
                     action = "append", type = "string", dest = "browserArgs",
@@ -391,16 +397,18 @@ Are you executing $objdir/_tests/testing
   
   # consoleLevel, fileLevel: set the logging level of the console and
   # file logs, if activated.
   # <http://mochikit.com/doc/html/MochiKit/Logging.html>
 
   testURL = TESTS_URL + options.testPath
   if options.chrome:
     testURL = CHROMETESTS_URL + options.testPath
+  elif options.a11y:
+    testURL = A11YTESTS_URL + options.testPath
   elif options.browserChrome:
     testURL = "about:blank"
 
   if options.browserChrome:
     makeTestConfig(options)
   else:
     urlOpts = []
     if options.autorun: