[483] | 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 | }); |
---|