Comment vérifier si un élément est visible avec WebDriver
Avec WebDriver
de Selenium 2. 0a2 j'ai du mal à vérifier si un élément est visible.
WebDriver.findElement
renvoie un WebElement
, qui n'offre malheureusement pas de méthode isVisible
. Je peux contourner cela en utilisant WebElement.clear
ou WebElement.click
qui jettent tous deux un ElementNotVisibleException
, mais cela se sent très sale.
De meilleures idées?
13 réponses
Même si je suis un peu en retard pour répondre à la question:
Vous pouvez maintenant utiliser WebElement.isDisplayed()
pour vérifier si un élément est visible.
Note:
Il y a plusieurs raisons pour lesquelles un élément pourrait être invisible. Le sélénium essaie de couvrir la plupart d'entre eux, mais il y a des cas de bord où cela ne fonctionne pas comme prévu.
Par exemple, isDisplayed()
retourne false
si un élément a display: none
ou opacity: 0
, mais au moins dans mon test, il ne détecte pas de manière fiable si un élément est couvert par un autre en raison du positionnement CSS.
J'ai les 2 façons suggérées suivantes:
-
Vous pouvez utiliser
isDisplayed()
comme ci-dessous:driver.findElement(By.id("idOfElement")).isDisplayed();
-
Vous pouvez définir une méthode comme indiqué ci-dessous et l'appeler:
public boolean isElementPresent(By by) { try { driver.findElement(by); return true; } catch (org.openqa.selenium.NoSuchElementException e) { return false; } }
Maintenant, vous pouvez faire l'affirmation ci-dessous pour vérifier l'élément est présent ou non:
assertTrue(isElementPresent(By.id("idOfElement")));
Si vous utilisez C#, ce serait driver.Afficher. Voici un exemple de mon propre projet:
if (!driver.FindElement(By.Name("newtagfield")).Displayed) //if the tag options is not displayed
driver.FindElement(By.Id("expand-folder-tags")).Click(); //make sure the folder and tags options are visible
Il est important de voir si l'élément est visible ou non car le Driver.FindElement
ne vérifiera que la source HTML. Mais le code contextuel pourrait être dans la page html, et ne pas être visible. Par conséquent, la fonction Driver.FindElement
renvoie un faux positif (et votre test échouera)
La vérification de l'ele est visible.
public static boolean isElementVisible(final By by)
throws InterruptedException {
boolean value = false;
if (driver.findElements(by).size() > 0) {
value = true;
}
return value;
}
Réponse courte: utiliser #visibilityOfElementLocated
Aucune des réponses utilisant isDisplayed
ou similaire n'est correcte. Ils vérifient seulement si la propriété display
n'est pas none
, pas si l'élément peut réellement être vu! Selenium avait un tas de méthodes utilitaires statiques ajoutées dans le ExpectedConditions
classe. Deux d'entre eux peuvent être utilisés dans ce cas:
- visibilityOfElementLocated (l'élément est autorisé à ne pas exister)
- visibilityOf (élément doit existe)
L'Utilisation de
@Test
// visibilityOfElementLocated has been statically imported
public demo(){
By searchButtonSelector = By.className("search_button");
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.get(homeUrl);
WebElement searchButton = wait.until(
visibilityOfElementLocated
(searchButtonSelector));
//clicks the search button
searchButton.click();
Vérification de visibilité personnalisée exécutée sur le client
C'était ma réponse avant de découvrir les méthodes utilitaires sur ExpectedConditions
. Cela pourrait toujours être pertinent, car je suppose qu'il fait plus que la méthode mentionnée ci-dessus, qui vérifie seulement que l'élément a une hauteur et une largeur.
En substance: cela ne peut pas être répondu par Java et les méthodes findElementBy*
et WebElement#isDisplayed
seuls, car ils ne peuvent que vous dire si un élément existe , pas si elle est réellement visible . L'OP n'a pas défini ce quevisible signifie, Mais cela implique normalement
- Il a un
opacity
> 0 - la propriété
display
est définie sur autre chose quenone
- l'accessoire
visibility
est défini survisible
- Il n'y a pas d'autres éléments qui le cachent (c'est l'élément le plus haut)
La plupart des gens incluraient également l'exigence qu'il se trouve également dans la fenêtre d'affichage (donc une personne pourrait pour le voir).
Pour une raison quelconque, ce besoin tout à fait normal n'est pas satisfait par L'API Java pure, tandis que les frontaux de Selenium qui s'appuie dessus implémentent souvent une variation de isVisible
, c'est pourquoi je savais que cela devrait être possible. Et après avoir parcouru la source du framework Node WebDriver.IO j'ai trouvé la source de isVisible
, qui est maintenant renommée pour le nom plus justement de isVisibleInViewport
dans la version 5.0-beta.
Fondamentalement, ils implémentent la commande personnalisée comme un appel qui délègue à un javascript qui s'exécute sur le client et fait le travail réel! C'est le bit "serveur":
export default function isDisplayedInViewport () {
return getBrowserObject(this).execute(isDisplayedInViewportScript, {
[ELEMENT_KEY]: this.elementId, // w3c compatible
ELEMENT: this.elementId // jsonwp compatible
})
}
Donc, le bit intéressant est le javascript envoyé pour fonctionner sur le client:
/**
* check if element is visible and within the viewport
* @param {HTMLElement} elem element to check
* @return {Boolean} true if element is within viewport
*/
export default function isDisplayedInViewport (elem) {
const dde = document.documentElement
let isWithinViewport = true
while (elem.parentNode && elem.parentNode.getBoundingClientRect) {
const elemDimension = elem.getBoundingClientRect()
const elemComputedStyle = window.getComputedStyle(elem)
const viewportDimension = {
width: dde.clientWidth,
height: dde.clientHeight
}
isWithinViewport = isWithinViewport &&
(elemComputedStyle.display !== 'none' &&
elemComputedStyle.visibility === 'visible' &&
parseFloat(elemComputedStyle.opacity, 10) > 0 &&
elemDimension.bottom > 0 &&
elemDimension.right > 0 &&
elemDimension.top < viewportDimension.height &&
elemDimension.left < viewportDimension.width)
elem = elem.parentNode
}
return isWithinViewport
}
Ce morceau de JS peut effectivement être copié (presque) verbatim dans votre propre base de code (supprimer export default
et remplacer const
par var
dans le cas de navigateurs non-evergreen)! Pour l'utiliser, lisez-le de File
dans un {[24] } qui peut être envoyé par Selenium pour s'exécuter sur le client.
Un autre script intéressant et connexe qui pourrait valoir la peine d'être examiné est selectByVisibleText .
Si vous n'avez pas exécuté JS en utilisant Selenium avant que vous puissiez avoir un petit coup d'oeil dans ce ou parcourir l'API JavaScriptExecutor.
Habituellement, essayez de toujours utiliser des scripts asynchrones non bloquants (ce qui signifie #executeAsyncScript), mais comme nous avons déjà un script synchrone bloquant, nous pourrions aussi bien utiliser la synchronisation normale appeler. L'objet retourné peut être plusieurs types D'objet, donc cast approprately. Cela pourrait être une façon de le faire:
/**
* Demo of a java version of webdriverio's isDisplayedInViewport
* https://github.com/webdriverio/webdriverio/blob/v5.0.0-beta.2/packages/webdriverio/src/commands/element/isDisplayedInViewport.js
* The super class GuiTest just deals with setup of the driver and such
*/
class VisibleDemoTest extends GuiTest {
public static String readScript(String name) {
try {
File f = new File("selenium-scripts/" + name + ".js");
BufferedReader reader = new BufferedReader( new FileReader( file ) );
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
} catch(IOError e){
throw new RuntimeError("No such Selenium script: " + f.getAbsolutePath());
}
}
public static Boolean isVisibleInViewport(RemoteElement e){
// according to the Webdriver spec a string that identifies an element
// should be deserialized into the corresponding web element,
// meaning the 'isDisplayedInViewport' function should receive the element,
// not just the string we passed to it originally - how this is done is not our concern
//
// This is probably when ELEMENT and ELEMENT_KEY refers to in the wd.io implementation
//
// Ref https://w3c.github.io/webdriver/#dfn-json-deserialize
return js.executeScript(readScript("isDisplayedInViewport"), e.getId());
}
public static Boolean isVisibleInViewport(String xPath){
driver().findElementByXPath("//button[@id='should_be_visible']");
}
@Test
public demo_isVisibleInViewport(){
// you can build all kinds of abstractions on top of the base method
// to make it more Selenium-ish using retries with timeouts, etc
assertTrue(isVisibleInViewport("//button[@id='should_be_visible']"));
assertFalse(isVisibleInViewport("//button[@id='should_be_hidden']"));
}
}
Voici comment je le ferais (veuillez ignorer les appels de classe worry Logger):
public boolean isElementExist(By by) {
int count = driver.findElements(by).size();
if (count>=1) {
Logger.LogMessage("isElementExist: " + by + " | Count: " + count, Priority.Medium);
return true;
}
else {
Logger.LogMessage("isElementExist: " + by + " | Could not find element", Priority.High);
return false;
}
}
public boolean isElementNotExist(By by) {
int count = driver.findElements(by).size();
if (count==0) {
Logger.LogMessage("ElementDoesNotExist: " + by, Priority.Medium);
return true;
}
else {
Logger.LogMessage("ElementDoesExist: " + by, Priority.High);
return false;
}
}
public boolean isElementVisible(By by) {
try {
if (driver.findElement(by).isDisplayed()) {
Logger.LogMessage("Element is Displayed: " + by, Priority.Medium);
return true;
}
}
catch(Exception e) {
Logger.LogMessage("Element is Not Displayed: " + by, Priority.High);
return false;
}
return false;
}
public boolean isElementFound( String text) {
try{
WebElement webElement = appiumDriver.findElement(By.xpath(text));
System.out.println("isElementFound : true :"+text + "true");
}catch(NoSuchElementException e){
System.out.println("isElementFound : false :"+text);
return false;
}
return true;
}
text is the xpath which you would be passing when calling the function.
the return value will be true if the element is present else false if element is not pressent
try{
if( driver.findElement(By.xpath("//div***")).isDisplayed()){
System.out.println("Element is Visible");
}
}
catch(NoSuchElementException e){
else{
System.out.println("Element is InVisible");
}
}
Élément.isDisplayed est inutile. Elle renvoie Vrai si l'élément n'est pas visible.
Essayez ceci
public boolean isPrebuiltTestButtonVisible() {
try {
if (preBuiltTestButton.isEnabled()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
element instanceof RenderedWebElement
ça devrait marcher. // Mais c'est pour l'ancienne version de selenium rc.
Veuillez noter:
RenderedWebElement
Il était obsolète Il y a quatre ans (en 2013). il était supporté jusqu'à selenium-2.0-rc-2 et retiré de selenium-2.0-rc-3 à partir de
Il n'y a donc pas une telle classe RenderedWebElement
dans la dernière version.La version actuelle est 2.46.0.Essayez d'utiliser la dernière version
Veuillez utiliser WebElement
à la place pas besoin de lancer et tout avec isDisplayed() isEnabled() and driver.findElements(By.xpath(accessor)).size() > 0
Quelque chose comme ce:
public static boolean isElementFoundDisplayedEnabled(WebDriver driver, String accessor){
return driver.findElements(By.xpath(accessor)).size() > 0 && driver.findElement(By.xpath(accessor)).isDisplayed() && driver.findElement(By.xpath(accessor)).isEnabled();
//isDisplayed(): method avoids the problem of having to parse an element's "style" attribute to check hidden/visible. False when element is not present
//isEnabled(): generally return true for everything but disabled input elements.
}