【问题标题】:WebDriver wait is not working properlyWebDriver 等待无法正常工作
【发布时间】:2018-02-15 15:36:45
【问题描述】:

如果您打开此链接 https://www.phptravels.net/ 它显示进度条之类的东西,然后您将在右上角看到“酒店”选项。我也尝试过隐式等待、WebDriverWait 和流利的等待。当我使用 element.isDisplayed() 时,它显示“true”,但是当我执行点击操作时,它会抛出异常。

    driver.manage().window().maximize();
        driver.get("https://www.phptravels.net/");

        String hotelsXpth = "//ul[@class='main-menu go-left RTL']/li/a/span[contains(text(),'Hotels')]";


         WebDriverWait wait = new WebDriverWait(driver, 20);
         wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath
         (hotelsXpth)));
         wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(
         hotelsXpth)));

         System.out.println(driver.findElement(By.xpath(hotelsXpth)).isDisplayed());
         driver.findElement(By.xpath(hotelsXpth)).click();

异常

    org.openqa.selenium.WebDriverException: unknown error: Element <span>...
 </span> is not clickable at point (705, 130). Other element would receive 
 the click: <div id="preloader" class="loader-wrapper">...</div>
  (Session info: chrome=63.0.3239.132)
  (Driver info: chromedriver=2.33.506120 
(e3e53437346286c0bc2d2dc9aa4915ba81d9023f),platform=Windows NT 10.0.14393 
x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 0 milliseconds
Build info: version: '3.8.1', revision: '6e95a6684b', time: '2017-12-
01T18:33:54.468Z'
System info: host: 'D-113060768', ip: '10.149.34.102', os.name: 'Windows             
10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_121'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptSslCerts: true, applicationCacheEnabled: false, 
browserConnectionEnabled: false, browserName: chrome, chrome: 
{chromedriverVersion: 2.33.506120 (e3e53437346286..., userDataDir: 
C:\Users\AS337139\AppData\L...}, cssSelectorsEnabled: true, databaseEnabled: 
false, handlesAlerts: true, hasTouchScreen: false, javascriptEnabled: true, 
locationContextEnabled: true, mobileEmulationEnabled: false, nativeEvents: 
true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: 
XP, platformName: XP, rotatable: false, setWindowRect: true, 
takesHeapSnapshot: true, takesScreenshot: true, unexpectedAlertBehaviour: , 
unhandledPromptBehavior: , version: 63.0.3239.132, webStorageEnabled: true}
Session ID: bbfef8e4da0b2a6b98181d54c454d504
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown 
Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)

有什么建议吗?

【问题讨论】:

标签: selenium selenium-webdriver automation wait


【解决方案1】:

问题在于 Selenium 知道 Hotels 链接是可见的,即使它位于“正在加载...”面板后面。因此,您等待酒店链接可见、可点击等的尝试将立即通过,它会尝试点击导致您看到的异常。

解决方法是等待加载面板关闭,然后单击您的按钮。为此,您只需为 Loading 面板获取一个定位器并等待它不可见。

由于我假设您会经常点击酒店菜单(可能还有其他菜单),所以我会编写一个函数来为您处理这些问题。

public static void clickMenu(String menu)
{
    driver.findElement(By.xpath("//nav[@id='offcanvas-menu']//span[contains(.,'" + menu + "')]")).click();
}

脚本本身看起来像

new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElementLocated(By.id("preloader"))); // wait for Loading panel to close
clickMenu("Hotels");

我什至可能会建议,因为您可能会重复使用代码来等待“加载”面板关闭,因此您也可以将其放入函数中。我将把它作为练习留给读者...... :)

【讨论】:

  • 这不能回答问题。 OP 无法通过 phptravels.net 的初始屏幕并需要帮助。您的回答都是基于经常点击酒店菜单(可能还有其他菜单),并没有试图解决真正的问题。
  • @DebanjanB 如果您仔细阅读我的回答,您会在第二段中看到我回答了这个问题。只有两句话。并且...第二个代码块中的第一行解决了等待问题。这是经过测试的代码,并且可以正常工作。
  • @DebanjanB 我处理了你的评论,但你还没有撤消你的反对票……为什么?
【解决方案2】:

我是为一个本地项目编写的,该项目使用一种屏蔽方法,通过在页面上放置不可见的 WebElement 来阻止用户输入。这些元素会在页面“忙碌”时保留,并在准备好接受输入时消失。修改下面的代码以检查类“preloader”而不是“blockUI”,它应该适合你。

public static void waitForBlockUIToDisappear() {
    // This function checks the entire currently-loaded web page for the
    // presence of any web element of the
    // class "blockUI" and loops until there are none. The presence of an
    // element with this class does exactly
    // what it implies: it blocks user input. If you get the error that a
    // different web element would receive
    // the click, for example, this is why and you'd need to call this
    // method before doing a click. Generally,
    // this function should be implemented before sending any input to a web
    // page - click, sendkeys, select...
    String blockUI = "//*[contains(@class,'blockUI')]";
    while (true) {
        if (driver.findElements(By.xpath(blockUI)).size() == 0)
            break;
    }
    ;
}

【讨论】:

  • 如果你传入要等待的定位器而不是在函数中硬编码它会更好。这样它就完全灵活/可重复使用。
  • 我同意。当我引用代码时,我确实想到了这一点。当时,那个特定的项目只有那一类拦截器。它们都是类名的变体,但它们都有共同的“blockUI”,因此包含使用。由于它编写的应用程序只使用了一个类,它使测试编码人员不必知道阻塞页面的类的名称变得更简单,但我相信在某些情况下传递类名将是有益的,也许作为重载版本。
猜你喜欢
  • 2016-11-27
  • 1970-01-01
  • 2021-02-20
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 2021-12-07
相关资源
最近更新 更多