Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(window["dojo"]){
2
	dojo.provide("doh._browserRunner");
3
}
4
 
5
// FIXME: need to add prompting for monkey-do testing
6
// FIXME: need to implement progress bar
7
// FIXME: need to implement errors in progress bar
8
 
9
(function(){
10
	if(window.parent == window){
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 _logBacklog = [];
47
		var sendToLogPane = function(args, skip){
48
			var msg = "";
49
			for(var x=0; x<args.length; x++){
50
				msg += " "+args[x];
51
			}
52
			// workarounds for IE. Wheeee!!!
53
			msg = msg.replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
54
			msg = msg.replace(" ", "&nbsp;");
55
			msg = msg.replace("\n", "<br>&nbsp;");
56
			if(!byId("logBody")){
57
				_logBacklog.push(msg);
58
				return;
59
			}else if((_logBacklog.length)&&(!skip)){
60
				var tm;
61
				while(tm=_logBacklog.shift()){
62
					sendToLogPane(tm, true);
63
				}
64
			}
65
			var tn = document.createElement("div");
66
			tn.innerHTML = msg;
67
			byId("logBody").appendChild(tn);
68
		}
69
 
70
		doh._init = (function(oi){
71
			return function(){
72
				var lb = byId("logBody");
73
				if(lb){
74
					// clear the console before each run
75
					while(lb.firstChild){
76
						lb.removeChild(lb.firstChild);
77
					}
78
				}
79
				oi.apply(doh, arguments);
80
			}
81
		})(doh._init);
82
 
83
		if(this["opera"] && opera.postError){
84
			doh.debug = function(){
85
				var msg = "";
86
				for(var x=0; x<arguments.length; x++){
87
					msg += " "+arguments[x];
88
				}
89
				sendToLogPane([msg]);
90
				opera.postError("DEBUG:"+msg);
91
			}
92
		}else if(window["console"]){
93
			if(console.info){
94
				doh.debug = function(){
95
					sendToLogPane.call(window, arguments);
96
					console.debug.apply(console, arguments);
97
				}
98
			}else{
99
				doh.debug = function(){
100
					var msg = "";
101
					for(var x=0; x<arguments.length; x++){
102
						msg += " "+arguments[x];
103
					}
104
					sendToLogPane([msg]);
105
					console.log("DEBUG:"+msg);
106
				}
107
			}
108
		}else{
109
			doh.debug = function(){
110
				sendToLogPane.call(window, arguments);
111
			}
112
		}
113
 
114
		var loaded = false;
115
		var groupTemplate = null;
116
		var testTemplate = null;
117
 
118
		var groupNodes = {};
119
 
120
		var _groupTogglers = {};
121
 
122
		var _getGroupToggler = function(group, toggle){
123
			if(_groupTogglers[group]){ return _groupTogglers[group]; }
124
			var rolledUp = true;
125
			return _groupTogglers[group] = function(evt, forceOpen){
126
				var nodes = groupNodes[group].__items;
127
				if(rolledUp||forceOpen){
128
					rolledUp = false;
129
					for(var x=0; x<nodes.length; x++){
130
						nodes[x].style.display = "";
131
					}
132
					toggle.innerHTML = "&#054;";
133
				}else{
134
					rolledUp = true;
135
					for(var x=0; x<nodes.length; x++){
136
						nodes[x].style.display = "none";
137
					}
138
					toggle.innerHTML = "&#052;";
139
				}
140
			};
141
		}
142
 
143
		var addGroupToList = function(group){
144
			if(!byId("testList")){ return; }
145
			var tb = byId("testList").tBodies[0];
146
			var tg = groupTemplate.cloneNode(true);
147
			var tds = tg.getElementsByTagName("td");
148
			var toggle = tds[0];
149
			toggle.onclick = _getGroupToggler(group, toggle);
150
			var cb = tds[1].getElementsByTagName("input")[0];
151
			cb.group = group;
152
			cb.onclick = function(evt){
153
				doh._groups[group].skip = (!this.checked);
154
			}
155
			tds[2].innerHTML = group;
156
			tds[3].innerHTML = "";
157
 
158
			tb.appendChild(tg);
159
			return tg;
160
		}
161
 
162
		var addFixtureToList = function(group, fixture){
163
			if(!testTemplate){ return; }
164
			var cgn = groupNodes[group];
165
			if(!cgn["__items"]){ cgn.__items = []; }
166
			var tn = testTemplate.cloneNode(true);
167
			var tds = tn.getElementsByTagName("td");
168
 
169
			tds[2].innerHTML = fixture.name;
170
			tds[3].innerHTML = "";
171
 
172
			var nn = (cgn.__lastFixture||cgn.__groupNode).nextSibling;
173
			if(nn){
174
				nn.parentNode.insertBefore(tn, nn);
175
			}else{
176
				cgn.__groupNode.parentNode.appendChild(tn);
177
			}
178
			// FIXME: need to make group display toggleable!!
179
			tn.style.display = "none";
180
			cgn.__items.push(tn);
181
			return cgn.__lastFixture = tn;
182
		}
183
 
184
		var getFixtureNode = function(group, fixture){
185
			if(groupNodes[group]){
186
				return groupNodes[group][fixture.name];
187
			}
188
			return null;
189
		}
190
 
191
		var getGroupNode = function(group){
192
			if(groupNodes[group]){
193
				return groupNodes[group].__groupNode;
194
			}
195
			return null;
196
		}
197
 
198
		var updateBacklog = [];
199
		doh._updateTestList = function(group, fixture, unwindingBacklog){
200
			if(!loaded){
201
				if(group && fixture){
202
					updateBacklog.push([group, fixture]);
203
				}
204
				return;
205
			}else if((updateBacklog.length)&&(!unwindingBacklog)){
206
				var tr;
207
				while(tr=updateBacklog.shift()){
208
					doh._updateTestList(tr[0], tr[1], true);
209
				}
210
			}
211
			if(group && fixture){
212
				if(!groupNodes[group]){
213
					groupNodes[group] = {
214
						"__groupNode": addGroupToList(group)
215
					};
216
				}
217
				if(!groupNodes[group][fixture.name]){
218
					groupNodes[group][fixture.name] = addFixtureToList(group, fixture)
219
				}
220
			}
221
		}
222
 
223
		doh._testRegistered = doh._updateTestList;
224
 
225
		doh._groupStarted = function(group){
226
			// console.debug("_groupStarted", group);
227
			var gn = getGroupNode(group);
228
			if(gn){
229
				gn.className = "inProgress";
230
			}
231
		}
232
 
233
		doh._groupFinished = function(group, success){
234
			// console.debug("_groupFinished", group);
235
			var gn = getGroupNode(group);
236
			if(gn){
237
				gn.className = (success) ? "success" : "failure";
238
			}
239
		}
240
 
241
		doh._testStarted = function(group, fixture){
242
			// console.debug("_testStarted", group, fixture.name);
243
			var fn = getFixtureNode(group, fixture);
244
			if(fn){
245
				fn.className = "inProgress";
246
			}
247
		}
248
 
249
		var _nameTimes = {};
250
		var _playSound = function(name){
251
			if(byId("hiddenAudio") && byId("audio") && byId("audio").checked){
252
				// console.debug("playing:", name);
253
				var nt = _nameTimes[name];
254
				// only play sounds once every second or so
255
				if((!nt)||(((new Date)-nt) > 700)){
256
					_nameTimes[name] = new Date();
257
					var tc = document.createElement("span");
258
					byId("hiddenAudio").appendChild(tc);
259
					tc.innerHTML = '<embed src="_sounds/'+name+'.wav" autostart="true" loop="false" hidden="true" width="1" height="1"></embed>';
260
				}
261
			}
262
		}
263
 
264
		doh._testFinished = function(group, fixture, success){
265
			var fn = getFixtureNode(group, fixture);
266
			if(fn){
267
				fn.getElementsByTagName("td")[3].innerHTML = (fixture.endTime-fixture.startTime)+"ms";
268
				fn.className = (success) ? "success" : "failure";
269
 
270
				if(!success){
271
					_playSound("doh");
272
					var gn = getGroupNode(group);
273
					if(gn){
274
						gn.className = "failure";
275
						_getGroupToggler(group)(null, true);
276
					}
277
				}
278
			}
279
			this.debug(((success) ? "PASSED" : "FAILED"), "test:", fixture.name);
280
		}
281
 
282
		// FIXME: move implementation to _browserRunner?
283
		doh.registerUrl = function(	/*String*/ group,
284
										/*String*/ url,
285
										/*Integer*/ timeout){
286
			var tg = new String(group);
287
			this.register(group, {
288
				name: url,
289
				setUp: function(){
290
					doh.currentGroupName = tg;
291
					doh.currentGroup = this;
292
					doh.currentUrl = url;
293
					this.d = new doh.Deferred();
294
					doh.currentTestDeferred = this.d;
295
					showTestPage();
296
					byId("testBody").src = url;
297
				},
298
				timeout: timeout||10000, // 10s
299
				// timeout: timeout||1000, // 10s
300
				runTest: function(){
301
					// FIXME: implement calling into the url's groups here!!
302
					return this.d;
303
				},
304
				tearDown: function(){
305
					doh.currentGroupName = null;
306
					doh.currentGroup = null;
307
					doh.currentTestDeferred = null;
308
					doh.currentUrl = null;
309
					// this.d.errback(false);
310
					// byId("testBody").src = "about:blank";
311
					showLogPage();
312
				}
313
			});
314
		}
315
 
316
		//
317
		// Utility code for runner.html
318
		//
319
		// var isSafari = navigator.appVersion.indexOf("Safari") >= 0;
320
		var tabzidx = 1;
321
		var _showTab = function(toShow, toHide){
322
			// FIXME: I don't like hiding things this way.
323
			byId(toHide).style.display = "none";
324
			with(byId(toShow).style){
325
				display = "";
326
				zIndex = ++tabzidx;
327
			}
328
		}
329
 
330
		showTestPage = function(){
331
			_showTab("testBody", "logBody");
332
		}
333
 
334
		showLogPage = function(){
335
			_showTab("logBody", "testBody");
336
		}
337
 
338
		var runAll = true;
339
		toggleRunAll = function(){
340
			// would be easier w/ query...sigh
341
			runAll = (!runAll);
342
			if(!byId("testList")){ return; }
343
			var tb = byId("testList").tBodies[0];
344
			var inputs = tb.getElementsByTagName("input");
345
			var x=0; var tn;
346
			while(tn=inputs[x++]){
347
				tn.checked = runAll;
348
				doh._groups[tn.group].skip = (!runAll);
349
			}
350
		}
351
 
352
		var listHeightTimer = null;
353
		var setListHeight = function(){
354
			if(listHeightTimer){
355
				clearTimeout(listHeightTimer);
356
			}
357
			var tl = byId("testList");
358
			if(!tl){ return; }
359
			listHeightTimer = setTimeout(function(){
360
				tl.style.display = "none";
361
				tl.style.display = "";
362
 
363
			}, 10);
364
		}
365
 
366
		_addOnEvt("resize", setListHeight);
367
		_addOnEvt("load", setListHeight);
368
		_addOnEvt("load", function(){
369
			if(loaded){ return; }
370
			loaded = true;
371
			groupTemplate = byId("groupTemplate");
372
			if(!groupTemplate){
373
				// make sure we've got an ammenable DOM structure
374
				return;
375
			}
376
			groupTemplate.parentNode.removeChild(groupTemplate);
377
			groupTemplate.style.display = "";
378
			testTemplate = byId("testTemplate");
379
			testTemplate.parentNode.removeChild(testTemplate);
380
			testTemplate.style.display = "";
381
			doh._updateTestList();
382
		});
383
 
384
		_addOnEvt("load",
385
			function(){
386
				doh._onEnd = function(){
387
					if(doh._failureCount == 0){
388
						doh.debug("WOOHOO!!");
389
						_playSound("woohoo");
390
					}else{
391
						console.debug("doh._failureCount:", doh._failureCount);
392
					}
393
					if(byId("play")){
394
						toggleRunning();
395
					}
396
				}
397
				if(!byId("play")){
398
					// make sure we've got an ammenable DOM structure
399
					return;
400
				}
401
				var isRunning = false;
402
				var toggleRunning = function(){
403
					// ugg, this would be so much better w/ dojo.query()
404
					if(isRunning){
405
						byId("play").style.display = byId("pausedMsg").style.display = "";
406
						byId("playingMsg").style.display = byId("pause").style.display = "none";
407
						isRunning = false;
408
					}else{
409
						byId("play").style.display = byId("pausedMsg").style.display = "none";
410
						byId("playingMsg").style.display = byId("pause").style.display = "";
411
						isRunning = true;
412
					}
413
				}
414
				doh.run = (function(oldRun){
415
					return function(){
416
						if(!doh._currentGroup){
417
							toggleRunning();
418
						}
419
						return oldRun.apply(doh, arguments);
420
					}
421
				})(doh.run);
422
				var btns = byId("toggleButtons").getElementsByTagName("span");
423
				var node; var idx=0;
424
				while(node=btns[idx++]){
425
					node.onclick = toggleRunning;
426
				}
427
			}
428
		);
429
	}else{
430
		// we're in an iframe environment. Time to mix it up a bit.
431
 
432
		_doh = window.parent.doh;
433
		var _thisGroup = _doh.currentGroupName;
434
		var _thisUrl = _doh.currentUrl;
435
		if(_thisGroup){
436
			doh._testRegistered = function(group, tObj){
437
				_doh._updateTestList(_thisGroup, tObj);
438
			}
439
			doh._onEnd = function(){
440
				_doh._errorCount += doh._errorCount;
441
				_doh._failureCount += doh._failureCount;
442
				_doh._testCount += doh._testCount;
443
				// should we be really adding raw group counts?
444
				_doh._groupCount += doh._groupCount;
445
				_doh.currentTestDeferred.callback(true);
446
			}
447
			var otr = doh._getTestObj;
448
			doh._getTestObj = function(){
449
				var tObj = otr.apply(doh, arguments);
450
				tObj.name = _thisUrl+"::"+arguments[0]+"::"+tObj.name;
451
				return tObj;
452
			}
453
			doh.debug = doh.hitch(_doh, "debug");
454
			doh.registerUrl = doh.hitch(_doh, "registerUrl");
455
			doh._testStarted = function(group, fixture){
456
				_doh._testStarted(_thisGroup, fixture);
457
			}
458
			doh._testFinished = function(g, f, s){
459
				_doh._testFinished(_thisGroup, f, s);
460
			}
461
			doh._report = function(){};
462
		}
463
	}
464
 
465
})();