New
authorPhilippe Le Hégaret <plh@w3.org>
Fri, 21 Nov 2008 18:20:33 +0000
changeset 10 c723c30e99cb
parent 9 2d791918f67b
child 11 ec5577c78753
New
testsuite/web-framework/JWP.js
testsuite/web-framework/NCAM.js
testsuite/web-framework/START.html
testsuite/web-framework/functions.js
testsuite/web-framework/generate_tests.js.xslt
testsuite/web-framework/style.css
testsuite/web-framework/tests.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/JWP.js	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,42 @@
+// Display a video with the specified DFXP captioning document
+
+var JWP_NAME = "JW FLV Media Player 4.2";
+
+addPlayer(JWP_NAME, "startJWPPlayer", "activeJWPTest", "stopJWPPlayer");
+
+function startJWPPlayer()
+{
+    alert("Note that the "
+	  + JWP_NAME
+	  + " only works properly when accessing captioning files from a web server.");
+}
+
+function activeJWPTest(test_number, filename, autostart, div) 
+{
+
+    div.innerHTML = '';
+
+    // @@ to be replaced with more appropriate code...
+    var embed = document.createElement("embed");
+    embed.setAttribute("src", "player.swf");
+    embed.setAttribute("flashvars", 
+		       "bufferlength=5&file=movie.flv&captions=" 
+		       + filename
+		       + "&mute=true&plugins=accessibility&autostart="
+		       + autostart);
+    embed.setAttribute("seamlesstabbing", "true");
+    embed.setAttribute("bgcolor", "white");
+    embed.setAttribute("width", "340");
+    embed.setAttribute("height", "376");
+    embed.setAttribute("align", "middle");
+    embed.setAttribute("allowScriptAccess", "always");
+    embed.setAttribute("type", "application/x-shockwave-flash");
+
+    // append the object
+    div.appendChild(embed);
+}
+
+function stopJWPPlayer()
+{
+    // nothing can be done?
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/NCAM.js	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,76 @@
+// Display a video with the specified DFXP captioning document
+// 1. Create one function with no parameter to start your player.
+// 2. Create a function to activate your player with a test, as follows:
+//    a. the function takes five parameters:
+//       1. integer: The test unique number [inte
+//       2. string: filename of the test
+//       3. boolean: if autostart should be on or off
+//       4. DOM Element: the DOM div element containing your player object
+//    b. the player goes in <div id="testarea">
+// 3. Create one function with no parameter to stop your player.
+// 4. Invoke addPlayer("name of the player", "YourActivateFunctionName", "YourStopFunctionName") to add your player
+
+addPlayer("NCAM Player 3.0.1", "startNCAMPlayer", "activeNCAMTest", "stopNCAMPlayer");
+
+function startNCAMPlayer() {
+}
+
+function activeNCAMTest(test_number, filename, autostart, div) {
+
+    var value = "ccPlayer.swf?ccVideoName=movie.flv&ccVideoAutoStart="
+		   + autostart
+		   + "&ccCaptSourceType=external&ccCaptionSource="
+		   + filename
+		   + "&ccCaptionLanguage=en&ccCaptionAutoHide=false";
+    if (-1 != navigator.userAgent.indexOf("MSIE")) {
+	// once again, a workaround for IE :-/
+	div.innerHTML =
+	    '<OBJECT width="340" height="376" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
+	    + 'codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" type="application/x-shockwave-flash">'
+	    + '<PARAM name="movie" class="object" value="'
+	    + value
+	    + '/><PARAM name="bgcolor" value="#cccccc"/><PARAM name="allowScriptAccess" value="sameDomain"/>'
+	    + '<EMBED width="340" height="376" src="'
+	    + value
+	    + '" bgcolor="#cccccc" allowscriptaccess="sameDomain" type="application/x-shockwave-flash"/></OBJECT>';
+    } else {
+	div.innerHTML = '';
+	// Create the object
+	var obj = document.createElement("object");
+	obj.setAttribute("classid", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000");
+	obj.setAttribute("codebase", "http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0");
+	obj.setAttribute("width", "340");
+	obj.setAttribute("height", "376");
+	obj.setAttribute("type", "application/x-shockwave-flash");
+	var p = document.createElement("param");
+	p.setAttribute("name", "movie");
+	p.setAttribute("class", "object");
+	p.setAttribute("value", value);
+	obj.appendChild(p);
+	p = document.createElement("param");
+	p.setAttribute("name", "bgcolor");
+	p.setAttribute("value", "#cccccc");
+	obj.appendChild(p);
+	p = document.createElement("param");
+	p.setAttribute("name", "allowScriptAccess");
+	p.setAttribute("value", "sameDomain");
+	obj.appendChild(p);
+	var embed = document.createElement("embed");
+	embed.setAttribute("src", value);
+	embed.setAttribute("bgcolor", "#cccccc");
+	embed.setAttribute("width", "340");
+	embed.setAttribute("height", "376");
+	embed.setAttribute("allowScriptAccess", "always");
+	embed.setAttribute("type", "application/x-shockwave-flash");
+	obj.appendChild(embed);
+	
+	// append the object
+	div.appendChild(obj);
+    }
+
+}
+
+function stopNCAMPlayer(test_number)
+{
+    // nothing can be done?
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/START.html	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,64 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+    <title>Run the DFXP 1.0 test suite</title>
+
+    <link type="text/css" rel="stylesheet" href="style.css">
+    <script type="text/javascript" src='functions.js'></script>
+    <script type="text/javascript" src='tests.js'></script>
+    <script type="text/javascript" src='NCAM.js'></script>
+    <script type="text/javascript" src="swfobject.js"></script>
+    <script type="text/javascript" src='JWP.js'></script>
+  </head>
+  <body onload='init();'>
+    <div id='header'>
+      <h2>Test an implementation against the DFXP 1.0 test suite</h2>
+      
+      <form action='nothing'>
+	<table class='options1'>
+	  <tbody>
+	    <tr>
+	      <th>Player in test</th>
+	      <td><select id='players' onchange="switchPlayer(this.selectedIndex);"></select></td>
+	    </tr>
+	    <tr>
+	      <th>Test set</th>
+	      <td><select id='categories' onchange="handleSelection(this.selectedIndex);"></select></td>
+	    </tr>
+	  </tbody>
+	</table>
+	<table class='options2'>
+	  <tbody>
+	    <tr>
+	      <td><input type="checkbox" id="skipOnResult" value="changed" onchange='switchSkipOnResult(this.checked);'></td>
+	      <th>Autostart next test</th>
+	    </tr>
+	    <tr>
+	      <td><input type="checkbox" id="autostart" value="changed" onchange='switchAutostart(this.checked);'></td>
+	      <th>Autostart video</th>
+	    </tr>
+	    </tr>
+	  </tbody>
+	</table>
+      </form>
+    </div>
+
+    <div id='testarea'>
+      <p id='result'></p>
+      <h2 id='title'></h2>
+      <p id='description'></p>  
+      <div id='testobject'></div>
+    </div>
+
+    <div id='content'>
+      <div id='tables'>
+	<div id='report'>
+	  <h3>Report</h3>
+	  <div id='report_content'></div>
+	</div>
+      </div>
+    </div>
+    
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/functions.js	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,629 @@
+
+//****************************
+// Handling the lists of tests
+//****************************
+
+
+// list of tests
+var tests = new Array();
+
+// Some constants to make it easier
+var NAME         = 0;
+var FILE         = 1;
+var DESCRIPTION  = 2;
+var CATEGORY     = 3;
+var CATEGORY_NUM = 4;
+
+function addTest(filename, name, description, category)
+{
+    var cat = addCategory(category);
+    tests[tests.length] = new Array(name, filename, description, cat);
+}
+
+//*********************************
+// Handling the lists of categories
+//
+// each test is attached to one category
+//
+//*********************************
+
+
+var categories = new Array();
+categories[0] = "All test sets";
+
+var category = 0;
+
+function addCategory(name)
+{
+    var i = 0;
+    while (i < categories.length) {
+	if (categories[i] == name) return i;
+	i++;
+    }
+    categories[i] = name;
+    return i;
+}
+
+function switchCategory(cat)
+{
+    category = cat;
+
+    var tables = document.getElementById("tables");
+
+    for (var c = 1; c < categories.length; c++ ) {
+	if (cat == 0) {
+	    tables.childNodes.item(c-1).style.cssText = '';
+	} else if (c == category) {
+	    // setAttribute("class" or "style" doesn't work in IE :-(
+	    tables.childNodes.item(c-1).style.cssText = '';
+	} else {
+	    // setAttribute("class" or "style" doesn't work in IE :-(
+	    tables.childNodes.item(c-1).style.cssText = 'display:none';
+	}
+    }
+    
+}
+
+//***************************
+// Handling the player to use
+//***************************
+
+// list of players
+var players = new Array();
+// the player in use
+var player = -1;
+var autostart = false;
+
+// A constant to make it easier to access the array
+// var NAME = 0; is already defined
+var START_FUNCTION_NAME = 1;
+var ACTIVATE_FUNCTION_NAME = 2;
+var STOP_FUNCTION_NAME = 3;
+
+function addPlayer(name,
+		   startFunctionName,
+		   activateFunctionName, 
+		   stopFunctionName)
+{
+    players[players.length] = new Array(name,
+					startFunctionName,
+					activateFunctionName,
+					stopFunctionName);
+}
+
+
+// switch from one player to an other
+function switchPlayer(nPlayer) {
+
+    // remove the test currently in use
+    clearTestArea();
+
+    // reset the table of pass/fail
+    resetAll();
+
+    // reset the report
+    var report_content = document.getElementById("report_content");
+    report_content.innerHTML = '';
+
+    // switch
+    player = nPlayer;
+
+    eval(players[player-1][START_FUNCTION_NAME] + "()");
+}
+
+function switchAutostart(nAutostart)
+{
+    autostart = nAutostart;
+}
+
+
+//***************************
+// Handling a test
+//***************************
+
+var currentTest = -1;
+
+function source_handler() {
+    if (this.readyState == 4
+	&& this.status == 200
+	&& this.responseText != null) {
+	// success!
+	var div = document.getElementById('testobject');
+	var pre = document.createElement("pre");
+	pre.appendChild(document.createTextNode(this.responseText));
+	div.appendChild(pre);
+    }
+}
+
+if (typeof XMLHttpRequest == "undefined" ) {
+    // Provide the XMLHttpRequest class for IE 5.x-6.x:
+    XMLHttpRequest = function() {
+	try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
+	try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
+	try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
+	try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
+	throw new Error( "This browser does not support XMLHttpRequest." )
+    };
+}
+
+// Display the source of a test
+function displayTest(test_number) 
+{
+    var title=document.getElementById("title");
+    var div = document.getElementById('testobject');
+
+    clearTestArea();
+
+    if (test_number > -1 && test_number < tests.length) {
+	title.innerHTML = tests[test_number][FILE];
+	try {
+	    var xhr = new XMLHttpRequest();
+	    xhr.onreadystatechange = source_handler;
+	    xhr.open("GET", tests[test_number][FILE], true);
+	    xhr.send("");
+	} catch (e) {
+	    div.innerHTML = "<p style='font-weight: bold'>No player selected...</p>";
+	}
+    }
+}
+
+// Run a dedicated test with the appropriate player
+function activeTest(test_number) 
+{
+    var title=document.getElementById("title");
+    var descr=document.getElementById("description");
+
+    if (test_number > -1 && test_number < tests.length) {
+	title.innerHTML = tests[test_number][NAME];
+	descr.innerHTML = tests[test_number][DESCRIPTION];
+	if (player == 0) {
+	    var div = document.getElementById('testobject');
+	    div.innerHTML = '<p><b>Choose a player...</b></p>';	    
+	} else {
+	    addResultButtons(test_number);
+	    
+	    eval(players[player-1][ACTIVATE_FUNCTION_NAME] + "("
+		 + test_number + ",\""
+		 + tests[test_number][FILE] + "\","
+		 + autostart
+		 + ", document.getElementById('testobject'))");
+	}
+	currentTest = test_number;
+    }
+}
+
+// return the next test number to be executed or -1 if none
+function nextTestNumber(test_number)
+{
+    var i = test_number + 1;
+    while (i < results.length) {
+	if (category == 0 || category == tests[i][CATEGORY]) {
+	    return i;
+	}
+	i++;
+    }
+    return -1;
+}
+
+// stop the current test and move to the next
+function moveToNextTest(test_number)
+{
+    var next = nextTestNumber(test_number);
+    if (next == -1) {
+	clearTestArea();
+    } else {
+	stopTest(currentTest);
+	activeTest(next);
+    }
+}
+
+// stop the player if running
+function stopTest(test_number)
+{
+    if (test_number > -1 && test_number < tests.length) {
+	if (player > 0) {
+	    eval(players[player-1][STOP_FUNCTION_NAME] + "("
+		 + test_number + ")");
+	    currentTest = -1;
+	}
+    }
+    currentTest = -1;
+}
+
+// Remove the current test
+// stop the player if running and clear the test area
+function clearTestArea()
+{
+    // first stop the test
+    stopTest(currentTest);
+
+    // clean up the HTML elements
+    var div = document.getElementById("testobject");
+    div.innerHTML = '';
+    var title = document.getElementById("title");
+    title.innerHTML = "";
+    var descr = document.getElementById("description");
+    descr.innerHTML = "";
+    var p = document.getElementById("result");
+    p.innerHTML = "";
+
+}
+
+//************************************
+// Handle the fail/pass/unknown status
+//************************************
+
+var results = new Array();
+
+var skipOnResult = false;
+
+// Some constants to make it easier to access the array
+var UNKNOWN = 0;
+var PASS    = 1;
+var FAIL    = 2;
+var CANT_TELL = 3;
+
+function initResults()
+{
+    for (i = 0; i < tests.length; i++) {
+	results[i] = UNKNOWN;
+    }
+}
+
+// reset the table of pass/fail
+function addResultButtons(test_number)
+{
+    var p = document.getElementById("result");
+    s =
+	"<input value='Pass' type='button' onclick='pass(" + test_number 
+	+ ");'> <input type='button' value='Fail' onclick='fail("
+	+ test_number + ");'> <input type='button' value='Cannot tell' onclick='cant_tell("
+	+ test_number + ");'>";
+    if (skipOnResult) {
+	s += " <input value='Skip' type='button' onclick='skip(" + test_number 
+	    + ");'>";
+    }
+    p.innerHTML = s;
+}
+
+function switchSkipOnResult(nSkip)
+{
+    skipOnResult = nSkip;
+}
+
+function setResultElement(e, result)
+{
+    var s = '';
+    if (result == PASS) {
+	s = 'pass';
+    } else if (result == FAIL) {
+	s = 'fail';
+    } else if (result == CANT_TELL) {
+	s = "cannot tell";
+    }
+    if (result != UNKNOWN) {
+	e.innerHTML = s;
+	e.setAttribute('className', s);    
+	e.setAttribute('class', s);    
+    }
+}
+
+// indicate that the test was passed
+function pass(test_number)
+{
+    var e = document.getElementById("r" + test_number);
+    setResultElement(e, PASS);
+
+    results[test_number] = PASS;
+
+    if (skipOnResult) {
+	moveToNextTest(test_number);
+    }
+}
+
+// indicate that the test was failed
+function fail(test_number)
+{
+    var e = document.getElementById("r" + test_number);
+    setResultElement(e, FAIL);
+
+    results[test_number] = FAIL;
+
+    if (skipOnResult) {
+	moveToNextTest(test_number);
+    }
+}
+
+// can't tell if the test was passed or failed
+function cant_tell(test_number)
+{
+    var e = document.getElementById("r" + test_number);
+    setResultElement(e, CANT_TELL);
+
+    results[test_number] = CANT_TELL;
+    if (skipOnResult) {
+	moveToNextTest(test_number);
+    }
+}
+
+// Just skip the test and move to next
+function skip(test_number)
+{
+    moveToNextTest(test_number);
+}
+
+// reset the table of pass/fail/can't tell
+function resetAll()
+{
+    for (i = 0; i < tests.length; i++) {
+	var e = document.getElementById("r" + i);
+	e.innerHTML = '';
+	e.removeAttribute('className');
+	e.removeAttribute('class');
+	// don't forget to clear the results array as well
+	results[i] = UNKNOWN;
+    }    
+}
+
+//*******************************************
+// Generate a report of all pass/fail/unknown
+//*******************************************
+
+function getFlashPlayerVersion()
+{    
+    if (navigator.plugins && navigator.mimeTypes.length) {
+        var plugin = navigator.plugins["Shockwave Flash"];
+        if (plugin && plugin.description) {
+            return plugin.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split(".");
+        }
+    }
+    return [0, 0, 0];
+}
+
+function report()
+{
+    var pass      = new Array();
+    var fail      = new Array();
+    var cant_tell = new Array();
+
+    for (i = 0; i < results.length; i++) {
+	if (results[i] == PASS) {
+	    pass[pass.length] = i;
+	} else if (results[i] == FAIL) {
+	    fail[fail.length] = i;
+	} else if (results[i] == CANT_TELL) {
+	    cant_tell[cant_tell.length] = i;
+	}
+    }
+    var total = pass.length+fail.length+cant_tell.length;
+
+    var report_content = document.getElementById("report_content");
+    report_content.innerHTML = '';
+
+    if (player == 0 || total == 0) {
+	if (player == 0) {
+	    var p = document.createElement("p");	    
+	    p.innerHTML = "Choose a player.";
+	    report_content.appendChild(p);
+	}
+	if (total == 0) {
+	    var p = document.createElement("p");	    
+	    p.innerHTML = "Report some results.";
+	    report_content.appendChild(p);
+	}
+	return;
+    }
+
+
+    var p = document.createElement("p");
+
+
+    p.innerHTML = new Date().toUTCString();
+    report_content.appendChild(p);
+
+    p = document.createElement("p");
+    p.innerHTML = "DFXP Player: " + players[player-1][NAME];
+    report_content.appendChild(p);
+    
+    var version = getFlashPlayerVersion();
+    p = document.createElement("p");
+    p.innerHTML = "Shockwave Flash: " + version[0] + "." + version[1] + " r" + version[2];
+    report_content.appendChild(p);
+    
+    p = document.createElement("p");
+    p.innerHTML = "Navigator: " + navigator.userAgent;
+    report_content.appendChild(p);
+
+    p = document.createElement("p");
+    p.innerHTML = total	+ " test result" 
+	+ ((total==0)?"":"s")
+	+ " collected out of " + tests.length + " tests.";
+    report_content.appendChild(p);
+    if (total != 0) {
+	if (pass.length != 0) {
+	    p = document.createElement("p");
+	    var s = '';
+	    for (i = 0; i<pass.length; i++) {
+		if (s != '') {
+		    s += ', ';
+		}
+		s += tests[pass[i]][NAME];
+	    }
+	    p.innerHTML = pass.length + " test"
+		+ ((pass.length>1)?"s":"") + " passed: " + s + ".";
+	    report_content.appendChild(p);
+	}
+	if (fail.length != 0) {
+	    p = document.createElement("p");
+	    s = '';
+	    for (i = 0; i<fail.length; i++) {
+		if (s != '') {
+		    s += ', ';
+		}
+		s += tests[fail[i]][NAME];
+	    }
+	    p.innerHTML = fail.length + " test" 
+		+ ((fail.length>1)?"s ":" ") + " failed:" + s + ".";
+	    report_content.appendChild(p);
+	}
+	if (cant_tell.length != 0) {
+	    p = document.createElement("p");
+	    s = '';
+	    for (i = 0; i<cant_tell.length; i++) {
+		if (s != '') {
+		    s += ', ';
+		}
+		s += tests[cant_tell[i]][NAME];
+	    }
+	    p.innerHTML = cant_tell.length + " test" 
+		+ ((cant_tell.length>1)?"s ":" ") + " cannot tell:" + s + ".";
+	    report_content.appendChild(p);
+	}
+    }
+}
+
+//*************************************************
+// handle the selection of a category or the report
+//*************************************************
+
+function handleSelection(index)
+{
+    var r = document.getElementById("report");
+    clearTestArea();
+    if (index == categories.length) {
+	switchCategory(-1);
+	report();
+	// setAttribute("class" or "style" doesn't work in IE :-(
+	r.style.cssText = '';
+    } else {
+	// setAttribute("class" or "style" doesn't work in IE :-(
+	r.style.cssText = 'display:none';
+	switchCategory(index);
+    }
+}
+
+//********************************************
+// onClick handler to display the tests
+//********************************************
+function onClickHandlerDisplayTest() {
+    displayTest(parseInt(this.getAttribute("test")));
+}
+//********************************************
+// onClick handler to activate the tests
+//********************************************
+function onClickHandlerActiveTest() {
+    activeTest(parseInt(this.getAttribute("test")));
+}
+
+//********************************************
+// init():
+// - initialize the results
+// - build player list
+// - initialize the player
+// - build category list
+// - build test table
+// - initialize skipOnResult and autostart
+//********************************************
+
+function init() {
+    if (!(document.implementation
+	  && document.implementation.hasFeature)) {
+	// no DOM support :-(
+	return;
+    }
+
+    initResults();
+
+    // populate the player list
+    var select = document.getElementById("players");
+
+    var opt = document.createElement("option");
+    opt.innerHTML = "Choose a player";
+    select.appendChild(opt);
+    for (i=0; i < players.length; i++) {
+	opt = document.createElement("option");
+	opt.innerHTML = players[i][NAME];
+	select.appendChild(opt);
+    }
+    if (players.length > 0) {
+	player = 0;
+    }
+
+    // populate the category list
+    var select = document.getElementById("categories");
+
+    for (i=0; i < categories.length; i++) {
+	opt = document.createElement("option");
+	opt.innerHTML = categories[i];
+	select.appendChild(opt);
+    }
+    opt = document.createElement("option");
+    opt.innerHTML = "See the report";
+    select.appendChild(opt);
+
+    var tables = document.getElementById("tables");
+    var isRemote = false;
+    if (document.URL.substring(0, 5) == "http:") {
+	isRemote = true;
+    }
+
+    for (c=categories.length-1; c>=1;c--) {
+	var div = document.createElement("div");
+	div.setAttribute("className", "table");
+	div.setAttribute("class", "table");
+	div.setAttribute("id", "cat" + c);
+	var h3 = document.createElement("h3");
+	h3.innerHTML = "Test set: " + categories[c];
+	div.appendChild(h3);
+	// populate the HTML table with the tests
+	var table = document.createElement("table");
+	// don't forget to add a tbody element for IE!
+	var tbody = document.createElement("tbody");
+	table.setAttribute("id", "tcat" + c);
+	for (i=0; i < tests.length; i++) {
+	    if (c == tests[i][CATEGORY]) {
+		var tr = document.createElement("tr");
+		var th = document.createElement("th");
+		var b = document.createElement("input");
+		b.setAttribute("type", "button");
+		// b.setAttribute("onclick", "activeTest(i)"); doesn't work on IE :-(
+		// so here is a workaround
+		b.setAttribute("test", (i).toString(10));
+		b.onclick = onClickHandlerActiveTest;
+		b.setAttribute("value", tests[i][NAME]);
+		th.appendChild(b);
+		tr.appendChild(th);
+		td = document.createElement("td"); // for the source
+		if (!isRemote) {
+		    var a = document.createElement("a");
+		    a.setAttribute("href", tests[i][FILE]);
+		    a.innerHTML = "[source]";
+		    td.appendChild(a);
+		} else {
+		    var span = document.createElement("span");
+		    span.setAttribute("test", (i).toString(10));
+		    span.onclick = onClickHandlerDisplayTest;
+		    span.innerHTML = "[source]";
+		    td.appendChild(span);		    
+		}
+		tr.appendChild(td);
+		td = document.createElement("td"); // for the result
+		td.setAttribute("id", "r" + i);
+		tr.appendChild(td);
+		tbody.appendChild(tr);
+		table.appendChild(tbody);
+	    }
+	}
+	div.appendChild(table);
+	tables.insertBefore(div, tables.firstChild);
+    }
+    handleSelection(0);
+
+    // initialize skipOnResult
+    var nSkipOnResult = document.getElementById("skipOnResult").checked;
+    switchSkipOnResult(nSkipOnResult);
+
+    // initialize autostart
+    var nAutostart = document.getElementById("autostart").checked;
+    switchAutostart(nAutostart);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/generate_tests.js.xslt	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,51 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet
+    version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:tt="http://www.w3.org/2006/10/ttaf1"
+    xmlns:tts="http://www.w3.org/2006/10/ttaf1#style" 
+    xmlns:ttm="http://www.w3.org/2006/10/ttaf1#metadata"
+    xmlns:ttp="http://www.w3.org/2006/10/ttaf1#parameter"
+    xmlns="http://www.w3.org/1999/xhtml"
+    xml:lang="en">
+
+    <xsl:output encoding="utf-8" method="text" />
+
+    <xsl:template match="/">
+      <xsl:for-each select='/files/file'>
+	<xsl:text>addTest("</xsl:text>
+	<xsl:value-of select='concat("../", text())'/>
+	<xsl:text>","</xsl:text>
+	<xsl:call-template name='filename'>
+	  <xsl:with-param name='f' select='text()'/>
+	</xsl:call-template>
+	<xsl:text>",</xsl:text>
+	<xsl:apply-templates select='document(concat("../", text()))/tt:tt' />
+	<xsl:text>);
+</xsl:text>
+      </xsl:for-each>
+
+    </xsl:template>
+
+    <xsl:template name='filename'>
+      <xsl:param name='f'/>
+
+      <xsl:choose>
+	<xsl:when test='contains($f, "/")'>
+	  <xsl:value-of select='substring-before(substring-after($f, "/"), ".")'/>
+	</xsl:when>
+	<xsl:otherwise>
+	  <xsl:value-of select='substring-before($f, ".")'/>
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:template>
+
+    <xsl:template match="tt:tt">
+      <xsl:text>"</xsl:text>
+      <xsl:value-of select='normalize-space(tt:head/tt:metadata/ttm:descr)'/>
+      <xsl:text>","</xsl:text>
+      <xsl:value-of select='normalize-space(substring-before(tt:head/tt:metadata/ttm:title, "-"))'/>
+      <xsl:text>"</xsl:text>
+    </xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/style.css	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,116 @@
+/* General settings */
+body {
+  color: black;
+  background: white;       
+}
+
+h1, h2, h3 { color: #005A9C; background: transparent }
+
+:link { color: #00C; background: transparent }
+:visited { color: #609; background: transparent }
+a:active { color: #C00; background: transparent }
+
+
+/* result buttons */
+#result { margin-top: 1em; }
+
+.pass { background-color: green; color: white; font-weight: bold; }
+.fail { background-color: red; color: white; font-weight: bold; }
+
+/* test */
+
+#description { 
+               padding-bottom:0.5ex;
+               padding-left: 1ex;
+               padding-right: 4ex;
+               border-bottom: 1px solid black;
+               margin-bottom:1ex;
+               }
+#testobject { 
+              padding-top: 1em;
+              }
+#testobject pre { 
+              margin-top: -1em;
+              font-size: small;
+              width: 85ex;
+              height: 33em;
+              overflow: scroll;
+              }
+
+/* The set of options in the top area */
+.options1 { 
+           float: left;
+           margin-left: 4ex;
+            }
+.options1 th {
+               text-align: right;
+ }
+.options2 { 
+           float: right;           
+           margin-right: 4ex;
+ }
+.options2 th {
+               text-align: left;
+ }
+
+
+/* table for tests in the left area */
+div#tables th { border: none;}
+div#tables th input {  width: 100%; margin: 0; text-align: left; }
+div #tables div.table { 
+  width: 40ex;
+}
+div#tables h3 {  margin-top: 1ex; padding-top: 0 }
+div#tables table a,
+div#tables table span { font-size: x-small; cursor: pointer }
+
+/* The three areas on screen */
+
+div#content
+  {
+  margin: 0;
+  padding: 8.5em 1ex 1ex 1ex;
+}
+
+div#testarea {
+  position: absolute;
+  top: 8.5em;
+  left: 50ex;
+  border-left: 2px solid #ccc;
+  padding-left: 1ex;
+}
+
+div#header {
+  position: absolute;
+  top: 0;
+  left: 0;
+  padding-left: 1ex;
+  width: 100%;
+  background: white;
+  border-bottom: 2px solid #ccc;
+}
+
[email protected] screen
+  {
+  div#testarea, div#header
+    {
+    position: fixed;
+    }
+  /* Don't do this at home */
+  * html
+    {
+    overflow-y: hidden;
+    }
+  * html div#content
+    {
+    overflow-y: auto;
+    height: 100%;
+    padding: 8.5em 1ex 1ex 1ex;
+    font-size: 100%;
+    }
+  * html div#testarea, * html div#header
+    {
+    position: absolute;  
+    }
+  /* All done. */
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testsuite/web-framework/tests.js	Fri Nov 21 18:20:33 2008 +0000
@@ -0,0 +1,27 @@
+addTest("../Content/Br001.xml","Br001","Test the br element.","Content Test");
+addTest("../Content/Paragraph001.xml","Paragraph001","Test the p element with no styling attribute.","Content Test");
+addTest("../Content/Paragraph002.xml","Paragraph002","Test the p element with no timing attributes (nothing is displayed).","Content Test");
+addTest("../Content/Paragraph003.xml","Paragraph003","Test the p element with styling and timing attributes.","Content Test");
+addTest("../Content/Span001.xml","Span001","Test the span element with no attributes.","Content Test");
+addTest("../Content/Span002.xml","Span002","Test the span element with a styling attribute.","Content Test");
+addTest("../Content/Span003.xml","Span003","Test the span element inside a span element.","Content Test");
+addTest("../Content/Span004.xml","Span004","Test the span element inside a span element.","Content Test");
+addTest("../Content/Span005.xml","Span005","Test the br element inside a span element.","Content Test");
+addTest("../Timing/BeginDur001.xml","BeginDur001","Test the begin and dur attributes on p elements.","Timing Test");
+addTest("../Timing/BeginEnd001.xml","BeginEnd001","Test the begin and end attributes on p elements.","Timing Test");
+addTest("../Timing/BeginEnd002.xml","BeginEnd002","Test the begin attribute with no end or dur attribute on p elements.","Timing Test");
+addTest("../Timing/BeginEnd003.xml","BeginEnd003","Test the begin and end attributes on p elements in random order. @@Is it a valid test?","Timing Test");
+addTest("../Styling/Color001.xml","Color001","Test tts:color attribute using a named color expression.","Styling Test");
+addTest("../Styling/Color002.xml","Color002","Test tts:color attribute using a hash (#rrggbb) color expression.","Styling Test");
+addTest("../Styling/Color003.xml","Color003","Test tts:color attribute using a hash (#rrggbbaa) color expression with opacity.","Styling Test");
+addTest("../Styling/Color004.xml","Color004","Test tts:color attribute using a rgb() color function.","Styling Test");
+addTest("../Styling/Color005.xml","Color005","Test tts:color attribute using a rgba() color function.","Styling Test");
+addTest("../Styling/Color006.xml","Color006","Test tts:color attribute using a inherit value.","Styling Test");
+addTest("../Styling/Color007.xml","Color007","Test tts:color attribute using a transparent value.","Styling Test");
+addTest("../Styling/Color008.xml","Color008","Test tts:color attribute with span elements.","Styling Test");
+addTest("../Styling/Color009.xml","Color009","Test tts:color style using a named color expression.","Styling Test");
+addTest("../Specification/DocumentExample120.xml","DocumentExample120","This test contains the document example from the section 1.2 of the DFXP 1.0 specification, without the layout region.","Specification Test");
+addTest("../Specification/DocumentExample822.xml","DocumentExample822","This test contains the document example from the section 8.2.2 of the DFXP 1.0 specification, with the region replacing with a styling.","Specification Test");
+addTest("../Specification/DocumentExample823.xml","DocumentExample823","This test contains the document example from the section 8.2.3 of the DFXP 1.0 specification, with the region replacing with a styling.","Specification Test");
+addTest("../Specification/DocumentExample824.xml","DocumentExample824","This test contains the document example from the section 8.2.4 of the DFXP 1.0 specification, with the region replacing with a styling.","Specification Test");
+addTest("../Specification/DocumentExample825.xml","DocumentExample825","This test contains the document example from the section 8.2.5 of the DFXP 1.0 specification, with the region replacing with a styling.","Specification Test");