Selenide 测试无法在新打开的 tab/window 上加载正确的元素

Selenide test not able to load correct element on a newly opened tab/window

我正在使用 Selenide to open a sample input form on w3schools.com (found here).

测试在表单中输入名称并单击提交,然后在单独的 tab/window 中打开一个新页面,在 div.

中显示请求参数

以下是我的测试代码:

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"))
    }
}

...其中 webdriver.chrome.driver 是指向 chromedriver.exe.

正确位置的传入环境变量

测试会打开初始表单页面并正确输入 first/last 名称。当它点击提交按钮时,它等待第二页加载并显示请求参数。

请注意,无论我的 waitUntil() 方法调用是否存在,错误都会发生。许多其他 Whosebug 帖子建议做类似的事情来解决问题,尽管 Selenide 文档说我的 then 子句中的 shouldHave() 方法调用应该自动执行流畅的等待。

这是我的测试用例的输出:

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]"}

很明显,根据测试输出,它正在抓取初始页面的 xPath,而不是第二页。

有什么我遗漏或做错了什么吗?我是否需要为每个新页面实例化一个新对象或其他东西?

很难在文档中找到答案,但我在一个问题here中发现您确实需要调用一个方法来切换到另一个window。

您必须调用静态方法 Selenide#switchTo(),其中 returns 一个 SelenideTargetLocator。在该对象上,您可以调用方法 window(),它采用基于 0 的索引 (int) 或 name/handle/title (String).

因此,在我的 Spock 测试的 and 子句中添加 switchTo() 方法后,工作结果如下所示:

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"))
}

注意:为了我的测试代码,由于测试只打开一个新标签,调用switchTo(1)在这里对Chrome工作正常,但是请注意,window/tab 顺序在其他浏览器中可能有所不同。