diff --git a/front_end/common/TestBase.js b/front_end/common/TestBase.js index 5b9cb4bef7..48fecf7b69 100644 --- a/front_end/common/TestBase.js +++ b/front_end/common/TestBase.js @@ -79,6 +79,7 @@ WebInspector.TestBase.prototype.releaseControl = function() clearTimeout(this.timerId_); this.timerId_ = -1; } + this.controlTaken_ = false; this.reportOk_(); }; @@ -107,7 +108,7 @@ WebInspector.TestBase.prototype.reportFailure_ = function(error) /** * Run specified test on a fresh instance of the test suite. - * @param {string} name Name of a test method from implementation class. + * @param {Array} args method name followed by its parameters. */ WebInspector.TestBase.prototype.dispatch = function(args) { @@ -122,6 +123,19 @@ WebInspector.TestBase.prototype.dispatch = function(args) }; +/** + * Wrap an async method with TestBase.{takeControl(), releaseControl()} + * and invoke TestBase.reportOk_ upon completion. + * @param {Array} args method name followed by its parameters. + */ +WebInspector.TestBase.prototype.waitForAsync = function(var_args) +{ + var args = Array.prototype.slice.call(arguments); + this.takeControl(); + args.push(this.releaseControl.bind(this)); + this.dispatch(args); +}; + /** * Overrides the method with specified name until it's called first time. * @param {!Object} receiver An object whose method to override. diff --git a/front_end/main/Tests.js b/front_end/main/Tests.js index e63ad97079..4e3588faf3 100644 --- a/front_end/main/Tests.js +++ b/front_end/main/Tests.js @@ -47,6 +47,7 @@ function createTestSuite(domAutomationController) function TestSuite() { WebInspector.TestBase.call(this, domAutomationController); + this._asyncInvocationId = 0; }; TestSuite.prototype = { @@ -651,10 +652,9 @@ TestSuite.prototype.waitForTestResultsInConsole = function() this.takeControl(); }; -TestSuite.prototype.invokeAsyncWithTimeline_ = function(functionName, callback) +TestSuite.prototype.startTimeline = function(callback) { - var test = this; - test.showPanel("timeline").then(function() { + this.showPanel("timeline").then(function() { WebInspector.panels.timeline._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStarted, onRecordingStarted); WebInspector.panels.timeline._toggleRecording(); }); @@ -662,32 +662,77 @@ TestSuite.prototype.invokeAsyncWithTimeline_ = function(functionName, callback) function onRecordingStarted() { WebInspector.panels.timeline._model.removeEventListener(WebInspector.TimelineModel.Events.RecordingStarted, onRecordingStarted); - test.evaluateInConsole_(functionName + "(function() { console.log('DONE'); });", function() {}); - WebInspector.multitargetConsoleModel.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, onConsoleMessage); + callback(); + } +} + +TestSuite.prototype.stopTimeline = function(callback) +{ + WebInspector.panels.timeline._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStopped, onRecordingStopped); + WebInspector.panels.timeline._toggleRecording(); + function onRecordingStopped() + { + WebInspector.panels.timeline._model.removeEventListener(WebInspector.TimelineModel.Events.RecordingStopped, onRecordingStopped); + callback(); } +} + +TestSuite.prototype.invokePageFunctionAsync = function(functionName, opt_args, callback_is_always_last) +{ + var callback = arguments[arguments.length - 1]; + var doneMessage = `DONE: ${functionName}.${++this._asyncInvocationId}`; + var argsString = arguments.length < 3 ? "" : Array.prototype.slice.call(arguments, 1, -1).map(arg => JSON.stringify(arg)).join(",") + ","; + this.evaluateInConsole_(`${functionName}(${argsString} function() { console.log('${doneMessage}'); });`, function() {}); + WebInspector.multitargetConsoleModel.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, onConsoleMessage); function onConsoleMessage(event) { var text = event.data.messageText; - if (text === "DONE") { + if (text === doneMessage) { WebInspector.multitargetConsoleModel.removeEventListener(WebInspector.ConsoleModel.Events.MessageAdded, onConsoleMessage); - pageActionsDone(); + callback(); } } +} - function pageActionsDone() +TestSuite.prototype.invokeAsyncWithTimeline_ = function(functionName, callback) +{ + var test = this; + + this.startTimeline(onRecordingStarted); + + function onRecordingStarted() { - WebInspector.panels.timeline._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStopped, onRecordingStopped); - WebInspector.panels.timeline._toggleRecording(); + test.invokePageFunctionAsync(functionName, pageActionsDone); } - function onRecordingStopped() + function pageActionsDone() { - WebInspector.panels.timeline._model.removeEventListener(WebInspector.TimelineModel.Events.RecordingStopped, onRecordingStopped); - callback(); + test.stopTimeline(callback); } }; +TestSuite.prototype.enableExperiment = function(name) +{ + Runtime.experiments.enableForTest(name); +} + +TestSuite.prototype.checkInputEventsPresent = function() +{ + var expectedEvents = new Set(arguments); + var model = WebInspector.panels.timeline._model; + var asyncEvents = model.mainThreadAsyncEvents(); + var input = asyncEvents.get(WebInspector.TimelineUIUtils.asyncEventGroups().input) || []; + var prefix = "InputLatency::"; + for (var e of input) { + if (!e.name.startsWith(prefix)) + continue; + expectedEvents.delete(e.name.substr(prefix.length)); + } + if (expectedEvents.size) + throw "Some expected events are not found: " + Array.from(expectedEvents.keys()).join(","); +} + /** * Serializes array of uiSourceCodes to string. * @param {!Array.} uiSourceCodes