Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Side by Side Diff: resources/inspector/tests.js

Issue 853002: Updating the Chromium reference build for Windows. The continuous... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/reference_builds/chrome/
Patch Set: Added the symbol files back. Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « resources/inspector/splaytree.js ('k') | resources/inspector/textViewer.css » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5
6 /**
7 * @fileoverview This file contains small testing framework along with the
8 * test suite for the frontend. These tests are a part of the continues build
9 * and are executed by the devtools_sanity_unittest.cc as a part of the
10 * Interactive UI Test suite.
11 */
12
13 if (window.domAutomationController) {
14
15 var ___interactiveUiTestsMode = true;
16
17 /**
18 * Test suite for interactive UI tests.
19 * @constructor
20 */
21 TestSuite = function() {
22 this.controlTaken_ = false;
23 this.timerId_ = -1;
24 };
25
26
27 /**
28 * Reports test failure.
29 * @param {string} message Failure description.
30 */
31 TestSuite.prototype.fail = function(message) {
32 if (this.controlTaken_) {
33 this.reportFailure_(message);
34 } else {
35 throw message;
36 }
37 };
38
39
40 /**
41 * Equals assertion tests that expected == actual.
42 * @param {Object} expected Expected object.
43 * @param {Object} actual Actual object.
44 * @param {string} opt_message User message to print if the test fails.
45 */
46 TestSuite.prototype.assertEquals = function(expected, actual, opt_message) {
47 if (expected != actual) {
48 var message = 'Expected: "' + expected + '", but was "' + actual + '"';
49 if (opt_message) {
50 message = opt_message + '(' + message + ')';
51 }
52 this.fail(message);
53 }
54 };
55
56
57 /**
58 * True assertion tests that value == true.
59 * @param {Object} value Actual object.
60 * @param {string} opt_message User message to print if the test fails.
61 */
62 TestSuite.prototype.assertTrue = function(value, opt_message) {
63 this.assertEquals(true, !!value, opt_message);
64 };
65
66
67 /**
68 * Contains assertion tests that string contains substring.
69 * @param {string} string Outer.
70 * @param {string} substring Inner.
71 */
72 TestSuite.prototype.assertContains = function(string, substring) {
73 if (string.indexOf(substring) == -1) {
74 this.fail('Expected to: "' + string + '" to contain "' + substring + '"');
75 }
76 };
77
78
79 /**
80 * Takes control over execution.
81 */
82 TestSuite.prototype.takeControl = function() {
83 this.controlTaken_ = true;
84 // Set up guard timer.
85 var self = this;
86 this.timerId_ = setTimeout(function() {
87 self.reportFailure_('Timeout exceeded: 20 sec');
88 }, 20000);
89 };
90
91
92 /**
93 * Releases control over execution.
94 */
95 TestSuite.prototype.releaseControl = function() {
96 if (this.timerId_ != -1) {
97 clearTimeout(this.timerId_);
98 this.timerId_ = -1;
99 }
100 this.reportOk_();
101 };
102
103
104 /**
105 * Async tests use this one to report that they are completed.
106 */
107 TestSuite.prototype.reportOk_ = function() {
108 window.domAutomationController.send('[OK]');
109 };
110
111
112 /**
113 * Async tests use this one to report failures.
114 */
115 TestSuite.prototype.reportFailure_ = function(error) {
116 if (this.timerId_ != -1) {
117 clearTimeout(this.timerId_);
118 this.timerId_ = -1;
119 }
120 window.domAutomationController.send('[FAILED] ' + error);
121 };
122
123
124 /**
125 * Runs all global functions starting with 'test' as unit tests.
126 */
127 TestSuite.prototype.runTest = function(testName) {
128 try {
129 this[testName]();
130 if (!this.controlTaken_) {
131 this.reportOk_();
132 }
133 } catch (e) {
134 this.reportFailure_(e);
135 }
136 };
137
138
139 /**
140 * @param {string} panelName Name of the panel to show.
141 */
142 TestSuite.prototype.showPanel = function(panelName) {
143 // Open Scripts panel.
144 var toolbar = document.getElementById('toolbar');
145 var button = toolbar.getElementsByClassName(panelName)[0];
146 button.click();
147 this.assertEquals(WebInspector.panels[panelName],
148 WebInspector.currentPanel);
149 };
150
151
152 /**
153 * Overrides the method with specified name until it's called first time.
154 * @param {Object} receiver An object whose method to override.
155 * @param {string} methodName Name of the method to override.
156 * @param {Function} override A function that should be called right after the
157 * overriden method returns.
158 * @param {boolean} opt_sticky Whether restore original method after first run
159 * or not.
160 */
161 TestSuite.prototype.addSniffer = function(receiver, methodName, override,
162 opt_sticky) {
163 var orig = receiver[methodName];
164 if (typeof orig != 'function') {
165 this.fail('Cannot find method to override: ' + methodName);
166 }
167 var test = this;
168 receiver[methodName] = function(var_args) {
169 try {
170 var result = orig.apply(this, arguments);
171 } finally {
172 if (!opt_sticky) {
173 receiver[methodName] = orig;
174 }
175 }
176 // In case of exception the override won't be called.
177 try {
178 override.apply(this, arguments);
179 } catch (e) {
180 test.fail('Exception in overriden method "' + methodName + '": ' + e);
181 }
182 return result;
183 };
184 };
185
186
187 // UI Tests
188
189
190 /**
191 * Tests that the real injected host is present in the context.
192 */
193 TestSuite.prototype.testHostIsPresent = function() {
194 this.assertTrue(typeof DevToolsHost == 'object' && !DevToolsHost.isStub);
195 };
196
197
198 /**
199 * Tests elements tree has an 'HTML' root.
200 */
201 TestSuite.prototype.testElementsTreeRoot = function() {
202 var doc = WebInspector.domAgent.document;
203 this.assertEquals('HTML', doc.documentElement.nodeName);
204 this.assertTrue(doc.documentElement.hasChildNodes());
205 };
206
207
208 /**
209 * Tests that main resource is present in the system and that it is
210 * the only resource.
211 */
212 TestSuite.prototype.testMainResource = function() {
213 var tokens = [];
214 var resources = WebInspector.resources;
215 for (var id in resources) {
216 tokens.push(resources[id].lastPathComponent);
217 }
218 this.assertEquals('simple_page.html', tokens.join(','));
219 };
220
221
222 /**
223 * Tests that resources tab is enabled when corresponding item is selected.
224 */
225 TestSuite.prototype.testEnableResourcesTab = function() {
226 this.showPanel('resources');
227
228 var test = this;
229 this.addSniffer(WebInspector, 'addResource',
230 function(identifier, payload) {
231 test.assertEquals('simple_page.html', payload.lastPathComponent);
232 WebInspector.panels.resources.refresh();
233 WebInspector.resources[identifier]._resourcesTreeElement.select();
234
235 test.releaseControl();
236 });
237
238 // Following call should lead to reload that we capture in the
239 // addResource override.
240 WebInspector.panels.resources._enableResourceTracking();
241
242 // We now have some time to report results to controller.
243 this.takeControl();
244 };
245
246
247 /**
248 * Tests resource headers.
249 */
250 TestSuite.prototype.testResourceHeaders = function() {
251 this.showPanel('resources');
252
253 var test = this;
254
255 var requestOk = false;
256 var responseOk = false;
257 var timingOk = false;
258
259 this.addSniffer(WebInspector, 'addResource',
260 function(identifier, payload) {
261 var resource = this.resources[identifier];
262 if (resource.mainResource) {
263 // We are only interested in secondary resources in this test.
264 return;
265 }
266
267 var requestHeaders = JSON.stringify(resource.requestHeaders);
268 test.assertContains(requestHeaders, 'Accept');
269 requestOk = true;
270 }, true);
271
272 this.addSniffer(WebInspector, 'updateResource',
273 function(identifier, payload) {
274 var resource = this.resources[identifier];
275 if (resource.mainResource) {
276 // We are only interested in secondary resources in this test.
277 return;
278 }
279
280 if (payload.didResponseChange) {
281 var responseHeaders = JSON.stringify(resource.responseHeaders);
282 test.assertContains(responseHeaders, 'Content-type');
283 test.assertContains(responseHeaders, 'Content-Length');
284 test.assertTrue(typeof resource.responseReceivedTime != 'undefnied');
285 responseOk = true;
286 }
287
288 if (payload.didTimingChange) {
289 test.assertTrue(typeof resource.startTime != 'undefnied');
290 timingOk = true;
291 }
292
293 if (payload.didCompletionChange) {
294 test.assertTrue(requestOk);
295 test.assertTrue(responseOk);
296 test.assertTrue(timingOk);
297 test.assertTrue(typeof resource.endTime != 'undefnied');
298 test.releaseControl();
299 }
300 }, true);
301
302 WebInspector.panels.resources._enableResourceTracking();
303 this.takeControl();
304 };
305
306
307 /**
308 * Test that profiler works.
309 */
310 TestSuite.prototype.testProfilerTab = function() {
311 this.showPanel('profiles');
312
313 var test = this;
314 this.addSniffer(WebInspector, 'addProfileHeader',
315 function(type, profile) {
316 var panel = WebInspector.panels.profiles;
317 panel.showProfile(profile);
318 var node = panel.visibleView.profileDataGridTree.children[0];
319 // Iterate over displayed functions and search for a function
320 // that is called 'fib' or 'eternal_fib'. If found, it will mean
321 // that we actually have profiled page's code.
322 while (node) {
323 if (node.functionName.indexOf('fib') != -1) {
324 test.releaseControl();
325 }
326 node = node.traverseNextNode(true, null, true);
327 }
328
329 test.fail();
330 });
331 var ticksCount = 0;
332 var tickRecord = '\nt,';
333 this.addSniffer(RemoteDebuggerAgent, 'DidGetNextLogLines',
334 function(log) {
335 var pos = 0;
336 while ((pos = log.indexOf(tickRecord, pos)) != -1) {
337 pos += tickRecord.length;
338 ticksCount++;
339 }
340 if (ticksCount > 100) {
341 InspectorController.stopProfiling();
342 }
343 }, true);
344
345 InspectorController.startProfiling();
346 this.takeControl();
347 };
348
349
350 /**
351 * Tests that scripts tab can be open and populated with inspected scripts.
352 */
353 TestSuite.prototype.testShowScriptsTab = function() {
354 var parsedDebuggerTestPageHtml = false;
355
356 // Intercept parsedScriptSource calls to check that all expected scripts are
357 // added to the debugger.
358 var test = this;
359 var receivedConsoleApiSource = false;
360 this.addSniffer(WebInspector, 'parsedScriptSource',
361 function(sourceID, sourceURL, source, startingLine) {
362 if (sourceURL == undefined) {
363 if (receivedConsoleApiSource) {
364 test.fail('Unexpected script without URL');
365 } else {
366 receivedConsoleApiSource = true;
367 }
368 } else if (sourceURL.search(/debugger_test_page.html$/) != -1) {
369 if (parsedDebuggerTestPageHtml) {
370 test.fail('Unexpected parse event: ' + sourceURL);
371 }
372 parsedDebuggerTestPageHtml = true;
373 } else {
374 test.fail('Unexpected script URL: ' + sourceURL);
375 }
376
377 if (!WebInspector.panels.scripts.visibleView) {
378 test.fail('No visible script view: ' + sourceURL);
379 }
380
381 // There should be two scripts: one for the main page and another
382 // one which is source of console API(see
383 // InjectedScript._ensureCommandLineAPIInstalled).
384 if (parsedDebuggerTestPageHtml && receivedConsoleApiSource) {
385 test.releaseControl();
386 }
387 }, true /* sticky */);
388
389 this.showPanel('scripts');
390
391 // Wait until all scripts are added to the debugger.
392 this.takeControl();
393 };
394
395
396 /**
397 * Tests that scripts list contains content scripts.
398 */
399 TestSuite.prototype.testContentScriptIsPresent = function() {
400 this.showPanel('scripts');
401 var test = this;
402
403 test._waitUntilScriptsAreParsed(
404 ['page_with_content_script.html$', 'simple_content_script.js$'],
405 function() {
406 test.releaseControl();
407 });
408
409 // Wait until all scripts are added to the debugger.
410 this.takeControl();
411 };
412
413
414 /**
415 * Tests that scripts are not duplicaed on Scripts tab switch.
416 */
417 TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch = function() {
418 var test = this;
419
420 // There should be two scripts: one for the main page and another
421 // one which is source of console API(see
422 // InjectedScript._ensureCommandLineAPIInstalled).
423 var expectedScriptsCount = 2;
424 var parsedScripts = [];
425
426
427 function switchToElementsTab() {
428 test.showPanel('elements');
429 setTimeout(switchToScriptsTab, 0);
430 }
431
432 function switchToScriptsTab() {
433 test.showPanel('scripts');
434 setTimeout(checkScriptsPanel, 0);
435 }
436
437 function checkScriptsPanel() {
438 test.assertTrue(!!WebInspector.panels.scripts.visibleView,
439 'No visible script view.');
440 var select = WebInspector.panels.scripts.filesSelectElement;
441 test.assertEquals(expectedScriptsCount, select.options.length,
442 'Unexpected options count');
443 test.releaseControl();
444 }
445
446 this.addSniffer(WebInspector, 'parsedScriptSource',
447 function(sourceID, sourceURL, source, startingLine) {
448 test.assertTrue(
449 parsedScripts.indexOf(sourceURL) == -1,
450 'Duplicated script: ' + sourceURL);
451 test.assertTrue(
452 parsedScripts.length < expectedScriptsCount,
453 'Too many scripts: ' + sourceURL);
454 parsedScripts.push(sourceURL);
455
456 if (parsedScripts.length == expectedScriptsCount) {
457 setTimeout(switchToElementsTab, 0);
458 }
459 }, true /* sticky */);
460
461 this.showPanel('scripts');
462
463 // Wait until all scripts are added to the debugger.
464 this.takeControl();
465 };
466
467
468 /**
469 * Tests that a breakpoint can be set.
470 */
471 TestSuite.prototype.testSetBreakpoint = function() {
472 var parsedDebuggerTestPageHtml = false;
473 var parsedDebuggerTestJs = false;
474
475 this.showPanel('scripts');
476
477 var scriptUrl = null;
478 var breakpointLine = 12;
479
480 var test = this;
481 this.addSniffer(devtools.DebuggerAgent.prototype, 'handleScriptsResponse_',
482 function(msg) {
483 var scriptSelect = document.getElementById('scripts-files');
484 var options = scriptSelect.options;
485
486 // There should be console API source (see
487 // InjectedScript._ensureCommandLineAPIInstalled) and the page script.
488 test.assertEquals(2, options.length, 'Unexpected number of scripts(' +
489 test.optionsToString_(options) + ')');
490
491 test.showMainPageScriptSource_(
492 'debugger_test_page.html',
493 function(view, url) {
494 view._addBreakpoint(breakpointLine);
495 // Force v8 execution.
496 RemoteToolsAgent.ExecuteVoidJavaScript();
497 test.waitForSetBreakpointResponse_(url, breakpointLine,
498 function() {
499 test.releaseControl();
500 });
501 });
502 });
503
504
505 this.takeControl();
506 };
507
508
509 /**
510 * Serializes options collection to string.
511 * @param {HTMLOptionsCollection} options
512 * @return {string}
513 */
514 TestSuite.prototype.optionsToString_ = function(options) {
515 var names = [];
516 for (var i = 0; i < options.length; i++) {
517 names.push('"' + options[i].text + '"');
518 }
519 return names.join(',');
520 };
521
522
523 /**
524 * Ensures that main HTML resource is selected in Scripts panel and that its
525 * source frame is setup. Invokes the callback when the condition is satisfied.
526 * @param {HTMLOptionsCollection} options
527 * @param {function(WebInspector.SourceView,string)} callback
528 */
529 TestSuite.prototype.showMainPageScriptSource_ = function(scriptName, callback) {
530 var test = this;
531
532 var scriptSelect = document.getElementById('scripts-files');
533 var options = scriptSelect.options;
534
535 // There should be console API source (see
536 // InjectedScript._ensureCommandLineAPIInstalled) and the page script.
537 test.assertEquals(2, options.length,
538 'Unexpected number of scripts(' + test.optionsToString_(options) + ')');
539
540 // Select page's script if it's not current option.
541 var scriptResource;
542 if (options[scriptSelect.selectedIndex].text === scriptName) {
543 scriptResource = options[scriptSelect.selectedIndex].representedObject;
544 } else {
545 var pageScriptIndex = -1;
546 for (var i = 0; i < options.length; i++) {
547 if (options[i].text === scriptName) {
548 pageScriptIndex = i;
549 break;
550 }
551 }
552 test.assertTrue(-1 !== pageScriptIndex,
553 'Script with url ' + scriptName + ' not found among ' +
554 test.optionsToString_(options));
555 scriptResource = options[pageScriptIndex].representedObject;
556
557 // Current panel is 'Scripts'.
558 WebInspector.currentPanel._showScriptOrResource(scriptResource);
559 test.assertEquals(pageScriptIndex, scriptSelect.selectedIndex,
560 'Unexpected selected option index.');
561 }
562
563 test.assertTrue(scriptResource instanceof WebInspector.Resource,
564 'Unexpected resource class.');
565 test.assertTrue(!!scriptResource.url, 'Resource URL is null.');
566 test.assertTrue(
567 scriptResource.url.search(scriptName + '$') != -1,
568 'Main HTML resource should be selected.');
569
570 var scriptsPanel = WebInspector.panels.scripts;
571
572 var view = scriptsPanel.visibleView;
573 test.assertTrue(view instanceof WebInspector.SourceView);
574
575 if (!view.sourceFrame._isContentLoaded()) {
576 test.addSniffer(view, '_sourceFrameSetupFinished', function(event) {
577 callback(view, scriptResource.url);
578 });
579 } else {
580 callback(view, scriptResource.url);
581 }
582 };
583
584
585 /*
586 * Evaluates the code in the console as if user typed it manually and invokes
587 * the callback when the result message is received and added to the console.
588 * @param {string} code
589 * @param {function(string)} callback
590 */
591 TestSuite.prototype.evaluateInConsole_ = function(code, callback) {
592 WebInspector.console.visible = true;
593 WebInspector.console.prompt.text = code;
594 WebInspector.console.promptElement.handleKeyEvent(
595 new TestSuite.KeyEvent('Enter'));
596
597 this.addSniffer(WebInspector.ConsoleView.prototype, 'addMessage',
598 function(commandResult) {
599 callback(commandResult.toMessageElement().textContent);
600 });
601 };
602
603
604 /*
605 * Waits for 'setbreakpoint' response, checks that corresponding breakpoint
606 * was successfully set and invokes the callback if it was.
607 * @param {string} scriptUrl
608 * @param {number} breakpointLine
609 * @param {function()} callback
610 */
611 TestSuite.prototype.waitForSetBreakpointResponse_ = function(scriptUrl,
612 breakpointLine,
613 callback) {
614 var test = this;
615 test.addSniffer(
616 devtools.DebuggerAgent.prototype,
617 'handleSetBreakpointResponse_',
618 function(msg) {
619 var bps = this.urlToBreakpoints_[scriptUrl];
620 test.assertTrue(!!bps, 'No breakpoints for line ' + breakpointLine);
621 var line = devtools.DebuggerAgent.webkitToV8LineNumber_(breakpointLine);
622 test.assertTrue(!!bps[line].getV8Id(),
623 'Breakpoint id was not assigned.');
624 callback();
625 });
626 };
627
628
629 /**
630 * Tests eval on call frame.
631 */
632 TestSuite.prototype.testEvalOnCallFrame = function() {
633 this.showPanel('scripts');
634
635 var breakpointLine = 16;
636
637 var test = this;
638 this.addSniffer(devtools.DebuggerAgent.prototype, 'handleScriptsResponse_',
639 function(msg) {
640 test.showMainPageScriptSource_(
641 'debugger_test_page.html',
642 function(view, url) {
643 view._addBreakpoint(breakpointLine);
644 // Force v8 execution.
645 RemoteToolsAgent.ExecuteVoidJavaScript();
646 test.waitForSetBreakpointResponse_(url, breakpointLine,
647 setBreakpointCallback);
648 });
649 });
650
651 function setBreakpointCallback() {
652 // Since breakpoints are ignored in evals' calculate() function is
653 // execute after zero-timeout so that the breakpoint is hit.
654 test.evaluateInConsole_(
655 'setTimeout("calculate(123)" , 0)',
656 function(resultText) {
657 test.assertTrue(!isNaN(resultText),
658 'Failed to get timer id: ' + resultText);
659 waitForBreakpointHit();
660 });
661 }
662
663 function waitForBreakpointHit() {
664 test.addSniffer(
665 devtools.DebuggerAgent.prototype,
666 'handleBacktraceResponse_',
667 function(msg) {
668 test.assertEquals(2, this.callFrames_.length,
669 'Unexpected stack depth on the breakpoint. ' +
670 JSON.stringify(msg));
671 test.assertEquals('calculate', this.callFrames_[0].functionName,
672 'Unexpected top frame function.');
673 // Evaluate 'e+1' where 'e' is an argument of 'calculate' function.
674 test.evaluateInConsole_(
675 'e+1',
676 function(resultText) {
677 test.assertEquals('124', resultText, 'Unexpected "e+1" value.');
678 test.releaseControl();
679 });
680 });
681 }
682
683 this.takeControl();
684 };
685
686
687 /**
688 * Tests that console auto completion works when script execution is paused.
689 */
690 TestSuite.prototype.testCompletionOnPause = function() {
691 this.showPanel('scripts');
692 var test = this;
693 this._executeCodeWhenScriptsAreParsed(
694 'handleClick()',
695 ['completion_on_pause.html$']);
696
697 this._waitForScriptPause(
698 {
699 functionsOnStack: ['innerFunction', 'handleClick',
700 '(anonymous function)'],
701 lineNumber: 9,
702 lineText: ' debugger;'
703 },
704 showConsole);
705
706 function showConsole() {
707 test.addSniffer(WebInspector.console, 'afterShow', testLocalsCompletion);
708 WebInspector.showConsole();
709 }
710
711 function testLocalsCompletion() {
712 checkCompletions(
713 'th',
714 ['parameter1', 'closureLocal', 'p', 'createClosureLocal'],
715 testThisCompletion);
716 }
717
718 function testThisCompletion() {
719 checkCompletions(
720 'this.',
721 ['field1', 'field2', 'm'],
722 testFieldCompletion);
723 }
724
725 function testFieldCompletion() {
726 checkCompletions(
727 'this.field1.',
728 ['id', 'name'],
729 function() {
730 test.releaseControl();
731 });
732 }
733
734 function checkCompletions(expression, expectedProperties, callback) {
735 test.addSniffer(WebInspector.console, '_reportCompletions',
736 function(bestMatchOnly, completionsReadyCallback, dotNotation,
737 bracketNotation, prefix, result, isException) {
738 test.assertTrue(!isException,
739 'Exception while collecting completions');
740 for (var i = 0; i < expectedProperties.length; i++) {
741 var name = expectedProperties[i];
742 test.assertTrue(result[name], 'Name ' + name +
743 ' not found among the completions: ' +
744 JSON.stringify(result));
745 }
746 setTimeout(callback, 0);
747 });
748 WebInspector.console.prompt.text = expression;
749 WebInspector.console.prompt.autoCompleteSoon();
750 }
751
752 this.takeControl();
753 };
754
755
756 /**
757 * Tests that inspected page doesn't hang on reload if it contains a syntax
758 * error and DevTools window is open.
759 */
760 TestSuite.prototype.testAutoContinueOnSyntaxError = function() {
761 this.showPanel('scripts');
762 var test = this;
763
764 function checkScriptsList() {
765 var scriptSelect = document.getElementById('scripts-files');
766 var options = scriptSelect.options;
767 // There should be only console API source (see
768 // InjectedScript._ensureCommandLineAPIInstalled) since the page script
769 // contains a syntax error.
770 for (var i = 0 ; i < options.length; i++) {
771 if (options[i].text.search('script_syntax_error.html$') != -1) {
772 test.fail('Script with syntax error should not be in the list of ' +
773 'parsed scripts.');
774 }
775 }
776 }
777
778 this.addSniffer(devtools.DebuggerAgent.prototype, 'handleScriptsResponse_',
779 function(msg) {
780 checkScriptsList();
781
782 // Reload inspected page.
783 test.evaluateInConsole_(
784 'window.location.reload(true);',
785 function(resultText) {
786 test.assertEquals('undefined', resultText,
787 'Unexpected result of reload().');
788 waitForExceptionEvent();
789 });
790 });
791
792 function waitForExceptionEvent() {
793 var exceptionCount = 0;
794 test.addSniffer(
795 devtools.DebuggerAgent.prototype,
796 'handleExceptionEvent_',
797 function(msg) {
798 exceptionCount++;
799 test.assertEquals(1, exceptionCount, 'Too many exceptions.');
800 test.assertEquals(undefined, msg.getBody().script,
801 'Unexpected exception: ' + JSON.stringify(msg));
802 test.releaseControl();
803 });
804
805 // Check that the script is not paused on parse error.
806 test.addSniffer(
807 WebInspector,
808 'pausedScript',
809 function(callFrames) {
810 test.fail('Script execution should not pause on syntax error.');
811 });
812 }
813
814 this.takeControl();
815 };
816
817
818 /**
819 * Checks current execution line against expectations.
820 * @param {WebInspector.SourceFrame} sourceFrame
821 * @param {number} lineNumber Expected line number
822 * @param {string} lineContent Expected line text
823 */
824 TestSuite.prototype._checkExecutionLine = function(sourceFrame, lineNumber,
825 lineContent) {
826 var sourceRow = sourceFrame.sourceRow(lineNumber);
827
828 var line = sourceRow.getElementsByClassName('webkit-line-content')[0];
829 this.assertEquals(lineNumber, sourceFrame.executionLine,
830 'Unexpected execution line number.');
831 this.assertEquals(lineContent, line.textContent,
832 'Unexpected execution line text.');
833
834 this.assertTrue(!!sourceRow, 'Execution line not found');
835 this.assertTrue(sourceRow.hasStyleClass('webkit-execution-line'),
836 'Execution line ' + lineNumber + ' is not highlighted. Class: ' +
837 sourceRow.className);
838 }
839
840
841 /**
842 * Checks that all expected scripts are present in the scripts list
843 * in the Scripts panel.
844 * @param {Array.<string>} expected Regular expressions describing
845 * expected script names.
846 * @return {boolean} Whether all the scripts are in 'scripts-files' select
847 * box
848 */
849 TestSuite.prototype._scriptsAreParsed = function(expected) {
850 var scriptSelect = document.getElementById('scripts-files');
851 var options = scriptSelect.options;
852
853 // Check that at least all the expected scripts are present.
854 var missing = expected.slice(0);
855 for (var i = 0 ; i < options.length; i++) {
856 for (var j = 0; j < missing.length; j++) {
857 if (options[i].text.search(missing[j]) != -1) {
858 missing.splice(j, 1);
859 break;
860 }
861 }
862 }
863 return missing.length == 0;
864 };
865
866
867 /**
868 * Waits for script pause, checks expectations, and invokes the callback.
869 * @param {Object} expectations Dictionary of expectations
870 * @param {function():void} callback
871 */
872 TestSuite.prototype._waitForScriptPause = function(expectations, callback) {
873 var test = this;
874 // Wait until script is paused.
875 test.addSniffer(
876 WebInspector,
877 'pausedScript',
878 function(callFrames) {
879 test.assertEquals(expectations.functionsOnStack.length,
880 callFrames.length,
881 'Unexpected stack depth');
882
883 var functionsOnStack = [];
884 for (var i = 0; i < callFrames.length; i++) {
885 functionsOnStack.push(callFrames[i].functionName);
886 }
887 test.assertEquals(
888 expectations.functionsOnStack.join(','),
889 functionsOnStack.join(','), 'Unexpected stack.');
890
891 checkSourceFrameWhenLoaded();
892 });
893
894 // Check that execution line where the script is paused is expected one.
895 function checkSourceFrameWhenLoaded() {
896 var frame = WebInspector.currentPanel.visibleView.sourceFrame;
897 if (frame._isContentLoaded()) {
898 checkExecLine();
899 } else {
900 frame.addEventListener('content loaded', checkExecLine);
901 }
902 function checkExecLine() {
903 test._checkExecutionLine(frame, expectations.lineNumber,
904 expectations.lineText);
905 // Make sure we don't listen anymore.
906 frame.removeEventListener('content loaded', checkExecLine);
907 callback();
908 }
909 }
910 };
911
912
913 /**
914 * Performs sequence of steps.
915 * @param {Array.<Object|Function>} Array [expectations1,action1,expectations2,
916 * action2,...,actionN].
917 */
918 TestSuite.prototype._performSteps = function(actions) {
919 var test = this;
920 var i = 0;
921 function doNextAction() {
922 if (i > 0) {
923 actions[i++]();
924 }
925 if (i < actions.length - 1) {
926 test._waitForScriptPause(actions[i++], doNextAction);
927 }
928 }
929 doNextAction();
930 };
931
932
933 /**
934 * Waits until all the scripts are parsed and asynchronously executes the code
935 * in the inspected page.
936 */
937 TestSuite.prototype._executeCodeWhenScriptsAreParsed = function(
938 code, expectedScripts) {
939 var test = this;
940
941 function executeFunctionInInspectedPage() {
942 // Since breakpoints are ignored in evals' calculate() function is
943 // execute after zero-timeout so that the breakpoint is hit.
944 test.evaluateInConsole_(
945 'setTimeout("' + code + '" , 0)',
946 function(resultText) {
947 test.assertTrue(!isNaN(resultText),
948 'Failed to get timer id: ' + resultText);
949 });
950 }
951
952 test._waitUntilScriptsAreParsed(
953 expectedScripts, executeFunctionInInspectedPage);
954 };
955
956
957 /**
958 * Waits until all the scripts are parsed and invokes the callback.
959 */
960 TestSuite.prototype._waitUntilScriptsAreParsed = function(
961 expectedScripts, callback) {
962 var test = this;
963
964 function waitForAllScripts() {
965 if (test._scriptsAreParsed(expectedScripts)) {
966 callback();
967 } else {
968 test.addSniffer(WebInspector, 'parsedScriptSource', waitForAllScripts);
969 }
970 }
971
972 waitForAllScripts();
973 };
974
975
976 /**
977 * Waits until all debugger scripts are parsed and executes 'a()' in the
978 * inspected page.
979 */
980 TestSuite.prototype._executeFunctionForStepTest = function() {
981 this._executeCodeWhenScriptsAreParsed(
982 'a()',
983 ['debugger_step.html$', 'debugger_step.js$']);
984 };
985
986
987 /**
988 * Tests step over in the debugger.
989 */
990 TestSuite.prototype.testStepOver = function() {
991 this.showPanel('scripts');
992 var test = this;
993
994 this._executeFunctionForStepTest();
995
996 this._performSteps([
997 {
998 functionsOnStack: ['d','a','(anonymous function)'],
999 lineNumber: 3,
1000 lineText: ' debugger;'
1001 },
1002 function() {
1003 document.getElementById('scripts-step-over').click();
1004 },
1005 {
1006 functionsOnStack: ['d','a','(anonymous function)'],
1007 lineNumber: 5,
1008 lineText: ' var y = fact(10);'
1009 },
1010 function() {
1011 document.getElementById('scripts-step-over').click();
1012 },
1013 {
1014 functionsOnStack: ['d','a','(anonymous function)'],
1015 lineNumber: 6,
1016 lineText: ' return y;'
1017 },
1018 function() {
1019 test.releaseControl();
1020 }
1021 ]);
1022
1023 test.takeControl();
1024 };
1025
1026
1027 /**
1028 * Tests step out in the debugger.
1029 */
1030 TestSuite.prototype.testStepOut = function() {
1031 this.showPanel('scripts');
1032 var test = this;
1033
1034 this._executeFunctionForStepTest();
1035
1036 this._performSteps([
1037 {
1038 functionsOnStack: ['d','a','(anonymous function)'],
1039 lineNumber: 3,
1040 lineText: ' debugger;'
1041 },
1042 function() {
1043 document.getElementById('scripts-step-out').click();
1044 },
1045 {
1046 functionsOnStack: ['a','(anonymous function)'],
1047 lineNumber: 8,
1048 lineText: ' printResult(result);'
1049 },
1050 function() {
1051 test.releaseControl();
1052 }
1053 ]);
1054
1055 test.takeControl();
1056 };
1057
1058
1059 /**
1060 * Tests step in in the debugger.
1061 */
1062 TestSuite.prototype.testStepIn = function() {
1063 this.showPanel('scripts');
1064 var test = this;
1065
1066 this._executeFunctionForStepTest();
1067
1068 this._performSteps([
1069 {
1070 functionsOnStack: ['d','a','(anonymous function)'],
1071 lineNumber: 3,
1072 lineText: ' debugger;'
1073 },
1074 function() {
1075 document.getElementById('scripts-step-over').click();
1076 },
1077 {
1078 functionsOnStack: ['d','a','(anonymous function)'],
1079 lineNumber: 5,
1080 lineText: ' var y = fact(10);'
1081 },
1082 function() {
1083 document.getElementById('scripts-step-into').click();
1084 },
1085 {
1086 functionsOnStack: ['fact','d','a','(anonymous function)'],
1087 lineNumber: 15,
1088 lineText: ' return r;'
1089 },
1090 function() {
1091 test.releaseControl();
1092 }
1093 ]);
1094
1095 test.takeControl();
1096 };
1097
1098
1099 /**
1100 * Gets a XPathResult matching given xpath.
1101 * @param {string} xpath
1102 * @param {number} resultType
1103 * @param {Node} opt_ancestor Context node. If not specified documentElement
1104 * will be used
1105 * @return {XPathResult} Type of returned value is determined by 'resultType' pa rameter
1106 */
1107
1108 TestSuite.prototype._evaluateXpath = function(
1109 xpath, resultType, opt_ancestor) {
1110 if (!opt_ancestor) {
1111 opt_ancestor = document.documentElement;
1112 }
1113 try {
1114 return document.evaluate(xpath, opt_ancestor, null, resultType, null);
1115 } catch(e) {
1116 this.fail('Error in expression: "' + xpath + '".' + e);
1117 }
1118 };
1119
1120
1121 /**
1122 * Gets first Node matching given xpath.
1123 * @param {string} xpath
1124 * @param {Node} opt_ancestor Context node. If not specified documentElement
1125 * will be used
1126 * @return {?Node}
1127 */
1128 TestSuite.prototype._findNode = function(xpath, opt_ancestor) {
1129 var result = this._evaluateXpath(xpath, XPathResult.FIRST_ORDERED_NODE_TYPE,
1130 opt_ancestor).singleNodeValue;
1131 this.assertTrue(!!result, 'Cannot find node on path: ' + xpath);
1132 return result;
1133 };
1134
1135
1136 /**
1137 * Gets a text matching given xpath.
1138 * @param {string} xpath
1139 * @param {Node} opt_ancestor Context node. If not specified documentElement
1140 * will be used
1141 * @return {?string}
1142 */
1143 TestSuite.prototype._findText = function(xpath, opt_ancestor) {
1144 var result = this._evaluateXpath(xpath, XPathResult.STRING_TYPE,
1145 opt_ancestor).stringValue;
1146 this.assertTrue(!!result, 'Cannot find text on path: ' + xpath);
1147 return result;
1148 };
1149
1150
1151 /**
1152 * Gets an iterator over nodes matching given xpath.
1153 * @param {string} xpath
1154 * @param {Node} opt_ancestor Context node. If not specified, documentElement
1155 * will be used
1156 * @return {XPathResult} Iterator over the nodes
1157 */
1158 TestSuite.prototype._nodeIterator = function(xpath, opt_ancestor) {
1159 return this._evaluateXpath(xpath, XPathResult.ORDERED_NODE_ITERATOR_TYPE,
1160 opt_ancestor);
1161 };
1162
1163
1164 /**
1165 * Checks the scopeSectionDiv against the expectations.
1166 * @param {Node} scopeSectionDiv The section div
1167 * @param {Object} expectations Expectations dictionary
1168 */
1169 TestSuite.prototype._checkScopeSectionDiv = function(
1170 scopeSectionDiv, expectations) {
1171 var scopeTitle = this._findText(
1172 './div[@class="header"]/div[@class="title"]/text()', scopeSectionDiv);
1173 this.assertEquals(expectations.title, scopeTitle,
1174 'Unexpected scope section title.');
1175 if (!expectations.properties) {
1176 return;
1177 }
1178 this.assertTrue(scopeSectionDiv.hasStyleClass('expanded'), 'Section "' +
1179 scopeTitle + '" is collapsed.');
1180
1181 var propertyIt = this._nodeIterator('./ol[@class="properties"]/li',
1182 scopeSectionDiv);
1183 var propertyLi;
1184 var foundProps = [];
1185 while (propertyLi = propertyIt.iterateNext()) {
1186 var name = this._findText('./span[@class="name"]/text()', propertyLi);
1187 var value = this._findText('./span[@class="value"]/text()', propertyLi);
1188 this.assertTrue(!!name, 'Invalid variable name: "' + name + '"');
1189 this.assertTrue(name in expectations.properties,
1190 'Unexpected property: ' + name);
1191 this.assertEquals(expectations.properties[name], value,
1192 'Unexpected "' + name + '" property value.');
1193 delete expectations.properties[name];
1194 foundProps.push(name + ' = ' + value);
1195 }
1196
1197 // Check that all expected properties were found.
1198 for (var p in expectations.properties) {
1199 this.fail('Property "' + p + '" was not found in scope "' + scopeTitle +
1200 '". Found properties: "' + foundProps.join(',') + '"');
1201 }
1202 };
1203
1204
1205 /**
1206 * Expands scope sections matching the filter and invokes the callback on
1207 * success.
1208 * @param {function(WebInspector.ObjectPropertiesSection, number):boolean}
1209 * filter
1210 * @param {Function} callback
1211 */
1212 TestSuite.prototype._expandScopeSections = function(filter, callback) {
1213 var sections = WebInspector.currentPanel.sidebarPanes.scopechain.sections;
1214
1215 var toBeUpdatedCount = 0;
1216 function updateListener() {
1217 --toBeUpdatedCount;
1218 if (toBeUpdatedCount == 0) {
1219 // Report when all scopes are expanded and populated.
1220 callback();
1221 }
1222 }
1223
1224 // Global scope is always the last one.
1225 for (var i = 0; i < sections.length - 1; i++) {
1226 var section = sections[i];
1227 if (!filter(sections, i)) {
1228 continue;
1229 }
1230 ++toBeUpdatedCount;
1231 var populated = section.populated;
1232
1233 this._hookGetPropertiesCallback(updateListener,
1234 function() {
1235 section.expand();
1236 if (populated) {
1237 // Make sure 'updateProperties' callback will be called at least once
1238 // after it was overridden.
1239 section.update();
1240 }
1241 });
1242 }
1243 };
1244
1245
1246 /**
1247 * Tests that scopes can be expanded and contain expected data.
1248 */
1249 TestSuite.prototype.testExpandScope = function() {
1250 this.showPanel('scripts');
1251 var test = this;
1252
1253 this._executeCodeWhenScriptsAreParsed(
1254 'handleClick()',
1255 ['debugger_closure.html$']);
1256
1257 this._waitForScriptPause(
1258 {
1259 functionsOnStack: ['innerFunction', 'handleClick',
1260 '(anonymous function)'],
1261 lineNumber: 8,
1262 lineText: ' debugger;'
1263 },
1264 expandAllSectionsExceptGlobal);
1265
1266 // Expanding Global scope takes for too long so we skeep it.
1267 function expandAllSectionsExceptGlobal() {
1268 test._expandScopeSections(function(sections, i) {
1269 return i < sections.length - 1;
1270 },
1271 examineScopes /* When all scopes are expanded and populated check
1272 them. */);
1273 }
1274
1275 // Check scope sections contents.
1276 function examineScopes() {
1277 var scopeVariablesSection = test._findNode('//div[@id="scripts-sidebar"]/' +
1278 'div[div[@class="title"]/text()="Scope Variables"]');
1279 var expectedScopes = [
1280 {
1281 title: 'Local',
1282 properties: {
1283 x:2009,
1284 innerFunctionLocalVar:2011,
1285 'this': 'global',
1286 }
1287 },
1288 {
1289 title: 'Closure',
1290 properties: {
1291 n:'TextParam',
1292 makeClosureLocalVar:'local.TextParam',
1293 }
1294 },
1295 {
1296 title: 'Global',
1297 },
1298 ];
1299 var it = test._nodeIterator('./div[@class="body"]/div',
1300 scopeVariablesSection);
1301 var scopeIndex = 0;
1302 var scopeDiv;
1303 while (scopeDiv = it.iterateNext()) {
1304 test.assertTrue(scopeIndex < expectedScopes.length,
1305 'Too many scopes.');
1306 test._checkScopeSectionDiv(scopeDiv, expectedScopes[scopeIndex]);
1307 ++scopeIndex;
1308 }
1309 test.assertEquals(expectedScopes.length, scopeIndex,
1310 'Unexpected number of scopes.');
1311
1312 test.releaseControl();
1313 }
1314
1315 test.takeControl();
1316 };
1317
1318
1319 /**
1320 * Returns child tree element for a property with given name.
1321 * @param {TreeElement} parent Parent tree element.
1322 * @param {string} childName
1323 * @param {string} objectPath Path to the object. Will be printed in the case
1324 * of failure.
1325 * @return {TreeElement}
1326 */
1327 TestSuite.prototype._findChildProperty = function(
1328 parent, childName, objectPath) {
1329 var children = parent.children;
1330 for (var i = 0; i < children.length; i++) {
1331 var treeElement = children[i];
1332 var property = treeElement.property;
1333 if (property.name == childName) {
1334 return treeElement;
1335 }
1336 }
1337 this.fail('Cannot find property "' + childName + '" in ' + objectPath);
1338 };
1339
1340
1341 /**
1342 * Executes the 'code' with InjectedScriptAccess.getProperties overriden
1343 * so that all callbacks passed to InjectedScriptAccess.getProperties are
1344 * extended with the 'hook'.
1345 * @param {Function} hook The hook function.
1346 * @param {Function} code A code snippet to be executed.
1347 */
1348 TestSuite.prototype._hookGetPropertiesCallback = function(hook, code) {
1349 var orig = InjectedScriptAccess.getProperties;
1350 InjectedScriptAccess.getProperties = function(objectProxy,
1351 ignoreHasOwnProperty, callback) {
1352 orig.call(InjectedScriptAccess, objectProxy, ignoreHasOwnProperty,
1353 function() {
1354 callback.apply(this, arguments);
1355 hook();
1356 });
1357 };
1358 try {
1359 code();
1360 } finally {
1361 InjectedScriptAccess.getProperties = orig;
1362 }
1363 };
1364
1365
1366 /**
1367 * Tests that all elements in prototype chain of an object have expected
1368 * intrinic proprties(__proto__, constructor, prototype).
1369 */
1370 TestSuite.prototype.testDebugIntrinsicProperties = function() {
1371 this.showPanel('scripts');
1372 var test = this;
1373
1374 this._executeCodeWhenScriptsAreParsed(
1375 'handleClick()',
1376 ['debugger_intrinsic_properties.html$']);
1377
1378 this._waitForScriptPause(
1379 {
1380 functionsOnStack: ['callDebugger', 'handleClick',
1381 '(anonymous function)'],
1382 lineNumber: 29,
1383 lineText: ' debugger;'
1384 },
1385 expandLocalScope);
1386
1387 var localScopeSection = null;
1388 function expandLocalScope() {
1389 test._expandScopeSections(function(sections, i) {
1390 if (i == 0) {
1391 test.assertTrue(sections[i].object.isLocal, 'Scope #0 is not Local.');
1392 localScopeSection = sections[i];
1393 return true;
1394 }
1395 return false;
1396 },
1397 examineLocalScope);
1398 }
1399
1400 function examineLocalScope() {
1401 var scopeExpectations = [
1402 'a', 'Object', [
1403 'constructor', 'function Child()', [
1404 'constructor', 'function Function()', null,
1405 'name', 'Child', null,
1406 'prototype', 'Object', [
1407 'childProtoField', '21', null
1408 ]
1409 ],
1410
1411 '__proto__', 'Object', [
1412 '__proto__', 'Object', [
1413 '__proto__', 'Object', [
1414 '__proto__', 'null', null,
1415 'constructor', 'function Object()', null,
1416 ],
1417 'constructor', 'function Parent()', [
1418 'name', 'Parent', null,
1419 'prototype', 'Object', [
1420 'parentProtoField', '11', null,
1421 ]
1422 ],
1423 'parentProtoField', '11', null,
1424 ],
1425 'constructor', 'function Child()', null,
1426 'childProtoField', '21', null,
1427 ],
1428
1429 'parentField', '10', null,
1430 'childField', '20', null,
1431 ]
1432 ];
1433
1434 checkProperty(
1435 localScopeSection.propertiesTreeOutline,
1436 '<Local Scope>',
1437 scopeExpectations);
1438 }
1439
1440 var propQueue = [];
1441 var index = 0;
1442 var expectedFinalIndex = 8;
1443
1444 function expandAndCheckNextProperty() {
1445 if (index == propQueue.length) {
1446 test.assertEquals(expectedFinalIndex, index,
1447 'Unexpected number of expanded objects.');
1448 test.releaseControl();
1449 return;
1450 }
1451
1452 // Read next property data from the queue.
1453 var treeElement = propQueue[index].treeElement;
1454 var path = propQueue[index].path;
1455 var expectations = propQueue[index].expectations;
1456 index++;
1457
1458 // Expand the property.
1459 test._hookGetPropertiesCallback(function() {
1460 checkProperty(treeElement, path, expectations);
1461 },
1462 function() {
1463 treeElement.expand();
1464 });
1465 }
1466
1467 function checkProperty(treeElement, path, expectations) {
1468 for (var i = 0; i < expectations.length; i += 3) {
1469 var name = expectations[i];
1470 var description = expectations[i+1];
1471 var value = expectations[i+2];
1472
1473 var propertyPath = path + '.' + name;
1474 var propertyTreeElement = test._findChildProperty(
1475 treeElement, name, path);
1476 test.assertTrue(propertyTreeElement,
1477 'Property "' + propertyPath + '" not found.');
1478 test.assertEquals(description,
1479 propertyTreeElement.property.value.description,
1480 'Unexpected "' + propertyPath + '" description.');
1481 if (value) {
1482 // Schedule property content check.
1483 propQueue.push({
1484 treeElement: propertyTreeElement,
1485 path: propertyPath,
1486 expectations: value,
1487 });
1488 }
1489 }
1490 // Check next property in the queue.
1491 expandAndCheckNextProperty();
1492 }
1493
1494 test.takeControl();
1495 };
1496
1497
1498 /**
1499 * Tests 'Pause' button will pause debugger when a snippet is evaluated.
1500 */
1501 TestSuite.prototype.testPauseInEval = function() {
1502 this.showPanel('scripts');
1503
1504 var test = this;
1505
1506 var pauseButton = document.getElementById('scripts-pause');
1507 pauseButton.click();
1508
1509 devtools.tools.evaluateJavaScript('fib(10)');
1510
1511 this.addSniffer(WebInspector, 'pausedScript',
1512 function() {
1513 test.releaseControl();
1514 });
1515
1516 test.takeControl();
1517 };
1518
1519
1520 /**
1521 * Key event with given key identifier.
1522 */
1523 TestSuite.KeyEvent = function(key) {
1524 this.keyIdentifier = key;
1525 };
1526 TestSuite.KeyEvent.prototype.preventDefault = function() {};
1527 TestSuite.KeyEvent.prototype.stopPropagation = function() {};
1528
1529
1530 /**
1531 * Tests console eval.
1532 */
1533 TestSuite.prototype.testConsoleEval = function() {
1534 var test = this;
1535 this.evaluateInConsole_('123',
1536 function(resultText) {
1537 test.assertEquals('123', resultText);
1538 test.releaseControl();
1539 });
1540
1541 this.takeControl();
1542 };
1543
1544
1545 /**
1546 * Tests console log.
1547 */
1548 TestSuite.prototype.testConsoleLog = function() {
1549 WebInspector.console.visible = true;
1550 var messages = WebInspector.console.messages;
1551 var index = 0;
1552
1553 var test = this;
1554 var assertNext = function(line, message, opt_class, opt_count, opt_substr) {
1555 var elem = messages[index++].toMessageElement();
1556 var clazz = elem.getAttribute('class');
1557 var expectation = (opt_count || '') + 'console_test_page.html:' +
1558 line + message;
1559 if (opt_substr) {
1560 test.assertContains(elem.textContent, expectation);
1561 } else {
1562 test.assertEquals(expectation, elem.textContent);
1563 }
1564 if (opt_class) {
1565 test.assertContains(clazz, 'console-' + opt_class);
1566 }
1567 };
1568
1569 assertNext('5', 'log', 'log-level');
1570 assertNext('7', 'debug', 'log-level');
1571 assertNext('9', 'info', 'log-level');
1572 assertNext('11', 'warn', 'warning-level');
1573 assertNext('13', 'error', 'error-level');
1574 assertNext('15', 'Message format number 1, 2 and 3.5');
1575 assertNext('17', 'Message format for string');
1576 assertNext('19', 'Object Object');
1577 assertNext('22', 'repeated', 'log-level', 5);
1578 assertNext('26', 'count: 1');
1579 assertNext('26', 'count: 2');
1580 assertNext('29', 'group', 'group-title');
1581 index++;
1582 assertNext('33', 'timer:', 'log-level', '', true);
1583 assertNext('35', '1 2 3', 'log-level');
1584 assertNext('37', 'HTMLDocument', 'log-level');
1585 assertNext('39', '<html>', 'log-level', '', true);
1586 };
1587
1588
1589 /**
1590 * Tests eval of global objects.
1591 */
1592 TestSuite.prototype.testEvalGlobal = function() {
1593 WebInspector.console.visible = true;
1594
1595 var inputs = ['foo', 'foobar'];
1596 var expectations = ['foo', 'fooValue',
1597 'foobar', 'ReferenceError: foobar is not defined'];
1598
1599 // Do not change code below - simply add inputs and expectations above.
1600 var initEval = function(input) {
1601 WebInspector.console.prompt.text = input;
1602 WebInspector.console.promptElement.handleKeyEvent(
1603 new TestSuite.KeyEvent('Enter'));
1604 };
1605 var test = this;
1606 var messagesCount = 0;
1607 var inputIndex = 0;
1608 this.addSniffer(WebInspector.ConsoleView.prototype, 'addMessage',
1609 function(commandResult) {
1610 messagesCount++;
1611 if (messagesCount == expectations.length) {
1612 var messages = WebInspector.console.messages;
1613 for (var i = 0; i < expectations; ++i) {
1614 var elem = messages[i++].toMessageElement();
1615 test.assertEquals(elem.textContent, expectations[i]);
1616 }
1617 test.releaseControl();
1618 } else if (messagesCount % 2 == 0) {
1619 initEval(inputs[inputIndex++]);
1620 }
1621 }, true);
1622
1623 initEval(inputs[inputIndex++]);
1624 this.takeControl();
1625 };
1626
1627
1628 /**
1629 * Test runner for the test suite.
1630 */
1631 var uiTests = {};
1632
1633
1634 /**
1635 * Run each test from the test suit on a fresh instance of the suite.
1636 */
1637 uiTests.runAllTests = function() {
1638 // For debugging purposes.
1639 for (var name in TestSuite.prototype) {
1640 if (name.substring(0, 4) == 'test' &&
1641 typeof TestSuite.prototype[name] == 'function') {
1642 uiTests.runTest(name);
1643 }
1644 }
1645 };
1646
1647
1648 /**
1649 * Run specified test on a fresh instance of the test suite.
1650 * @param {string} name Name of a test method from TestSuite class.
1651 */
1652 uiTests.runTest = function(name) {
1653 new TestSuite().runTest(name);
1654 };
1655
1656
1657 }
OLDNEW
« no previous file with comments | « resources/inspector/splaytree.js ('k') | resources/inspector/textViewer.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698