悬停元素列表 - Selenium Java WebDriver
Hover list of elements - Selenium Java WebDriver
下面是我尝试使用 Selenium WebDriver (2.53.1) 和 Java.
进行测试的场景
在网页上,我有一个星星列表。我想将鼠标悬停在每个星星上,当我们将鼠标悬停时,星星会突出显示。然后单击其中一颗星星。当每个星星悬停时,css 会发生变化。
悬停前
<div class="wh-rating-choices" style="display: none;">
<div class="wh-rating-choices-holder">
<a href="#">1</a>
<a href="#">2</a>
<a href="#">3</a>
<a href="#">4</a>
<a href="#">5</a>
<em>Your Rating: <span></span></em>
</div>
</div>
悬停后
<div class="wh-rating-choices" style="display: none;">
<div class="wh-rating-choices-holder">
<a href="#" class="hover">1</a>
<a href="#" class="hover">2</a>
<a href="#" class="hover">3</a>
<a href="#" class="hover">4</a>
<a href="#" class="hover">5</a>
<em>Your Rating: <span>Excellent</span></em>
</div>
</div>
所以基本上,在成功悬停时,class 'hover' 被添加到 html/css。
我试过的代码如下。
List<WebElement> allStars = driver.findElements(By.xpath("//a[@class='hover']"));
System.out.println("<<<<<<<<<<<<------List of all stars, size------------>>>>>>>>>>"+allStars.size());
for (WebElement e : allStars) {
Actions act = new Actions(driver);
act.moveToElement(e).build().perform();
Thread.sleep(5000);
}
与悬停之前一样,未添加 class 'hover',WebElements 列表始终为零。尝试了某些 selenium 站点上建议的一些选项,但没有用。请帮助,如何进行此操作。
看来你很接近。您需要为具有 class="hover"
的 <a>
元素诱导 WebDriverWait 可点击,您可以使用以下解决方案:
WebElement rating_holder = driver.findElement(By.xpath("//div[@class='wh-rating-choices']"));
((JavascriptExecutor)driver).executeScript("arguments[0].removeAttribute('style')", rating_holder)
List<WebElement> allStars = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//div[@class='wh-rating-choices']/div[@class='wh-rating-choices-holder']//a")));
System.out.println("<<<<<<<<<<<<------List of all stars, size------------>>>>>>>>>>"+allStars.size());
for (WebElement e : allStars) {
if(e.getAttribute("innerHTML").contains("5"))
{
new Actions(driver).moveToElement(e).build().perform();
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='wh-rating-choices-holder']//a[@class='hover']"))).click();
}
}
您的代码存在问题,您正在寻找 A
标签,这些标签甚至在悬停之前就已经具有 'hover' class。如您所述,'hover' class 直到 悬停后才会被添加。因此,您需要将初始定位器更改为 而不是 包括 'hover' class.
我更喜欢使用 CSS 选择器而不是 XPath,除非需要 XPath(通过包含的文本或 DOM 遍历查找元素)。您可以进行一些谷歌搜索以获取更多信息。这是经过测试的代码。
// find all A tags inside the containing DIV
List<WebElement> stars = driver.findElements(By.cssSelector("div.wh-rating-choices-holder > a"));
// loop through each element and hover
Actions action = new Actions(driver);
for (WebElement e : stars)
{
action.moveToElement(e).perform();
}
// after all the hovering is done, fetch the same elements but expect that they will now contain the 'hover' class
stars = driver.findElements(By.cssSelector("div.wh-rating-choices-holder > a.hover"));
// Assert (TestNG) that there are 5 stars that were hovered
Assert.assertEquals(stars.size(), 5, "Verify 5 elements were hovered");
// click the 5th star
stars.get(4).click();
我刚刚测试了一个解决方案,但它很粗糙。但是,它有效。
注意:直接导航到第五颗星(带有文本“5”的元素)对我不起作用。似乎您需要将鼠标悬停以打开评分框,然后将鼠标悬停到第五颗星,这样您就可以将它们全部显示为 class="hover".
这是我做的:
-- 使用 Actions
导航到上面的元素 ("Write a review")
-- 以1个像素为增量向下移动(正"y")
--每次递增后,测试带class"wh-rating-choices"的元素是否包含字符串"block"
-- 如果是,则移动到带有 class "wh-rating-choices-holder"
的元素下包含文本“5”的元素
我在 python 中对其进行了测试,但这是在 Java 中应该起作用的:
Actions action = new Actions(driver);
int inc = 0;
while (inc < 100) {
WebElement top = driver.findElement(By.xpath("//*[contains(text(), 'Write a Review')]"));
action.moveToElement(top, 0, inc).contextClick().perform();
Thread.sleep(200);
a = driver.findElement(By.xpath("//*[contains(@class, 'wh-rating-choices')]"));
if (a.getAttribute("style").contains("block") {
aa = driver.findElement(By.xpath("//*[contains(@class, 'wh-rating-choices-holder')]"));
bb = aa.findElement(By.xpath(".//*[contains(text(), '5')]"));
action.moveToElement(bb).perform();
break;
}
inc++;
}
System.out.println(bb.getAttribute("outerHTML"));
Thread.sleep(200)
可能有点矫枉过正,尝试更低的值,例如 50 或 20。
PS。您可能需要先关闭弹出窗口,即具有 class="af-icon-cross"
的弹出窗口
下面是我尝试使用 Selenium WebDriver (2.53.1) 和 Java.
进行测试的场景在网页上,我有一个星星列表。我想将鼠标悬停在每个星星上,当我们将鼠标悬停时,星星会突出显示。然后单击其中一颗星星。当每个星星悬停时,css 会发生变化。
悬停前
<div class="wh-rating-choices" style="display: none;">
<div class="wh-rating-choices-holder">
<a href="#">1</a>
<a href="#">2</a>
<a href="#">3</a>
<a href="#">4</a>
<a href="#">5</a>
<em>Your Rating: <span></span></em>
</div>
</div>
悬停后
<div class="wh-rating-choices" style="display: none;">
<div class="wh-rating-choices-holder">
<a href="#" class="hover">1</a>
<a href="#" class="hover">2</a>
<a href="#" class="hover">3</a>
<a href="#" class="hover">4</a>
<a href="#" class="hover">5</a>
<em>Your Rating: <span>Excellent</span></em>
</div>
</div>
所以基本上,在成功悬停时,class 'hover' 被添加到 html/css。
我试过的代码如下。
List<WebElement> allStars = driver.findElements(By.xpath("//a[@class='hover']"));
System.out.println("<<<<<<<<<<<<------List of all stars, size------------>>>>>>>>>>"+allStars.size());
for (WebElement e : allStars) {
Actions act = new Actions(driver);
act.moveToElement(e).build().perform();
Thread.sleep(5000);
}
与悬停之前一样,未添加 class 'hover',WebElements 列表始终为零。尝试了某些 selenium 站点上建议的一些选项,但没有用。请帮助,如何进行此操作。
看来你很接近。您需要为具有 class="hover"
的 <a>
元素诱导 WebDriverWait 可点击,您可以使用以下解决方案:
WebElement rating_holder = driver.findElement(By.xpath("//div[@class='wh-rating-choices']"));
((JavascriptExecutor)driver).executeScript("arguments[0].removeAttribute('style')", rating_holder)
List<WebElement> allStars = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//div[@class='wh-rating-choices']/div[@class='wh-rating-choices-holder']//a")));
System.out.println("<<<<<<<<<<<<------List of all stars, size------------>>>>>>>>>>"+allStars.size());
for (WebElement e : allStars) {
if(e.getAttribute("innerHTML").contains("5"))
{
new Actions(driver).moveToElement(e).build().perform();
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='wh-rating-choices-holder']//a[@class='hover']"))).click();
}
}
您的代码存在问题,您正在寻找 A
标签,这些标签甚至在悬停之前就已经具有 'hover' class。如您所述,'hover' class 直到 悬停后才会被添加。因此,您需要将初始定位器更改为 而不是 包括 'hover' class.
我更喜欢使用 CSS 选择器而不是 XPath,除非需要 XPath(通过包含的文本或 DOM 遍历查找元素)。您可以进行一些谷歌搜索以获取更多信息。这是经过测试的代码。
// find all A tags inside the containing DIV
List<WebElement> stars = driver.findElements(By.cssSelector("div.wh-rating-choices-holder > a"));
// loop through each element and hover
Actions action = new Actions(driver);
for (WebElement e : stars)
{
action.moveToElement(e).perform();
}
// after all the hovering is done, fetch the same elements but expect that they will now contain the 'hover' class
stars = driver.findElements(By.cssSelector("div.wh-rating-choices-holder > a.hover"));
// Assert (TestNG) that there are 5 stars that were hovered
Assert.assertEquals(stars.size(), 5, "Verify 5 elements were hovered");
// click the 5th star
stars.get(4).click();
我刚刚测试了一个解决方案,但它很粗糙。但是,它有效。
注意:直接导航到第五颗星(带有文本“5”的元素)对我不起作用。似乎您需要将鼠标悬停以打开评分框,然后将鼠标悬停到第五颗星,这样您就可以将它们全部显示为 class="hover".
这是我做的:
-- 使用 Actions
导航到上面的元素 ("Write a review")-- 以1个像素为增量向下移动(正"y")
--每次递增后,测试带class"wh-rating-choices"的元素是否包含字符串"block"
-- 如果是,则移动到带有 class "wh-rating-choices-holder"
的元素下包含文本“5”的元素我在 python 中对其进行了测试,但这是在 Java 中应该起作用的:
Actions action = new Actions(driver);
int inc = 0;
while (inc < 100) {
WebElement top = driver.findElement(By.xpath("//*[contains(text(), 'Write a Review')]"));
action.moveToElement(top, 0, inc).contextClick().perform();
Thread.sleep(200);
a = driver.findElement(By.xpath("//*[contains(@class, 'wh-rating-choices')]"));
if (a.getAttribute("style").contains("block") {
aa = driver.findElement(By.xpath("//*[contains(@class, 'wh-rating-choices-holder')]"));
bb = aa.findElement(By.xpath(".//*[contains(text(), '5')]"));
action.moveToElement(bb).perform();
break;
}
inc++;
}
System.out.println(bb.getAttribute("outerHTML"));
Thread.sleep(200)
可能有点矫枉过正,尝试更低的值,例如 50 或 20。
PS。您可能需要先关闭弹出窗口,即具有 class="af-icon-cross"