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