Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Unified Diff: third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js

Issue 2975523002: DevTools: add console test helpers to new test runner & migrate a console test (Closed)
Patch Set: fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..119ee5c3191650f123c9c3a1836b3ccd1195c835 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
@@ -7,10 +7,13 @@
* @suppress {accessControls}
*/
+/** @typedef {function(!Element, !ConsoleModel.ConsoleMessage=):string} */
+ConsoleTestRunner.Formatter;
+
/**
- * @param {boolean} printOriginatingCommand
- * @param {boolean} dumpClassNames
- * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter
+ * @param {boolean=} printOriginatingCommand
+ * @param {boolean=} dumpClassNames
+ * @param {!ConsoleTestRunner.Formatter=} formatter
*/
ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpClassNames, formatter) {
TestRunner.addResults(
@@ -18,9 +21,9 @@ ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpCl
};
/**
- * @param {boolean} printOriginatingCommand
- * @param {boolean} dumpClassNames
- * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter
+ * @param {boolean=} printOriginatingCommand
+ * @param {boolean=} dumpClassNames
+ * @param {!ConsoleTestRunner.Formatter=} formatter
* @return {!Array<string>}
*/
ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingCommand, dumpClassNames, formatter) {
@@ -64,10 +67,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 +145,384 @@ ConsoleTestRunner.fixConsoleViewportDimensions = function(width, height) {
viewport.element.style.height = height + 'px';
viewport.element.style.position = 'absolute';
viewport.invalidate();
-};
+};
+
+ConsoleTestRunner.selectMainExecutionContext = function() {
+ 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
+ */
+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) {
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
+ override(viewMessage);
+ };
+
+ TestRunner.addSniffer(Console.ConsoleView.prototype, '_consoleMessageAddedForTest', sniffer, opt_sticky);
+};
+
+/**
+ * @param {string} code
+ * @param {!Function=} callback
+ * @param {boolean=} dontForceMainContext
+ */
+ConsoleTestRunner.evaluateInConsoleAndDump = function(code, callback, dontForceMainContext) {
+ 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.
+
+ /**
+ * @param {string} text
+ */
+ function mycallback(text) {
+ 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) {
+ /**
+ * @param {string} string
+ */
+ function isNotEmptyLine(string) {
+ return string.trim().length > 0;
+ }
+
+ /**
+ * @param {string} string
+ */
+ 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
+ * @param {!ConsoleTestRunner.Formatter=} messageFormatter
+ */
+ConsoleTestRunner.dumpConsoleMessagesIgnoreErrorStackFrames = function(
+ printOriginatingCommand, dumpClassNames, messageFormatter) {
+ TestRunner.addResults(ConsoleTestRunner.dumpConsoleMessagesIntoArray(
+ printOriginatingCommand, dumpClassNames,
+ messageFormatter ? ConsoleTestRunner.formatterIgnoreStackFrameUrls.bind(this, messageFormatter) : undefined));
+};
+
+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
+ */
+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]);
caseq 2017/07/12 01:04:33 just TestRunner.addResults(result)?
chenwilliam 2017/07/12 22:02:58 Done.
+};
+
+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 = Counters.WarningErrorCounter._instanceForTest;
+ for (var index = 0; index < counter._titles.length; ++index)
+ TestRunner.addResult(counter._titles[index]);
+ ConsoleTestRunner.dumpConsoleClassesBrief();
+};
+
+/**
+ * @param {!Function} callback
+ * @param {function(!Element):boolean} deepFilter
+ * @param {function(!ObjectUI.ObjectPropertiesSection):boolean} sectionFilter
+ */
+ConsoleTestRunner.expandConsoleMessages = function(callback, deepFilter, sectionFilter) {
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.
+ 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);
+};
+
+/**
+ * @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);
+
+ /**
+ * @param {!Node} container
+ * @param {number} offset
+ * @return {?{container: !Node, offset: number}}
+ */
+ function selectionContainerAndOffset(container, offset) {
+ /** @type {?Node} */
+ var node = container;
+ if (offset === 0 && container.nodeType !== Node.TEXT_NODE) {
+ container = /** @type {!Node} */ (container.traverseNextTextNode());
+ node = container;
+ }
+ var charCount = 0;
+ while ((node = node.traverseNextTextNode(container))) {
+ var length = node.textContent.length;
+ if (charCount + length >= offset)
+ return {container: node, offset: offset - charCount};
+
+ charCount += length;
+ }
+ return null;
+ }
+};

Powered by Google App Engine
This is Rietveld 408576698