OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview using private properties isn't a Closure violation in tests. | 6 * @fileoverview using private properties isn't a Closure violation in tests. |
7 * @suppress {accessControls} | 7 * @suppress {accessControls} |
8 */ | 8 */ |
9 | 9 |
10 /** @typedef {function(!Element, !ConsoleModel.ConsoleMessage=):string} */ | |
11 ConsoleTestRunner.Formatter; | |
12 | |
10 /** | 13 /** |
11 * @param {boolean} printOriginatingCommand | 14 * @param {boolean=} printOriginatingCommand |
12 * @param {boolean} dumpClassNames | 15 * @param {boolean=} dumpClassNames |
13 * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter | 16 * @param {!ConsoleTestRunner.Formatter=} formatter |
14 */ | 17 */ |
15 ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpCl assNames, formatter) { | 18 ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpCl assNames, formatter) { |
16 TestRunner.addResults( | 19 TestRunner.addResults( |
17 ConsoleTestRunner.dumpConsoleMessagesIntoArray(printOriginatingCommand, du mpClassNames, formatter)); | 20 ConsoleTestRunner.dumpConsoleMessagesIntoArray(printOriginatingCommand, du mpClassNames, formatter)); |
18 }; | 21 }; |
19 | 22 |
20 /** | 23 /** |
21 * @param {boolean} printOriginatingCommand | 24 * @param {boolean=} printOriginatingCommand |
22 * @param {boolean} dumpClassNames | 25 * @param {boolean=} dumpClassNames |
23 * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter | 26 * @param {!ConsoleTestRunner.Formatter=} formatter |
24 * @return {!Array<string>} | 27 * @return {!Array<string>} |
25 */ | 28 */ |
26 ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman d, dumpClassNames, formatter) { | 29 ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman d, dumpClassNames, formatter) { |
27 formatter = formatter || ConsoleTestRunner.prepareConsoleMessageText; | 30 formatter = formatter || ConsoleTestRunner.prepareConsoleMessageText; |
28 var result = []; | 31 var result = []; |
29 ConsoleTestRunner.disableConsoleViewport(); | 32 ConsoleTestRunner.disableConsoleViewport(); |
30 var consoleView = Console.ConsoleView.instance(); | 33 var consoleView = Console.ConsoleView.instance(); |
31 if (consoleView._needsFullUpdate) | 34 if (consoleView._needsFullUpdate) |
32 consoleView._updateMessageList(); | 35 consoleView._updateMessageList(); |
33 var viewMessages = consoleView._visibleViewMessages; | 36 var viewMessages = consoleView._visibleViewMessages; |
(...skipping 23 matching lines...) Expand all Loading... | |
57 } | 60 } |
58 | 61 |
59 if (printOriginatingCommand && uiMessage.consoleMessage().originatingMessage ()) | 62 if (printOriginatingCommand && uiMessage.consoleMessage().originatingMessage ()) |
60 result.push('Originating from: ' + uiMessage.consoleMessage().originatingM essage().messageText); | 63 result.push('Originating from: ' + uiMessage.consoleMessage().originatingM essage().messageText); |
61 } | 64 } |
62 return result; | 65 return result; |
63 }; | 66 }; |
64 | 67 |
65 /** | 68 /** |
66 * @param {!Element} messageElement | 69 * @param {!Element} messageElement |
67 * @param {!ConsoleModel.ConsoleMessage} consoleMessage | |
68 * @return {string} | 70 * @return {string} |
69 */ | 71 */ |
70 ConsoleTestRunner.prepareConsoleMessageText = function(messageElement, consoleMe ssage) { | 72 ConsoleTestRunner.prepareConsoleMessageText = function(messageElement) { |
71 var messageText = messageElement.deepTextContent().replace(/\u200b/g, ''); | 73 var messageText = messageElement.deepTextContent().replace(/\u200b/g, ''); |
72 // Replace scriptIds with generic scriptId string to avoid flakiness. | 74 // Replace scriptIds with generic scriptId string to avoid flakiness. |
73 messageText = messageText.replace(/VM\d+/g, 'VM'); | 75 messageText = messageText.replace(/VM\d+/g, 'VM'); |
74 // Remove line and column of evaluate method. | 76 // Remove line and column of evaluate method. |
75 messageText = messageText.replace(/(at eval \(eval at evaluate) \(:\d+:\d+\)/, '$1'); | 77 messageText = messageText.replace(/(at eval \(eval at evaluate) \(:\d+:\d+\)/, '$1'); |
76 | 78 |
77 if (messageText.startsWith('Navigated to')) { | 79 if (messageText.startsWith('Navigated to')) { |
78 var fileName = messageText.split(' ').pop().split('/').pop(); | 80 var fileName = messageText.split(' ').pop().split('/').pop(); |
79 messageText = 'Navigated to ' + fileName; | 81 messageText = 'Navigated to ' + fileName; |
80 } | 82 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 /** | 138 /** |
137 * @param {number} width | 139 * @param {number} width |
138 * @param {number} height | 140 * @param {number} height |
139 */ | 141 */ |
140 ConsoleTestRunner.fixConsoleViewportDimensions = function(width, height) { | 142 ConsoleTestRunner.fixConsoleViewportDimensions = function(width, height) { |
141 var viewport = Console.ConsoleView.instance()._viewport; | 143 var viewport = Console.ConsoleView.instance()._viewport; |
142 viewport.element.style.width = width + 'px'; | 144 viewport.element.style.width = width + 'px'; |
143 viewport.element.style.height = height + 'px'; | 145 viewport.element.style.height = height + 'px'; |
144 viewport.element.style.position = 'absolute'; | 146 viewport.element.style.position = 'absolute'; |
145 viewport.invalidate(); | 147 viewport.invalidate(); |
146 }; | 148 }; |
149 | |
150 ConsoleTestRunner.selectMainExecutionContext = function() { | |
151 var executionContexts = TestRunner.runtimeModel.executionContexts(); | |
152 for (var context of executionContexts) { | |
153 if (context.isDefault) { | |
154 UI.context.setFlavor(SDK.ExecutionContext, context); | |
155 return; | |
156 } | |
157 } | |
158 }; | |
159 | |
160 /** | |
161 * @param {string} code | |
162 * @param {!Function=} callback | |
163 * @param {boolean=} dontForceMainContext | |
164 */ | |
165 ConsoleTestRunner.evaluateInConsole = function(code, callback, dontForceMainCont ext) { | |
166 if (!dontForceMainContext) | |
167 ConsoleTestRunner.selectMainExecutionContext(); | |
168 callback = TestRunner.safeWrap(callback); | |
169 | |
170 var consoleView = Console.ConsoleView.instance(); | |
171 consoleView._prompt._appendCommand(code, true); | |
172 ConsoleTestRunner.addConsoleViewSniffer(function(commandResult) { | |
173 callback(commandResult.toMessageElement().deepTextContent()); | |
174 }); | |
175 }; | |
176 | |
177 /** | |
178 * @param {!Function} override | |
179 * @param {boolean=} opt_sticky | |
180 */ | |
181 ConsoleTestRunner.addConsoleViewSniffer = function(override, opt_sticky) { | |
182 var sniffer = function(viewMessage) { | |
caseq
2017/07/12 01:04:33
why not just pass override directly? Also, perhaps
chenwilliam
2017/07/12 22:02:58
I passed the override directly.
See earlier comme
| |
183 override(viewMessage); | |
184 }; | |
185 | |
186 TestRunner.addSniffer(Console.ConsoleView.prototype, '_consoleMessageAddedForT est', sniffer, opt_sticky); | |
187 }; | |
188 | |
189 /** | |
190 * @param {string} code | |
191 * @param {!Function=} callback | |
192 * @param {boolean=} dontForceMainContext | |
193 */ | |
194 ConsoleTestRunner.evaluateInConsoleAndDump = function(code, callback, dontForceM ainContext) { | |
195 callback = TestRunner.safeWrap(callback); | |
caseq
2017/07/12 01:04:33
No need for this, you already wrap in evalueteInCo
chenwilliam
2017/07/12 22:02:58
Done.
| |
196 | |
197 /** | |
198 * @param {string} text | |
199 */ | |
200 function mycallback(text) { | |
201 text = text.replace(/\bVM\d+/g, 'VM'); | |
202 TestRunner.addResult(code + ' = ' + text); | |
203 callback(text); | |
204 } | |
205 ConsoleTestRunner.evaluateInConsole(code, mycallback, dontForceMainContext); | |
206 }; | |
207 | |
208 /** | |
209 * @return {number} | |
210 */ | |
211 ConsoleTestRunner.consoleMessagesCount = function() { | |
212 var consoleView = Console.ConsoleView.instance(); | |
213 return consoleView._consoleMessages.length; | |
214 }; | |
215 | |
216 /** | |
217 * @param {function(!Element):string} messageFormatter | |
218 * @param {!Element} node | |
219 * @return {string} | |
220 */ | |
221 ConsoleTestRunner.formatterIgnoreStackFrameUrls = function(messageFormatter, nod e) { | |
222 /** | |
223 * @param {string} string | |
224 */ | |
225 function isNotEmptyLine(string) { | |
226 return string.trim().length > 0; | |
227 } | |
228 | |
229 /** | |
230 * @param {string} string | |
231 */ | |
232 function ignoreStackFrameAndMutableData(string) { | |
233 var buffer = string.replace(/\u200b/g, ''); | |
234 buffer = buffer.replace(/VM\d+/g, 'VM'); | |
235 return buffer.replace(/^\s+at [^\]]+(]?)$/, '$1'); | |
236 } | |
237 | |
238 messageFormatter = messageFormatter || TestRunner.textContentWithLineBreaks; | |
239 var buffer = messageFormatter(node); | |
240 return buffer.split('\n').map(ignoreStackFrameAndMutableData).filter(isNotEmpt yLine).join('\n'); | |
241 }; | |
242 | |
243 /** | |
244 * @param {!Element} element | |
245 * @param {!ConsoleModel.ConsoleMessage} message | |
246 * @return {string} | |
247 */ | |
248 ConsoleTestRunner.simpleFormatter = function(element, message) { | |
249 return message.messageText + ':' + message.line + ':' + message.column; | |
250 }; | |
251 | |
252 /** | |
253 * @param {boolean=} printOriginatingCommand | |
254 * @param {boolean=} dumpClassNames | |
255 * @param {!ConsoleTestRunner.Formatter=} messageFormatter | |
256 */ | |
257 ConsoleTestRunner.dumpConsoleMessagesIgnoreErrorStackFrames = function( | |
258 printOriginatingCommand, dumpClassNames, messageFormatter) { | |
259 TestRunner.addResults(ConsoleTestRunner.dumpConsoleMessagesIntoArray( | |
260 printOriginatingCommand, dumpClassNames, | |
261 messageFormatter ? ConsoleTestRunner.formatterIgnoreStackFrameUrls.bind(th is, messageFormatter) : undefined)); | |
262 }; | |
263 | |
264 ConsoleTestRunner.dumpConsoleMessagesWithStyles = function() { | |
265 var messageViews = Console.ConsoleView.instance()._visibleViewMessages; | |
266 for (var i = 0; i < messageViews.length; ++i) { | |
267 var element = messageViews[i].element(); | |
268 var messageText = ConsoleTestRunner.prepareConsoleMessageText(element); | |
269 TestRunner.addResult(messageText); | |
270 var spans = element.querySelectorAll('.console-message-text *'); | |
271 for (var j = 0; j < spans.length; ++j) | |
272 TestRunner.addResult('Styled text #' + j + ': ' + (spans[j].style.cssText || 'NO STYLES DEFINED')); | |
273 } | |
274 }; | |
275 | |
276 /** | |
277 * @param {boolean=} sortMessages | |
278 */ | |
279 ConsoleTestRunner.dumpConsoleMessagesWithClasses = function(sortMessages) { | |
280 var result = []; | |
281 var messageViews = Console.ConsoleView.instance()._visibleViewMessages; | |
282 for (var i = 0; i < messageViews.length; ++i) { | |
283 var element = messageViews[i].element(); | |
284 var contentElement = messageViews[i].contentElement(); | |
285 var messageText = ConsoleTestRunner.prepareConsoleMessageText(element); | |
286 result.push(messageText + ' ' + element.getAttribute('class') + ' > ' + cont entElement.getAttribute('class')); | |
287 } | |
288 if (sortMessages) | |
289 result.sort(); | |
290 for (var i = 0; i < result.length; ++i) | |
291 TestRunner.addResult(result[i]); | |
caseq
2017/07/12 01:04:33
just TestRunner.addResults(result)?
chenwilliam
2017/07/12 22:02:58
Done.
| |
292 }; | |
293 | |
294 ConsoleTestRunner.dumpConsoleClassesBrief = function() { | |
295 var messageViews = Console.ConsoleView.instance()._visibleViewMessages; | |
296 for (var i = 0; i < messageViews.length; ++i) | |
297 TestRunner.addResult(messageViews[i].toMessageElement().className); | |
298 }; | |
299 | |
300 ConsoleTestRunner.dumpConsoleCounters = function() { | |
301 var counter = Counters.WarningErrorCounter._instanceForTest; | |
302 for (var index = 0; index < counter._titles.length; ++index) | |
303 TestRunner.addResult(counter._titles[index]); | |
304 ConsoleTestRunner.dumpConsoleClassesBrief(); | |
305 }; | |
306 | |
307 /** | |
308 * @param {!Function} callback | |
309 * @param {function(!Element):boolean} deepFilter | |
310 * @param {function(!ObjectUI.ObjectPropertiesSection):boolean} sectionFilter | |
311 */ | |
312 ConsoleTestRunner.expandConsoleMessages = function(callback, deepFilter, section Filter) { | |
caseq
2017/07/12 01:04:33
Let's switch all these to promises!
chenwilliam
2017/07/12 22:02:58
See earlier comment about promisifying the API.
| |
313 Console.ConsoleView.instance()._invalidateViewport(); | |
314 var messageViews = Console.ConsoleView.instance()._visibleViewMessages; | |
315 | |
316 // Initiate round-trips to fetch necessary data for further rendering. | |
317 for (var i = 0; i < messageViews.length; ++i) | |
318 messageViews[i].element(); | |
319 | |
320 TestRunner.deprecatedRunAfterPendingDispatches(expandTreeElements); | |
321 | |
322 function expandTreeElements() { | |
323 for (var i = 0; i < messageViews.length; ++i) { | |
324 var element = messageViews[i].element(); | |
325 for (var node = element; node; node = node.traverseNextNode(element)) { | |
326 if (node.treeElementForTest) | |
327 node.treeElementForTest.expand(); | |
328 if (node._expandStackTraceForTest) | |
329 node._expandStackTraceForTest(); | |
330 if (!node._section) | |
331 continue; | |
332 if (sectionFilter && !sectionFilter(node._section)) | |
333 continue; | |
334 node._section.expand(); | |
335 | |
336 if (!deepFilter) | |
337 continue; | |
338 var treeElements = node._section.rootElement().children(); | |
339 for (var j = 0; j < treeElements.length; ++j) { | |
340 for (var treeElement = treeElements[j]; treeElement; | |
341 treeElement = treeElement.traverseNextTreeElement(true, null, tru e)) { | |
342 if (deepFilter(treeElement)) | |
343 treeElement.expand(); | |
344 } | |
345 } | |
346 } | |
347 } | |
348 TestRunner.deprecatedRunAfterPendingDispatches(callback); | |
349 } | |
350 }; | |
351 | |
352 /** | |
353 * @param {!Function} callback | |
354 */ | |
355 ConsoleTestRunner.expandGettersInConsoleMessages = function(callback) { | |
356 var messageViews = Console.ConsoleView.instance()._visibleViewMessages; | |
357 var properties = []; | |
358 var propertiesCount = 0; | |
359 TestRunner.addSniffer(ObjectUI.ObjectPropertyTreeElement.prototype, '_updateEx pandable', propertyExpandableUpdated); | |
360 for (var i = 0; i < messageViews.length; ++i) { | |
361 var element = messageViews[i].element(); | |
362 for (var node = element; node; node = node.traverseNextNode(element)) { | |
363 if (node.classList && node.classList.contains('object-value-calculate-valu e-button')) { | |
364 ++propertiesCount; | |
365 node.click(); | |
366 properties.push(node.parentElement.parentElement); | |
367 } | |
368 } | |
369 } | |
370 | |
371 function propertyExpandableUpdated() { | |
372 --propertiesCount; | |
373 if (propertiesCount === 0) { | |
374 for (var i = 0; i < properties.length; ++i) | |
375 properties[i].click(); | |
376 TestRunner.deprecatedRunAfterPendingDispatches(callback); | |
377 } else { | |
378 TestRunner.addSniffer( | |
379 ObjectUI.ObjectPropertyTreeElement.prototype, '_updateExpandable', pro pertyExpandableUpdated); | |
380 } | |
381 } | |
382 }; | |
383 | |
384 /** | |
385 * @param {!Function} callback | |
386 */ | |
387 ConsoleTestRunner.expandConsoleMessagesErrorParameters = function(callback) { | |
388 var messageViews = Console.ConsoleView.instance()._visibleViewMessages; | |
389 // Initiate round-trips to fetch necessary data for further rendering. | |
390 for (var i = 0; i < messageViews.length; ++i) | |
391 messageViews[i].element(); | |
392 TestRunner.deprecatedRunAfterPendingDispatches(callback); | |
393 }; | |
394 | |
395 /** | |
396 * @param {!Function} callback | |
397 */ | |
398 ConsoleTestRunner.waitForRemoteObjectsConsoleMessages = function(callback) { | |
399 var messages = Console.ConsoleView.instance()._visibleViewMessages; | |
400 for (var i = 0; i < messages.length; ++i) | |
401 messages[i].toMessageElement(); | |
402 TestRunner.deprecatedRunAfterPendingDispatches(callback); | |
403 }; | |
404 | |
405 /** | |
406 * @return {!Promise} | |
407 */ | |
408 ConsoleTestRunner.waitUntilConsoleEditorLoaded = function() { | |
409 var fulfill; | |
410 var promise = new Promise(x => (fulfill = x)); | |
411 var editor = Console.ConsoleView.instance()._prompt._editor; | |
412 if (editor) | |
413 fulfill(editor); | |
414 else | |
415 TestRunner.addSniffer(Console.ConsolePrompt.prototype, '_editorSetForTest', _ => fulfill(editor)); | |
416 return promise; | |
417 }; | |
418 | |
419 /** | |
420 * @param {!Function} callback | |
421 */ | |
422 ConsoleTestRunner.waitUntilMessageReceived = function(callback) { | |
423 TestRunner.addSniffer(ConsoleModel.consoleModel, 'addMessage', callback, false ); | |
424 }; | |
425 | |
426 /** | |
427 * @return {!Promise} | |
428 */ | |
429 ConsoleTestRunner.waitUntilMessageReceivedPromise = function() { | |
430 var callback; | |
431 var promise = new Promise(fullfill => (callback = fullfill)); | |
432 ConsoleTestRunner.waitUntilMessageReceived(callback); | |
433 return promise; | |
434 }; | |
435 | |
436 /** | |
437 * @param {number} count | |
438 * @param {!Function} callback | |
439 */ | |
440 ConsoleTestRunner.waitUntilNthMessageReceived = function(count, callback) { | |
441 function override() { | |
442 if (--count === 0) | |
443 TestRunner.safeWrap(callback)(); | |
444 else | |
445 TestRunner.addSniffer(ConsoleModel.consoleModel, 'addMessage', override, f alse); | |
446 } | |
447 TestRunner.addSniffer(ConsoleModel.consoleModel, 'addMessage', override, false ); | |
448 }; | |
449 | |
450 /** | |
451 * @param {number} count | |
452 * @return {!Promise} | |
453 */ | |
454 ConsoleTestRunner.waitUntilNthMessageReceivedPromise = function(count) { | |
455 var callback; | |
456 var promise = new Promise(fullfill => (callback = fullfill)); | |
457 ConsoleTestRunner.waitUntilNthMessageReceived(count, callback); | |
458 return promise; | |
459 }; | |
460 | |
461 /** | |
462 * @param {string} namePrefix | |
463 */ | |
464 ConsoleTestRunner.changeExecutionContext = function(namePrefix) { | |
465 var selector = Console.ConsoleView.instance()._consoleContextSelector; | |
466 for (var executionContext of selector._items) { | |
467 if (selector.titleFor(executionContext).startsWith(namePrefix)) { | |
468 UI.context.setFlavor(SDK.ExecutionContext, executionContext); | |
469 return; | |
470 } | |
471 } | |
472 TestRunner.addResult('FAILED: context with prefix: ' + namePrefix + ' not foun d in the context list'); | |
473 }; | |
474 | |
475 /** | |
476 * @param {number} expectedCount | |
477 * @param {!Function} callback | |
478 */ | |
479 ConsoleTestRunner.waitForConsoleMessages = function(expectedCount, callback) { | |
480 var consoleView = Console.ConsoleView.instance(); | |
481 checkAndReturn(); | |
482 | |
483 function checkAndReturn() { | |
484 if (consoleView._visibleViewMessages.length === expectedCount) { | |
485 TestRunner.addResult('Message count: ' + expectedCount); | |
486 callback(); | |
487 } else { | |
488 TestRunner.addSniffer(consoleView, '_messageAppendedForTests', checkAndRet urn); | |
489 } | |
490 } | |
491 }; | |
492 | |
493 /** | |
494 * @param {number} fromMessage | |
495 * @param {number} fromTextOffset | |
496 * @param {number} toMessage | |
497 * @param {number} toTextOffset | |
498 * @suppressGlobalPropertiesCheck | |
499 */ | |
500 ConsoleTestRunner.selectConsoleMessages = function(fromMessage, fromTextOffset, toMessage, toTextOffset) { | |
501 var consoleView = Console.ConsoleView.instance(); | |
502 var from = selectionContainerAndOffset(consoleView.itemElement(fromMessage).el ement(), fromTextOffset); | |
503 var to = selectionContainerAndOffset(consoleView.itemElement(toMessage).elemen t(), toTextOffset); | |
504 window.getSelection().setBaseAndExtent(from.container, from.offset, to.contain er, to.offset); | |
505 | |
506 /** | |
507 * @param {!Node} container | |
508 * @param {number} offset | |
509 * @return {?{container: !Node, offset: number}} | |
510 */ | |
511 function selectionContainerAndOffset(container, offset) { | |
512 /** @type {?Node} */ | |
513 var node = container; | |
514 if (offset === 0 && container.nodeType !== Node.TEXT_NODE) { | |
515 container = /** @type {!Node} */ (container.traverseNextTextNode()); | |
516 node = container; | |
517 } | |
518 var charCount = 0; | |
519 while ((node = node.traverseNextTextNode(container))) { | |
520 var length = node.textContent.length; | |
521 if (charCount + length >= offset) | |
522 return {container: node, offset: offset - charCount}; | |
523 | |
524 charCount += length; | |
525 } | |
526 return null; | |
527 } | |
528 }; | |
OLD | NEW |