Selenium HTMLUnitDriver 无法登录

Selenium HTMLUnitDriver Cannot Sign in

更新

我正在尝试登录此网站:

Salesforce Trailhead

很遗憾,我没有成功。这是我的代码:

WebDriver driver = new HtmlUnitDriver();

driver.get("https://trailhead.salesforce.com/en/home");
System.out.println(driver.getTitle());

WebElement btnLogin = driver.findElement(By.xpath("//*[@id=\"main-wrapper\"]/header/div[1]/div[2]/span[2]/div/span/button"));
System.out.println(btnLogin);

driver.quit();

我正在尝试从 header 获取登录按钮,但是我找不到元素,这是我收到的异常消息:

Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate a node using //*[@id="main-wrapper"]/header/div1/div[2]/span[2]/div/span/button

我正在尝试从下方测试答案,但没有成功。我想更好地了解 WebDriverWait 的工作原理和 until() 方法。

谢谢。

问题是有多个登录按钮。您的代码等待 第一个按钮 可见。不幸的是,它不会。所以 Selenium 一直等到超时。
我建议创建一种方法,通过遍历所有 saleforce 登录按钮并检查 属性 isDisplayed() 来找到正确的按钮。如果是,请使用按钮。请参阅下面的示例。

private WebElement findLoginButton(WebDriver d, By by) {
    List<WebElement> elements = d.findElements(by);
    for (Iterator<WebElement> e = elements.iterator(); e.hasNext();) {
        WebElement item = e.next();
        if(item.isDisplayed())
                return item;
    }
    return null;
}

@Test
public void testSaleforce() {
    WebDriver driver = new HtmlUnitDriver();
    driver.get("https://trailhead.salesforce.com/en/home");
    System.out.println(driver.getTitle());
    WebElement btnLogin = driver.findElement(By.xpath("//*[@data-react-class='auth/LoginModalBtn']"));
    System.out.println(btnLogin);
    btnLogin.click();
    WebDriverWait wait = new WebDriverWait(driver,10);
    WebElement btnLoginSalesforce = wait.until((WebDriver d) -> findLoginButton(d,By.cssSelector(".th-modal-btn__salesforce")));
    btnLoginSalesforce.click();
    ...
}

在此网页中,开发人员非常友好地向 HTML 添加特殊 (HTML5) 属性以进行测试,称为 'data-test'。借助此属性,您可以使用 CSS 选择器在您的 Selenium 代码中定位 Webelements。因此不需要复杂的 Xpath 选择器,也不需要像@Buaban 建议的那样遍历按钮。

我测试了以下 C# 代码并成功点击了登录按钮。

 IWebElement btnLogin = Driver.FindElement(By.CssSelector("button[data-test=header-login]"));

 btnLogin.Click();

我想你用的是Java,那么它将是:

 WebElement btnLogin = driver.findElement(By.cssSelector("button[data-test=header-login]"));

 btnLogin.click();

要获得更稳定的解决方案,您必须使用显式等待:

WebDriverWait wait = new WebDriverWait(driver, 20);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.css(""button[data-test=header-login]"")));

Selenium 将尝试每 500 毫秒查找一次按钮,最长 20 秒。 NoSuchElementExceptions 将被忽略,直到找到按钮或经过 20 秒。如果 20 秒后仍未找到按钮,将抛出超时异常。