WebDriver等待无法正常工作

时间:2018-02-15 15:36:46

标签: selenium selenium-webdriver automation wait

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

    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)

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

我为一个使用屏蔽方法的本地项目写了这个,它通过在页面上放置不可见的WebElements来阻止用户输入。当页面“忙碌”时,这些元素将保留。当它准备好接受输入时就离开。修改下面的代码以检查类&#34; preloader&#34;而不是&#34; blockUI&#34;它应该适合你。

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;
    }
    ;
}

答案 1 :(得分:0)

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

修复是等待“加载”面板关闭,然后单击按钮。要做到这一点,你只需要为“加载”面板获取一个定位器并等待它不可见。

由于我假设您经常点击酒店菜单(可能还有其他菜单),我会编写一个能够为您处理的功能。

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

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