summaryrefslogtreecommitdiff
path: root/frontend/gamma/tests/SimpleTest
authorGiulio Cesare Solaroli <giulio.cesare@clipperz.com>2011-10-02 23:56:18 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@clipperz.com>2011-10-02 23:56:18 (UTC)
commitef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (side-by-side diff)
treec403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/gamma/tests/SimpleTest
parent597ecfbc0249d83e1b856cbd558340c01237a360 (diff)
downloadclipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip
clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz
clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2
First version of the newly restructured repository
Diffstat (limited to 'frontend/gamma/tests/SimpleTest') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/tests/SimpleTest/SimpleTest.Async.js169
-rw-r--r--frontend/gamma/tests/SimpleTest/SimpleTest.js424
-rw-r--r--frontend/gamma/tests/SimpleTest/TestRunner.js233
-rw-r--r--frontend/gamma/tests/SimpleTest/test.css28
4 files changed, 854 insertions, 0 deletions
diff --git a/frontend/gamma/tests/SimpleTest/SimpleTest.Async.js b/frontend/gamma/tests/SimpleTest/SimpleTest.Async.js
new file mode 100644
index 0000000..040cdbf
--- a/dev/null
+++ b/frontend/gamma/tests/SimpleTest/SimpleTest.Async.js
@@ -0,0 +1,169 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library is free software: you can redistribute
+ it and/or modify it under the terms of the GNU Affero General Public
+ License as published by the Free Software Foundation, either version
+ 3 of the License, or (at your option) any later version.
+
+* Javascript Crypto Library is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Affero General Public License for more details.
+
+* You should have received a copy of the GNU Affero General Public
+ License along with Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+MochiKit.Base.update(Clipperz.Async.Deferred.prototype, {
+/*
+ '_addTest': function(anExpectedValue, aDescription, isDeep, aResult) {
+ if (isDeep) {
+ SimpleTest.isDeeply(aResult, anExpectedValue, aDescription);
+ } else {
+ SimpleTest.is(aResult, anExpectedValue, aDescription);
+ }
+
+ return aResult;
+ },
+*/
+ 'addTest': function (anExpectedValue, aDescription, isDeep) {
+// this.addMethod(this, '_addTest', anExpectedValue, aDescription, isDeep);
+// this.addCallback(Clipperz.Async.test, anExpectedValue, aDescription, isDeep);
+
+ if (isDeep) {
+// SimpleTest.isDeeply(aResult, anExpectedValue, aDescription);
+ this.addCallback(Clipperz.Async.Test.isDeeply(anExpectedValue, aDescription));
+ } else {
+// SimpleTest.is(aResult, anExpectedValue, aDescription);
+ this.addCallback(Clipperz.Async.Test.is(anExpectedValue, aDescription));
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldSucceed': function (aDescription) {
+ this.addCallbackPass(SimpleTest.ok, true, aDescription);
+ this.addErrbackPass (SimpleTest.ok, false, aDescription);
+ this.addBoth(MochiKit.Async.succeed, null);
+ },
+
+ 'shouldFail': function (aDescription) {
+ this.addCallbackPass(SimpleTest.ok, false, aDescription);
+ this.addErrbackPass (SimpleTest.ok, true, aDescription);
+ this.addBoth(MochiKit.Async.succeed, null);
+ },
+
+ //-------------------------------------------------------------------------
+
+});
+
+
+Clipperz.Async.Test = {};
+MochiKit.Base.update(Clipperz.Async.Test, {
+
+ 'is': function (anExpectedResult, aDescription) {
+ return MochiKit.Base.partial(function (anExpectedResult, aDescription, aResult) {
+ SimpleTest.is(aResult, anExpectedResult, aDescription);
+
+ return aResult;
+ }, anExpectedResult, aDescription);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'ok': function (aDescription) {
+ return MochiKit.Base.partial(function (aDescription, aResult) {
+ SimpleTest.ok(aResult, aDescription);
+
+ return aResult;
+ }, aDescription);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fail': function(aDescription) {
+ return MochiKit.Base.partial(function (aDescription, aResult) {
+ SimpleTest.ok(!aResult, aDescription);
+
+ return aResult;
+ }, aDescription);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isDeeply': function (anExpectedResult, aDescription) {
+ return MochiKit.Base.partial(function (anExpectedResult, aDescription, aResult) {
+ SimpleTest.isDeeply(aResult, anExpectedResult, aDescription);
+
+ return aResult;
+ }, anExpectedResult, aDescription);
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
+SimpleTest.runDeferredTests = function (aName, aTestSet, aTestArguments) {
+ try {
+ var deferredTests;
+ var aTestName;
+ var title;
+
+ deferredTests = new Clipperz.Async.Deferred(aName + " <deferred test set>", aTestArguments);
+
+ title = aName;
+
+ aTestName = window.location.href.match(/#.*/);
+ if (aTestName && (aTestName != '#')) {
+ aTestName = aTestName[0].slice(1);
+ if (aTestName in aTestSet) {
+ //Clipperz.log("single test execution, via fragment identifier", aTestName);
+ title += ' [' + aTestName + ']';
+ deferredTests.addCallback(aTestSet[aTestName], aTestArguments);
+ deferredTests.addErrback(SimpleTest.ok, false, aTestName);
+ } else {
+ title = 'WRONG TEST NAME'
+ deferredTests.addBoth(is, aTestName, null, "Wrong test name selected to run");
+ }
+ } else {
+ for (aTestName in aTestSet) {
+ deferredTests.addCallback(aTestSet[aTestName], aTestArguments);
+ deferredTests.addErrback(SimpleTest.ok, false, aTestName);
+ deferredTests.addBoth(MochiKit.Async.wait, 0.5);
+ }
+ deferredTests.addBoth(is, true, true, "FINISH: completed the full stack of tests");
+ }
+
+ MochiKit.DOM.currentDocument().title = title;
+
+ deferredTests.addBoth(SimpleTest.finish);
+ deferredTests.callback();
+
+ SimpleTest.waitForExplicitFinish();
+ } catch (err) {
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+ }
+}
diff --git a/frontend/gamma/tests/SimpleTest/SimpleTest.js b/frontend/gamma/tests/SimpleTest/SimpleTest.js
new file mode 100644
index 0000000..418954f
--- a/dev/null
+++ b/frontend/gamma/tests/SimpleTest/SimpleTest.js
@@ -0,0 +1,424 @@
+/**
+ * SimpleTest, a partial Test.Simple/Test.More API compatible test library.
+ *
+ * Why?
+ *
+ * Test.Simple doesn't work on IE < 6.
+ * TODO:
+ * * Support the Test.Simple API used by MochiKit, to be able to test MochiKit
+ * itself against IE 5.5
+ *
+**/
+
+if (typeof(SimpleTest) == "undefined") {
+ var SimpleTest = {};
+}
+
+// Check to see if the TestRunner is present and has logging
+if (typeof(parent) != "undefined" && parent.TestRunner) {
+ SimpleTest._logEnabled = parent.TestRunner.logEnabled;
+}
+
+SimpleTest._tests = [];
+SimpleTest._stopOnLoad = true;
+SimpleTest._scopeCopy = {};
+
+/**
+ * Saves a copy of the specified scope variables.
+ */
+SimpleTest.saveScope = function (scope) {
+ SimpleTest._scopeCopy = {};
+ for (var k in scope) {
+ SimpleTest._scopeCopy[k] = scope[k];
+ }
+}
+
+/**
+ * Verifies the specified scope against the stored copy and reports
+ * any differences as test failures.
+ */
+SimpleTest.verifyScope = function (scope) {
+ var filter = ['test', '_firebug','_FirebugConsole','XMLHttpRequest','Audio',
+ 'XSLTProcessor','Option','Image','scrollMaxX','scrollMaxY',
+ 'clipboardData'];
+ for (var k in scope) {
+ if (MochiKit.Base.findValue(filter, k) < 0) {
+ var v = scope[k];
+ var old = SimpleTest._scopeCopy[k];
+ if (v !== old && typeof(old) === "undefined") {
+ SimpleTest.ok(false, "scope modified, variable " + k + " was added");
+ } else if (v !== old) {
+ SimpleTest.ok(false, "scope modified, variable " + k + " changed from: " + old + ", to: " + v);
+ }
+ }
+ }
+ for (var k in SimpleTest._scopeCopy) {
+ if (!(k in scope)) {
+ SimpleTest.ok(false, "scope modified, variable " + k + " has been removed");
+ }
+ }
+}
+
+/**
+ * Something like assert.
+ */
+SimpleTest.ok = function (condition, name, diag) {
+ var test = {'result': !!condition, 'name': name, 'diag': diag || ""};
+ if (SimpleTest._logEnabled) {
+ var msg = test.result ? "PASS" : "FAIL";
+ msg += " | " + test.name;
+ if (test.result) {
+ parent.TestRunner.logger.log(msg);
+ } else {
+ msg += " | " + test.diag;
+ parent.TestRunner.logger.error(msg);
+ }
+ }
+ SimpleTest._tests.push(test);
+};
+
+/**
+ * Roughly equivalent to ok(a==b, name)
+ */
+SimpleTest.is = function (a, b, name) {
+ var repr = MochiKit.Base.repr;
+ SimpleTest.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b));
+};
+
+/**
+ * Roughly equivalent to ok(compare(a,b)==0, name)
+ */
+SimpleTest.eq = function (a, b, name) {
+ var base = MochiKit.Base;
+ var repr = base.repr;
+ try {
+ SimpleTest.ok(base.compare(a, b) == 0, name, "got " + repr(a) + ", expected " + repr(b));
+ } catch (e) {
+ SimpleTest.ok(false, name, "exception in compare: " + repr(e));
+ }
+};
+
+
+/**
+ * Makes a test report, returns it as a DIV element.
+**/
+SimpleTest.report = function () {
+ var DIV = MochiKit.DOM.DIV;
+ var passed = 0;
+ var failed = 0;
+ var results = MochiKit.Base.map(
+ function (test) {
+ var cls, msg;
+ if (test.result) {
+ passed++;
+ cls = "test_ok";
+ msg = "ok - " + test.name;
+ } else {
+ failed++;
+ cls = "test_not_ok";
+ msg = "not ok - " + test.name;
+ if (test.diag != null && test.diag != "") {
+ msg += ": " + test.diag;
+ }
+ }
+ return DIV({"class": cls}, msg);
+ },
+ SimpleTest._tests
+ );
+ var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail');
+ return DIV({'class': 'tests_report'},
+ DIV({'class': 'tests_summary ' + summary_class},
+ DIV({'class': 'tests_passed'}, "Passed: " + passed),
+ DIV({'class': 'tests_failed'}, "Failed: " + failed)),
+ results
+ );
+};
+
+/**
+ * Toggle element visibility
+**/
+SimpleTest.toggle = function(el) {
+ if (MochiKit.Style.getStyle(el, 'display') == 'block') {
+ el.style.display = 'none';
+ } else {
+ el.style.display = 'block';
+ }
+};
+
+/**
+ * Toggle visibility for divs with a specific class.
+**/
+SimpleTest.toggleByClass = function (cls) {
+ var elems = MochiKit.DOM.getElementsByTagAndClassName('div', cls);
+ MochiKit.Base.map(SimpleTest.toggle, elems);
+ return false;
+};
+
+/**
+ * Shows the report in the browser
+**/
+
+SimpleTest.showReport = function() {
+ var base = MochiKit.Base;
+ var dom = MochiKit.DOM;
+ var togglePassed = dom.A({'href': '#'}, "Toggle passed tests");
+ var toggleFailed = dom.A({'href': '#'}, "Toggle failed tests");
+ togglePassed.onclick = base.partial(SimpleTest.toggleByClass, 'test_ok');
+ toggleFailed.onclick = base.partial(SimpleTest.toggleByClass, 'test_not_ok');
+ var body = document.getElementsByTagName("body")[0];
+ var firstChild = body.childNodes[0];
+ var addNode;
+ if (firstChild) {
+ addNode = function (el) {
+ body.insertBefore(el, firstChild);
+ };
+ } else {
+ addNode = function (el) {
+ body.appendChild(el)
+ };
+ }
+ addNode(togglePassed);
+ addNode(dom.SPAN(null, " "));
+ addNode(toggleFailed);
+ addNode(SimpleTest.report());
+};
+
+/**
+ * Tells SimpleTest to don't finish the test when the document is loaded,
+ * useful for asynchronous tests.
+ *
+ * When SimpleTest.waitForExplicitFinish is called,
+ * explicit SimpleTest.finish() is required.
+**/
+SimpleTest.waitForExplicitFinish = function () {
+ SimpleTest._stopOnLoad = false;
+};
+
+/**
+ * Talks to the TestRunner if being ran on a iframe and the parent has a
+ * TestRunner object.
+**/
+SimpleTest.talkToRunner = function () {
+ if (typeof(parent) != "undefined" && parent.TestRunner) {
+ parent.TestRunner.testFinished(document);
+ }
+};
+
+/**
+ * Finishes the tests. This is automatically called, except when
+ * SimpleTest.waitForExplicitFinish() has been invoked.
+**/
+SimpleTest.finish = function () {
+ SimpleTest.showReport();
+ SimpleTest.talkToRunner();
+};
+
+
+MochiKit.DOM.addLoadEvent(function() {
+ if (SimpleTest._stopOnLoad) {
+ SimpleTest.finish();
+ }
+});
+
+// --------------- Test.Builder/Test.More isDeeply() -----------------
+
+
+SimpleTest.DNE = {dne: 'Does not exist'};
+SimpleTest.LF = "\r\n";
+SimpleTest._isRef = function (object) {
+ var type = typeof(object);
+ return type == 'object' || type == 'function';
+};
+
+
+SimpleTest._deepCheck = function (e1, e2, stack, seen) {
+ var ok = false;
+ // Either they're both references or both not.
+ var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2));
+ if (e1 == null && e2 == null) {
+ ok = true;
+ } else if (e1 != null ^ e2 != null) {
+ ok = false;
+ } else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) {
+ ok = false;
+ } else if (sameRef && e1 == e2) {
+ // Handles primitives and any variables that reference the same
+ // object, including functions.
+ ok = true;
+ } else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) {
+ ok = SimpleTest._eqArray(e1, e2, stack, seen);
+ } else if (typeof e1 == "object" && typeof e2 == "object") {
+ ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
+ } else {
+ // If we get here, they're not the same (function references must
+ // always simply rererence the same function).
+ stack.push({ vals: [e1, e2] });
+ ok = false;
+ }
+ return ok;
+};
+
+SimpleTest._eqArray = function (a1, a2, stack, seen) {
+ // Return if they're the same object.
+ if (a1 == a2) return true;
+
+ // JavaScript objects have no unique identifiers, so we have to store
+ // references to them all in an array, and then compare the references
+ // directly. It's slow, but probably won't be much of an issue in
+ // practice. Start by making a local copy of the array to as to avoid
+ // confusing a reference seen more than once (such as [a, a]) for a
+ // circular reference.
+ for (var j = 0; j < seen.length; j++) {
+ if (seen[j][0] == a1) {
+ return seen[j][1] == a2;
+ }
+ }
+
+ // If we get here, we haven't seen a1 before, so store it with reference
+ // to a2.
+ seen.push([ a1, a2 ]);
+
+ var ok = true;
+ // Only examines enumerable attributes. Only works for numeric arrays!
+ // Associative arrays return 0. So call _eqAssoc() for them, instead.
+ var max = a1.length > a2.length ? a1.length : a2.length;
+ if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen);
+ for (var i = 0; i < max; i++) {
+ var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i];
+ var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i];
+ stack.push({ type: 'Array', idx: i, vals: [e1, e2] });
+ if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+ stack.pop();
+ } else {
+ break;
+ }
+ }
+ return ok;
+};
+
+SimpleTest._eqAssoc = function (o1, o2, stack, seen) {
+ // Return if they're the same object.
+ if (o1 == o2) return true;
+
+ // JavaScript objects have no unique identifiers, so we have to store
+ // references to them all in an array, and then compare the references
+ // directly. It's slow, but probably won't be much of an issue in
+ // practice. Start by making a local copy of the array to as to avoid
+ // confusing a reference seen more than once (such as [a, a]) for a
+ // circular reference.
+ seen = seen.slice(0);
+ for (var j = 0; j < seen.length; j++) {
+ if (seen[j][0] == o1) {
+ return seen[j][1] == o2;
+ }
+ }
+
+ // If we get here, we haven't seen o1 before, so store it with reference
+ // to o2.
+ seen.push([ o1, o2 ]);
+
+ // They should be of the same class.
+
+ var ok = true;
+ // Only examines enumerable attributes.
+ var o1Size = 0; for (var i in o1) o1Size++;
+ var o2Size = 0; for (var i in o2) o2Size++;
+ var bigger = o1Size > o2Size ? o1 : o2;
+ for (var i in bigger) {
+ var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i];
+ var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i];
+ stack.push({ type: 'Object', idx: i, vals: [e1, e2] });
+ if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+ stack.pop();
+ } else {
+ break;
+ }
+ }
+ return ok;
+};
+
+SimpleTest._formatStack = function (stack) {
+ var variable = '$Foo';
+ for (var i = 0; i < stack.length; i++) {
+ var entry = stack[i];
+ var type = entry['type'];
+ var idx = entry['idx'];
+ if (idx != null) {
+ if (/^\d+$/.test(idx)) {
+ // Numeric array index.
+ variable += '[' + idx + ']';
+ } else {
+ // Associative array index.
+ idx = idx.replace("'", "\\'");
+ variable += "['" + idx + "']";
+ }
+ }
+ }
+
+ var vals = stack[stack.length-1]['vals'].slice(0, 2);
+ var vars = [
+ variable.replace('$Foo', 'got'),
+ variable.replace('$Foo', 'expected')
+ ];
+
+ var out = "Structures begin differing at:" + SimpleTest.LF;
+ for (var i = 0; i < vals.length; i++) {
+ var val = vals[i];
+ if (val == null) {
+ val = 'undefined';
+ } else {
+ val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'";
+ }
+ }
+
+ out += vars[0] + ' = ' + vals[0] + SimpleTest.LF;
+ out += vars[1] + ' = ' + vals[1] + SimpleTest.LF;
+
+ return ' ' + out;
+};
+
+
+SimpleTest.isDeeply = function (it, as, name) {
+ var ok;
+ // ^ is the XOR operator.
+ if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) {
+ // One's a reference, one isn't.
+ ok = false;
+ } else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) {
+ // Neither is an object.
+ ok = SimpleTest.is(it, as, name);
+ } else {
+ // We have two objects. Do a deep comparison.
+ var stack = [], seen = [];
+ if ( SimpleTest._deepCheck(it, as, stack, seen)) {
+ ok = SimpleTest.ok(true, name);
+ } else {
+ ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
+ }
+ }
+ return ok;
+};
+
+SimpleTest.typeOf = function (object) {
+ var c = Object.prototype.toString.apply(object);
+ var name = c.substring(8, c.length - 1);
+ if (name != 'Object') return name;
+ // It may be a non-core class. Try to extract the class name from
+ // the constructor function. This may not work in all implementations.
+ if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) {
+ return RegExp.$1;
+ }
+ // No idea. :-(
+ return name;
+};
+
+SimpleTest.isa = function (object, clas) {
+ return SimpleTest.typeOf(object) == clas;
+};
+
+
+
+// Global symbols:
+var ok = SimpleTest.ok;
+var is = SimpleTest.is;
+var isDeeply = SimpleTest.isDeeply;
diff --git a/frontend/gamma/tests/SimpleTest/TestRunner.js b/frontend/gamma/tests/SimpleTest/TestRunner.js
new file mode 100644
index 0000000..81a36cf
--- a/dev/null
+++ b/frontend/gamma/tests/SimpleTest/TestRunner.js
@@ -0,0 +1,233 @@
+/**
+ * TestRunner: A test runner for SimpleTest
+ * TODO:
+ *
+ * * Avoid moving iframes: That causes reloads on mozilla and opera.
+ *
+ *
+**/
+var TestRunner = {};
+TestRunner.logEnabled = false;
+TestRunner._iframes = {};
+TestRunner._iframeDocuments = {};
+TestRunner._iframeRows = {};
+TestRunner._currentTest = 0;
+TestRunner._urls = [];
+TestRunner._testsDiv = DIV();
+TestRunner._progressDiv = DIV();
+TestRunner._summaryDiv = DIV(null,
+ H1(null, "Tests Summary"),
+ TABLE(null,
+ THEAD(null,
+ TR(null,
+ TH(null, "Test"),
+ TH(null, "Passed"),
+ TH(null, "Failed")
+ )
+ ),
+ TFOOT(/*null, TR(null, TH(null, "-"), TH(null, "--"), TH(null, "---"))*/),
+ TBODY()
+ )
+);
+
+/**
+ * This function is called after generating the summary.
+**/
+TestRunner.onComplete = null;
+
+/**
+ * If logEnabled is true, this is the logger that will be used.
+**/
+TestRunner.logger = MochiKit.Logging.logger;
+
+/**
+ * Toggle element visibility
+**/
+TestRunner._toggle = function(el) {
+ if (el.className == "noshow") {
+ el.className = "";
+ el.style.cssText = "";
+ } else {
+ el.className = "noshow";
+ el.style.cssText = "width:0px; height:0px; border:0px;";
+ }
+};
+
+
+/**
+ * Creates the iframe that contains a test
+**/
+TestRunner._makeIframe = function (url) {
+ var iframe = document.createElement('iframe');
+ iframe.src = url;
+ iframe.name = url;
+ iframe.width = "500";
+ var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+ var tr = TR(null, TD({'colspan': '3'}, iframe));
+ iframe._row = tr;
+ tbody.appendChild(tr);
+ return iframe;
+};
+
+/**
+ * TestRunner entry point.
+ *
+ * The arguments are the URLs of the test to be ran.
+ *
+**/
+TestRunner.runTests = function (/*url...*/) {
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log("SimpleTest START");
+
+ var body = document.getElementsByTagName("body")[0];
+ appendChildNodes(body,
+ TestRunner._testsDiv,
+ TestRunner._progressDiv,
+ TestRunner._summaryDiv
+ );
+ for (var i = 0; i < arguments.length; i++) {
+ TestRunner._urls.push(arguments[i]);
+ }
+
+ TestRunner.runNextTest();
+};
+
+/**
+ * Run the next test. If no test remains, calls makeSummary
+**/
+TestRunner.runNextTest = function() {
+ if (TestRunner._currentTest < TestRunner._urls.length) {
+ var url = TestRunner._urls[TestRunner._currentTest];
+ var progress = SPAN(null,
+ "Running ", A({href:url}, url), "..."
+ );
+
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log(scrapeText(progress));
+
+ TestRunner._progressDiv.appendChild(progress);
+ TestRunner._iframes[url] = TestRunner._makeIframe(url);
+ } else {
+ TestRunner.makeSummary();
+ if (TestRunner.onComplete) {
+ TestRunner.onComplete();
+ }
+ }
+};
+
+/**
+ * This stub is called by SimpleTest when a test is finished.
+**/
+TestRunner.testFinished = function (doc) {
+ appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR());
+ var finishedURL = TestRunner._urls[TestRunner._currentTest];
+
+ if (TestRunner.logEnabled)
+ TestRunner.logger.debug("SimpleTest finished " + finishedURL);
+
+ TestRunner._iframeDocuments[finishedURL] = doc;
+ // TestRunner._iframes[finishedURL].style.display = "none";
+ if (finishedURL != null) {
+ TestRunner._toggle(TestRunner._iframes[finishedURL]);
+ TestRunner._currentTest++;
+ TestRunner.runNextTest();
+ }
+};
+
+/**
+ * Display the summary in the browser
+**/
+/*
+TestRunner.makeSummary = function() {
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log("SimpleTest FINISHED");
+ var rows = [];
+ for (var url in TestRunner._iframeDocuments) {
+ var doc = TestRunner._iframeDocuments[url];
+ var nOK = withDocument(doc,
+ partial(getElementsByTagAndClassName, 'div', 'test_ok')
+ ).length;
+ var nNotOK = withDocument(doc,
+ partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
+ ).length;
+ var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
+ var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
+ var row = TR(
+ {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},
+ TD(null, url),
+ TD(null, nOK),
+ TD(null, nNotOK)
+ );
+ row.onclick = toggle;
+ var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+ tbody.insertBefore(row, TestRunner._iframes[url]._row)
+ }
+};
+*/
+
+TestRunner.makeSummary = function() {
+ var base = MochiKit.Base;
+ var dom = MochiKit.DOM;
+ var iter = MochiKit.Iter;
+ var total_Ok, total_not_Ok;
+
+ total_Ok = 0;
+ total_not_Ok = 0;
+
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log("SimpleTest FINISHED");
+ var rows = [];
+ for (var url in TestRunner._iframeDocuments) {
+ var doc = TestRunner._iframeDocuments[url];
+ var nOK = withDocument(doc,
+ partial(getElementsByTagAndClassName, 'div', 'test_ok')
+ ).length;
+ var nNotOK = withDocument(doc,
+ partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
+ ).length;
+ var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
+ var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
+ var row = TR(
+ {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},
+ TD(null, url),
+ TD(null, nOK),
+ TD(null, nNotOK)
+ );
+ row.onclick = toggle;
+ var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+ tbody.insertBefore(row, TestRunner._iframes[url]._row);
+
+ total_Ok += nOK;
+ total_not_Ok += nNotOK;
+ }
+
+ {
+ var tfoot = TestRunner._summaryDiv.getElementsByTagName("tfoot")[0];
+ tfoot.appendChild(TR(null,
+ TH(null, ""),
+ TH({'style':"color:green;"}, total_Ok),
+ TH({'style':"color:" + ((total_not_Ok == 0) ? 'black' : 'red') + ";"}, total_not_Ok)
+ ));
+ }
+
+ var testRunnerResults;
+ var i, c;
+
+ testRunnerResults = dom.DIV({'style': 'display:none; visibility:hidden;'}, null);
+
+ c = total_Ok;
+ for (i=0; i<c; i++) {
+ dom.appendChildNodes(testRunnerResults, dom.DIV({'class': 'test_ok'}, "ok"));
+ }
+
+ c = total_not_Ok;
+ for (i=0; i<c; i++) {
+ dom.appendChildNodes(testRunnerResults, dom.DIV({'class': 'test_not_ok'}, "fail"));
+ }
+
+ document.getElementsByTagName("body")[0].appendChild(testRunnerResults);
+
+ if (typeof(parent) != "undefined" && parent.TestRunner) {
+ parent.TestRunner.testFinished(document);
+ }
+};
diff --git a/frontend/gamma/tests/SimpleTest/test.css b/frontend/gamma/tests/SimpleTest/test.css
new file mode 100644
index 0000000..38a4014
--- a/dev/null
+++ b/frontend/gamma/tests/SimpleTest/test.css
@@ -0,0 +1,28 @@
+.test_ok {
+ color: green;
+ display: none;
+}
+.test_not_ok {
+ color: red;
+ display: block;
+}
+
+.test_ok, .test_not_ok {
+ border-bottom-width: 2px;
+ border-bottom-style: solid;
+ border-bottom-color: black;
+}
+
+.all_pass {
+ background-color: lime;
+}
+
+.some_fail {
+ background-color: red;
+}
+
+.tests_report {
+ border-width: 2px;
+ border-style: solid;
+ width: 20em;
+}