webentwicklung-frage-antwort-db.com.de

Wie verwende ich xPath in Selenium WebDriver, um SVG-Elemente zu erfassen?

Ich teste eine auf OpenLayers basierende API mit Selenium WebDriver (Java-Version).

Ich möchte eine Funktion testen, die OpenLayers. Control.ModifyFeature verwendet. Ich möchte auf gezeichnete Features (SVG) klicken, dann ziehen und prüfen, ob diese vorhanden, sichtbar oder versteckt sind.

Ich habe ein Polygon gezeichnet und es ausgewählt. Siehe das Bild unten:

polygon_and_handles

Der HTML-Code dieser SVG-Elemente ist hier:

<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>

Angenommen, ich möchte die roten Punkte auswählen.

Ich tat dies:

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

Es wird jedoch immer eine leere Liste [] zurückgegeben.

Was mache ich hier falsch? Könnte mir bitte jemand helfen?

Danke vielmals.

EDIT 1 - Funktion: verticesAreVisible

Vor den Klickaktionen möchte ich die Elemente abrufen und prüfen, ob sie sichtbar sind. Ich benutze diese Funktion.

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 - Richtige 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

Möglicherweise müssen Sie das Attribut Aktionen mit name in Xpath verwenden. Verwenden Sie es in Ihrem XPath -

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

Dann versuchen Sie den folgenden Code-Ausschnitt - 

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

Versuchen Sie @fill anstelle von fill und OpenLayers_Geometry_Point anstelle von OpenLayers.Geometry.Point.

3
peetya

Um nur sichtbare Elemente zu erhalten, können Sie Folgendes verwenden:

wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("bla bla")));
0
       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