From 8ebcecb0c82401aa40235a71c0557d991b1519de Mon Sep 17 00:00:00 2001 From: David Burns Date: Tue, 15 Oct 2013 15:40:48 +0100 Subject: [PATCH] Bug 759485: Add submit to HTMLElement on Marionette to submit forms without click() or send_keys(); r=mdas --- .../client/marionette/marionette.py | 5 + .../marionette/tests/unit/test_submit.py | 38 +++++ .../marionette/tests/unit/unit-tests.ini | 1 + .../client/marionette/www/formPage.html | 132 +++++++++++++++--- testing/marionette/marionette-listener.js | 30 +++- testing/marionette/marionette-server.js | 17 +++ 6 files changed, 206 insertions(+), 17 deletions(-) create mode 100644 testing/marionette/client/marionette/tests/unit/test_submit.py diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index 906ca15dc65..d2dbaafcf98 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -160,6 +160,11 @@ class HTMLElement(object): return self.marionette._send_message('getElementValueOfCssProperty', 'value', id=self.id, propertyName=property_name) + def submit(self): + ''' + Submits if the element is a form or is within a form + ''' + return self.marionette._send_message('submitElement', 'ok', id=self.id) class Actions(object): ''' diff --git a/testing/marionette/client/marionette/tests/unit/test_submit.py b/testing/marionette/client/marionette/tests/unit/test_submit.py new file mode 100644 index 00000000000..956a1b1c6f9 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_submit.py @@ -0,0 +1,38 @@ +# 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 time +from marionette_test import MarionetteTestCase +from errors import NoSuchElementException + + +class TestSubmit(MarionetteTestCase): + + def test_should_be_able_to_submit_forms(self): + test_html = self.marionette.absolute_url("formPage.html") + self.marionette.navigate(test_html) + self.marionette.find_element("name", "login").submit() + self.assertEqual(self.marionette.title, "We Arrive Here") + + def test_should_submit_a_form_when_any_input_element_within_that_form_is_submitted(self): + test_html = self.marionette.absolute_url("formPage.html") + self.marionette.navigate(test_html) + self.marionette.find_element("id", "checky").submit() + for i in range(5): + try: + self.marionette.find_element('id', 'email') + except NoSuchElementException: + time.sleep(1) + self.assertEqual(self.marionette.title, "We Arrive Here") + + def test_should_submit_a_form_when_any_element_wihin_that_form_is_submitted(self): + test_html = self.marionette.absolute_url("formPage.html") + self.marionette.navigate(test_html) + self.marionette.find_element("xpath", "//form/p").submit() + for i in range(5): + try: + self.marionette.find_element('id', 'email') + except NoSuchElementException: + time.sleep(1) + self.assertEqual(self.marionette.title, "We Arrive Here") diff --git a/testing/marionette/client/marionette/tests/unit/unit-tests.ini b/testing/marionette/client/marionette/tests/unit/unit-tests.ini index ea7d6750ba0..545e4685cee 100644 --- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini @@ -93,3 +93,4 @@ b2g = false [test_implicit_waits.py] [test_date_time_value.py] [test_getactiveframe_oop.py] +[test_submit.py] \ No newline at end of file diff --git a/testing/marionette/client/marionette/www/formPage.html b/testing/marionette/client/marionette/www/formPage.html index 547e6ce6383..ee1ff9f2b97 100644 --- a/testing/marionette/client/marionette/www/formPage.html +++ b/testing/marionette/client/marionette/www/formPage.html @@ -1,16 +1,116 @@ - - - We Leave From Here - - - - - - - - + + + We Leave From Here + + + + +There should be a form here: + +
+ + +
+ +
+ Here's a checkbox: + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + Cheese
+ Peas
+ Cheese and peas
+ Not a sausage
+ Not another sausage + + + +

I like cheese

+ + + Cumberland sausage +
+ + + +
+

+ +

+
+ + + diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index 11e1ca551d8..7797224ed4d 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -141,7 +141,8 @@ function startListeners() { addMessageListenerId("Marionette:getElementText", getElementText); addMessageListenerId("Marionette:getElementTagName", getElementTagName); addMessageListenerId("Marionette:isElementDisplayed", isElementDisplayed); - addMessageListenerId("Marionette:getElementValueOfCssProperty", getElementValueOfCssProperty) + addMessageListenerId("Marionette:getElementValueOfCssProperty", getElementValueOfCssProperty); + addMessageListenerId("Marionette:submitElement", submitElement); addMessageListenerId("Marionette:getElementSize", getElementSize); addMessageListenerId("Marionette:isElementEnabled", isElementEnabled); addMessageListenerId("Marionette:isElementSelected", isElementSelected); @@ -217,6 +218,7 @@ function deleteSession(msg) { removeMessageListenerId("Marionette:getElementTagName", getElementTagName); removeMessageListenerId("Marionette:isElementDisplayed", isElementDisplayed); removeMessageListenerId("Marionette:getElementValueOfCssProperty", getElementValueOfCssProperty); + removeMessageListenerId("Marionette:submitElement", submitElement); removeMessageListenerId("Marionette:getElementSize", getElementSize); removeMessageListenerId("Marionette:isElementEnabled", isElementEnabled); removeMessageListenerId("Marionette:isElementSelected", isElementSelected); @@ -1408,6 +1410,32 @@ function getElementValueOfCssProperty(msg){ } } +/** + * Submit a form on a content page by either using form or element in a form + * @param object msg + * 'json' JSON object containing 'id' member of the element + */ +function submitElement (msg) { + let command_id = msg.json.command_id; + try { + let el = elementManager.getKnownElement(msg.json.id, curFrame); + while (el.parentNode != null && el.tagName.toLowerCase() != 'form') { + el = el.parentNode; + } + if (el.tagName && el.tagName.toLowerCase() == 'form') { + el.submit(); + sendOk(command_id); + } + else { + sendError("Element is not a form element or in a form", 7, null, command_id); + } + + } + catch (e) { + sendError(e.message, e.code, e.stack, command_id); + } +} + /** * Get the size of the element and return it */ diff --git a/testing/marionette/marionette-server.js b/testing/marionette/marionette-server.js index e4aa487aeaf..995efff0b8e 100644 --- a/testing/marionette/marionette-server.js +++ b/testing/marionette/marionette-server.js @@ -1696,6 +1696,22 @@ MarionetteServerConnection.prototype = { command_id); }, + /** + * Submit a form on a content page by either using form or element in a form + * @param object aRequest + * 'id' member holds the reference id to + * the element that will be checked + */ + submitElement: function MDA_submitElement(aRequest) { + let command_id = this.command_id = this.getCommandId(); + if (this.context == "chrome") { + this.sendError("Command 'submitElement' is not available in chrome context", 500, null, this.command_id); + } + else { + this.sendAsync("submitElement", {id: aRequest.parameters.id}, command_id); + } + }, + /** * Check if element is enabled * @@ -2237,6 +2253,7 @@ MarionetteServerConnection.prototype.requestTypes = { "getElementTagName": MarionetteServerConnection.prototype.getElementTagName, "isElementDisplayed": MarionetteServerConnection.prototype.isElementDisplayed, "getElementValueOfCssProperty": MarionetteServerConnection.prototype.getElementValueOfCssProperty, + "submitElement": MarionetteServerConnection.prototype.submitElement, "getElementSize": MarionetteServerConnection.prototype.getElementSize, "isElementEnabled": MarionetteServerConnection.prototype.isElementEnabled, "isElementSelected": MarionetteServerConnection.prototype.isElementSelected,