From 9614cb8e2c04e16fdf84246d12760ded1dec388f Mon Sep 17 00:00:00 2001 From: Yiming Yang Date: Fri, 11 Jan 2013 11:33:58 -0800 Subject: [PATCH] Bug 827403 - Implement 'timeouts' command, r=mdas --- .../client/marionette/marionette.py | 8 +++ .../marionette/tests/unit/test_timeouts.py | 57 +++++++++++++++++++ .../marionette/tests/unit/unit-tests.ini | 3 + testing/marionette/marionette-actors.js | 56 ++++++++++++++++-- testing/marionette/marionette-listener.js | 27 ++++++--- 5 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 testing/marionette/client/marionette/tests/unit/test_timeouts.py diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index f27b7365146c..f63aa88328b0 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -95,6 +95,9 @@ class Marionette(object): CONTEXT_CHROME = 'chrome' CONTEXT_CONTENT = 'content' + TIMEOUT_SEARCH = 'implicit' + TIMEOUT_SCRIPT = 'script' + TIMEOUT_PAGE = 'page load' def __init__(self, host='localhost', port=2828, bin=None, profile=None, emulator=None, sdcard=None, emulatorBinary=None, @@ -386,6 +389,11 @@ class Marionette(object): response = self._send_message('goUrl', 'ok', value=url) return response + def timeouts(self, timeout_type, ms): + assert(timeout_type == self.TIMEOUT_SEARCH or timeout_type == self.TIMEOUT_SCRIPT or timeout_type == self.TIMEOUT_PAGE) + response = self._send_message('timeouts', 'ok', timeoutType=timeout_type, ms=ms) + return response + def go_back(self): response = self._send_message('goBack', 'ok') return response diff --git a/testing/marionette/client/marionette/tests/unit/test_timeouts.py b/testing/marionette/client/marionette/tests/unit/test_timeouts.py new file mode 100644 index 000000000000..9e587c5fca37 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_timeouts.py @@ -0,0 +1,57 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +from marionette_test import MarionetteTestCase +from marionette import HTMLElement +from errors import NoSuchElementException, JavascriptException, MarionetteException, ScriptTimeoutException + +class TestTimeouts(MarionetteTestCase): + def test_pagetimeout_notdefinetimeout_pass(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + + def test_pagetimeout_fail(self): + self.marionette.timeouts("page load", 0) + test_html = self.marionette.absolute_url("test.html") + self.assertRaises(MarionetteException, self.marionette.navigate, test_html) + + def test_pagetimeout_pass(self): + self.marionette.timeouts("page load", 300) + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + + def test_searchtimeout_notfound_settimeout(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + self.marionette.timeouts("implicit", 1000) + self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page") + self.marionette.timeouts("implicit", 0) + self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page") + + def test_searchtimeout_found_settimeout(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + self.marionette.timeouts("implicit", 4000) + self.assertEqual(HTMLElement, type(self.marionette.find_element("id", "newDiv"))) + + def test_searchtimeout_found(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "newDiv") + + def test_execute_async_timeout_settimeout(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + self.marionette.timeouts("script", 10000) + self.assertRaises(ScriptTimeoutException, self.marionette.execute_async_script, "var x = 1;") + + def test_no_timeout_settimeout(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + self.marionette.timeouts("script", 10000) + self.assertTrue(self.marionette.execute_async_script(""" + var callback = arguments[arguments.length - 1]; + setTimeout(function() { callback(true); }, 500); + """)) diff --git a/testing/marionette/client/marionette/tests/unit/unit-tests.ini b/testing/marionette/client/marionette/tests/unit/unit-tests.ini index 19155c53e340..85fee3757fb6 100644 --- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini @@ -41,6 +41,9 @@ b2g = false [test_navigation.py] b2g = false +[test_timeouts.py] +b2g = false + [test_simpletest_pass.js] [test_simpletest_sanity.py] [test_simpletest_chrome.js] diff --git a/testing/marionette/marionette-actors.js b/testing/marionette/marionette-actors.js index 49c703941579..e086e985155e 100644 --- a/testing/marionette/marionette-actors.js +++ b/testing/marionette/marionette-actors.js @@ -150,6 +150,7 @@ function MarionetteDriverActor(aConnection) this.curBrowser = null; // points to current browser this.context = "content"; this.scriptTimeout = null; + this.pageTimeout = null; this.timer = null; this.marionetteLog = new MarionetteLogObj(); this.marionettePerf = new MarionettePerfData(); @@ -940,19 +941,32 @@ MarionetteDriverActor.prototype = { let command_id = this.command_id = this.getCommandId(); if (this.context != "chrome") { aRequest.command_id = command_id; + aRequest.pageTimeout = this.pageTimeout; this.sendAsync("goUrl", aRequest); return; } this.getCurrentWindow().location.href = aRequest.value; let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + let start = new Date().getTime(); + let end = null; function checkLoad() { - if (curWindow.document.readyState == "complete") { - sendOk(command_id); + end = new Date().getTime(); + let elapse = end - start; + if (this.pageTimeout == null || elapse <= this.pageTimeout){ + if (curWindow.document.readyState == "complete") { + sendOk(command_id); + return; + } + else{ + checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT); + } + } + else{ + sendError("Error loading page", 13, null, command_id); return; - } - checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT); - } + } + }//end checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT); }, @@ -1206,6 +1220,37 @@ MarionetteDriverActor.prototype = { } }, +/** + * Set timeout for page loading, searching and scripts + * + * @param object aRequest + * 'type' hold the type of timeout + * 'ms' holds the timeout in milliseconds + */ + timeouts: function MDA_timeouts(aRequest){ + /*setTimeout*/ + this.command_id = this.getCommandId(); + let timeout_type = aRequest.timeoutType; + let timeout = parseInt(aRequest.ms); + if (isNaN(timeout)) { + this.sendError("Not a Number", 500, null, this.command_id); + } + else { + if (timeout_type == "implicit") { + aRequest.value = aRequest.ms; + this.setSearchTimeout(aRequest); + } + else if (timeout_type == "script") { + aRequest.value = aRequest.ms; + this.setScriptTimeout(aRequest); + } + else { + this.pageTimeout = timeout; + this.sendOk(this.command_id); + } + } + }, + /** * Find an element using the indicated search strategy. * @@ -1928,6 +1973,7 @@ MarionetteDriverActor.prototype.requestTypes = { "setContext": MarionetteDriverActor.prototype.setContext, "executeScript": MarionetteDriverActor.prototype.execute, "setScriptTimeout": MarionetteDriverActor.prototype.setScriptTimeout, + "timeouts": MarionetteDriverActor.prototype.timeouts, "executeAsyncScript": MarionetteDriverActor.prototype.executeWithCallback, "executeJSScript": MarionetteDriverActor.prototype.executeJSScript, "setSearchTimeout": MarionetteDriverActor.prototype.setSearchTimeout, diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index 14bd0655ef25..1698169c4dde 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -544,23 +544,32 @@ function setSearchTimeout(msg) { */ function goUrl(msg) { let command_id = msg.json.command_id; - addEventListener("DOMContentLoaded", function onDOMContentLoaded(event) { - // Prevent DOMContentLoaded events from frames from invoking this code, - // unless the event is coming from the frame associated with the current - // window (i.e., someone has used switch_to_frame). - if (!event.originalTarget.defaultView.frameElement || - event.originalTarget.defaultView.frameElement == curWindow.frameElement) { + // Prevent DOMContentLoaded events from frames from invoking this code, + // unless the event is coming from the frame associated with the current + // window (i.e., someone has used switch_to_frame). + let onDOMContentLoaded = function onDOMContentLoaded(event){ + if (msg.json.pageTimeout != null){ + checkTimer.cancel(); + } + if (!event.originalTarget.defaultView.frameElement || + event.originalTarget.defaultView.frameElement == curWindow.frameElement) { removeEventListener("DOMContentLoaded", onDOMContentLoaded, false); - let errorRegex = /about:.+(error)|(blocked)\?/; if (curWindow.document.readyState == "interactive" && errorRegex.exec(curWindow.document.baseURI)) { sendError("Error loading page", 13, null, command_id); return; } - sendOk(command_id); } - }, false); + }; + function timerFunc(){ + sendError("Error loading page", 13, null, command_id); + removeEventListener("DOMContentLoaded", onDOMContentLoaded, false); + } + if (msg.json.pageTimeout != null){ + checkTimer.initWithCallback(timerFunc, msg.json.pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT); + } + addEventListener("DOMContentLoaded", onDOMContentLoaded, false); curWindow.location = msg.json.value; }