Fixed minor bug with Safari and the test suite.
[jquery.git] / build / test / data / testrunner.js
1 var asyncTimeout = 2 // seconds for async timeout
2
3 var fixture;
4 var Test;
5 var stats = {
6         all: 0,
7         bad: 0
8 };
9 var queue = [];
10 var blocking = false;
11 var timeout;
12
13 function synchronize(callback) {
14         queue[queue.length] = callback;
15         if(!blocking) {
16                 process();
17         }
18 }
19
20 function process() {
21         while(queue.length && !blocking) {
22                 var call = queue[0];
23                 queue = queue.slice(1);
24                 call();
25         }
26 }
27
28 function stop() {
29         blocking = true;
30         timeout = setTimeout(start, asyncTimeout * 1000);
31 }
32 function start() {
33         if(timeout)
34                 clearTimeout(timeout);
35         blocking = false;
36         process();
37 }
38
39 function runTest(tests) {
40         var startTime = new Date();
41         fixture = document.getElementById('main').innerHTML;
42         tests();
43         synchronize(function() {
44                 var runTime = new Date() - startTime;
45                 var result = document.createElement("div");
46                 result.innerHTML = 'Tests completed in ' + runTime + ' milliseconds.<br/>' +
47                         stats.bad + ' tests of ' + stats.all + ' failed.';
48                 document.getElementsByTagName("body")[0].appendChild(result);
49         });
50 }
51
52 function test(name, callback) {
53         synchronize(function() {
54                 Test = [];
55                 try {
56                         callback();
57                 } catch(e) {
58                         if( console && console.error ) {
59                                 console.error("Test " + name + " died, exception and test follows");
60                                 console.error(e);
61                                 console.warn(callback.toString());
62                         }
63                         Test.push( [ false, "Died on test #" + (Test.length+1) + ": " + e ] );
64                 }
65         });
66         synchronize(function() {
67                 reset();
68                 
69                 var good = 0, bad = 0;
70                 var ol = document.createElement("ol");
71         
72                 var li = "", state = "pass";
73                 for ( var i = 0; i < Test.length; i++ ) {
74                         var li = document.createElement("li");
75                         li.className = Test[i][0] ? "pass" : "fail";
76                         li.innerHTML = Test[i][1];
77                         ol.appendChild( li );
78                         
79                         stats.all++;
80                         if ( !Test[i][0] ) {
81                                 state = "fail";
82                                 bad++;
83                                 stats.bad++;
84                         } else good++;
85                 }
86         
87                 var li = document.createElement("li");
88                 li.className = state;
89         
90                 var b = document.createElement("b");
91                 b.innerHTML = name + " <b style='color:black;'>(<b class='fail'>" + bad + "</b>, <b class='pass'>" + good + "</b>, " + Test.length + ")</b>";
92                 b.onclick = function(){
93                         var n = this.nextSibling;
94                         if ( jQuery.css( n, "display" ) == "none" )
95                                 n.style.display = "block";
96                         else
97                                 n.style.display = "none";
98                 };
99                 li.appendChild( b );
100                 li.appendChild( ol );
101         
102                 document.getElementById("tests").appendChild( li );             
103         });
104 }
105
106 /**
107  * Resets the test setup. Useful for tests that modify the DOM.
108  */
109 function reset() {
110         document.getElementById('main').innerHTML = fixture;
111 }
112
113 /**
114  * Asserts true.
115  * @example ok( $("a").size() > 5, "There must be at least 5 anchors" );
116  */
117 function ok(a, msg) {
118         Test.push( [ !!a, msg ] );
119 }
120
121 /**
122  * Asserts that two arrays are the same
123  */
124 function isSet(a, b, msg) {
125         var ret = true;
126         if ( a && b && a.length == b.length ) {
127                 for ( var i in a )
128                         if ( a[i] != b[i] )
129                                 ret = false;
130         } else
131                 ret = false;
132         if ( !ret && console )
133                 console.log( msg, a, b );
134         Test.push( [ ret, msg ] );
135 }
136
137 /**
138  * Returns an array of elements with the given IDs, eg.
139  * @example q("main", "foo", "bar")
140  * @result [<div id="main">, <span id="foo">, <input id="bar">]
141  */
142 function q() {
143         var r = [];
144         for ( var i = 0; i < arguments.length; i++ )
145                 r.push( document.getElementById( arguments[i] ) );
146         return r;
147 }
148
149 /**
150  * Asserts that a select matches the given IDs
151  * @example t("Check for something", "//[a]", ["foo", "baar"]);
152  * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar'
153  */
154 function t(a,b,c) {
155         var f = jQuery.find(b);
156         var s = "";
157         for ( var i = 0; i < f.length; i++ )
158                 s += (s && ",") + '"' + f[i].id + '"';
159         isSet(f, q.apply(q,c), a + " (" + b + ")");
160 }