e345a14dd4b26a8acbfa5991ba924c3c2bc667fa
[WebKit-https.git] / 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
15 InspectorTest.completeTest = function()
16 {
17     function testDispatchQueueIsEmpty() {
18         if (!WebInspector.dispatchQueueIsEmpty()) {
19             // Wait for unprocessed messages.
20             setTimeout(testDispatchQueueIsEmpty, 10);
21             return;
22         }
23         RuntimeAgent.evaluate("didEvaluateForTestInFrontend(" + InspectorTest.completeTestCallId + ", \"\")", "test");
24     }
25     testDispatchQueueIsEmpty();
26 }
27
28 InspectorTest.evaluateInConsole = function(code, callback)
29 {
30     callback = InspectorTest.safeWrap(callback);
31
32     WebInspector.console.visible = true;
33     WebInspector.console.prompt.text = code;
34     var event = document.createEvent("KeyboardEvent");
35     event.initKeyboardEvent("keydown", true, true, null, "Enter", "");
36     WebInspector.console.promptElement.dispatchEvent(event);
37     InspectorTest.addSniffer(WebInspector.ConsoleView.prototype, "addMessage",
38         function(commandResult) {
39             callback(commandResult.toMessageElement().textContent);
40         });
41 }
42
43 InspectorTest.evaluateInConsoleAndDump = function(code, callback)
44 {
45     callback = InspectorTest.safeWrap(callback);
46
47     function mycallback(text)
48     {
49         InspectorTest.addResult(code + " = " + text);
50         callback(text);
51     }
52     InspectorTest.evaluateInConsole(code, mycallback);
53 }
54
55 InspectorTest.evaluateInPage = function(code, callback)
56 {
57     callback = InspectorTest.safeWrap(callback);
58
59     function mycallback(error, result, wasThrown)
60     {
61         if (!error)
62             callback(WebInspector.RemoteObject.fromPayload(result), wasThrown);
63     }
64     RuntimeAgent.evaluate(code, "console", false, mycallback);
65 }
66
67 InspectorTest.evaluateInPageWithTimeout = function(code)
68 {
69     InspectorTest.evaluateInPage("setTimeout(unescape('" + escape(code) + "'))");
70 }
71
72 InspectorTest.showResource = function(resourceURL, callback)
73 {
74     callback = InspectorTest.safeWrap(callback);
75     for (var url in WebInspector.resourceTreeModel._resourcesByURL) {
76         if (url.indexOf(resourceURL) !== -1) {
77             var resource = WebInspector.resourceTreeModel._resourcesByURL[url];
78             WebInspector.panels.resources.showResource(resource, 1);
79             var sourceFrame = WebInspector.panels.resources._resourceViewForResource(resource);
80             if (sourceFrame.loaded)
81                 callback(sourceFrame);
82             else
83                 sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, callback.bind(null, sourceFrame));
84             return;
85         }
86     }
87     InspectorTest.addSniffer(WebInspector.resourceTreeModel, "_bindResourceURL", InspectorTest.showResource.bind(InspectorTest, url, callback));
88 };
89
90 InspectorTest.addResult = function(text)
91 {
92     results.push(text);
93     if (resultsSynchronized)
94         addResultToPage(text);
95     else {
96         clearResults();
97         for (var i = 0; i < results.length; ++i)
98             addResultToPage(results[i]);
99         resultsSynchronized = true;
100     }
101
102     function clearResults()
103     {
104         InspectorTest.evaluateInPage("clearOutput()");
105     }
106
107     function addResultToPage(text)
108     {
109         InspectorTest.evaluateInPage("output(unescape('" + escape(text) + "'))");
110     }
111 }
112
113 InspectorTest.addResults = function(textArray)
114 {
115     if (!textArray)
116         return;
117     for (var i = 0, size = textArray.length; i < size; ++i)
118         InspectorTest.addResult(textArray[i]);
119 }
120
121 function onError(event)
122 {
123     window.removeEventListener("error", onError);
124     InspectorTest.addResult("Uncaught exception in inspector front-end: " + event.message + " [" + event.filename + ":" + event.lineno + "]");
125     InspectorTest.completeTest();
126 }
127
128 window.addEventListener("error", onError);
129
130 InspectorTest.addObject = function(object, nondeterministicProps, prefix, firstLinePrefix)
131 {
132     prefix = prefix || "";
133     firstLinePrefix = firstLinePrefix || prefix;
134     InspectorTest.addResult(firstLinePrefix + "{");
135     for (var prop in object) {
136         if (typeof object.hasOwnProperty === "function" && !object.hasOwnProperty(prop))
137             continue;
138         var prefixWithName = "    " + prefix + prop + " : ";
139         var propValue = object[prop];
140         if (nondeterministicProps && prop in nondeterministicProps)
141             InspectorTest.addResult(prefixWithName + "<" + typeof propValue + ">");
142         else
143             InspectorTest.dump(propValue, nondeterministicProps, "    " + prefix, prefixWithName);
144     }
145     InspectorTest.addResult(prefix + "}");
146 }
147
148 InspectorTest.addArray = function(array, nondeterministicProps, prefix, firstLinePrefix)
149 {
150     prefix = prefix || "";
151     firstLinePrefix = firstLinePrefix || prefix;
152     InspectorTest.addResult(firstLinePrefix + "[");
153     for (var i = 0; i < array.length; ++i)
154         InspectorTest.dump(array[i], nondeterministicProps, prefix + "    ");
155     InspectorTest.addResult(prefix + "]");
156 }
157
158 InspectorTest.dump = function(value, nondeterministicProps, prefix, prefixWithName)
159 {
160     prefixWithName = prefixWithName || prefix;
161     if (value === null)
162         InspectorTest.addResult(prefixWithName + "null");
163     else if (value instanceof Array)
164         InspectorTest.addArray(value, nondeterministicProps, prefix, prefixWithName);
165     else if (typeof value === "object")
166         InspectorTest.addObject(value, nondeterministicProps, prefix, prefixWithName);
167     else if (typeof value === "string")
168         InspectorTest.addResult(prefixWithName + "\"" + value + "\"");
169     else
170         InspectorTest.addResult(prefixWithName + value);
171 }
172
173 InspectorTest.assertGreaterOrEqual = function(expected, actual, message)
174 {
175     if (actual < expected)
176         InspectorTest.addResult("FAILED: " + (message ? message + ": " : "") + actual + " < " + expected);
177 }
178
179 InspectorTest.navigate = function(url, callback)
180 {
181     InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(callback);
182
183     if (WebInspector.panels.network)
184         WebInspector.panels.network._reset();
185     InspectorTest.evaluateInConsole("window.location = '" + url + "'");
186 }
187
188 InspectorTest.reloadPage = function(callback)
189 {
190     InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(callback);
191
192     if (WebInspector.panels.network)
193         WebInspector.panels.network._reset();
194     PageAgent.reload(false);
195 }
196
197 InspectorTest.pageLoaded = function()
198 {
199     resultsSynchronized = false;
200     InspectorTest.addResult("Page reloaded.");
201     if (InspectorTest._pageLoadedCallback) {
202         var callback = InspectorTest._pageLoadedCallback;
203         delete InspectorTest._pageLoadedCallback;
204         callback();
205     }
206 }
207
208 InspectorTest.runWhenPageLoads = function(callback)
209 {
210     var oldCallback = InspectorTest._pageLoadedCallback;
211     function chainedCallback()
212     {
213         if (oldCallback)
214             oldCallback();
215         callback();
216     }
217     InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(chainedCallback);
218 }
219
220 InspectorTest.runAfterPendingDispatches = function(callback)
221 {
222     callback = InspectorTest.safeWrap(callback);
223     InspectorBackend.runAfterPendingDispatches(callback);
224 }
225
226 InspectorTest.createKeyEvent = function(keyIdentifier, ctrlKey, altKey, shiftKey, metaKey)
227 {
228     var evt = document.createEvent("KeyboardEvent");
229     evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, keyIdentifier, "", ctrlKey, altKey, shiftKey, metaKey);
230     return evt;
231 }
232
233 InspectorTest.runTestSuite = function(testSuite)
234 {
235     var testSuiteTests = testSuite.slice();
236
237     function runner()
238     {
239         if (!testSuiteTests.length) {
240             InspectorTest.completeTest();
241             return;
242         }
243         var nextTest = testSuiteTests.shift();
244         InspectorTest.addResult("");
245         InspectorTest.addResult("Running: " + /function\s([^(]*)/.exec(nextTest)[1]);
246         InspectorTest.safeWrap(nextTest)(runner, runner);
247     }
248     runner();
249 }
250
251 InspectorTest.assertEquals = function(expected, found, message)
252 {
253     if (expected === found)
254         return;
255
256     var error;
257     if (message)
258         error = "Failure (" + message + "):";
259     else
260         error = "Failure:";
261     throw new Error(error + " expected <" + expected + "> found <" + found + ">");
262 }
263
264 InspectorTest.assertTrue = function(found, message)
265 {
266     InspectorTest.assertEquals(true, !!found, message);
267 }
268
269 InspectorTest.safeWrap = function(func, onexception)
270 {
271     function result()
272     {
273         if (!func)
274             return;
275         var wrapThis = this;
276         try {
277             return func.apply(wrapThis, arguments);
278         } catch(e) {
279             InspectorTest.addResult("Exception while running: " + func + "\n" + (e.stack || e));
280             if (onexception)
281                 InspectorTest.safeWrap(onexception)();
282             else
283                 InspectorTest.completeTest();
284         }
285     }
286     return result;
287 }
288
289 InspectorTest.addSniffer = function(receiver, methodName, override, opt_sticky)
290 {
291     override = InspectorTest.safeWrap(override);
292
293     var original = receiver[methodName];
294     if (typeof original !== "function")
295         throw ("Cannot find method to override: " + methodName);
296
297     receiver[methodName] = function(var_args) {
298         try {
299             var result = original.apply(this, arguments);
300         } finally {
301             if (!opt_sticky)
302                 receiver[methodName] = original;
303         }
304         // In case of exception the override won't be called.
305         try {
306             override.apply(this, arguments);
307         } catch (e) {
308             throw ("Exception in overriden method '" + methodName + "': " + e);
309         }
310         return result;
311     };
312 }
313
314 InspectorTest.override = function(receiver, methodName, override, opt_sticky)
315 {
316     override = InspectorTest.safeWrap(override);
317
318     var original = receiver[methodName];
319     if (typeof original !== "function")
320         throw ("Cannot find method to override: " + methodName);
321
322     receiver[methodName] = function(var_args) {
323         try {
324             try {
325                 var result = override.apply(this, arguments);
326             } catch (e) {
327                 throw ("Exception in overriden method '" + methodName + "': " + e);
328             }
329         } finally {
330             if (!opt_sticky)
331                 receiver[methodName] = original;
332         }
333         return result;
334     };
335
336     return original;
337 }
338
339 InspectorTest.textContentWithLineBreaks = function(node)
340 {
341     var buffer = "";
342     var currentNode = node;
343     while (currentNode = currentNode.traverseNextNode(node)) {
344         if (currentNode.nodeType === Node.TEXT_NODE)
345             buffer += currentNode.nodeValue;
346         else if (currentNode.nodeName === "LI")
347             buffer += "\n    ";
348         else if (currentNode.classList.contains("console-message"))
349             buffer += "\n\n";
350     }
351     return buffer;
352 }
353
354 };
355
356 var runTestCallId = 0;
357 var completeTestCallId = 1;
358 var frontendReopeningCount = 0;
359
360 function reopenFrontend()
361 {
362     closeFrontend(openFrontendAndIncrement);
363 }
364
365 function closeFrontend(callback)
366 {
367     // Do this asynchronously to allow InspectorBackendDispatcher to send response
368     // back to the frontend before it's destroyed.
369     setTimeout(function() {
370         layoutTestController.closeWebInspector();
371         callback();
372     }, 0);
373 }
374
375 function openFrontendAndIncrement()
376 {
377     frontendReopeningCount++;
378     layoutTestController.showWebInspector();
379     runTest();
380 }
381
382 function runAfterIframeIsLoaded()
383 {
384     if (window.layoutTestController)
385         layoutTestController.waitUntilDone();
386     function step()
387     {
388         if (!window.iframeLoaded)
389             setTimeout(step, 100);
390         else
391             runTest();
392     }
393     setTimeout(step, 100);
394 }
395
396 function runTest(enableWatchDogWhileDebugging)
397 {
398     if (!window.layoutTestController)
399         return;
400
401     layoutTestController.dumpAsText();
402     layoutTestController.waitUntilDone();
403
404     function runTestInFrontend(initializationFunctions, testFunction, completeTestCallId)
405     {
406         if (window.InspectorTest) {
407             InspectorTest.pageLoaded();
408             return;
409         }
410
411         InspectorTest = {};
412         InspectorTest.completeTestCallId = completeTestCallId;
413
414         for (var i = 0; i < initializationFunctions.length; ++i) {
415             try {
416                 initializationFunctions[i]();
417             } catch (e) {
418                 console.error("Exception in test initialization: " + e);
419                 InspectorTest.completeTest();
420             }
421         }
422
423         WebInspector.showPanel("audits");
424         try {
425             testFunction();
426         } catch (e) {
427             console.error("Exception during test execution: " + e);
428             InspectorTest.completeTest();
429         }
430     }
431
432     var initializationFunctions = [];
433     for (var name in window) {
434         if (name.indexOf("initialize_") === 0 && typeof window[name] === "function")
435             initializationFunctions.push(window[name].toString());
436     }
437     var parameters = ["[" + initializationFunctions + "]", test, completeTestCallId];
438     var toEvaluate = "(" + runTestInFrontend + ")(" + parameters.join(", ") + ");";
439     layoutTestController.evaluateInWebInspector(runTestCallId, toEvaluate);
440
441     if (enableWatchDogWhileDebugging) {
442         function watchDog()
443         {
444             console.log("Internal watchdog triggered at 20 seconds. Test timed out.");
445             closeInspectorAndNotifyDone();
446         }
447         window._watchDogTimer = setTimeout(watchDog, 20000);
448     }
449 }
450
451 function didEvaluateForTestInFrontend(callId)
452 {
453     if (callId !== completeTestCallId)
454         return;
455     delete window.completeTestCallId;
456     // Close inspector asynchrously to allow caller of this
457     // function send response before backend dispatcher and frontend are destroyed.
458     setTimeout(closeInspectorAndNotifyDone, 0);
459 }
460
461 function closeInspectorAndNotifyDone()
462 {
463     if (window._watchDogTimer)
464         clearTimeout(window._watchDogTimer);
465
466     layoutTestController.closeWebInspector();
467     setTimeout(function() {
468         layoutTestController.notifyDone();
469     }, 0);
470 }
471
472 var outputElement;
473
474 function output(text)
475 {
476     if (!outputElement) {
477         var intermediate = document.createElement("div");
478         document.body.appendChild(intermediate);
479
480         var intermediate2 = document.createElement("div");
481         intermediate.appendChild(intermediate2);
482
483         outputElement = document.createElement("div");
484         outputElement.className = "output";
485         outputElement.style.whiteSpace = "pre";
486         intermediate2.appendChild(outputElement);
487     }
488     outputElement.appendChild(document.createTextNode(text));
489     outputElement.appendChild(document.createElement("br"));
490 }
491
492 function clearOutput()
493 {
494     if (outputElement) {
495         outputElement.parentNode.removeChild(outputElement);
496         outputElement = null;
497     }
498 }