How to submit a form in Geb (WebDriver) that has no submit button
Asked Answered
M

2

5

I'm building up a test in Geb (WebDriver) that has the need to work with a form that has no submit button. From the user's perspective, it is as simple to use as typing in the search term and hitting the enter key on their keyboard.

Using Geb in a purely script form I can get around this by appending the special key code to the text being typed in, as seen in the following:

import org.openqa.selenium.Keys

$('input[id=myInputField]') << "michael"+Keys.ENTER

That works fine. But if I want to use Geb's recommended Page Object pattern (http://www.gebish.org/manual/0.7.1/pages.html#the_page_object_pattern), I don't see what I should do. What do I define in the content section of my EmployeeSearchPage object to duplicate the missing searchButton and its "to" object reference that tells Geb how to handle the resulting page?

class EmployeeSearchPage extends Page {
    static url = "http://localhost:8888/directory/"
    static at = { title == "Employee Directory" }
    static content = {
        searchField { $("input[id=myInputField]") }
        // THE FOLLOWING BUTTON DOESN'T EXIST IN MY CASE
        searchButton(to: EmployeeListPage) { $("input[value='SUBMIT']") }
    }
}

I realize that I could add a submit button to the form that I could for the test and use CSS to position it out of the user's view, but why should I have to adapt the app to the test? Things should work the other way around.

I've been evaluating a lot of web testing frameworks and find that this type of form presents a problem for many of them - at least as far as their documentation is concerned.

Any ideas? Thanks!

Megalith answered 7/1, 2013 at 18:20 Comment(0)
A
7

You don't need to use js integration to achieve what you want.

You can also define methods on your page class, not only content. You could implement a submit method that would do what you are looking for in the following way:

class EmployeeSearchPage extends Page {
    static url = "http://localhost:8888/directory/"
    static at = { title == "Employee Directory" }
    static content = {
        searchField { $("input[id=myInputField]") 
    }

    void submitForm() {
        searchField << Keys.ENTER
        browser.page EmployeeSearchResultsPage
    }
}

and then to use it:

to EmployeeSearchPage
searchField << 'michael' // searchField = 'michael' would have the same effect
submitForm()
Albrecht answered 8/1, 2013 at 13:6 Comment(4)
This looks good in theory, but is causing a stale element exception: "Caught: org.openqa.selenium.StaleElementReferenceException: getAttribute execution failed;" It is being thrown from my call to your submitForm() method added to my page object. In specific, on the line that appends Keys.ENTER. Any thoughts?Megalith
I don't think that it has much to do with the solution. It has most probably to do with the fact that your page is highly dynamic - something is removing/reading the input on your page or a page reload happens asynchronously after pressing enter. Is that the case? Can you please provide the full stacktrace? This info might lead me to what calls from Geb to WebDriver might cause it.Albrecht
Yes, I got around that problem just now, but the second line in the method is causing the issue now that I have. The stack trace is far too long to paste here, though (nearly 9000 characters). This is the meat of it: groovy.lang.MissingMethodException: No signature of method: geb.navigator.NonEmptyNavigator.page() is applicable for argument types: (java.lang.Class) values: [class EmployeeSearchResultsPage] Possible solutions: tag(), tag(), take(int), wait(), last(), parent()Megalith
Oh yes, sorry. I forgot that we are inside of Page class here so we don't have a direct access to Browser's methods. The following should work: browser.page EmployeeSearchResultsPageAlbrecht
T
1

Geb provides support to execute JavaScript in the context of the browser, details can be found here in the Geb documentation.

You could use this to submit the form exactly like you would submit it using JavaScript in the webapp itself. For example, if you are using jQuery it would be as simple as:

js.exec('$("#myForm").submit()')
Thymol answered 8/1, 2013 at 7:56 Comment(1)
Thanks Rueben. I've already done that, but it kinda misses my point. In the Geb Page Object pattern, the definition of the initial page's "searchButton" actually informs the system directly that it is headed to an instance of the EmployeeListPage. Submitting the form via Javascript, while it gets you there, does not do the same thing. It's not even as nice as $("a").click(DestinationPage), which also tells Geb what to expect on the result side. It just seems to be a hole in the Page Object pattern.Megalith

© 2022 - 2024 — McMap. All rights reserved.