- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / webui / net_internals / net_internals_test.js
1 // Copyright (c) 2012 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  * @fileoverview The way these tests work is as follows:
7  * C++ in net_internals_ui_browsertest.cc does any necessary setup, and then
8  * calls the entry point for a test with RunJavascriptTest.  The called
9  * function can then use the assert/expect functions defined in test_api.js.
10  * All callbacks from the browser are wrapped in such a way that they can
11  * also use the assert/expect functions.
12  *
13  * A test ends when testDone is called.  This can be done by the test itself,
14  * but will also be done by the test framework when an assert/expect test fails
15  * or an exception is thrown.
16  */
17
18 // Include the C++ browser test class when generating *.cc files.
19 GEN('#include ' +
20     '"chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h"');
21
22 var NetInternalsTest = (function() {
23   /**
24    * A shorter poll interval is used for tests, since a few tests wait for
25    * polled values to change.
26    * @type {number}
27    * @const
28    */
29   var TESTING_POLL_INTERVAL_MS = 50;
30
31   /**
32    * Private pointer to the currently active test framework.  Needed so static
33    * functions can access some of the inner workings of the test framework.
34    * @type {NetInternalsTest}
35    */
36   var activeTest_ = null;
37
38   function NetInternalsTest() {
39     activeTest_ = this;
40   }
41
42   NetInternalsTest.prototype = {
43     __proto__: testing.Test.prototype,
44
45     /**
46      * Define the C++ fixture class and include it.
47      * @type {?string}
48      * @override
49      */
50     typedefCppFixture: 'NetInternalsTest',
51
52     /** @inheritDoc */
53     browsePreload: 'chrome://net-internals/',
54
55     /** @inheritDoc */
56     isAsync: true,
57
58     setUp: function() {
59       // Enforce accessibility auditing, but suppress some false positives.
60       this.accessibilityIssuesAreErrors = true;
61       // False positive because a unicode character is used to draw a square.
62       // If it was actual text it'd be too low-contrast, but a square is fine.
63       this.accessibilityAuditConfig.ignoreSelectors(
64           'lowContrastElements', '#timeline-view-selection-ul label');
65       // Suppress this error; the black-on-gray button is readable.
66       this.accessibilityAuditConfig.ignoreSelectors(
67           'lowContrastElements', '#export-view-save-log-file');
68       // False positive because the background color highlights and then
69       // fades out with a transition when there's an error.
70       this.accessibilityAuditConfig.ignoreSelectors(
71           'lowContrastElements', '#hsts-view-query-output span');
72       // False positives for unknown reason.
73       this.accessibilityAuditConfig.ignoreSelectors(
74           'focusableElementNotVisibleAndNotAriaHidden',
75           '#hsts-view-tab-content *');
76
77       // Wrap g_browser.receive around a test function so that assert and expect
78       // functions can be called from observers.
79       g_browser.receive =
80           this.continueTest(WhenTestDone.EXPECT,
81                             BrowserBridge.prototype.receive.bind(g_browser));
82
83       g_browser.setPollInterval(TESTING_POLL_INTERVAL_MS);
84
85       var runTest = this.deferRunTest(WhenTestDone.EXPECT);
86
87       // If we've already received the constants, start the tests.
88       if (Constants) {
89         // Stat test asynchronously, to avoid running a nested test function.
90         window.setTimeout(runTest, 0);
91         return;
92       }
93
94       // Otherwise, wait until we do.
95       console.log('Received constants late.');
96
97       /**
98        * Observer that starts the tests once we've received the constants.
99        */
100       function ConstantsObserver() {
101         this.testStarted_ = false;
102       }
103
104       ConstantsObserver.prototype.onReceivedConstants = function() {
105         if (!this.testStarted_) {
106           this.testStarted_ = true;
107           // Stat test asynchronously, to avoid running a nested test function,
108           // and so we don't call any constants observers used by individual
109           // tests.
110           window.setTimeout(runTest, 0);
111         }
112       };
113
114       g_browser.addConstantsObserver(new ConstantsObserver());
115     }
116   };
117
118   /**
119    * A callback function for use by asynchronous Tasks that need a return value
120    * from the NetInternalsTest::MessageHandler.  Must be null when no such
121    * Task is running.  Set by NetInternalsTest.setCallback.  Automatically
122    * cleared once called.  Must only be called through
123    * NetInternalsTest::MessageHandler::RunCallback, from the browser process.
124    */
125   NetInternalsTest.callback = null;
126
127   /**
128    * Sets NetInternalsTest.callback.  Any arguments will be passed to the
129    * callback function.
130    * @param {function} callbackFunction Callback function to be called from the
131    *     browser.
132    */
133   NetInternalsTest.setCallback = function(callbackFunction) {
134     // Make sure no Task has already set the callback function.
135     assertEquals(null, NetInternalsTest.callback);
136
137     // Wrap |callbackFunction| in a function that clears
138     // |NetInternalsTest.callback| before calling |callbackFunction|.
139     var callbackFunctionWrapper = function() {
140       NetInternalsTest.callback = null;
141       callbackFunction.apply(null, Array.prototype.slice.call(arguments));
142     };
143
144     // Wrap |callbackFunctionWrapper| with test framework code.
145     NetInternalsTest.callback =
146         activeTest_.continueTest(WhenTestDone.EXPECT, callbackFunctionWrapper);
147   };
148
149   /**
150    * Returns the first tbody that's a descendant of |ancestorId|. If the
151    * specified node is itself a table body node, just returns that node.
152    * Returns null if no such node is found.
153    * @param {string} ancestorId ID of an HTML element with a tbody descendant.
154    * @return {node} The tbody node, or null.
155    */
156   NetInternalsTest.getTbodyDescendent = function(ancestorId) {
157     if ($(ancestorId).nodeName == 'TBODY')
158       return $(ancestorId);
159     // The tbody element of the first styled table in |parentId|.
160     return document.querySelector('#' + ancestorId + ' tbody');
161   };
162
163   /**
164    * Finds the first tbody that's a descendant of |ancestorId|, including the
165    * |ancestorId| element itself, and returns the number of rows it has.
166    * Returns -1 if there's no such table.  Excludes hidden rows.
167    * @param {string} ancestorId ID of an HTML element with a tbody descendant.
168    * @return {number} Number of rows the style table's body has.
169    */
170   NetInternalsTest.getTbodyNumRows = function(ancestorId) {
171     // The tbody element of the first styled table in |parentId|.
172     var tbody = NetInternalsTest.getTbodyDescendent(ancestorId);
173     if (!tbody)
174       return -1;
175     var visibleChildren = 0;
176     for (var i = 0; i < tbody.children.length; ++i) {
177       if (NetInternalsTest.nodeIsVisible(tbody.children[i]))
178         ++visibleChildren;
179     }
180     return visibleChildren;
181   };
182
183   /**
184    * Finds the first tbody that's a descendant of |ancestorId|, including the
185    * |ancestorId| element itself, and checks if it has exactly |expectedRows|
186    * rows.  Does not count hidden rows.
187    * @param {string} ancestorId ID of an HTML element with a tbody descendant.
188    * @param {number} expectedRows Expected number of rows in the table.
189    */
190   NetInternalsTest.checkTbodyRows = function(ancestorId, expectedRows) {
191     expectEquals(expectedRows,
192                  NetInternalsTest.getTbodyNumRows(ancestorId),
193                  'Incorrect number of rows in ' + ancestorId);
194   };
195
196   /**
197    * Finds the tbody that's a descendant of |ancestorId|, including the
198    * |ancestorId| element itself, and returns the text of the specified cell.
199    * If the cell does not exist, throws an exception.  Skips over hidden rows.
200    * @param {string} ancestorId ID of an HTML element with a tbody descendant.
201    * @param {number} row Row of the value to retrieve.
202    * @param {number} column Column of the value to retrieve.
203    */
204   NetInternalsTest.getTbodyText = function(ancestorId, row, column) {
205     var tbody = NetInternalsTest.getTbodyDescendent(ancestorId);
206     var currentChild = tbody.children[0];
207     while (currentChild) {
208       if (NetInternalsTest.nodeIsVisible(currentChild)) {
209         if (row == 0)
210           return currentChild.children[column].innerText;
211         --row;
212       }
213       currentChild = currentChild.nextElementSibling;
214     }
215     return 'invalid row';
216   };
217
218   /**
219    * Returns the view and menu item node for the tab with given id.
220    * Asserts if the tab can't be found.
221    * @param {string}: tabId Id of the tab to lookup.
222    * @return {Object}
223    */
224   NetInternalsTest.getTab = function(tabId) {
225     var tabSwitcher = MainView.getInstance().tabSwitcher();
226     var view = tabSwitcher.getTabView(tabId);
227     var menuItem = tabSwitcher.getMenuItemNode_(tabId);
228
229     assertNotEquals(view, undefined, tabId + ' does not exist.');
230     assertNotEquals(menuItem, undefined, tabId + ' does not exist.');
231
232     return {
233       view: view,
234       menuItem: menuItem,
235     };
236   };
237
238   /**
239    * Returns true if the node is visible.
240    * @param {Node}: node Node to check the visibility state of.
241    * @return {bool} Whether or not the node is visible.
242    */
243   NetInternalsTest.nodeIsVisible = function(node) {
244     return node.style.display != 'none';
245   };
246
247   /**
248    * Returns true if the specified tab's handle is visible, false otherwise.
249    * Asserts if the handle can't be found.
250    * @param {string}: tabId Id of the tab to check.
251    * @return {bool} Whether or not the tab's handle is visible.
252    */
253   NetInternalsTest.tabHandleIsVisible = function(tabId) {
254     var tabHandleNode = NetInternalsTest.getTab(tabId).menuItem;
255     return NetInternalsTest.nodeIsVisible(tabHandleNode);
256   };
257
258   /**
259    * Returns the id of the currently active tab.
260    * @return {string} ID of the active tab.
261    */
262   NetInternalsTest.getActiveTabId = function() {
263     return MainView.getInstance().tabSwitcher().getActiveTabId();
264   };
265
266   /**
267    * Returns the tab id of a tab, given its associated URL hash value.  Asserts
268    *     if |hash| has no associated tab.
269    * @param {string}: hash Hash associated with the tab to return the id of.
270    * @return {string} String identifier of the tab with the given hash.
271    */
272   NetInternalsTest.getTabId = function(hash) {
273     /**
274      * Map of tab handle names to location hashes.  Since the text fixture
275      * must be runnable independent of net-internals, for generating the
276      * test's cc files, must be careful to only create this map while a test
277      * is running.
278      * @type {object.<string, string>}
279      */
280     var hashToTabHandleIdMap = {
281       capture: CaptureView.TAB_ID,
282       export: ExportView.TAB_ID,
283       import: ImportView.TAB_ID,
284       proxy: ProxyView.TAB_ID,
285       events: EventsView.TAB_ID,
286       waterfall: WaterfallView.TAB_ID,
287       timeline: TimelineView.TAB_ID,
288       dns: DnsView.TAB_ID,
289       sockets: SocketsView.TAB_ID,
290       spdy: SpdyView.TAB_ID,
291       quic: QuicView.TAB_ID,
292       httpPipeline: HttpPipelineView.TAB_ID,
293       httpCache: HttpCacheView.TAB_ID,
294       modules: ModulesView.TAB_ID,
295       tests: TestView.TAB_ID,
296       hsts: HSTSView.TAB_ID,
297       logs: LogsView.TAB_ID,
298       prerender: PrerenderView.TAB_ID,
299       bandwidth: BandwidthView.TAB_ID,
300       chromeos: CrosView.TAB_ID,
301       visualizer: CrosLogVisualizerView.TAB_ID
302     };
303
304     assertEquals(typeof hashToTabHandleIdMap[hash], 'string',
305                  'Invalid tab anchor: ' + hash);
306     var tabId = hashToTabHandleIdMap[hash];
307     assertEquals('object', typeof NetInternalsTest.getTab(tabId),
308                  'Invalid tab: ' + tabId);
309     return tabId;
310   };
311
312   /**
313    * Switches to the specified tab.
314    * @param {string}: hash Hash associated with the tab to switch to.
315    */
316   NetInternalsTest.switchToView = function(hash) {
317     var tabId = NetInternalsTest.getTabId(hash);
318
319     // Make sure the tab handle is visible, as we only simulate normal usage.
320     expectTrue(NetInternalsTest.tabHandleIsVisible(tabId),
321                tabId + ' does not have a visible tab handle.');
322     var tabHandleNode = NetInternalsTest.getTab(tabId).menuItem;
323
324     // Simulate selecting the menuitem.
325     tabHandleNode.selected = true;
326     tabHandleNode.parentNode.onchange();
327
328     // Make sure the hash changed.
329     assertEquals('#' + hash, document.location.hash);
330
331     // Make sure only the specified tab is visible.
332     var tabSwitcher = MainView.getInstance().tabSwitcher();
333     var tabIdToView = tabSwitcher.getAllTabViews();
334     for (var curTabId in tabIdToView) {
335       expectEquals(curTabId == tabId,
336                    tabSwitcher.getTabView(curTabId).isVisible(),
337                    curTabId + ': Unexpected visibility state.');
338     }
339   };
340
341   /**
342    * Checks the visibility of all tab handles against expected values.
343    * @param {object.<string, bool>}: tabVisibilityState Object with a an entry
344    *     for each tab's hash, and a bool indicating if it should be visible or
345    *     not.
346    * @param {bool+}: tourTabs True if tabs expected to be visible should should
347    *     each be navigated to as well.
348    */
349   NetInternalsTest.checkTabHandleVisibility = function(tabVisibilityState,
350                                                        tourTabs) {
351     // The currently active tab should have a handle that is visible.
352     expectTrue(NetInternalsTest.tabHandleIsVisible(
353                    NetInternalsTest.getActiveTabId()));
354
355     // Check visibility state of all tabs.
356     var tabCount = 0;
357     for (var hash in tabVisibilityState) {
358       var tabId = NetInternalsTest.getTabId(hash);
359       assertEquals('object', typeof NetInternalsTest.getTab(tabId),
360                    'Invalid tab: ' + tabId);
361       expectEquals(tabVisibilityState[hash],
362                    NetInternalsTest.tabHandleIsVisible(tabId),
363                    tabId + ' visibility state is unexpected.');
364       if (tourTabs && tabVisibilityState[hash])
365         NetInternalsTest.switchToView(hash);
366       tabCount++;
367     }
368
369     // Check that every tab was listed.
370     var tabSwitcher = MainView.getInstance().tabSwitcher();
371     var tabIdToView = tabSwitcher.getAllTabViews();
372     var expectedTabCount = 0;
373     for (tabId in tabIdToView)
374       expectedTabCount++;
375     expectEquals(tabCount, expectedTabCount);
376   };
377
378   /**
379    * This class allows multiple Tasks to be queued up to be run sequentially.
380    * A Task can wait for asynchronous callbacks from the browser before
381    * completing, at which point the next queued Task will be run.
382    * @param {bool}: endTestWhenDone True if testDone should be called when the
383    *     final task completes.
384    * @param {NetInternalsTest}: test Test fixture passed to Tasks.
385    * @constructor
386    */
387   NetInternalsTest.TaskQueue = function(endTestWhenDone) {
388     // Test fixture for passing to tasks.
389     this.tasks_ = [];
390     this.isRunning_ = false;
391     this.endTestWhenDone_ = endTestWhenDone;
392   };
393
394   NetInternalsTest.TaskQueue.prototype = {
395     /**
396      * Adds a Task to the end of the queue.  Each Task may only be added once
397      * to a single queue.  Also passes the text fixture to the Task.
398      * @param {Task}: task The Task to add.
399      */
400     addTask: function(task) {
401       this.tasks_.push(task);
402       task.setTaskQueue_(this);
403     },
404
405     /**
406      * Adds a Task to the end of the queue.  The task will call the provided
407      * function, and then complete.
408      * @param {function}: taskFunction The function the task will call.
409      */
410     addFunctionTask: function(taskFunction) {
411       this.addTask(new NetInternalsTest.CallFunctionTask(taskFunction));
412     },
413
414     /**
415      * Starts running the Tasks in the queue, passing its arguments, if any,
416      * to the first Task's start function.  May only be called once.
417      */
418     run: function() {
419       assertFalse(this.isRunning_);
420       this.isRunning_ = true;
421       this.runNextTask_(Array.prototype.slice.call(arguments));
422     },
423
424     /**
425      * If there are any Tasks in |tasks_|, removes the first one and runs it.
426      * Otherwise, sets |isRunning_| to false.  If |endTestWhenDone_| is true,
427      * calls testDone.
428      * @param {array} argArray arguments to be passed on to next Task's start
429      *     method.  May be a 0-length array.
430      */
431     runNextTask_: function(argArray) {
432       assertTrue(this.isRunning_);
433       // The last Task may have used |NetInternalsTest.callback|.  Make sure
434       // it's now null.
435       expectEquals(null, NetInternalsTest.callback);
436
437       if (this.tasks_.length > 0) {
438         var nextTask = this.tasks_.shift();
439         nextTask.start.apply(nextTask, argArray);
440       } else {
441         this.isRunning_ = false;
442         if (this.endTestWhenDone_)
443           testDone();
444       }
445     }
446   };
447
448   /**
449    * A Task that can be added to a TaskQueue.  A Task is started with a call to
450    * the start function, and must call its own onTaskDone when complete.
451    * @constructor
452    */
453   NetInternalsTest.Task = function() {
454     this.taskQueue_ = null;
455     this.isDone_ = false;
456     this.completeAsync_ = false;
457   };
458
459   NetInternalsTest.Task.prototype = {
460     /**
461      * Starts running the Task.  Only called once per Task, must be overridden.
462      * Any arguments passed to the last Task's onTaskDone, or to run (If the
463      * first task) will be passed along.
464      */
465     start: function() {
466       assertNotReached('Start function not overridden.');
467     },
468
469     /**
470      * Updates value of |completeAsync_|.  If set to true, the next Task will
471      * start asynchronously.  Useful if the Task completes on an event that
472      * the next Task may care about.
473      */
474     setCompleteAsync: function(value) {
475       this.completeAsync_ = value;
476     },
477
478     /**
479      * @return {bool} True if this task has completed by calling onTaskDone.
480      */
481     isDone: function() {
482       return this.isDone_;
483     },
484
485     /**
486      * Sets the TaskQueue used by the task in the onTaskDone function.  May only
487      * be called by the TaskQueue.
488      * @param {TaskQueue}: taskQueue The TaskQueue |this| has been added to.
489      */
490     setTaskQueue_: function(taskQueue) {
491       assertEquals(null, this.taskQueue_);
492       this.taskQueue_ = taskQueue;
493     },
494
495     /**
496      * Must be called when a task is complete, and can only be called once for a
497      * task.  Runs the next task, if any, passing along all arguments.
498      */
499     onTaskDone: function() {
500       assertFalse(this.isDone_);
501       this.isDone_ = true;
502
503       // Function to run the next task in the queue.
504       var runNextTask = this.taskQueue_.runNextTask_.bind(
505                             this.taskQueue_,
506                             Array.prototype.slice.call(arguments));
507
508       // If we need to start the next task asynchronously, we need to wrap
509       // it with the test framework code.
510       if (this.completeAsync_) {
511         window.setTimeout(activeTest_.continueTest(WhenTestDone.EXPECT,
512                                                    runNextTask),
513                           0);
514         return;
515       }
516
517       // Otherwise, just run the next task directly.
518       runNextTask();
519     },
520   };
521
522   /**
523    * A Task that can be added to a TaskQueue.  A Task is started with a call to
524    * the start function, and must call its own onTaskDone when complete.
525    * @extends {NetInternalsTest.Task}
526    * @constructor
527    */
528   NetInternalsTest.CallFunctionTask = function(taskFunction) {
529     NetInternalsTest.Task.call(this);
530     assertEquals('function', typeof taskFunction);
531     this.taskFunction_ = taskFunction;
532   };
533
534   NetInternalsTest.CallFunctionTask.prototype = {
535     __proto__: NetInternalsTest.Task.prototype,
536
537     /**
538      * Runs the function and then completes.  Passes all arguments, if any,
539      * along to the function.
540      */
541     start: function() {
542       this.taskFunction_.apply(null, Array.prototype.slice.call(arguments));
543       this.onTaskDone();
544     }
545   };
546
547   /**
548    * A Task that converts the given path into a URL served by the TestServer.
549    * The resulting URL will be passed to the next task.  Will also start the
550    * TestServer, if needed.
551    * @param {string} path Path to convert to a URL.
552    * @extends {NetInternalsTest.Task}
553    * @constructor
554    */
555   NetInternalsTest.GetTestServerURLTask = function(path) {
556     NetInternalsTest.Task.call(this);
557     assertEquals('string', typeof path);
558     this.path_ = path;
559   };
560
561   NetInternalsTest.GetTestServerURLTask.prototype = {
562     __proto__: NetInternalsTest.Task.prototype,
563
564     /**
565      * Sets |NetInternals.callback|, and sends the path to the browser process.
566      */
567     start: function() {
568       NetInternalsTest.setCallback(this.onURLReceived_.bind(this));
569       chrome.send('getTestServerURL', [this.path_]);
570     },
571
572     /**
573      * Completes the Task, passing the url on to the next Task.
574      * @param {string} url TestServer URL of the input path.
575      */
576     onURLReceived_: function(url) {
577       assertEquals('string', typeof url);
578       this.onTaskDone(url);
579     }
580   };
581
582   /**
583    * A Task that creates an incognito window and only completes once it has
584    * navigated to about:blank.  The waiting is required to avoid reentrancy
585    * issues, since the function to create the incognito browser also waits
586    * for the navigation to complete.  May not be called if there's already an
587    * incognito browser in existence.
588    * @extends {NetInternalsTest.Task}
589    * @constructor
590    */
591   NetInternalsTest.CreateIncognitoBrowserTask = function() {
592     NetInternalsTest.Task.call(this);
593   };
594
595   NetInternalsTest.CreateIncognitoBrowserTask.prototype = {
596     __proto__: NetInternalsTest.Task.prototype,
597
598     /**
599      * Tells the browser process to create an incognito browser, and sets
600      * up a callback to be called on completion.
601      */
602     start: function() {
603       // Reuse the BrowserBridge's callback mechanism, since it's already
604       // wrapped in our test harness.
605       assertEquals('undefined',
606                    typeof g_browser.onIncognitoBrowserCreatedForTest);
607       g_browser.onIncognitoBrowserCreatedForTest =
608           this.onIncognitoBrowserCreatedForTest.bind(this);
609
610       chrome.send('createIncognitoBrowser');
611     },
612
613     /**
614      * Deletes the callback function, and completes the task.
615      */
616     onIncognitoBrowserCreatedForTest: function() {
617       delete g_browser.onIncognitoBrowserCreatedForTest;
618       this.onTaskDone();
619     }
620   };
621
622   /**
623    * Returns a task that closes an incognito window created with the task
624    * above.  May only be called if there's an incognito window created by
625    * the above function that has yet to be closed.  Returns immediately.
626    * @return {Task} Task that closes incognito browser window.
627    */
628   NetInternalsTest.getCloseIncognitoBrowserTask = function() {
629     return new NetInternalsTest.CallFunctionTask(
630         function() {
631           chrome.send('closeIncognitoBrowser');
632         });
633   };
634
635   /**
636    * Returns true if a node does not have a 'display' property of 'none'.
637    * @param {node}: node The node to check.
638    */
639   NetInternalsTest.isDisplayed = function(node) {
640     var style = getComputedStyle(node);
641     return style.getPropertyValue('display') != 'none';
642   };
643
644   /**
645    * Creates a new NetLog source.  Note that the id may conflict with events
646    * received from the browser.
647    * @param {int}: type The source type.
648    * @param {int}: id The source id.
649    * @constructor
650    */
651   NetInternalsTest.Source = function(type, id) {
652     assertNotEquals(getKeyWithValue(EventSourceType, type), '?');
653     assertGE(id, 0);
654     this.type = type;
655     this.id = id;
656   };
657
658   /**
659    * Creates a new NetLog event.
660    * @param {Source}: source The source associated with the event.
661    * @param {int}: type The event id.
662    * @param {int}: time When the event occurred.
663    * @param {int}: phase The event phase.
664    * @param {object}: params The event parameters.  May be null.
665    * @constructor
666    */
667   NetInternalsTest.Event = function(source, type, time, phase, params) {
668     assertNotEquals(getKeyWithValue(EventType, type), '?');
669     assertNotEquals(getKeyWithValue(EventPhase, phase), '?');
670
671     this.source = source;
672     this.phase = phase;
673     this.type = type;
674     this.time = '' + time;
675     this.phase = phase;
676     if (params)
677       this.params = params;
678   };
679
680   /**
681    * Creates a new NetLog begin event.  Parameters are the same as Event,
682    * except there's no |phase| argument.
683    * @see Event
684    */
685   NetInternalsTest.createBeginEvent = function(source, type, time, params) {
686     return new NetInternalsTest.Event(source, type, time,
687                                       EventPhase.PHASE_BEGIN, params);
688   };
689
690   /**
691    * Creates a new NetLog end event.  Parameters are the same as Event,
692    * except there's no |phase| argument.
693    * @see Event
694    */
695   NetInternalsTest.createEndEvent = function(source, type, time, params) {
696     return new NetInternalsTest.Event(source, type, time,
697                                       EventPhase.PHASE_END, params);
698   };
699
700   /**
701    * Creates a new NetLog end event matching the given begin event.
702    * @param {Event}: beginEvent The begin event.  Returned event will have the
703    *                 same source and type.
704    * @param {int}: time When the event occurred.
705    * @param {object}: params The event parameters.  May be null.
706    * @see Event
707    */
708   NetInternalsTest.createMatchingEndEvent = function(beginEvent, time, params) {
709     return NetInternalsTest.createEndEvent(
710                beginEvent.source, beginEvent.type, time, params);
711   };
712
713   /**
714    * Checks that only the given status view node is visible.
715    * @param {string}: nodeId ID of the node that should be visible.
716    */
717   NetInternalsTest.expectStatusViewNodeVisible = function(nodeId) {
718     var allIds = [
719       CaptureStatusView.MAIN_BOX_ID,
720       LoadedStatusView.MAIN_BOX_ID,
721       HaltedStatusView.MAIN_BOX_ID
722     ];
723
724     for (var i = 0; i < allIds.length; ++i) {
725       var curId = allIds[i];
726       expectEquals(nodeId == curId, NetInternalsTest.nodeIsVisible($(curId)));
727     }
728   };
729
730   return NetInternalsTest;
731 })();