web-dev-qa-db-fra.com

la méthode getText () du pilote Selenium chrome renvoie parfois une chaîne vide

J'ai un cas curieux où la méthode getText() du pilote chrome Selenium (Java) renvoie une chaîne vide pour certains éléments, même si elle renvoie une chaîne non vide pour d'autres éléments avec la même xpath. Voici un peu de la page.

<div __gwt_cell="cell-gwt-uid-223" style="outline-style:none;">
<div>Text_1</div>
<div>Text_2</div>
<div>Text_3</div>
<div>Text_4</div>
<div>Text_5</div>
<div>Text_6</div>
</div>

pour chacune des balises internes, je peux obtenir des valeurs de retour valides pour getTagName(), getLocation(), isEnabled() et isDisplayed(). Cependant, getText () renvoie une chaîne vide pour certains div. 

De plus, je remarque que si j’utilise le pilote mac chrome, c’est toujours le ‘Text_5’ pour lequel getText() renvoie une chaîne vide. Si j’utilise le pilote Windows Chrome, c’est toujours le «Text_2» pour lequel getText() renvoie une chaîne vide. Si j'utilise le pilote firefox, getText() renvoie le texte attendu de tous les div.

Quelqu'un at-il eu cette difficulté?

Dans mon code, j'utilise quelque chose comme ça…

ArrayList<WebElement> list = (ArrayList<WebElement>) driver.findElements(By.xpath(“my xPath here”));
for (WebElement e: list) System.out.println(e.getText());

Comme suggéré ci-dessous, voici la xPath réelle que j'utilise. L'extrait de page ci-dessus traite des deux derniers div.

//*[@class='gwt-DialogBox']//tr[contains(@class,'data-grid-table-row')]//td[contains(@class,'lms-assignment-selection-wizard-cell')]/div/div
35

Update: L'attribut textContent est une meilleure option et est pris en charge par la majorité des navigateurs. Les différences sont expliquées en détail dans cet article de blog: innerText vs. textContent

En guise d'alternative, l'attribut innerText renverra le contenu textuel d'un élément existant dans le DOM.

element.getAttribute("innerText")

La méthode isDisplayed() peut parfois trébucher lorsque l'élément n'est pas vraiment caché mais en dehors de la fenêtre d'affichage. getText() renvoie une chaîne vide pour un tel élément.

Vous pouvez également importer l'élément dans la fenêtre en le faisant défiler à l'aide de javascript, comme suit:

((JavaScriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", element);

et getText() devrait alors renvoyer la valeur correcte.

Des détails sur la méthode isDisplayed() peuvent être trouvés dans cette question SO:

Comment fonctionne la méthode isDisplayed () de Selenium WebDriver

66
Faiz

WebElement.getAttribute ("value") devrait vous aider!

4
sathish p

Ce n'est pas une solution, donc je ne sais pas si cela doit figurer dans une réponse, mais c'est trop long pour un commentaire et inclut des liens, alors je le mets en réponse.

J'ai eu ce problème aussi. Après avoir creusé un peu, il semble que le problème se pose lorsque vous essayez d’obtenir le texte d’un élément qui n’est pas visible à l’écran. (Comme @Faiz le commente ci-dessus). faites défiler vers le bas et l'élément se trouve près du haut du document et n'est plus visible après le défilement. Je vois que vous avez un appel FindElements () qui obtient une liste d'éléments. Au moins certains ne sont probablement pas visibles; vous pouvez vérifier cela en essayant boolean b = webElement.isDisplayed(); sur chaque élément de la liste et en vérifiant le résultat. (Voir ici pour une très longue discussion sur cette question vieille d'un an et toujours pas résolue.)

Apparemment, ceci est une décision de conception délibérée (voir ici ); gettext sur des éléments invisibles est supposé retourner vide. Pourquoi ils sont si fermes à ce sujet, je ne sais pas. Diverses solutions de contournement ont été suggérées, notamment en cliquant sur l'élément avant d'obtenir son texte ou en le faisant défiler. (Voir le lien ci-dessus pour un exemple de code pour ce dernier.) Je ne peux pas en garantir, car je ne les ai pas essayés, mais ils essaient simplement de rendre l'élément visible, de sorte que le texte soit disponible. Vous ne savez pas si c'est pratique pour votre application; ce n'était pas pour le mien. Pour une raison quelconque, FirefoxDriver n'a pas ce problème, c'est ce que j'utilise. 

Je suis désolé, je ne peux pas vous donner une meilleure réponse - peut-être si vous soumettez un rapport de bogue sur la page des problèmes ils verront que beaucoup de personnes trouvent qu'il s'agit d'un bogue plutôt que d'une fonctionnalité et qu'ils vont changer la fonctionnalité. 

Bonne chance! bsg

MODIFIER

Voir cette question pour une solution de contournement possible. Vous ne pourrez pas l'utiliser exactement comme indiqué si isDisplayed renvoie true, mais si vous savez quel élément est à l'origine du problème ou si le texte n'est pas normalement vide et que vous pouvez définir une condition 'si la chaîne est vide' pour intercepter quand ça arrive, tu peux toujours l'essayer. Cela ne fonctionne pas pour tout le monde, malheureusement.

NEW UPDATE Je viens d'essayer la réponse donnée ci-dessous et cela a fonctionné pour moi. Alors merci, Faiz!

3
bsg

J'ai rencontré un problème similaire récemment.

Je devais vérifier que l'onglet "LIFE EVENTS" du menu était présent dans la boîte de défilement. Le problème est qu'il existe de nombreux onglets de menu et que vous devez faire défiler l'écran pour afficher le reste des onglets de menu. Donc, ma solution initiale a bien fonctionné avec les onglets de menu visibles mais pas avec ceux qui étaient invisibles.

J'ai utilisé le xpath ci-dessous pour faire pointer Selenium sur l'élément parent de la boîte de défilement entière.

@FindBy(xpath = "//div[contains(@class, 'menu-tree')]")
protected WebElement menuTree;

J'ai ensuite créé une liste de WebElements que je pouvais incrémenter via . La solution fonctionnait si l'onglet de menu était visible et renvoyait un true. Mais si l'onglet du menu était invisible, il retournait faux

public boolean menuTabPresent(String theMenuTab) {
    List<WebElement> menuTabs = new ArrayList<WebElement>();
    menuTabs = menuTree.findElements(By.xpath("//i/following-sibling::span"));

    for(WebElement e: menuTabs) {
        System.out.println(e.getText());
        if(e.getText().contains(theMenuTab)) {
            return true;
        }
    }
    return false;
}

J'ai trouvé 2 des solutions au problème qui fonctionnent aussi bien l'une que l'autre.

    for(WebElement e: menuTabs) {
        scrollElementIntoView(e); //Solution 1
        System.out.println(e.getAttribute("textContent")); //Solution 2
        if(e.getAttribute("textContent").contains(theMenuTab)) {
            return true;
        }
    }
    return false;

La solution 1 appelle la méthode ci-dessous. Il en résulte que la boîte de défilement se déplace physiquement pendant que Selenium est en cours d'exécution.

protected void scrollElementIntoView(WebElement element) {
    ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true)", element);
}

La solution 2 récupère le contenu du texte (même pour les onglets de menu non visibles) de l'attribut sur lequel vous pointez. Ainsi, faire le travail correctement que .getText () n'était pas capable de faire dans cette situation.

1
Nick Gibbens

si vous ne vous souciez pas de la position affichée ou de défilement, vous pouvez également écrire

String text = ((JavaScriptExecutor)driver).executeScript("return $(arguments[0]).text();", element);

ou sans jquery

String text = ((JavaScriptExecutor)driver).executeScript("return arguments[0].innerText;", element);
1
Kambiz
for (int count=0;count<=sizeofdd;count++)
{       
   String GetInnerHTML=getddvalue.get(count).getAttribute("innerHTML");
}

où, 1. getddvalue est le WebElement 2. sizeofdd est la taille de getddvalue

1
Nand

En rapport avec getText() j'ai aussi un problème et j'ai résolu donc:

WebElement errMsg;
errMsg = driver.findElement(By.xpath("//div[@id='mbr-login-error']"));
WebElement parent = driver.findElement(By.xpath("//form[@id='mbr-login-form']"));
List<WebElement> children = parent.findElements(By.tagName("div")); 
System.out.println("Size is: "+children.size());
//((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", children);
for(int i = 0;i<children.size();i++)
{
    System.out.println(i + " " + children.get(i).getText());
}
int indexErr = children.indexOf(errMsg);
System.out.println("index " + indexErr);
Assert.assertEquals(expected, children.get(indexErr).getText());

Aucune des solutions ci-dessus n'a fonctionné pour moi.

0
user4533396