1 | define(["dojo", "doh/runner", "dojo/_firebug/firebug"], function(dojo, doh) { |
---|
2 | doh.isBrowser= true; |
---|
3 | var topdog; |
---|
4 | try{ |
---|
5 | topdog = (window.parent == window) || !Boolean(window.parent.doh); |
---|
6 | }catch(e){ |
---|
7 | //can't access window.parent.doh, then consider ourselves as topdog |
---|
8 | topdog=true; |
---|
9 | } |
---|
10 | if(topdog){ |
---|
11 | // we're the top-dog window. |
---|
12 | |
---|
13 | // borrowed from Dojo, etc. |
---|
14 | var byId = function(id){ |
---|
15 | return document.getElementById(id); |
---|
16 | }; |
---|
17 | |
---|
18 | var _addOnEvt = function( type, // string |
---|
19 | refOrName, // function or string |
---|
20 | scope){ // object, defaults is window |
---|
21 | |
---|
22 | if(!scope){ scope = window; } |
---|
23 | |
---|
24 | var funcRef = refOrName; |
---|
25 | if(typeof refOrName == "string"){ |
---|
26 | funcRef = scope[refOrName]; |
---|
27 | } |
---|
28 | var enclosedFunc = function(){ return funcRef.apply(scope, arguments); }; |
---|
29 | |
---|
30 | if((window["dojo"])&&(type == "load")){ |
---|
31 | dojo.addOnLoad(enclosedFunc); |
---|
32 | }else{ |
---|
33 | if(window["attachEvent"]){ |
---|
34 | window.attachEvent("on"+type, enclosedFunc); |
---|
35 | }else if(window["addEventListener"]){ |
---|
36 | window.addEventListener(type, enclosedFunc, false); |
---|
37 | }else if(document["addEventListener"]){ |
---|
38 | document.addEventListener(type, enclosedFunc, false); |
---|
39 | } |
---|
40 | } |
---|
41 | }; |
---|
42 | |
---|
43 | // |
---|
44 | // Over-ride or implement base runner.js-provided methods |
---|
45 | // |
---|
46 | var escapeXml = function(str){ |
---|
47 | //summary: |
---|
48 | // Adds escape sequences for special characters in XML: &<>"' |
---|
49 | // Optionally skips escapes for single quotes |
---|
50 | return str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """); // string |
---|
51 | }; |
---|
52 | |
---|
53 | var formatTime = function(n){ |
---|
54 | switch(true){ |
---|
55 | case n<1000: //<1s |
---|
56 | return n+"ms"; |
---|
57 | case n<60000: //<1m |
---|
58 | return Math.round(n/100)/10+"s"; |
---|
59 | case n<3600000: //<1h |
---|
60 | return Math.round(n/6000)/10+"m"; |
---|
61 | default: //>1h |
---|
62 | return Math.round(n/360000)/10+"h"; |
---|
63 | } |
---|
64 | }; |
---|
65 | |
---|
66 | var _logBacklog = [], _loggedMsgLen = 0; |
---|
67 | var sendToLogPane = function(args, skip){ |
---|
68 | var msg = ""; |
---|
69 | for(var x=0; x<args.length; x++){ |
---|
70 | msg += " "+args[x]; |
---|
71 | } |
---|
72 | |
---|
73 | msg = escapeXml(msg); |
---|
74 | |
---|
75 | // workarounds for IE. Wheeee!!! |
---|
76 | msg = msg.replace("\t", " ") |
---|
77 | .replace(" ", " ") |
---|
78 | .replace("\n", "<br> "); |
---|
79 | if(!byId("logBody")){ |
---|
80 | _logBacklog.push(msg); |
---|
81 | return; |
---|
82 | }else if(_logBacklog.length && !skip){ |
---|
83 | var tm; |
---|
84 | while((tm=_logBacklog.shift())){ |
---|
85 | sendToLogPane(tm, true); |
---|
86 | } |
---|
87 | } |
---|
88 | var logBody=byId("logBody"); |
---|
89 | var tn = document.createElement("div"); |
---|
90 | tn.innerHTML = msg; |
---|
91 | //tn.id="logmsg_"+logBody.childNodes.length; |
---|
92 | logBody.appendChild(tn); |
---|
93 | _loggedMsgLen++; |
---|
94 | } |
---|
95 | |
---|
96 | var findTarget = function(n){ |
---|
97 | while(n && !n.getAttribute('_target')){ |
---|
98 | n=n.parentNode; |
---|
99 | if(!n.getAttribute){ |
---|
100 | n=null; |
---|
101 | } |
---|
102 | } |
---|
103 | return n; |
---|
104 | } |
---|
105 | |
---|
106 | doh._jumpToLog = function(e){ |
---|
107 | //console.log(e); |
---|
108 | |
---|
109 | var node = findTarget(e?e.target:window.event.srcElement); |
---|
110 | if(!node){ |
---|
111 | return; |
---|
112 | } |
---|
113 | var _t = Number(node.getAttribute('_target')); |
---|
114 | var lb = byId("logBody"); |
---|
115 | if(_t>=lb.childNodes.length){ |
---|
116 | return; |
---|
117 | } |
---|
118 | var t = lb.childNodes[_t]; |
---|
119 | t.scrollIntoView(); |
---|
120 | if(window.dojo){ |
---|
121 | //t.parentNode.parentNode is <div class="tabBody">, only it has a explicitly set background-color, |
---|
122 | //all children of it are transparent |
---|
123 | var bgColor = dojo.style(t.parentNode.parentNode,'backgroundColor'); |
---|
124 | //node.parentNode is the tr which has background-color set explicitly |
---|
125 | var hicolor = dojo.style(node.parentNode,'backgroundColor'); |
---|
126 | var unhilight = dojo.animateProperty({ |
---|
127 | node: t, |
---|
128 | duration: 500, |
---|
129 | properties: |
---|
130 | { |
---|
131 | backgroundColor: { start:hicolor, end: bgColor } |
---|
132 | }, |
---|
133 | onEnd: function(){ |
---|
134 | t.style.backgroundColor=""; |
---|
135 | } |
---|
136 | }); |
---|
137 | var hilight = dojo.animateProperty({ |
---|
138 | node: t, |
---|
139 | duration: 500, |
---|
140 | properties: |
---|
141 | { |
---|
142 | backgroundColor: { start:bgColor, end: hicolor } |
---|
143 | }, |
---|
144 | onEnd: function(){ |
---|
145 | unhilight.play(); |
---|
146 | } |
---|
147 | }); |
---|
148 | hilight.play(); |
---|
149 | } |
---|
150 | }; |
---|
151 | |
---|
152 | doh._jumpToSuite = function(e){ |
---|
153 | var node = findTarget(e ? e.target : window.event.srcElement); |
---|
154 | if(!node){ |
---|
155 | return; |
---|
156 | } |
---|
157 | var _g = node.getAttribute('_target'); |
---|
158 | var gn = getGroupNode(_g); |
---|
159 | if(!gn){ |
---|
160 | return; |
---|
161 | } |
---|
162 | gn.scrollIntoView(); |
---|
163 | }; |
---|
164 | |
---|
165 | doh._init = (function(oi){ |
---|
166 | return function(){ |
---|
167 | var lb = byId("logBody"); |
---|
168 | if(lb){ |
---|
169 | // clear the console before each run |
---|
170 | while(lb.firstChild){ |
---|
171 | lb.removeChild(lb.firstChild); |
---|
172 | } |
---|
173 | _loggedMsgLen = 0; |
---|
174 | } |
---|
175 | this._totalTime = 0; |
---|
176 | this._suiteCount = 0; |
---|
177 | oi.apply(doh, arguments); |
---|
178 | } |
---|
179 | })(doh._init); |
---|
180 | |
---|
181 | doh._setupGroupForRun = (function(os){ |
---|
182 | //overload _setupGroupForRun to record which log line to jump to when a suite is clicked |
---|
183 | return function(groupName){ |
---|
184 | var tg = doh._groups[groupName]; |
---|
185 | doh._curTestCount = tg.length; |
---|
186 | doh._curGroupCount = 1; |
---|
187 | var gn = getGroupNode(groupName); |
---|
188 | if(gn){ |
---|
189 | //two lines will be added, scroll the second line into view |
---|
190 | gn.getElementsByTagName("td")[2].setAttribute('_target',_loggedMsgLen+1); |
---|
191 | } |
---|
192 | os.apply(doh,arguments); |
---|
193 | } |
---|
194 | })(doh._setupGroupForRun); |
---|
195 | |
---|
196 | var originalDohReport= doh._report; |
---|
197 | doh._report = function(){ |
---|
198 | var tb = byId("testList"); |
---|
199 | if(tb){ |
---|
200 | var tfoots=tb.getElementsByTagName('tfoot'); |
---|
201 | if(tfoots.length){ |
---|
202 | tb.removeChild(tfoots[0]); |
---|
203 | } |
---|
204 | var foot = tb.createTFoot(); |
---|
205 | var row = foot.insertRow(-1); |
---|
206 | row.className = 'inProgress'; |
---|
207 | var cell=row.insertCell(-1); |
---|
208 | cell.colSpan=2; |
---|
209 | cell.innerHTML="Result"; |
---|
210 | cell = row.insertCell(-1); |
---|
211 | cell.innerHTML=this._testCount+" tests in "+this._groupCount+" groups /<span class='failure'>"+this._errorCount+"</span> errors, <span class='failure'>"+this._failureCount+"</span> failures"; |
---|
212 | cell.setAttribute('_target',_loggedMsgLen+1); |
---|
213 | row.insertCell(-1).innerHTML=formatTime(doh._totalTime); |
---|
214 | } |
---|
215 | |
---|
216 | //This location can do the final performance rendering for the results |
---|
217 | //of any performance tests. |
---|
218 | var plotResults = null; |
---|
219 | var standby; |
---|
220 | if(doh.perfTestResults){ |
---|
221 | require(["dojox/math/stats", "dojox/charting/Chart2D", "dojox/charting/DataChart", "dojox/charting/plot2d/Scatter", "dojox/charting/plot2d/Lines", "dojo/data/ItemFileReadStore"], function(stats) { |
---|
222 | dojo.mixin(doh, stats); |
---|
223 | |
---|
224 | plotResults = doh._dojoPlotPerfResults; |
---|
225 | try{ |
---|
226 | var g; |
---|
227 | var pBody = byId("perfTestsBody"); |
---|
228 | var chartsToRender = []; |
---|
229 | // store analytics for reading later |
---|
230 | // keyed on test group name, each value is in turn an object keyed on test name |
---|
231 | doh.perfTestAnalytics={}; |
---|
232 | doh.showPerfTestsPage(); |
---|
233 | for(g in doh.perfTestResults){ |
---|
234 | doh.perfTestAnalytics[g]={}; |
---|
235 | var grp = doh.perfTestResults[g]; |
---|
236 | var hdr = document.createElement("h1"); |
---|
237 | hdr.appendChild(document.createTextNode("Group: " + g)); |
---|
238 | pBody.appendChild(hdr); |
---|
239 | var ind = document.createElement("blockquote"); |
---|
240 | pBody.appendChild(ind); |
---|
241 | var f; |
---|
242 | for(f in grp){ |
---|
243 | var fResults = grp[f]; |
---|
244 | if(!fResults){ continue; } |
---|
245 | var fhdr = document.createElement("h3"); |
---|
246 | fhdr.appendChild(document.createTextNode("TEST: " + f)); |
---|
247 | fhdr.style.textDecoration = "underline"; |
---|
248 | ind.appendChild(fhdr); |
---|
249 | var div = document.createElement("div"); |
---|
250 | ind.appendChild(div); |
---|
251 | |
---|
252 | //Figure out the basic info |
---|
253 | var results = "<b>TRIAL SIZE: </b>" + fResults.trials[0].testIterations + " iterations<br>" + |
---|
254 | "<b>NUMBER OF TRIALS: </b>" + fResults.trials.length + "<br>"; |
---|
255 | |
---|
256 | //Figure out the average test pass cost. |
---|
257 | var i; |
---|
258 | var iAvgArray = []; |
---|
259 | var tAvgArray = []; |
---|
260 | for(i = 0; i < fResults.trials.length; i++){ |
---|
261 | iAvgArray.push(fResults.trials[i].average); |
---|
262 | tAvgArray.push(fResults.trials[i].executionTime); |
---|
263 | } |
---|
264 | var analytics=doh.perfTestAnalytics[g][f]={ |
---|
265 | averageTrialExecutionTime: doh.mean(tAvgArray), |
---|
266 | maxTestIterationTime: doh.max(iAvgArray), |
---|
267 | minTestIterationTime: doh.min(iAvgArray), |
---|
268 | averageTestIterationTime: doh.mean(iAvgArray), |
---|
269 | medianTestIterationTime: doh.median(iAvgArray), |
---|
270 | varianceTestIterationTime: doh.variance(iAvgArray), |
---|
271 | standardDeviationTestIterationTime: doh.sd(iAvgArray) |
---|
272 | }; |
---|
273 | results += "<b>AVERAGE TRIAL EXECUTION TIME: </b>" + analytics.averageTrialExecutionTime.toFixed(10) + "ms.<br>"; |
---|
274 | results += "<b>MAXIMUM TEST ITERATION TIME: </b>" + analytics.maxTestIterationTime.toFixed(10) + "ms.<br>"; |
---|
275 | results += "<b>MINIMUM TEST ITERATION TIME: </b>" + analytics.minTestIterationTime.toFixed(10) + "ms.<br>"; |
---|
276 | results += "<b>AVERAGE TEST ITERATION TIME: </b>" + analytics.averageTestIterationTime.toFixed(10) + "ms.<br>"; |
---|
277 | results += "<b>MEDIAN TEST ITERATION TIME: </b>" + analytics.medianTestIterationTime.toFixed(10) + "ms.<br>"; |
---|
278 | results += "<b>VARIANCE TEST ITERATION TIME: </b>" + analytics.varianceTestIterationTime.toFixed(10) + "ms.<br>"; |
---|
279 | results += "<b>STANDARD DEVIATION ON TEST ITERATION TIME: </b>" +analytics.standardDeviationTestIterationTime.toFixed(10) + "ms.<br>"; |
---|
280 | |
---|
281 | //Okay, attach it all in. |
---|
282 | div.innerHTML = results; |
---|
283 | |
---|
284 | div = document.createElement("div"); |
---|
285 | div.innerHTML = "<h3>Average Test Execution Time (in milliseconds, with median line)</h3>"; |
---|
286 | ind.appendChild(div); |
---|
287 | div = document.createElement("div"); |
---|
288 | dojo.style(div, "width", "600px"); |
---|
289 | dojo.style(div, "height", "250px"); |
---|
290 | ind.appendChild(div); |
---|
291 | chartsToRender.push({ |
---|
292 | div: div, |
---|
293 | title: "Average Test Execution Time", |
---|
294 | data: iAvgArray |
---|
295 | }); |
---|
296 | |
---|
297 | div = document.createElement("div"); |
---|
298 | div.innerHTML = "<h3>Average Trial Execution Time (in milliseconds, with median line)</h3>"; |
---|
299 | ind.appendChild(div); |
---|
300 | div = document.createElement("div"); |
---|
301 | dojo.style(div, "width", "600px"); |
---|
302 | dojo.style(div, "height", "250px"); |
---|
303 | ind.appendChild(div); |
---|
304 | chartsToRender.push({ |
---|
305 | div: div, |
---|
306 | title: "Average Trial Execution Time", |
---|
307 | data: tAvgArray |
---|
308 | }); |
---|
309 | } |
---|
310 | } |
---|
311 | |
---|
312 | //Lazy-render these to give the browser time and not appear locked. |
---|
313 | var delayedRenders = function() { |
---|
314 | if(chartsToRender.length){ |
---|
315 | var chartData = chartsToRender.shift(); |
---|
316 | plotResults(chartData.div, chartData.title, chartData.data); |
---|
317 | } |
---|
318 | setTimeout(delayedRenders, 50); |
---|
319 | }; |
---|
320 | setTimeout(delayedRenders, 150); |
---|
321 | }catch(e){ |
---|
322 | doh.debug(e); |
---|
323 | } |
---|
324 | }); |
---|
325 | } |
---|
326 | originalDohReport.apply(doh,arguments); |
---|
327 | }; |
---|
328 | |
---|
329 | |
---|
330 | doh.error = undefined; |
---|
331 | if(this["opera"] && opera.postError){ |
---|
332 | doh.debug = function(){ |
---|
333 | var msg = ""; |
---|
334 | for(var x=0; x<arguments.length; x++){ |
---|
335 | msg += " "+arguments[x]; |
---|
336 | } |
---|
337 | sendToLogPane([msg]); |
---|
338 | opera.postError("DEBUG:"+msg); |
---|
339 | } |
---|
340 | }else if(window["console"]){ |
---|
341 | if(console.error){ |
---|
342 | doh.error = function(){ |
---|
343 | sendToLogPane.call(window, arguments); |
---|
344 | console.error(Array.prototype.join.call(arguments, " ")) |
---|
345 | }; |
---|
346 | } |
---|
347 | if(console.debug){ |
---|
348 | doh.debug = function(){ |
---|
349 | sendToLogPane.call(window, arguments); |
---|
350 | console.debug(Array.prototype.join.call(arguments, " ")) |
---|
351 | }; |
---|
352 | }else if(console.info){ |
---|
353 | doh.debug = function(){ |
---|
354 | sendToLogPane.call(window, arguments); |
---|
355 | console.info(Array.prototype.join.call(arguments, " ")) |
---|
356 | }; |
---|
357 | }else{ |
---|
358 | doh.debug = function(){ |
---|
359 | sendToLogPane.call(window, arguments); |
---|
360 | console.log("DEBUG:"+ Array.prototype.join.call(arguments, " ")); |
---|
361 | }; |
---|
362 | } |
---|
363 | }else{ |
---|
364 | doh.debug = function(){ |
---|
365 | sendToLogPane.call(window, arguments); |
---|
366 | } |
---|
367 | } |
---|
368 | doh.error = doh.error || doh.debug; |
---|
369 | var loaded = false; |
---|
370 | var groupTemplate = null; |
---|
371 | var testTemplate = null; |
---|
372 | |
---|
373 | var groupNodes = {}; |
---|
374 | |
---|
375 | var _groupTogglers = {}; |
---|
376 | |
---|
377 | var _getGroupToggler = function(group, toggle){ |
---|
378 | if(_groupTogglers[group]){ return _groupTogglers[group]; } |
---|
379 | var rolledUp = true; |
---|
380 | return (_groupTogglers[group] = function(evt, forceOpen){ |
---|
381 | var nodes = groupNodes[group].__items; |
---|
382 | var x; |
---|
383 | if(rolledUp||forceOpen){ |
---|
384 | rolledUp = false; |
---|
385 | for(x=0; x<nodes.length; x++){ |
---|
386 | nodes[x].style.display = ""; |
---|
387 | } |
---|
388 | toggle.innerHTML = "▼"; |
---|
389 | }else{ |
---|
390 | rolledUp = true; |
---|
391 | for(x=0; x<nodes.length; x++){ |
---|
392 | nodes[x].style.display = "none"; |
---|
393 | } |
---|
394 | toggle.innerHTML = "►"; |
---|
395 | } |
---|
396 | }); |
---|
397 | }; |
---|
398 | |
---|
399 | var addGroupToList = function(group){ |
---|
400 | if(!byId("testList")){ return; } |
---|
401 | var tb = byId("testList").tBodies[0]; |
---|
402 | var tg = groupTemplate.cloneNode(true); |
---|
403 | var tds = tg.getElementsByTagName("td"); |
---|
404 | var toggle = tds[0]; |
---|
405 | toggle.onclick = _getGroupToggler(group, toggle); |
---|
406 | var cb = tds[1].getElementsByTagName("input")[0]; |
---|
407 | cb.group = group; |
---|
408 | cb.onclick = function(evt){ |
---|
409 | doh._groups[group].skip = (!this.checked); |
---|
410 | } |
---|
411 | tds[2].innerHTML = "<div class='testGroupName'>"+group+"</div><div style='width:0;'> </div>"; |
---|
412 | tds[3].innerHTML = ""; |
---|
413 | |
---|
414 | tb.appendChild(tg); |
---|
415 | return tg; |
---|
416 | } |
---|
417 | |
---|
418 | var addFixtureToList = function(group, fixture){ |
---|
419 | if(!testTemplate){ return; } |
---|
420 | var cgn = groupNodes[group]; |
---|
421 | if(!cgn["__items"]){ cgn.__items = []; } |
---|
422 | var tn = testTemplate.cloneNode(true); |
---|
423 | var tds = tn.getElementsByTagName("td"); |
---|
424 | |
---|
425 | tds[2].innerHTML = fixture.name; |
---|
426 | tds[3].innerHTML = ""; |
---|
427 | |
---|
428 | var nn = (cgn.__lastFixture||cgn.__groupNode).nextSibling; |
---|
429 | if(nn){ |
---|
430 | nn.parentNode.insertBefore(tn, nn); |
---|
431 | }else{ |
---|
432 | cgn.__groupNode.parentNode.appendChild(tn); |
---|
433 | } |
---|
434 | // FIXME: need to make group display toggleable!! |
---|
435 | tn.style.display = "none"; |
---|
436 | cgn.__items.push(tn); |
---|
437 | return (cgn.__lastFixture = tn); |
---|
438 | } |
---|
439 | |
---|
440 | var getFixtureNode = function(group, fixture){ |
---|
441 | if(groupNodes[group]){ |
---|
442 | return groupNodes[group][fixture.name]; |
---|
443 | } |
---|
444 | return null; |
---|
445 | } |
---|
446 | |
---|
447 | var getGroupNode = function(group){ |
---|
448 | if(groupNodes[group]){ |
---|
449 | return groupNodes[group].__groupNode; |
---|
450 | } |
---|
451 | return null; |
---|
452 | } |
---|
453 | |
---|
454 | var updateBacklog = []; |
---|
455 | doh._updateTestList = function(group, fixture, unwindingBacklog){ |
---|
456 | if(!loaded){ |
---|
457 | if(group && fixture){ |
---|
458 | updateBacklog.push([group, fixture]); |
---|
459 | } |
---|
460 | return; |
---|
461 | }else if(updateBacklog.length && !unwindingBacklog){ |
---|
462 | var tr; |
---|
463 | while((tr=updateBacklog.shift())){ |
---|
464 | doh._updateTestList(tr[0], tr[1], true); |
---|
465 | } |
---|
466 | } |
---|
467 | if(group && fixture){ |
---|
468 | if(!groupNodes[group]){ |
---|
469 | groupNodes[group] = { |
---|
470 | "__groupNode": addGroupToList(group) |
---|
471 | }; |
---|
472 | } |
---|
473 | if(!groupNodes[group][fixture.name]){ |
---|
474 | groupNodes[group][fixture.name] = addFixtureToList(group, fixture) |
---|
475 | } |
---|
476 | } |
---|
477 | } |
---|
478 | |
---|
479 | doh._testRegistered = doh._updateTestList; |
---|
480 | |
---|
481 | doh._groupStarted = function(group){ |
---|
482 | if(this._suiteCount == 0){ |
---|
483 | this._runedSuite = 0; |
---|
484 | this._currentGlobalProgressBarWidth = 0; |
---|
485 | this._suiteCount = this._testCount; |
---|
486 | } |
---|
487 | // console.debug("_groupStarted", group); |
---|
488 | if(doh._inGroup != group){ |
---|
489 | doh._groupTotalTime = 0; |
---|
490 | doh._runed = 0; |
---|
491 | doh._inGroup = group; |
---|
492 | this._runedSuite++; |
---|
493 | } |
---|
494 | var gn = getGroupNode(group); |
---|
495 | if(gn){ |
---|
496 | gn.className = "inProgress"; |
---|
497 | } |
---|
498 | } |
---|
499 | |
---|
500 | doh._groupFinished = function(group, success){ |
---|
501 | // console.debug("_groupFinished", group); |
---|
502 | var gn = getGroupNode(group); |
---|
503 | if(gn && doh._inGroup == group){ |
---|
504 | doh._totalTime += doh._groupTotalTime; |
---|
505 | gn.getElementsByTagName("td")[3].innerHTML = formatTime(doh._groupTotalTime); |
---|
506 | gn.getElementsByTagName("td")[2].lastChild.className = ""; |
---|
507 | doh._inGroup = null; |
---|
508 | //doh._runedSuite++; |
---|
509 | var failure = doh._updateGlobalProgressBar(this._runedSuite/this._groupCount,success,group); |
---|
510 | gn.className = failure ? "failure" : "success"; |
---|
511 | //doh._runedSuite--; |
---|
512 | doh._currentGlobalProgressBarWidth = parseInt(this._runedSuite/this._groupCount*10000)/100; |
---|
513 | //byId("progressOuter").style.width = parseInt(this._runedSuite/this._suiteCount*100)+"%"; |
---|
514 | } |
---|
515 | if(doh._inGroup == group){ |
---|
516 | this.debug("Total time for GROUP \"",group,"\" is ",formatTime(doh._groupTotalTime)); |
---|
517 | } |
---|
518 | } |
---|
519 | |
---|
520 | doh._testStarted = function(group, fixture){ |
---|
521 | // console.debug("_testStarted", group, fixture.name); |
---|
522 | var fn = getFixtureNode(group, fixture); |
---|
523 | if(fn){ |
---|
524 | fn.className = "inProgress"; |
---|
525 | } |
---|
526 | } |
---|
527 | |
---|
528 | var _nameTimes = {}; |
---|
529 | var _playSound = function(name){ |
---|
530 | if(byId("hiddenAudio") && byId("audio") && byId("audio").checked){ |
---|
531 | // console.debug("playing:", name); |
---|
532 | var nt = _nameTimes[name]; |
---|
533 | // only play sounds once every second or so |
---|
534 | if((!nt)||(((new Date)-nt) > 700)){ |
---|
535 | _nameTimes[name] = new Date(); |
---|
536 | var tc = document.createElement("span"); |
---|
537 | byId("hiddenAudio").appendChild(tc); |
---|
538 | tc.innerHTML = '<embed src="_sounds/'+name+'.wav" autostart="true" loop="false" hidden="true" width="1" height="1"></embed>'; |
---|
539 | } |
---|
540 | } |
---|
541 | } |
---|
542 | |
---|
543 | doh._updateGlobalProgressBar = function(p,success,group){ |
---|
544 | var outerContainer=byId("progressOuter"); |
---|
545 | |
---|
546 | var gdiv=outerContainer.childNodes[doh._runedSuite-1]; |
---|
547 | if(!gdiv){ |
---|
548 | gdiv=document.createElement('div'); |
---|
549 | outerContainer.appendChild(gdiv); |
---|
550 | gdiv.className='success'; |
---|
551 | gdiv.setAttribute('_target',group); |
---|
552 | } |
---|
553 | if(!success && !gdiv._failure){ |
---|
554 | gdiv._failure=true; |
---|
555 | gdiv.className='failure'; |
---|
556 | if(group){ |
---|
557 | gdiv.setAttribute('title','failed group '+group); |
---|
558 | } |
---|
559 | } |
---|
560 | var tp=parseInt(p*10000)/100; |
---|
561 | gdiv.style.width = (tp-doh._currentGlobalProgressBarWidth)+"%"; |
---|
562 | return gdiv._failure; |
---|
563 | } |
---|
564 | doh._testFinished = function(group, fixture, success){ |
---|
565 | var fn = getFixtureNode(group, fixture); |
---|
566 | var elapsed = fixture.endTime-fixture.startTime; |
---|
567 | if(fn){ |
---|
568 | fn.getElementsByTagName("td")[3].innerHTML = formatTime(elapsed); |
---|
569 | fn.className = (success) ? "success" : "failure"; |
---|
570 | fn.getElementsByTagName("td")[2].setAttribute('_target', _loggedMsgLen); |
---|
571 | if(!success){ |
---|
572 | _playSound("doh"); |
---|
573 | var gn = getGroupNode(group); |
---|
574 | if(gn){ |
---|
575 | gn.className = "failure"; |
---|
576 | _getGroupToggler(group)(null, true); |
---|
577 | } |
---|
578 | } |
---|
579 | } |
---|
580 | if(doh._inGroup == group){ |
---|
581 | var gn = getGroupNode(group); |
---|
582 | doh._runed++; |
---|
583 | if(gn && doh._curTestCount){ |
---|
584 | var p = doh._runed/doh._curTestCount; |
---|
585 | var groupfail = this._updateGlobalProgressBar((doh._runedSuite+p-1)/doh._groupCount,success,group); |
---|
586 | |
---|
587 | var pbar = gn.getElementsByTagName("td")[2].lastChild; |
---|
588 | pbar.className = groupfail?"failure":"success"; |
---|
589 | pbar.style.width = parseInt(p*100)+"%"; |
---|
590 | gn.getElementsByTagName("td")[3].innerHTML = parseInt(p*10000)/100+"%"; |
---|
591 | } |
---|
592 | } |
---|
593 | this._groupTotalTime += elapsed; |
---|
594 | this.debug((success ? "PASSED" : "FAILED"), "test:", fixture.name, elapsed, 'ms'); |
---|
595 | }; |
---|
596 | |
---|
597 | doh._registerUrl = function(group, url, timeout, type, dohArgs){ |
---|
598 | group= group || url; |
---|
599 | this._registerTest(group, { |
---|
600 | name: url, |
---|
601 | setUp: function(){ |
---|
602 | doh.currentGroupName = group; |
---|
603 | doh.currentGroup = this; |
---|
604 | doh.currentUrl = url; |
---|
605 | doh.dohArgs = dohArgs; |
---|
606 | this.d = new doh.Deferred(); |
---|
607 | doh.currentTestDeferred = this.d; |
---|
608 | doh.showTestPage(); |
---|
609 | byId("testBody").src = url; |
---|
610 | }, |
---|
611 | timeout: timeout||10000, // 10s |
---|
612 | // timeout: timeout||1000, // 10s |
---|
613 | runTest: function(){ |
---|
614 | // FIXME: implement calling into the url's groups here!! |
---|
615 | return this.d; |
---|
616 | }, |
---|
617 | tearDown: function(){ |
---|
618 | doh.currentGroupName = null; |
---|
619 | doh.currentGroup = null; |
---|
620 | doh.currentTestDeferred = null; |
---|
621 | doh.currentUrl = null; |
---|
622 | // this.d.errback(false); |
---|
623 | // byId("testBody").src = "about:blank"; |
---|
624 | doh.showLogPage(); |
---|
625 | } |
---|
626 | }, type); |
---|
627 | }; |
---|
628 | |
---|
629 | // |
---|
630 | // Utility code for runner.html |
---|
631 | // |
---|
632 | // var isSafari = navigator.appVersion.indexOf("Safari") >= 0; |
---|
633 | var tabzidx = 1; |
---|
634 | var _showTab = function(toShow, toHide){ |
---|
635 | // FIXME: I don't like hiding things this way. |
---|
636 | var i; |
---|
637 | for(i = 0; i < toHide.length; i++){ |
---|
638 | var node = byId(toHide[i]); |
---|
639 | if(node){ |
---|
640 | node.style.display="none"; |
---|
641 | } |
---|
642 | } |
---|
643 | toShow = byId(toShow); |
---|
644 | if(toShow){ |
---|
645 | with(toShow.style){ |
---|
646 | display = ""; |
---|
647 | zIndex = ++tabzidx; |
---|
648 | } |
---|
649 | } |
---|
650 | } |
---|
651 | |
---|
652 | doh.showTestPage = function(){ |
---|
653 | _showTab("testBody", ["logBody", "perfTestsBody"]); |
---|
654 | } |
---|
655 | |
---|
656 | doh.showLogPage = function(){ |
---|
657 | _showTab("logBody", ["testBody", "perfTestsBody"]); |
---|
658 | } |
---|
659 | |
---|
660 | doh.showPerfTestsPage = function(){ |
---|
661 | _showTab("perfTestsBody", ["testBody", "logBody"]); |
---|
662 | } |
---|
663 | |
---|
664 | var runAll = true; |
---|
665 | doh.toggleRunAll = function(){ |
---|
666 | // would be easier w/ query...sigh |
---|
667 | runAll = !runAll; |
---|
668 | if(!byId("testList")){ return; } |
---|
669 | var tb = byId("testList").tBodies[0]; |
---|
670 | var inputs = tb.getElementsByTagName("input"); |
---|
671 | var x=0; var tn; |
---|
672 | while((tn=inputs[x++])){ |
---|
673 | tn.checked = runAll; |
---|
674 | doh._groups[tn.group].skip = (!runAll); |
---|
675 | } |
---|
676 | } |
---|
677 | |
---|
678 | var listHeightTimer = null; |
---|
679 | var setListHeight = function(){ |
---|
680 | if(listHeightTimer){ |
---|
681 | clearTimeout(listHeightTimer); |
---|
682 | } |
---|
683 | var tl = byId("testList"); |
---|
684 | if(!tl){ return; } |
---|
685 | listHeightTimer = setTimeout(function(){ |
---|
686 | tl.style.display = "none"; |
---|
687 | tl.style.display = ""; |
---|
688 | |
---|
689 | }, 10); |
---|
690 | } |
---|
691 | |
---|
692 | _addOnEvt("resize", setListHeight); |
---|
693 | _addOnEvt("load", setListHeight); |
---|
694 | _addOnEvt("load", function(){ |
---|
695 | if(loaded){ return; } |
---|
696 | loaded = true; |
---|
697 | groupTemplate = byId("groupTemplate"); |
---|
698 | if(!groupTemplate){ |
---|
699 | // make sure we've got an ammenable DOM structure |
---|
700 | return; |
---|
701 | } |
---|
702 | groupTemplate.parentNode.removeChild(groupTemplate); |
---|
703 | groupTemplate.style.display = ""; |
---|
704 | testTemplate = byId("testTemplate"); |
---|
705 | testTemplate.parentNode.removeChild(testTemplate); |
---|
706 | testTemplate.style.display = ""; |
---|
707 | doh._updateTestList(); |
---|
708 | }); |
---|
709 | |
---|
710 | _addOnEvt("load", |
---|
711 | function(){ |
---|
712 | // let robot code run if it gets to this first |
---|
713 | var __onEnd = doh._onEnd; |
---|
714 | doh._onEnd = function(){ |
---|
715 | __onEnd.apply(doh, arguments); |
---|
716 | if(doh._failureCount == 0){ |
---|
717 | doh.debug("WOOHOO!!"); |
---|
718 | _playSound("woohoo"); |
---|
719 | }else{ |
---|
720 | console.debug("doh._failureCount:", doh._failureCount); |
---|
721 | } |
---|
722 | if(byId("play")){ |
---|
723 | toggleRunning(); |
---|
724 | } |
---|
725 | } |
---|
726 | if(!byId("play")){ |
---|
727 | // make sure we've got an amenable DOM structure |
---|
728 | return; |
---|
729 | } |
---|
730 | var isRunning = false; |
---|
731 | var toggleRunning = function(){ |
---|
732 | // ugg, this would be so much better w/ dojo.query() |
---|
733 | if(isRunning){ |
---|
734 | byId("play").style.display = byId("pausedMsg").style.display = ""; |
---|
735 | byId("playingMsg").style.display = byId("pause").style.display = "none"; |
---|
736 | isRunning = false; |
---|
737 | }else{ |
---|
738 | byId("play").style.display = byId("pausedMsg").style.display = "none"; |
---|
739 | byId("playingMsg").style.display = byId("pause").style.display = ""; |
---|
740 | isRunning = true; |
---|
741 | } |
---|
742 | } |
---|
743 | doh.run = (function(oldRun){ |
---|
744 | return function(){ |
---|
745 | if(!doh._currentGroup){ |
---|
746 | toggleRunning(); |
---|
747 | } |
---|
748 | return oldRun.apply(doh, arguments); |
---|
749 | } |
---|
750 | })(doh.run); |
---|
751 | var btns = byId("toggleButtons").getElementsByTagName("span"); |
---|
752 | var node; var idx=0; |
---|
753 | while((node=btns[idx++])){ |
---|
754 | node.onclick = toggleRunning; |
---|
755 | } |
---|
756 | |
---|
757 | //Performance report generating functions! |
---|
758 | doh._dojoPlotPerfResults = function(div, name, dataArray) { |
---|
759 | var median = doh.median(dataArray); |
---|
760 | var medarray = []; |
---|
761 | |
---|
762 | var i; |
---|
763 | for(i = 0; i < dataArray.length; i++){ |
---|
764 | medarray.push(median); |
---|
765 | } |
---|
766 | |
---|
767 | var data = { |
---|
768 | label: "name", |
---|
769 | items: [ |
---|
770 | {name: name, trials: dataArray}, |
---|
771 | {name: "Median", trials: medarray} |
---|
772 | ] |
---|
773 | }; |
---|
774 | var ifs = new dojo.data.ItemFileReadStore({data: data}); |
---|
775 | |
---|
776 | var min = Math.floor(doh.min(dataArray)); |
---|
777 | var max = Math.ceil(doh.max(dataArray)); |
---|
778 | var step = (max - min)/10; |
---|
779 | |
---|
780 | //Lets try to pad out the bottom and top a bit |
---|
781 | //Then recalc the step. |
---|
782 | if(min > 0){ |
---|
783 | min = min - step; |
---|
784 | if(min < 0){ |
---|
785 | min = 0; |
---|
786 | } |
---|
787 | min = Math.floor(min); |
---|
788 | } |
---|
789 | if(max > 0){ |
---|
790 | max = max + step; |
---|
791 | max = Math.ceil(max); |
---|
792 | } |
---|
793 | step = (max - min)/10; |
---|
794 | |
---|
795 | var chart = new dojox.charting.DataChart(div, { |
---|
796 | type: dojox.charting.plot2d.Lines, |
---|
797 | displayRange:dataArray.length, |
---|
798 | xaxis: {min: 1, max: dataArray.length, majorTickStep: Math.ceil((dataArray.length - 1)/10), htmlLabels: false}, |
---|
799 | yaxis: {min: min, max: max, majorTickStep: step, vertical: true, htmlLabels: false} |
---|
800 | }); |
---|
801 | chart.setStore(ifs, {name:"*"}, "trials"); |
---|
802 | }; |
---|
803 | |
---|
804 | } |
---|
805 | ); |
---|
806 | }else{ |
---|
807 | // we're in an iframe environment. Time to mix it up a bit. |
---|
808 | |
---|
809 | _doh = window.parent.doh; |
---|
810 | var _thisGroup = _doh.currentGroupName; |
---|
811 | var _thisUrl = _doh.currentUrl; |
---|
812 | if(_thisGroup){ |
---|
813 | doh._onEnd = function(){ |
---|
814 | _doh._errorCount += doh._errorCount; |
---|
815 | _doh._failureCount += doh._failureCount; |
---|
816 | _doh._testCount += doh._testCount; |
---|
817 | // should we be really adding raw group counts? |
---|
818 | //_doh._groupCount += doh._groupCount; |
---|
819 | _doh.currentTestDeferred.callback(true); |
---|
820 | }; |
---|
821 | doh._testRegistered = function(group, fixture){ |
---|
822 | fixture.name = _thisUrl+"::"+arguments[0]+"::"+fixture.name; |
---|
823 | _doh._updateTestList(_thisGroup, fixture); |
---|
824 | }; |
---|
825 | doh.debug = doh.hitch(_doh, "debug"); |
---|
826 | doh.error = doh.hitch(_doh, "error"); |
---|
827 | doh.registerUrl = doh.hitch(_doh, "registerUrl"); |
---|
828 | doh._testStarted = function(group, fixture){ |
---|
829 | _doh._testStarted(_thisGroup, fixture); |
---|
830 | }; |
---|
831 | doh._testFinished = function(g, f, s){ |
---|
832 | _doh._testFinished(_thisGroup, f, s); |
---|
833 | |
---|
834 | //Okay, there may be performance info we need to filter back |
---|
835 | //to the parent, so do that here. |
---|
836 | if(doh.perfTestResults){ |
---|
837 | try{ |
---|
838 | gName = g.toString(); |
---|
839 | var localFName = f.name; |
---|
840 | while(localFName.indexOf("::") >= 0){ |
---|
841 | localFName = localFName.substring(localFName.indexOf("::") + 2, localFName.length); |
---|
842 | } |
---|
843 | if(!_doh.perfTestResults){ |
---|
844 | _doh.perfTestResults = {}; |
---|
845 | } |
---|
846 | if(!_doh.perfTestResults[gName]){ |
---|
847 | _doh.perfTestResults[gName] = {}; |
---|
848 | } |
---|
849 | _doh.perfTestResults[gName][f.name] = doh.perfTestResults[gName][localFName]; |
---|
850 | }catch (e){ |
---|
851 | doh.debug(e); |
---|
852 | } |
---|
853 | } |
---|
854 | }; |
---|
855 | doh._groupStarted = function(g){ |
---|
856 | if(!this._setParent){ |
---|
857 | _doh._curTestCount = this._testCount; |
---|
858 | _doh._curGroupCount = this._groupCount; |
---|
859 | this._setParent = true; |
---|
860 | } |
---|
861 | }; |
---|
862 | doh._report = function(){ |
---|
863 | }; |
---|
864 | } |
---|
865 | } |
---|
866 | return doh; |
---|
867 | }); |
---|