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