Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / http / tests / inspector / inspector-test.js
1 var initialize_InspectorTest = function() {
2
3 var results = [];
4 var resultsSynchronized = false;
5
6 function consoleOutputHook(messageType)
7 {
8     InspectorTest.addResult(messageType + ": " + Array.prototype.slice.call(arguments, 1));
9 }
10
11 console.log = consoleOutputHook.bind(InspectorTest, "log");
12 console.error = consoleOutputHook.bind(InspectorTest, "error");
13 console.info = consoleOutputHook.bind(InspectorTest, "info");
14 console.assert = function(condition, object)
15 {
16     if (condition)
17         return;
18     var message = "Assertion failed: " + (typeof object !== "undefined" ? object : "");
19     InspectorTest.addResult(new Error(message).stack);
20 }
21
22 InspectorTest.Output = {   // override in window.initialize_yourName
23     testComplete: function() 
24     {
25         RuntimeAgent.evaluate("didEvaluateForTestInFrontend(" + InspectorTest.completeTestCallId + ", \"\")", "test");
26     },
27
28     addResult: function(text) 
29     {
30         InspectorTest.evaluateInPage("output(unescape('" + escape(text) + "'))");
31     },
32     
33     clearResults: function() 
34     {
35         InspectorTest.evaluateInPage("clearOutput()");
36     }
37 };
38
39 InspectorTest.startDumpingProtocolMessages = function()
40 {
41     InspectorBackendClass.Connection.prototype._dumpProtocolMessage = testRunner.logToStderr.bind(testRunner);
42     InspectorBackendClass.Options.dumpInspectorProtocolMessages = 1;
43 }
44
45 InspectorTest.completeTest = function()
46 {
47     InspectorTest.Output.testComplete();
48 }
49
50 InspectorTest.evaluateInConsole = function(code, callback)
51 {
52     callback = InspectorTest.safeWrap(callback);
53
54     WebInspector.inspectorView.panel("console");
55     var consoleView = WebInspector.ConsolePanel._view();
56     consoleView.visible = true;
57     consoleView._prompt.text = code;
58     var event = document.createEvent("KeyboardEvent");
59     event.initKeyboardEvent("keydown", true, true, null, "Enter", "");
60     consoleView._prompt.proxyElement.dispatchEvent(event);
61     InspectorTest.addConsoleSniffer(
62         function(commandResult) {
63             callback(commandResult.toMessageElement().textContent);
64         });
65 }
66
67 InspectorTest.evaluateInConsoleAndDump = function(code, callback)
68 {
69     callback = InspectorTest.safeWrap(callback);
70
71     function mycallback(text)
72     {
73         InspectorTest.addResult(code + " = " + text);
74         callback(text);
75     }
76     InspectorTest.evaluateInConsole(code, mycallback);
77 }
78
79 InspectorTest.evaluateInPage = function(code, callback)
80 {
81     callback = InspectorTest.safeWrap(callback);
82
83     function mycallback(error, result, wasThrown)
84     {
85         if (!error)
86             callback(WebInspector.runtimeModel.createRemoteObject(result), wasThrown);
87     }
88     RuntimeAgent.evaluate(code, "console", false, mycallback);
89 }
90
91 InspectorTest.evaluateInPageWithTimeout = function(code)
92 {
93     InspectorTest.evaluateInPage("setTimeout(unescape('" + escape(code) + "'))");
94 }
95
96 var lastEvalId = 0;
97 var pendingEvalRequests = {};
98
99 InspectorTest.invokePageFunctionAsync = function(functionName, callback)
100 {
101     var id = ++lastEvalId;
102     pendingEvalRequests[id] = InspectorTest.safeWrap(callback);
103     var asyncEvalWrapper = function(callId, functionName)
104     {
105         function evalCallback(result)
106         {
107             testRunner.evaluateInWebInspector(evalCallbackCallId, "InspectorTest.didInvokePageFunctionAsync(" + callId + ", " + JSON.stringify(result) + ");");
108         }
109         eval(functionName + "(" + evalCallback + ")");
110     }
111     InspectorTest.evaluateInPage("(" + asyncEvalWrapper.toString() + ")(" + id + ", unescape('" + escape(functionName) + "'))");
112 }
113
114 InspectorTest.didInvokePageFunctionAsync = function(callId, value)
115 {
116     var callback = pendingEvalRequests[callId];
117     if (!callback) {
118         InspectorTest.addResult("Missing callback for async eval " + callId + ", perhaps callback invoked twice?");
119         return;
120     }
121     delete pendingEvalRequests[callId];
122     callback(value);
123 }
124
125 InspectorTest.check = function(passCondition, failureText)
126 {
127     if (!passCondition)
128         InspectorTest.addResult("FAIL: " + failureText);
129 }
130
131 InspectorTest.addResult = function(text)
132 {
133     results.push(text);
134     if (resultsSynchronized)
135         InspectorTest.Output.addResult(text);
136     else {
137         InspectorTest.Output.clearResults();
138         for (var i = 0; i < results.length; ++i)
139             InspectorTest.Output.addResult(results[i]);
140         resultsSynchronized = true;
141     }
142 }
143
144 InspectorTest.addResults = function(textArray)
145 {
146     if (!textArray)
147         return;
148     for (var i = 0, size = textArray.length; i < size; ++i)
149         InspectorTest.addResult(textArray[i]);
150 }
151
152 window.onerror = function (message, filename, lineno, colno, error)
153 {
154     InspectorTest.addResult("Uncaught exception in inspector front-end: " + message + " [" + error.stack + "]");
155     InspectorTest.completeTest();
156 }
157
158 InspectorTest.formatters = {};
159
160 InspectorTest.formatters.formatAsTypeName = function(value)
161 {
162     return "<" + typeof value + ">";
163 }
164
165 InspectorTest.formatters.formatAsRecentTime = function(value)
166 {
167     if (typeof value !== "object" || !(value instanceof Date))
168         return InspectorTest.formatAsTypeName(value);
169     var delta = Date.now() - value;
170     return 0 <= delta && delta < 30 * 60 * 1000 ? "<plausible>" : value;
171 }
172
173 InspectorTest.formatters.formatAsURL = function(value)
174 {
175     if (!value)
176         return value;
177     var lastIndex = value.lastIndexOf("inspector/");
178     if (lastIndex < 0)
179         return value;
180     return ".../" + value.substr(lastIndex);
181 }
182
183 InspectorTest.addObject = function(object, customFormatters, prefix, firstLinePrefix)
184 {
185     prefix = prefix || "";
186     firstLinePrefix = firstLinePrefix || prefix;
187     InspectorTest.addResult(firstLinePrefix + "{");
188     var propertyNames = Object.keys(object);
189     propertyNames.sort();
190     for (var i = 0; i < propertyNames.length; ++i) {
191         var prop = propertyNames[i];
192         if (typeof object.hasOwnProperty === "function" && !object.hasOwnProperty(prop))
193             continue;
194         var prefixWithName = "    " + prefix + prop + " : ";
195         var propValue = object[prop];
196         if (customFormatters && customFormatters[prop]) {
197             var formatterName = customFormatters[prop];
198             if (formatterName !== "skip") {
199                 var formatter = InspectorTest.formatters[formatterName];
200                 InspectorTest.addResult(prefixWithName + formatter(propValue));
201             }
202         } else
203             InspectorTest.dump(propValue, customFormatters, "    " + prefix, prefixWithName);
204     }
205     InspectorTest.addResult(prefix + "}");
206 }
207
208 InspectorTest.addArray = function(array, customFormatters, prefix, firstLinePrefix)
209 {
210     prefix = prefix || "";
211     firstLinePrefix = firstLinePrefix || prefix;
212     InspectorTest.addResult(firstLinePrefix + "[");
213     for (var i = 0; i < array.length; ++i)
214         InspectorTest.dump(array[i], customFormatters, prefix + "    ");
215     InspectorTest.addResult(prefix + "]");
216 }
217
218 InspectorTest.dump = function(value, customFormatters, prefix, prefixWithName)
219 {
220     prefixWithName = prefixWithName || prefix;
221     if (prefixWithName && prefixWithName.length > 80) {
222         InspectorTest.addResult(prefixWithName + "was skipped due to prefix length limit");
223         return;
224     }
225     if (value === null)
226         InspectorTest.addResult(prefixWithName + "null");
227     else if (value instanceof Array)
228         InspectorTest.addArray(value, customFormatters, prefix, prefixWithName);
229     else if (typeof value === "object")
230         InspectorTest.addObject(value, customFormatters, prefix, prefixWithName);
231     else if (typeof value === "string")
232         InspectorTest.addResult(prefixWithName + "\"" + value + "\"");
233     else
234         InspectorTest.addResult(prefixWithName + value);
235 }
236
237 InspectorTest.assertGreaterOrEqual = function(a, b, message)
238 {
239     if (a < b)
240         InspectorTest.addResult("FAILED: " + (message ? message + ": " : "") + a + " < " + b);
241 }
242
243 InspectorTest.registerModule = function(moduleName, loadImmediately)
244 {
245     runtime._registerModule(moduleName);
246     if (loadImmediately)
247         runtime.loadModule(moduleName);
248 }
249
250 InspectorTest.navigate = function(url, callback)
251 {
252     InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(callback);
253
254     WebInspector.inspectorView.panel("network")._reset();
255     InspectorTest.evaluateInConsole("window.location = '" + url + "'");
256 }
257
258 InspectorTest.recordNetwork = function()
259 {
260     WebInspector.inspectorView.panel("network")._networkLogView._recordButton.toggled = true;
261 }
262
263 InspectorTest.hardReloadPage = function(callback, scriptToEvaluateOnLoad, scriptPreprocessor)
264 {
265     InspectorTest._innerReloadPage(true, callback, scriptToEvaluateOnLoad, scriptPreprocessor);
266 }
267
268 InspectorTest.reloadPage = function(callback, scriptToEvaluateOnLoad, scriptPreprocessor)
269 {
270     InspectorTest._innerReloadPage(false, callback, scriptToEvaluateOnLoad, scriptPreprocessor);
271 }
272
273 InspectorTest._innerReloadPage = function(hardReload, callback, scriptToEvaluateOnLoad, scriptPreprocessor)
274 {
275     InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(callback);
276
277     if (WebInspector.panels.network)
278         WebInspector.panels.network._reset();
279     PageAgent.reload(hardReload, scriptToEvaluateOnLoad, scriptPreprocessor);
280 }
281
282 InspectorTest.pageLoaded = function()
283 {
284     resultsSynchronized = false;
285     InspectorTest.addResult("Page reloaded.");
286     if (InspectorTest._pageLoadedCallback) {
287         var callback = InspectorTest._pageLoadedCallback;
288         delete InspectorTest._pageLoadedCallback;
289         callback();
290     }
291 }
292
293 InspectorTest.runWhenPageLoads = function(callback)
294 {
295     var oldCallback = InspectorTest._pageLoadedCallback;
296     function chainedCallback()
297     {
298         if (oldCallback)
299             oldCallback();
300         callback();
301     }
302     InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(chainedCallback);
303 }
304
305 InspectorTest.runAfterPendingDispatches = function(callback)
306 {
307     callback = InspectorTest.safeWrap(callback);
308     InspectorBackend.connection().runAfterPendingDispatches(callback);
309 }
310
311 InspectorTest.createKeyEvent = function(keyIdentifier, ctrlKey, altKey, shiftKey, metaKey)
312 {
313     var evt = document.createEvent("KeyboardEvent");
314     evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, keyIdentifier, "", ctrlKey, altKey, shiftKey, metaKey);
315     return evt;
316 }
317
318 InspectorTest.runTestSuite = function(testSuite)
319 {
320     var testSuiteTests = testSuite.slice();
321
322     function runner()
323     {
324         if (!testSuiteTests.length) {
325             InspectorTest.completeTest();
326             return;
327         }
328         var nextTest = testSuiteTests.shift();
329         InspectorTest.addResult("");
330         InspectorTest.addResult("Running: " + /function\s([^(]*)/.exec(nextTest)[1]);
331         InspectorTest.safeWrap(nextTest)(runner);
332     }
333     runner();
334 }
335
336 InspectorTest.assertEquals = function(expected, found, message)
337 {
338     if (expected === found)
339         return;
340
341     var error;
342     if (message)
343         error = "Failure (" + message + "):";
344     else
345         error = "Failure:";
346     throw new Error(error + " expected <" + expected + "> found <" + found + ">");
347 }
348
349 InspectorTest.assertTrue = function(found, message)
350 {
351     InspectorTest.assertEquals(true, !!found, message);
352 }
353
354 InspectorTest.safeWrap = function(func, onexception)
355 {
356     function result()
357     {
358         if (!func)
359             return;
360         var wrapThis = this;
361         try {
362             return func.apply(wrapThis, arguments);
363         } catch(e) {
364             InspectorTest.addResult("Exception while running: " + func + "\n" + (e.stack || e));
365             if (onexception)
366                 InspectorTest.safeWrap(onexception)();
367             else
368                 InspectorTest.completeTest();
369         }
370     }
371     return result;
372 }
373
374 InspectorTest.addSniffer = function(receiver, methodName, override, opt_sticky)
375 {
376     override = InspectorTest.safeWrap(override);
377
378     var original = receiver[methodName];
379     if (typeof original !== "function")
380         throw ("Cannot find method to override: " + methodName);
381
382     receiver[methodName] = function(var_args) {
383         try {
384             var result = original.apply(this, arguments);
385         } finally {
386             if (!opt_sticky)
387                 receiver[methodName] = original;
388         }
389         // In case of exception the override won't be called.
390         try {
391             Array.prototype.push.call(arguments, result);
392             override.apply(this, arguments);
393         } catch (e) {
394             throw ("Exception in overriden method '" + methodName + "': " + e);
395         }
396         return result;
397     };
398 }
399
400 InspectorTest.addConsoleSniffer = function(override, opt_sticky)
401 {
402     var sniffer = function (viewMessage) {
403         override(viewMessage);
404     };
405
406     WebInspector.inspectorView.panel("console");
407     InspectorTest.addSniffer(WebInspector.ConsoleView.prototype, "_showConsoleMessage", sniffer, opt_sticky);
408 }
409
410 InspectorTest.override = function(receiver, methodName, override, opt_sticky)
411 {
412     override = InspectorTest.safeWrap(override);
413
414     var original = receiver[methodName];
415     if (typeof original !== "function")
416         throw ("Cannot find method to override: " + methodName);
417
418     receiver[methodName] = function(var_args) {
419         try {
420             try {
421                 var result = override.apply(this, arguments);
422             } catch (e) {
423                 throw ("Exception in overriden method '" + methodName + "': " + e);
424             }
425         } finally {
426             if (!opt_sticky)
427                 receiver[methodName] = original;
428         }
429         return result;
430     };
431
432     return original;
433 }
434
435 InspectorTest.textContentWithLineBreaks = function(node)
436 {
437     var buffer = "";
438     var currentNode = node;
439     while (currentNode = currentNode.traverseNextNode(node)) {
440         if (currentNode.nodeType === Node.TEXT_NODE)
441             buffer += currentNode.nodeValue;
442         else if (currentNode.nodeName === "LI")
443             buffer += "\n    ";
444         else if (currentNode.classList.contains("console-message"))
445             buffer += "\n\n";
446     }
447     return buffer;
448 }
449
450 InspectorTest.hideInspectorView = function()
451 {
452     WebInspector.inspectorView.element.setAttribute("style", "display:none !important");
453 }
454
455 InspectorTest.StringOutputStream = function(callback)
456 {
457     this._callback = callback;
458     this._buffer = "";
459 };
460
461 InspectorTest.StringOutputStream.prototype = {
462     open: function(fileName, callback)
463     {
464         callback(true);
465     },
466
467     write: function(chunk, callback)
468     {
469         this._buffer += chunk;
470         if (callback)
471             callback(this);
472     },
473
474     close: function()
475     {
476         this._callback(this._buffer);
477     }
478 };
479
480 InspectorTest.MockSetting = function(value)
481 {
482     this._value = value;
483 };
484
485 InspectorTest.MockSetting.prototype = {
486     get: function() {
487         return this._value;
488     },
489
490     set: function(value) {
491         this._value = value;
492     }
493 };
494
495
496 /**
497  * @constructor
498  * @param {!string} dirPath
499  * @param {!string} name
500  * @param {!function(?WebInspector.TempFile)} callback
501  */
502 InspectorTest.TempFileMock = function(dirPath, name, callback)
503 {
504     this._chunks = [];
505     this._name = name;
506     setTimeout(callback.bind(this, this), 0);
507 }
508
509 InspectorTest.TempFileMock.prototype = {
510     /**
511      * @param {!string} data
512      * @param {!function(boolean)} callback
513      */
514     write: function(data, callback)
515     {
516         this._chunks.push(data);
517         setTimeout(callback.bind(this, true), 0);
518     },
519
520     finishWriting: function() { },
521
522     /**
523      * @param {function(?string)} callback
524      */
525     read: function(callback)
526     {
527         callback(this._chunks.join(""));
528     },
529
530     /**
531      * @param {!WebInspector.OutputStream} outputStream
532      * @param {!WebInspector.OutputStreamDelegate} delegate
533      */
534     writeToOutputSteam: function(outputStream, delegate)
535     {
536         var name = this._name;
537         var text = this._chunks.join("");
538         var chunkedReaderMock = {
539             loadedSize: function()
540             {
541                 return text.length;
542             },
543
544             fileSize: function()
545             {
546                 return text.length;
547             },
548
549             fileName: function()
550             {
551                 return name;
552             },
553
554             cancel: function() { }
555         }
556         delegate.onTransferStarted(chunkedReaderMock);
557         outputStream.write(text);
558         delegate.onChunkTransferred(chunkedReaderMock);
559         outputStream.close();
560         delegate.onTransferFinished(chunkedReaderMock);
561     },
562
563     remove: function() { }
564 }
565
566 InspectorTest.dumpLoadedModules = function(next)
567 {
568     InspectorTest.addResult("Loaded modules:");
569     var modules = self.runtime._modules;
570     for (var i = 0; i < modules.length; ++i) {
571         if (modules[i]._loaded) {
572             InspectorTest.addResult("    " + modules[i]._descriptor.name);
573         }
574     }
575     if (next)
576         next();
577 }
578
579 InspectorTest.TimeoutMock = function()
580 {
581     this._timeoutId = 0;
582     this._timeoutIdToProcess = {};
583     this._timeoutIdToMillis = {};
584     this.setTimeout = this.setTimeout.bind(this);
585     this.clearTimeout = this.clearTimeout.bind(this);
586 }
587 InspectorTest.TimeoutMock.prototype = {
588     setTimeout: function(operation, timeout)
589     {
590         this._timeoutIdToProcess[++this._timeoutId] = operation;
591         this._timeoutIdToMillis[this._timeoutId] = timeout;
592         return this._timeoutId;
593     },
594
595     clearTimeout: function(timeoutId)
596     {
597         delete this._timeoutIdToProcess[timeoutId];
598         delete this._timeoutIdToMillis[timeoutId];
599     },
600
601     activeTimersTimeouts: function()
602     {
603         return Object.values(this._timeoutIdToMillis);
604     },
605
606     fireAllTimers: function()
607     {
608         for (var timeoutId in this._timeoutIdToProcess)
609             this._timeoutIdToProcess[timeoutId].call(window);
610         this._timeoutIdToProcess = {};
611         this._timeoutIdToMillis = {};
612     }
613 }
614
615 WebInspector.TempFile = InspectorTest.TempFileMock;
616
617 WebInspector.targetManager.observeTargets({
618     targetAdded: function(target)
619     {
620         if (!WebInspector.domModel)
621             WebInspector.domModel = target.domModel;
622         if (!WebInspector.consoleModel)
623             WebInspector.consoleModel = target.consoleModel;
624         if (!WebInspector.networkManager)
625             WebInspector.networkManager = target.networkManager;
626         if (!WebInspector.timelineManager)
627             WebInspector.timelineManager = target.timelineManager;
628     },
629
630     targetRemoved: function(target) { }
631 });
632
633 };  // initialize_InspectorTest
634
635 var initializeCallId = 0;
636 var runTestCallId = 1;
637 var completeTestCallId = 2;
638 var evalCallbackCallId = 3;
639 var frontendReopeningCount = 0;
640
641 function reopenFrontend()
642 {
643     closeFrontend(openFrontendAndIncrement);
644 }
645
646 function closeFrontend(callback)
647 {
648     // Do this asynchronously to allow InspectorBackendDispatcher to send response
649     // back to the frontend before it's destroyed.
650     setTimeout(function() {
651         testRunner.closeWebInspector();
652         callback();
653     }, 0);
654 }
655
656 function openFrontendAndIncrement()
657 {
658     frontendReopeningCount++;
659     testRunner.showWebInspector();
660     setTimeout(runTest, 0);
661 }
662
663 function runAfterIframeIsLoaded()
664 {
665     if (window.testRunner)
666         testRunner.waitUntilDone();
667     function step()
668     {
669         if (!window.iframeLoaded)
670             setTimeout(step, 100);
671         else
672             runTest();
673     }
674     setTimeout(step, 100);
675 }
676
677 function runTest(enableWatchDogWhileDebugging)
678 {
679     if (!window.testRunner)
680         return;
681
682     testRunner.dumpAsText();
683     testRunner.waitUntilDone();
684
685     function initializeFrontend(initializationFunctions)
686     {
687         if (window.InspectorTest) {
688             InspectorTest.pageLoaded();
689             return;
690         }
691
692         InspectorTest = {};
693     
694         for (var i = 0; i < initializationFunctions.length; ++i) {
695             try {
696                 initializationFunctions[i]();
697             } catch (e) {
698                 console.error("Exception in test initialization: " + e);
699                 InspectorTest.completeTest();
700             }
701         }
702     }
703
704     function runTestInFrontend(testFunction, completeTestCallId)
705     {
706         if (InspectorTest.completeTestCallId) 
707             return;
708
709         InspectorTest.completeTestCallId = completeTestCallId;
710
711         try {
712             testFunction();
713         } catch (e) {
714             console.error("Exception during test execution: " + e,  (e.stack ? e.stack : "") );
715             InspectorTest.completeTest();
716         }
717     }
718
719     var initializationFunctions = [ String(initialize_InspectorTest) ];
720     for (var name in window) {
721         if (name.indexOf("initialize_") === 0 && typeof window[name] === "function" && name !== "initialize_InspectorTest")
722             initializationFunctions.push(window[name].toString());
723     }
724     var parameters = ["[" + initializationFunctions + "]"];
725     var toEvaluate = "(" + initializeFrontend + ")(" + parameters.join(", ") + ");";
726     testRunner.evaluateInWebInspector(initializeCallId, toEvaluate);
727
728     parameters = [test, completeTestCallId];
729     toEvaluate = "(" + runTestInFrontend + ")(" + parameters.join(", ") + ");";
730     testRunner.evaluateInWebInspector(runTestCallId, toEvaluate);
731
732     if (enableWatchDogWhileDebugging) {
733         function watchDog()
734         {
735             console.log("Internal watchdog triggered at 20 seconds. Test timed out.");
736             closeInspectorAndNotifyDone();
737         }
738         window._watchDogTimer = setTimeout(watchDog, 20000);
739     }
740 }
741
742 function runTestAfterDisplay(enableWatchDogWhileDebugging)
743 {
744     if (!window.testRunner)
745         return;
746
747     testRunner.waitUntilDone();
748     requestAnimationFrame(runTest.bind(this, enableWatchDogWhileDebugging));
749 }
750
751 function didEvaluateForTestInFrontend(callId)
752 {
753     if (callId !== completeTestCallId)
754         return;
755     delete window.completeTestCallId;
756     if (outputElement && window.quietUntilDone)
757         outputElementParent.appendChild(outputElement);
758     closeInspectorAndNotifyDone();
759 }
760
761 function closeInspectorAndNotifyDone()
762 {
763     if (window._watchDogTimer)
764         clearTimeout(window._watchDogTimer);
765
766     testRunner.closeWebInspector();
767     setTimeout(function() {
768         testRunner.notifyDone();
769     }, 0);
770 }
771
772 var outputElement;
773 var outputElementParent;
774 var savedOutput;
775
776 function createOutputElement()
777 {
778     var intermediate = document.createElement("div");
779     document.body.appendChild(intermediate);
780
781     outputElementParent = document.createElement("div");
782     intermediate.appendChild(outputElementParent);
783
784     outputElement = document.createElement("div");
785     outputElement.className = "output";
786     outputElement.id = "output";
787     outputElement.style.whiteSpace = "pre";
788     if (!window.quietUntilDone)
789         outputElementParent.appendChild(outputElement);
790 }
791
792 function output(text)
793 {
794     if (!outputElement)
795         createOutputElement();
796     outputElement.appendChild(document.createTextNode(text));
797     outputElement.appendChild(document.createElement("br"));
798 }
799
800 function clearOutput()
801 {
802     if (outputElement) {
803         outputElement.remove();
804         outputElement = null;
805     }
806 }
807
808 function saveOutput()
809 {
810     savedOutput = outputElement ? outputElement.innerHTML : "";
811 }
812
813 function restoreOutput()
814 {
815     if (!savedOutput)
816         return;
817     createOutputElement();
818     outputElement.innerHTML = savedOutput;
819 }
820
821 function StandaloneTestRunnerStub()
822 {
823 }
824
825 StandaloneTestRunnerStub.prototype = {
826     dumpAsText: function()
827     {
828     },
829
830     waitUntilDone: function()
831     {
832     },
833
834     closeWebInspector: function()
835     {
836         window.opener.postMessage(["closeWebInspector"], "*");
837     },
838
839     notifyDone: function()
840     {
841         var actual = document.body.innerText + "\n";
842         window.opener.postMessage(["notifyDone", actual], "*");
843     },
844
845     evaluateInWebInspector: function(callId, script)
846     {
847         window.opener.postMessage(["evaluateInWebInspector", callId, script], "*");
848     },
849
850     display: function() { }
851 }
852
853 if (!window.testRunner && window.opener)
854     window.testRunner = new StandaloneTestRunnerStub();