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 // Include test fixture.
6 GEN_INCLUDE(['net_internals_test.js']);
11 // @return {Array<object>} List of events for an abbreviated URL request.
12 function urlRequestEvents(id) {
15 'phase': EventPhase.PHASE_BEGIN,
18 'type': EventSourceType.URL_REQUEST
21 'type': EventType.REQUEST_ALIVE
25 'load_flags': 68223104,
28 'url': 'http://www.google.com/'
30 'phase': EventPhase.PHASE_BEGIN,
33 'type': EventSourceType.URL_REQUEST
36 'type': EventType.URL_REQUEST_START_JOB
39 'phase': EventPhase.PHASE_END,
42 'type': EventSourceType.URL_REQUEST
45 'type': EventType.URL_REQUEST_START_JOB
48 'phase': EventPhase.PHASE_BEGIN,
51 'type': EventSourceType.URL_REQUEST
54 'type': EventType.HTTP_TRANSACTION_SEND_REQUEST
59 'Host: www.google.com',
60 'Connection: keep-alive',
61 'User-Agent: Mozilla/5.0',
63 'Accept-Encoding: gzip,deflate,sdch',
64 'Accept-Language: en-US,en;q=0.8',
65 'Accept-Charset: ISO-8859-1',
66 'X-Random-Header-With-Quotes: "Quoted String"""',
68 'line': 'GET / HTTP/1.1\r\n'
70 'phase': EventPhase.PHASE_NONE,
73 'type': EventSourceType.URL_REQUEST
76 'type': EventType.HTTP_TRANSACTION_SEND_REQUEST_HEADERS
79 'phase': EventPhase.PHASE_END,
82 'type': EventSourceType.URL_REQUEST
85 'type': EventType.HTTP_TRANSACTION_SEND_REQUEST
88 'phase': EventPhase.PHASE_END,
91 'type': EventSourceType.URL_REQUEST
94 'type': EventType.REQUEST_ALIVE
100 * Tests the filters, both in terms of filtering correctly and UI.
102 TEST_F('NetInternalsTest', 'netInternalsEventsViewFilter', function() {
103 // Sets the filter and checks the results.
104 // @param {string} filter Filter to use.
105 // @param {Array<boolean>} matches Ordered list of whether or not each source
106 // matches |filter|. Order must match display order after applying the
108 function checkFilter(filter, matches) {
109 EventsView.getInstance().setFilterText_(filter);
112 for (var i = 0; i < matches.length; ++i) {
117 // Updating the display is normally done asynchronously, so have to manually
118 // call update function to check displayed event count.
119 EventsView.getInstance().repaintFilterCounter_();
121 expectEquals(postFilter + ' of ' + matches.length,
122 $(EventsView.FILTER_COUNT_ID).innerText,
125 var tbody = $(EventsView.TBODY_ID);
126 assertEquals(matches.length, tbody.childElementCount, filter);
128 var visibleCount = 0;
129 for (var i = 0; i < tbody.childElementCount; ++i) {
130 expectEquals(matches[i],
131 NetInternalsTest.nodeIsVisible(tbody.children[i]),
136 EventsTracker.getInstance().deleteAllLogEntries();
137 checkFilter('', [], 0);
139 // A completed request.
140 g_browser.receivedLogEntries(urlRequestEvents(31));
141 checkFilter('', [true], 1);
143 // An incomplete request.
144 g_browser.receivedLogEntries(urlRequestEvents(56).slice(0, 3));
145 checkFilter('', [true, true], 2);
147 // Filters used alone and in all combinations.
148 // |text| is the string to add to the filter.
149 // |matches| is a 2-element array of booleans indicating which of the two
150 // requests passes the filter.
152 {text: 'http://www.google.com', matches: [true, true] },
153 {text: 'MyMagicPony', matches: [false, false] },
154 {text: 'type:URL_REQUEST', matches: [true, true] },
155 {text: 'type:SOCKET,URL_REQUEST', matches: [true, true] },
156 {text: 'type:SOCKET', matches: [false, false] },
157 {text: '-type:PONY', matches: [true, true] },
158 {text: '-type:URL_REQUEST', matches: [false, false] },
159 {text: 'id:31,32', matches: [true, false] },
160 {text: '-id:31,32', matches: [false, true] },
161 {text: 'id:32,56,', matches: [false, true] },
162 {text: '-is:active', matches: [true, false] },
163 {text: 'is:active', matches: [false, true] },
164 {text: '-is:error', matches: [true, true] },
165 {text: 'is:error', matches: [false, false] },
166 // Partial match of source type.
167 {text: 'URL_REQ', matches: [true, true] },
168 // Partial match of event type type.
169 {text: 'SEND_REQUEST', matches: [true, false] },
170 // Check that ":" works in strings.
171 { text: 'Host:', matches: [true, false] },
172 { text: '::', matches: [false, false] },
174 { text: '"Quoted String"', matches: [true, false] },
175 { text: '"Quoted source"', matches: [false, false] },
176 { text: '"\\"Quoted String\\""', matches: [true, false] },
177 { text: '"\\"\\"Quoted String\\""', matches: [false, false] },
178 { text: '\\"\\"\\"', matches: [true, false] },
179 { text: '\\"\\"\\"\\"', matches: [false, false] },
180 { text: '"Host: www.google.com"', matches: [true, false], },
181 { text: 'Connection:" keep-alive"', matches: [true, false], },
182 { text: '-Connection:" keep-alive"', matches: [false, true], },
183 { text: '"Host: GET"', matches: [false, false] },
184 // Make sure sorting has no effect on filters. Sort by ID so order is
186 { text: 'sort:"id"', matches: [true, true] },
187 { text: '-sort:"shoe size"', matches: [true, true] },
188 { text: '"-sort:shoe size"', matches: [false, false] },
191 for (var filter1 = 0; filter1 < testFilters.length; ++filter1) {
192 checkFilter(testFilters[filter1].text, testFilters[filter1].matches);
193 // Check |filter1| in combination with all the other filters.
194 for (var filter2 = 0; filter2 < testFilters.length; ++filter2) {
196 for (var i = 0; i < testFilters[filter1].matches.length; ++i) {
197 // The merged filter matches an entry if both individual filters do.
198 matches[i] = testFilters[filter1].matches[i] &&
199 testFilters[filter2].matches[i];
202 checkFilter(testFilters[filter1].text + ' ' + testFilters[filter2].text,
208 // Tests with unmatched quotes. Unlike the strings above, combining them with
209 // other filters is not the same as applying both filters independently.
210 checkFilter('"Quoted String', [true, false]);
211 checkFilter('"Quoted String source', [false, false]);
212 checkFilter('Quoted" String', [true, false]);
213 checkFilter('Quoted" source', [false, false]);
214 checkFilter('Quoted "String', [true, false]);
216 // Test toggling sort method, without any filters.
217 var eventsView = EventsView.getInstance();
218 eventsView.setFilterText_('');
219 $(EventsView.SORT_BY_DESCRIPTION_ID).click();
220 expectEquals('sort:desc', eventsView.getFilterText_());
221 $(EventsView.SORT_BY_DESCRIPTION_ID).click();
222 expectEquals('-sort:desc', eventsView.getFilterText_());
223 $(EventsView.SORT_BY_ID_ID).click();
224 expectEquals('sort:id', eventsView.getFilterText_());
226 // Sort by default is by ID, so toggling ID when there's no filter results in
228 eventsView.setFilterText_('');
229 $(EventsView.SORT_BY_ID_ID).click();
230 expectEquals('-sort:id', eventsView.getFilterText_());
231 $(EventsView.SORT_BY_ID_ID).click();
232 expectEquals('sort:id', eventsView.getFilterText_());
234 // Test toggling sort method with filters.
235 eventsView.setFilterText_('text');
236 $(EventsView.SORT_BY_ID_ID).click();
237 expectEquals('-sort:id text', eventsView.getFilterText_());
238 $(EventsView.SORT_BY_ID_ID).click();
239 expectEquals('sort:id text', eventsView.getFilterText_());
240 $(EventsView.SORT_BY_SOURCE_TYPE_ID).click();
241 expectEquals('sort:source text', eventsView.getFilterText_());
242 eventsView.setFilterText_('text sort:id "more text"');
243 $(EventsView.SORT_BY_ID_ID).click();
244 expectEquals('-sort:id text "more text"', eventsView.getFilterText_());
249 })(); // Anonymous namespace