Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js b/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js |
| index 1f84b8738f8794a4c78c9a1915beaf1af1e46a52..72517df95ee35a0c24ec4bfcad5586882b121b77 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js |
| @@ -10,7 +10,7 @@ |
| /** |
| * @param {boolean} printOriginatingCommand |
| * @param {boolean} dumpClassNames |
|
luoe
2017/07/07 22:26:40
The first two printOriginating, dumpClassNames are
chenwilliam
2017/07/10 21:14:34
Done.
|
| - * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter |
| + * @param {function(!Element, !ConsoleModel.ConsoleMessage=):string=} formatter |
| */ |
| ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpClassNames, formatter) { |
| TestRunner.addResults( |
| @@ -20,7 +20,7 @@ ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpCl |
| /** |
| * @param {boolean} printOriginatingCommand |
| * @param {boolean} dumpClassNames |
|
luoe
2017/07/07 22:26:40
ditto
chenwilliam
2017/07/10 21:14:34
Done.
|
| - * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter |
| + * @param {function(!Element, !ConsoleModel.ConsoleMessage=):string=} formatter |
| * @return {!Array<string>} |
| */ |
| ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingCommand, dumpClassNames, formatter) { |
| @@ -64,10 +64,9 @@ ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman |
| /** |
| * @param {!Element} messageElement |
| - * @param {!ConsoleModel.ConsoleMessage} consoleMessage |
| * @return {string} |
| */ |
| -ConsoleTestRunner.prepareConsoleMessageText = function(messageElement, consoleMessage) { |
| +ConsoleTestRunner.prepareConsoleMessageText = function(messageElement) { |
| var messageText = messageElement.deepTextContent().replace(/\u200b/g, ''); |
| // Replace scriptIds with generic scriptId string to avoid flakiness. |
| messageText = messageText.replace(/VM\d+/g, 'VM'); |
| @@ -143,4 +142,385 @@ ConsoleTestRunner.fixConsoleViewportDimensions = function(width, height) { |
| viewport.element.style.height = height + 'px'; |
| viewport.element.style.position = 'absolute'; |
| viewport.invalidate(); |
| -}; |
| +}; |
| + |
| +ConsoleTestRunner.selectMainExecutionContext = function() { |
|
chenwilliam
2017/07/06 23:58:32
Most of this was copy and paste from console-test.
|
| + var executionContexts = TestRunner.runtimeModel.executionContexts(); |
| + for (var context of executionContexts) { |
| + if (context.isDefault) { |
| + UI.context.setFlavor(SDK.ExecutionContext, context); |
| + return; |
| + } |
| + } |
| +}; |
| + |
| +/** |
| + * @param {string} code |
| + * @param {!Function} callback |
| + * @param {boolean} dontForceMainContext |
|
luoe
2017/07/07 22:26:40
callback and dontForce are Optional
chenwilliam
2017/07/10 21:14:34
Done.
|
| + */ |
| +ConsoleTestRunner.evaluateInConsole = function(code, callback, dontForceMainContext) { |
| + if (!dontForceMainContext) |
| + ConsoleTestRunner.selectMainExecutionContext(); |
| + callback = TestRunner.safeWrap(callback); |
| + |
| + var consoleView = Console.ConsoleView.instance(); |
| + consoleView._prompt._appendCommand(code, true); |
| + ConsoleTestRunner.addConsoleViewSniffer(function(commandResult) { |
| + callback(commandResult.toMessageElement().deepTextContent()); |
| + }); |
| +}; |
| + |
| +/** |
| + * @param {!Function} override |
| + * @param {boolean=} opt_sticky |
| + */ |
| +ConsoleTestRunner.addConsoleViewSniffer = function(override, opt_sticky) { |
| + var sniffer = function(viewMessage) { |
| + override(viewMessage); |
| + }; |
| + |
| + TestRunner.addSniffer(Console.ConsoleView.prototype, '_consoleMessageAddedForTest', sniffer, opt_sticky); |
| +}; |
| + |
| +/** |
| + * @param {string} code |
| + * @param {!Function} callback |
| + * @param {boolean} dontForceMainContext |
|
luoe
2017/07/07 22:26:39
callback and dontForce are Optional
chenwilliam
2017/07/10 21:14:34
Done.
|
| + */ |
| +ConsoleTestRunner.evaluateInConsoleAndDump = function(code, callback, dontForceMainContext) { |
| + callback = TestRunner.safeWrap(callback); |
| + |
| + function mycallback(text) { |
|
luoe
2017/07/07 22:26:40
JSDoc for this, too? :D
chenwilliam
2017/07/10 21:14:35
Done.
|
| + text = text.replace(/\bVM\d+/g, 'VM'); |
| + TestRunner.addResult(code + ' = ' + text); |
| + callback(text); |
| + } |
| + ConsoleTestRunner.evaluateInConsole(code, mycallback, dontForceMainContext); |
| +}; |
| + |
| +/** |
| + * @return {number} |
| + */ |
| +ConsoleTestRunner.consoleMessagesCount = function() { |
| + var consoleView = Console.ConsoleView.instance(); |
| + return consoleView._consoleMessages.length; |
| +}; |
| + |
| +/** |
| + * @param {function(!Element):string} messageFormatter |
| + * @param {!Element} node |
| + * @return {string} |
| + */ |
| +ConsoleTestRunner.formatterIgnoreStackFrameUrls = function(messageFormatter, node) { |
| + function isNotEmptyLine(string) { |
|
luoe
2017/07/07 22:26:40
JSDoc these too?
chenwilliam
2017/07/10 21:14:35
Done.
|
| + return string.trim().length > 0; |
| + } |
| + |
| + function ignoreStackFrameAndMutableData(string) { |
| + var buffer = string.replace(/\u200b/g, ''); |
| + buffer = buffer.replace(/VM\d+/g, 'VM'); |
| + return buffer.replace(/^\s+at [^\]]+(]?)$/, '$1'); |
| + } |
| + |
| + messageFormatter = messageFormatter || TestRunner.textContentWithLineBreaks; |
| + var buffer = messageFormatter(node); |
| + return buffer.split('\n').map(ignoreStackFrameAndMutableData).filter(isNotEmptyLine).join('\n'); |
| +}; |
| + |
| +/** |
| + * @param {!Element} element |
| + * @param {!ConsoleModel.ConsoleMessage} message |
| + * @return {string} |
| + */ |
| +ConsoleTestRunner.simpleFormatter = function(element, message) { |
| + return message.messageText + ':' + message.line + ':' + message.column; |
| +}; |
| + |
| +/** |
| + * @param {boolean} printOriginatingCommand |
| + * @param {boolean} dumpClassNames |
|
luoe
2017/07/07 22:26:39
First two are optional
chenwilliam
2017/07/10 21:14:34
Done.
|
| + * @param {function(!Element, !ConsoleModel.ConsoleMessage=):string} messageFormatter |
| + */ |
| +ConsoleTestRunner.dumpConsoleMessagesIgnoreErrorStackFrames = function( |
| + printOriginatingCommand, dumpClassNames, messageFormatter) { |
| + TestRunner.addResults(ConsoleTestRunner.dumpConsoleMessagesIntoArray( |
| + printOriginatingCommand, dumpClassNames, |
| + ConsoleTestRunner.formatterIgnoreStackFrameUrls.bind(this, messageFormatter))); |
| +}; |
| + |
| +ConsoleTestRunner.dumpConsoleMessagesWithStyles = function() { |
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + for (var i = 0; i < messageViews.length; ++i) { |
| + var element = messageViews[i].element(); |
| + var messageText = ConsoleTestRunner.prepareConsoleMessageText(element); |
| + TestRunner.addResult(messageText); |
| + var spans = element.querySelectorAll('.console-message-text *'); |
| + for (var j = 0; j < spans.length; ++j) |
| + TestRunner.addResult('Styled text #' + j + ': ' + (spans[j].style.cssText || 'NO STYLES DEFINED')); |
| + } |
| +}; |
| + |
| +/** |
| + * @param {boolean} sortMessages |
|
luoe
2017/07/07 22:26:40
Optional
chenwilliam
2017/07/10 21:14:35
Done.
|
| + */ |
| +ConsoleTestRunner.dumpConsoleMessagesWithClasses = function(sortMessages) { |
| + var result = []; |
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + for (var i = 0; i < messageViews.length; ++i) { |
| + var element = messageViews[i].element(); |
| + var contentElement = messageViews[i].contentElement(); |
| + var messageText = ConsoleTestRunner.prepareConsoleMessageText(element); |
| + result.push(messageText + ' ' + element.getAttribute('class') + ' > ' + contentElement.getAttribute('class')); |
| + } |
| + if (sortMessages) |
| + result.sort(); |
| + for (var i = 0; i < result.length; ++i) |
| + TestRunner.addResult(result[i]); |
| +}; |
| + |
| +ConsoleTestRunner.dumpConsoleClassesBrief = function() { |
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + for (var i = 0; i < messageViews.length; ++i) |
| + TestRunner.addResult(messageViews[i].toMessageElement().className); |
| +}; |
| + |
| +ConsoleTestRunner.dumpConsoleCounters = function() { |
| + var counter = Main.Main.WarningErrorCounter._instanceForTest; |
| + for (var index = 0; index < counter._titles.length; ++index) |
| + TestRunner.addResult(counter._titles[index]); |
| + ConsoleTestRunner.dumpConsoleClassesBrief(); |
| +}; |
| + |
| +/** |
| + * @param {!Function} callback |
| + * @param {!Function} deepFilter |
| + * @param {!Function} sectionFilter |
|
luoe
2017/07/07 22:26:40
I think JSDoc for function params on *filter would
chenwilliam
2017/07/10 21:14:34
Done.
|
| + */ |
| +ConsoleTestRunner.expandConsoleMessages = function(callback, deepFilter, sectionFilter) { |
| + Console.ConsoleView.instance()._invalidateViewport(); |
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + |
| + // Initiate round-trips to fetch necessary data for further rendering. |
| + for (var i = 0; i < messageViews.length; ++i) |
| + messageViews[i].element(); |
| + |
| + TestRunner.deprecatedRunAfterPendingDispatches(expandTreeElements); |
| + |
| + function expandTreeElements() { |
| + for (var i = 0; i < messageViews.length; ++i) { |
| + var element = messageViews[i].element(); |
| + for (var node = element; node; node = node.traverseNextNode(element)) { |
| + if (node.treeElementForTest) |
| + node.treeElementForTest.expand(); |
| + if (node._expandStackTraceForTest) |
| + node._expandStackTraceForTest(); |
| + if (!node._section) |
| + continue; |
| + if (sectionFilter && !sectionFilter(node._section)) |
| + continue; |
| + node._section.expand(); |
| + |
| + if (!deepFilter) |
| + continue; |
| + var treeElements = node._section.rootElement().children(); |
| + for (var j = 0; j < treeElements.length; ++j) { |
| + for (var treeElement = treeElements[j]; treeElement; |
| + treeElement = treeElement.traverseNextTreeElement(true, null, true)) { |
| + if (deepFilter(treeElement)) |
| + treeElement.expand(); |
| + } |
| + } |
| + } |
| + } |
| + TestRunner.deprecatedRunAfterPendingDispatches(callback); |
| + } |
| +}; |
| + |
| +/** |
| + * @param {!Function} callback |
| + */ |
| +ConsoleTestRunner.expandGettersInConsoleMessages = function(callback) { |
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + var properties = []; |
| + var propertiesCount = 0; |
| + TestRunner.addSniffer(ObjectUI.ObjectPropertyTreeElement.prototype, '_updateExpandable', propertyExpandableUpdated); |
| + for (var i = 0; i < messageViews.length; ++i) { |
| + var element = messageViews[i].element(); |
| + for (var node = element; node; node = node.traverseNextNode(element)) { |
| + if (node.classList && node.classList.contains('object-value-calculate-value-button')) { |
| + ++propertiesCount; |
| + node.click(); |
| + properties.push(node.parentElement.parentElement); |
| + } |
| + } |
| + } |
| + |
| + function propertyExpandableUpdated() { |
| + --propertiesCount; |
| + if (propertiesCount === 0) { |
| + for (var i = 0; i < properties.length; ++i) |
| + properties[i].click(); |
| + TestRunner.deprecatedRunAfterPendingDispatches(callback); |
| + } else { |
| + TestRunner.addSniffer( |
| + ObjectUI.ObjectPropertyTreeElement.prototype, '_updateExpandable', propertyExpandableUpdated); |
| + } |
| + } |
| +}; |
| + |
| +/** |
| + * @param {!Function} callback |
| + */ |
| +ConsoleTestRunner.expandConsoleMessagesErrorParameters = function(callback) { |
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + // Initiate round-trips to fetch necessary data for further rendering. |
| + for (var i = 0; i < messageViews.length; ++i) |
| + messageViews[i].element(); |
| + TestRunner.deprecatedRunAfterPendingDispatches(callback); |
| +}; |
| + |
| +/** |
| + * @param {!Function} callback |
| + */ |
| +ConsoleTestRunner.waitForRemoteObjectsConsoleMessages = function(callback) { |
| + var messages = Console.ConsoleView.instance()._visibleViewMessages; |
| + for (var i = 0; i < messages.length; ++i) |
| + messages[i].toMessageElement(); |
| + TestRunner.deprecatedRunAfterPendingDispatches(callback); |
| +}; |
| + |
| +ConsoleTestRunner.checkConsoleMessagesDontHaveParameters = function() { |
|
luoe
2017/07/07 22:26:39
Looks like this function is no longer used? Let's
chenwilliam
2017/07/10 21:14:34
Done.
|
| + var messageViews = Console.ConsoleView.instance()._visibleViewMessages; |
| + for (var i = 0; i < messageViews.length; ++i) { |
| + var m = messageViews[i].consoleMessage(); |
| + TestRunner.addResult('Message[' + i + ']:'); |
| + TestRunner.addResult( |
| + 'Message: ' + Bindings.displayNameForURL(/** @type {string} */ (m.url)) + ':' + m.line + ' ' + m.message); |
| + if ('_parameters' in m) { |
| + if (m._parameters) |
| + TestRunner.addResult('FAILED: message parameters list is not empty: ' + m.parameters); |
| + else |
| + TestRunner.addResult('SUCCESS: message parameters list is empty. '); |
| + } else { |
| + TestRunner.addResult('FAILED: didn\'t find _parameters field in the message.'); |
| + } |
| + } |
| +}; |
| + |
| +/** |
| + * @return {!Promise} |
| + */ |
| +ConsoleTestRunner.waitUntilConsoleEditorLoaded = function() { |
| + var fulfill; |
| + var promise = new Promise(x => (fulfill = x)); |
| + var editor = Console.ConsoleView.instance()._prompt._editor; |
| + if (editor) |
| + fulfill(editor); |
| + else |
| + TestRunner.addSniffer(Console.ConsolePrompt.prototype, '_editorSetForTest', _ => fulfill(editor)); |
| + return promise; |
| +}; |
| + |
| +/** |
| + * @param {!Function} callback |
| + */ |
| +ConsoleTestRunner.waitUntilMessageReceived = function(callback) { |
| + TestRunner.addSniffer(ConsoleModel.consoleModel, 'addMessage', callback, false); |
| +}; |
| + |
| +/** |
| + * @return {!Promise} |
| + */ |
| +ConsoleTestRunner.waitUntilMessageReceivedPromise = function() { |
| + var callback; |
| + var promise = new Promise(fullfill => (callback = fullfill)); |
| + ConsoleTestRunner.waitUntilMessageReceived(callback); |
| + return promise; |
| +}; |
| + |
| +/** |
| + * @param {number} count |
| + * @param {!Function} callback |
| + */ |
| +ConsoleTestRunner.waitUntilNthMessageReceived = function(count, callback) { |
| + function override() { |
| + if (--count === 0) |
| + TestRunner.safeWrap(callback)(); |
| + else |
| + TestRunner.addSniffer(ConsoleModel.consoleModel, 'addMessage', override, false); |
| + } |
| + TestRunner.addSniffer(ConsoleModel.consoleModel, 'addMessage', override, false); |
| +}; |
| + |
| +/** |
| + * @param {number} count |
| + * @return {!Promise} |
| + */ |
| +ConsoleTestRunner.waitUntilNthMessageReceivedPromise = function(count) { |
| + var callback; |
| + var promise = new Promise(fullfill => (callback = fullfill)); |
| + ConsoleTestRunner.waitUntilNthMessageReceived(count, callback); |
| + return promise; |
| +}; |
| + |
| +/** |
| + * @param {string} namePrefix |
| + */ |
| +ConsoleTestRunner.changeExecutionContext = function(namePrefix) { |
| + var selector = Console.ConsoleView.instance()._consoleContextSelector; |
| + for (var executionContext of selector._items) { |
| + if (selector.titleFor(executionContext).startsWith(namePrefix)) { |
| + UI.context.setFlavor(SDK.ExecutionContext, executionContext); |
| + return; |
| + } |
| + } |
| + TestRunner.addResult('FAILED: context with prefix: ' + namePrefix + ' not found in the context list'); |
| +}; |
| + |
| +/** |
| + * @param {number} expectedCount |
| + * @param {!Function} callback |
| + */ |
| +ConsoleTestRunner.waitForConsoleMessages = function(expectedCount, callback) { |
| + var consoleView = Console.ConsoleView.instance(); |
| + checkAndReturn(); |
| + |
| + function checkAndReturn() { |
| + if (consoleView._visibleViewMessages.length === expectedCount) { |
| + TestRunner.addResult('Message count: ' + expectedCount); |
| + callback(); |
| + } else { |
| + TestRunner.addSniffer(consoleView, '_messageAppendedForTests', checkAndReturn); |
| + } |
| + } |
| +}; |
| + |
| +/** |
| + * @param {number} fromMessage |
| + * @param {number} fromTextOffset |
| + * @param {number} toMessage |
| + * @param {number} toTextOffset |
| + * @suppressGlobalPropertiesCheck |
| + */ |
| +ConsoleTestRunner.selectConsoleMessages = function(fromMessage, fromTextOffset, toMessage, toTextOffset) { |
| + var consoleView = Console.ConsoleView.instance(); |
| + var from = selectionContainerAndOffset(consoleView.itemElement(fromMessage).element(), fromTextOffset); |
| + var to = selectionContainerAndOffset(consoleView.itemElement(toMessage).element(), toTextOffset); |
| + window.getSelection().setBaseAndExtent(from.container, from.offset, to.container, to.offset); |
| + |
| + function selectionContainerAndOffset(container, offset) { |
|
luoe
2017/07/07 22:26:39
jsdoc here too?
chenwilliam
2017/07/10 21:14:34
Done.
|
| + if (offset === 0 && container.nodeType !== Node.TEXT_NODE) |
| + container = container.traverseNextTextNode(); |
| + var charCount = 0; |
| + var node = container; |
| + while ((node = node.traverseNextTextNode(true))) { |
| + var length = node.textContent.length; |
| + if (charCount + length >= offset) |
| + return {container: node, offset: offset - charCount}; |
| + |
| + charCount += length; |
| + } |
| + return null; |
| + } |
| +}; |