2 Copyright (c) 2009 John Resig
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use,
8 copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
33 doPost = !!window.top.postMessage;
36 var search = window.location.search,
38 if( ( index = search.indexOf( "swarmURL=" ) ) != -1 )
39 url = decodeURIComponent( search.slice( index + 9 ) );
41 if ( !DEBUG && (!url || url.indexOf("http") !== 0) ) {
45 var submitTimeout = 5;
50 // Expose the TestSwarm API
53 heartbeat: function(){
55 clearTimeout( curHeartbeat );
58 curHeartbeat = setTimeout(function(){
59 submit({ fail: -1, total: -1 });
62 serialize: function(){
63 return trimSerialize();
67 // Prevent careless things from executing
68 window.print = window.confirm = window.alert = window.open = function(){};
70 window.onerror = function(e){
71 document.body.appendChild( document.createTextNode( "ERROR: " + e ));
72 submit({ fail: 0, error: 1, total: 1 });
77 // http://docs.jquery.com/QUnit
78 if ( typeof QUnit !== "undefined" ) {
79 QUnit.done = function(results){
87 QUnit.log = window.TestSwarm.heartbeat;
88 window.TestSwarm.heartbeat();
90 window.TestSwarm.serialize = function(){
91 // Clean up the HTML (remove any un-needed test markup)
92 remove("nothiddendiv");
93 remove("loadediframe");
97 // Show any collapsed results
98 var ol = document.getElementsByTagName("ol");
99 for ( var i = 0; i < ol.length; i++ ) {
100 ol[i].style.display = "block";
103 return trimSerialize();
106 // UnitTestJS (Prototype, Scriptaculous)
107 // http://github.com/tobie/unittest_js/tree/master
108 } else if ( typeof Test !== "undefined" && Test && Test.Unit && Test.Unit.runners ) {
109 var total_runners = Test.Unit.runners.length, cur_runners = 0;
110 var total = 0, fail = 0, error = 0;
112 for (var i = 0; i < Test.Unit.runners.length; i++) (function(i){
113 var finish = Test.Unit.runners[i].finish;
114 Test.Unit.runners[i].finish = function(){
117 var results = this.getResult();
118 total += results.assertions;
119 fail += results.failures;
120 error += results.errors;
122 if ( ++cur_runners === total_runners ) {
133 // http://jania.pe.kr/aw/moin.cgi/JSSpec
134 } else if ( typeof JSSpec !== "undefined" && JSSpec && JSSpec.Logger ) {
135 var onRunnerEnd = JSSpec.Logger.prototype.onRunnerEnd;
136 JSSpec.Logger.prototype.onRunnerEnd = function(){
137 onRunnerEnd.call(this);
139 // Show any collapsed results
140 var ul = document.getElementsByTagName("ul");
141 for ( var i = 0; i < ul.length; i++ ) {
142 ul[i].style.display = "block";
146 fail: JSSpec.runner.getTotalFailures(),
147 error: JSSpec.runner.getTotalErrors(),
148 total: JSSpec.runner.totalExamples
152 window.TestSwarm.serialize = function(){
153 // Show any collapsed results
154 var ul = document.getElementsByTagName("ul");
155 for ( var i = 0; i < ul.length; i++ ) {
156 ul[i].style.display = "block";
159 return trimSerialize();
163 // http://www.jsunit.net/
164 // Note: Injection file must be included before the frames
165 // are document.write()d into the page.
166 } else if ( typeof JsUnitTestManager !== "undefined" ) {
167 var _done = JsUnitTestManager.prototype._done;
168 JsUnitTestManager.prototype._done = function(){
172 fail: this.failureCount,
173 error: this.errorCount,
174 total: this.totalCount
178 window.TestSwarm.serialize = function(){
179 return "<pre>" + this.log.join("\n") + "</pre>";
183 // http://seleniumhq.org/projects/core/
184 } else if ( typeof SeleniumTestResult !== "undefined" && typeof LOG !== "undefined" ) {
185 // Completely overwrite the postback
186 SeleniumTestResult.prototype.post = function(){
188 fail: this.metrics.numCommandFailures,
189 error: this.metrics.numCommandErrors,
190 total: this.metrics.numCommandPasses + this.metrics.numCommandFailures + this.metrics.numCommandErrors
194 window.TestSwarm.serialize = function(){
196 while ( LOG.pendingMessages.length ) {
197 var msg = LOG.pendingMessages.shift();
198 results.push( msg.type + ": " + msg.msg );
201 return "<pre>" + results.join("\n") + "</pre>";
204 // Dojo Objective Harness
205 // http://docs.dojocampus.org/quickstart/doh
206 } else if ( typeof doh !== "undefined" && doh._report ) {
207 var _report = doh._report;
208 doh._report = function(){
209 _report.apply(this, arguments);
212 fail: doh._failureCount,
213 error: doh._errorCount,
214 total: doh._testCount
218 window.TestSwarm.serialize = function(){
219 return "<pre>" + document.getElementById("logBody").innerHTML + "</pre>";
222 // git://github.com/nathansobo/screw-unit.git
223 } else if ( typeof Screw !== "undefined" && typeof jQuery !== 'undefined' && Screw && Screw.Unit ) {
224 $(Screw).bind("after", function() {
225 var passed = $('.passed').length;
226 var failed = $('.failed').length;
230 total: failed + passed
234 $(Screw).bind("loaded", function() {
236 .bind("passed", window.TestSwarm.heartbeat)
237 .bind("failed", window.TestSwarm.heartbeat);
238 window.TestSwarm.heartbeat();
241 window.TestSwarm.serialize = function(){
242 return trimSerialize();
246 function trimSerialize(doc) {
247 doc = doc || document;
249 var scripts = doc.getElementsByTagName("script");
250 while ( scripts.length ) {
251 remove( scripts[0] );
254 var root = window.location.href.replace(/(https?:\/\/.*?)\/.*/, "$1");
255 var cur = window.location.href.replace(/[^\/]*$/, "");
257 var links = doc.getElementsByTagName("link");
258 for ( var i = 0; i < links.length; i++ ) {
259 var href = links[i].href;
260 if ( href.indexOf("/") === 0 ) {
262 } else if ( !/^https?:\/\//.test( href ) ) {
265 links[i].href = href;
268 return ("<html>" + doc.documentElement.innerHTML + "</html>")
269 .replace(/\s+/g, " ");
272 function remove(elem){
273 if ( typeof elem === "string" ) {
274 elem = document.getElementById( elem );
278 elem.parentNode.removeChild( elem );
282 function submit(params){
283 if ( curHeartbeat ) {
284 clearTimeout( curHeartbeat );
287 var paramItems = (url.split("?")[1] || "").split("&");
289 for ( var i = 0; i < paramItems.length; i++ ) {
290 if ( paramItems[i] ) {
291 var parts = paramItems[i].split("=");
292 if ( !params[ parts[0] ] ) {
293 params[ parts[0] ] = parts[1];
298 if ( !params.state ) {
299 params.state = "saverun";
302 if ( !params.results ) {
303 params.results = window.TestSwarm.serialize();
307 // Build Query String
310 for ( var i in params ) {
311 query += ( query ? "&" : "" ) + i + "=" +
312 encodeURIComponent(params[i]);
318 window.top.postMessage( query, "*" );
322 var form = document.createElement("form");
324 form.method = "POST";
326 for ( var i in params ) {
327 var input = document.createElement("input");
328 input.type = "hidden";
330 input.value = params[i];
331 form.appendChild( input );
335 alert( form.innerHTML );
338 // Watch for the result submission timing out
339 setTimeout(function(){
341 }, submitTimeout * 1000);
343 document.body.appendChild( form );