0

I am using Selenide to open a sample input form on w3schools.com (found here).

The test inputs a name into the form and clicks submit, which then opens a new page in a separate tab/window which displays the request params in a div.

Sample HTML form screenshot

Returned results screenshot

The following is my test code:

import com.codeborne.selenide.Configuration
import org.openqa.grid.internal.utils.configuration.StandaloneConfiguration
import org.openqa.selenium.remote.server.SeleniumServer
import spock.lang.Specification

import static com.codeborne.selenide.Condition.*
import static com.codeborne.selenide.Selectors.byName
import static com.codeborne.selenide.Selectors.byTitle
import static com.codeborne.selenide.Selenide.*

class DummyTest extends Specification {

    def "Test w3schools form submit"() {
        given: "Server setup configurations"
            Configuration.browser = 'chrome'
            StandaloneConfiguration configuration = new StandaloneConfiguration()
            SeleniumServer server = new SeleniumServer(configuration)
            server.boot()

        when: "Name info is submitted into the form"
            open("http://www.w3schools.com/html/html_forms.asp")
            $(byName("firstname")).setValue("Clark")
            $(byName("lastname")).setValue("Kent")
            $x('//*[@id="main"]/div[3]/div/form/input[3]').click()

            // Maybe this will fix the erroneous element problem?
            $(byTitle('HTML Forms')).waitUntil(disappears, 5000)

        then: "New page should display the passed-in request params"
            $x("/html/body/div[1]").shouldHave(text("firstname=Clark&lastname=Kent"))
    }
}

...where webdriver.chrome.driver is a passed-in environment variable pointing to the correct location of chromedriver.exe.

The test does open the initial form page and type in the first/last name correctly. When it clicks the submit button, it waits for the second page to load and display the request params.

As a note, the error happens regardless of whether or not my waitUntil() method call is present or not. Many of the other StackOverflow posts suggest doing something like that to fix the problem, though the Selenide docs say that the shouldHave() method call in my then clause should automatically do a fluent wait.

This is the output of my test case:

Condition failed with Exception:

$x("/html/body/div[1]").shouldHave(text("firstname=Clark&lastname=Kent"))
|                       |          |
|                       |          text 'firstname=Clark&lastname=Kent'
|                       Element should have text 'firstname=Clark&lastname=Kent' {By.xpath: /html/body/div[1]}
|                       Element: '<div class="w3-container top">w3schools.com
|                       THE WORLD'S LARGEST WEB DEVELOPER SITE</div>'
|                       Screenshot: file:/C:/Workspace/IntelliJ/dummy-selenide-project/build/reports/tests/1498836183270.0.png
|                       Timeout: 4 s.
NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[1]"}

So, it's clear that, as per the test output, it's grabbing the xPath of the initial page, not the second page.

Is there something that I'm missing or doing wrong? Do I need to instantiate a new object or something for every new page?

4

1 回答 1

0

It was difficult to find the answer in the docs, but I found out in a question here that you do need to call a method to switch to another window.

You must call the static method Selenide#switchTo(), which returns a SelenideTargetLocator. On that object, you can call the method window(), which either takes a 0-based index (int) or a name/handle/title (String).

So, after adding the switchTo() method in my and clause for my Spock test, the working result looks like this:

def "Test w3schools form submit"() {
    given: "Server setup configurations"
        Configuration.browser = 'chrome'
        StandaloneConfiguration configuration = new StandaloneConfiguration()
        SeleniumServer server = new SeleniumServer(configuration)
        server.boot()

    when: "Name info is submitted into the form"
        open("http://www.w3schools.com/html/html_forms.asp")
        $(byName("firstname")).setValue("Clark")
        $(byName("lastname")).setValue("Kent")
        $x('//*[@id="main"]/div[3]/div/form/input[3]').click()

    and: "Switch to newly opened window"
        switchTo().window(1)

    then: "New page should display the passed-in request params"
        $x("/html/body/div[1]").shouldHave(text("firstname=Clark&lastname=Kent"))
}

Note: For sake of my test code, since the test only opens one new tab, calling switchTo(1) works fine here for Chrome, but note that the window/tab order may be different in other browsers.

于 2017-06-30T18:48:43.307 回答