web-dev-qa-db-fra.com

Comment utiliser xPath dans Selenium WebDriver pour récupérer des éléments SVG?

Je teste une API, basée sur OpenLayers, avec Selenium WebDriver (version Java).

Je veux tester une fonctionnalité qui utilise OpenLayers. Control.ModifyFeature. Je veux cliquer sur les entités dessinées (SVG), les faire glisser ensuite et vérifier si elles sont présentes, visibles ou masquées.

J'ai dessiné un polygone et je l'ai sélectionné. Voir l'image ci-dessous:

polygon_and_handles

Le code HTML de ces éléments SVG est ici:

<svg id="OpenLayers_Layer_Vector_161_svgRoot" width="1235" height="495" viewBox="0 0 1235 495" style="display: block;">
    <g id="OpenLayers_Layer_Vector_161_root" transform="" style="visibility: visible;">
        <g id="OpenLayers_Layer_Vector_161_vroot">
            <path id="OpenLayers_Geometry_Polygon_200" d=" M 393.0000000000964,213.9999999999891 486.0000000003338,275.9999999997126 384.00000000036925,284.9999999994434 393.0000000000964,213.9999999999891 z" fill-rule="evenodd" fill="blue" fill-opacity="0.4" stroke="blue" stroke-opacity="1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="pointer" />
            <circle id="OpenLayers_Geometry_Point_619" cx="439.50000000021464" cy="244.99999999985084" r="6" fill="#009900" fill-opacity="0.5" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_621" cx="435.00000000035106" cy="280.49999999958163" r="6" fill="#009900" fill-opacity="0.5" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_623" cx="388.50000000023283" cy="249.4999999997126" r="6" fill="#009900" fill-opacity="0.5" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_202" cx="393.0000000000964" cy="213.9999999999891" r="6" fill="#990000" fill-opacity="1" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_203" cx="486.0000000003338" cy="275.9999999997126" r="6" fill="#990000" fill-opacity="1" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_204" cx="384.00000000036925" cy="284.9999999994434" r="6" fill="#990000" fill-opacity="1" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
        </g>
        <g id="OpenLayers_Layer_Vector_161_troot" />
    </g>
</svg>

Supposons que je veuille sélectionner les points rouges.

J'ai fait ça:

String xpath = "//circle[contains(@id, 'OpenLayers_Geometry_Point') AND fill = '#990000']";
List<WebElement> vertices = driver.findElements(By.xpath(xpath));

Mais il retourne toujours une liste vide [].

Qu'est-ce que je fais mal ici? Quelqu'un pourrait-t'il m'aider s'il vous plaît?

Merci beaucoup.

EDIT 1 - Fonction: verticesAreVisible

Avant de cliquer sur les actions, je souhaite obtenir les éléments et vérifier s'ils sont visibles. J'utilise cette fonction.

public static boolean verticesAreVisible(WebDriver driver, String xpath) {
    List<WebElement> list = driver.findElements(By.xpath(xpath));
    if (list.isEmpty()) {
        return false;
    }
    boolean visible = true;
    for (int i = 0; i < list.size(); i++) {
        visible = visible && list.get(i).isDisplayed();
    }
    return !verticesAreNotVisible(driver) && visible;
}

EDIT 2 - Corrigez xPath

// This solution from Razib is valid if the SVG is on the root note
String xpath = "/*[name()='svg']/*[name()='circle']";
// I changed it so that any descendant is valid "//"
String xpath = "//*[name()='svg']//*[name()='circle']";
// Since I wanted only the red vertices, I added this
String xpath = "//*[name()='svg']//*[name()='circle' and @fill='#990000']";
10
joaorodr84

Vous devrez peut-être utiliser l'attribut Actions avec name dans Xpath. Dans votre XPath, utilisez-le -

"/*[name()='svg']/*[name()='SVG OBJECT']"  

Ensuite, essayez l'extrait de code suivant - 

WebElement svgObj = driver.findElement(By.xpath(XPATH));
Actions actionBuilder = new Actions(driver);
actionBuilder.click(svgObj).build().perform();
13
Razib

Essayez @fill au lieu de fill et OpenLayers_Geometry_Point au lieu de OpenLayers.Geometry.Point.

3
peetya

Pour obtenir uniquement des éléments visibles, vous pouvez utiliser:

wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("bla bla")));
0
LoveLovelyJava one
       We also faced the similar issue in one of the screens where we have SVG implementation, I resolved using action class.

Action Class Package :
Java.lang.Object
org.openqa.Selenium.interactions.Actions

Sample Code : 

        WebElement svgObject= driver.findElement(By.xpath(XPATH));
        Actions actionBuilderObj = new Actions(driver);
        actionBuilderObj .click(svgObject).build().perform();
0
shiv