com.xceptance.xlt.engine.xltdriver.HtmlUnitElementFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xlt Show documentation
Show all versions of xlt Show documentation
XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Copyright (c) 2005-2022 Xceptance Software Technologies GmbH
package com.xceptance.xlt.engine.xltdriver;
import static org.openqa.selenium.htmlunit.HtmlUnitDriver.INVALIDSELECTIONERROR;
import static org.openqa.selenium.htmlunit.HtmlUnitDriver.INVALIDXPATHERROR;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.InvalidSelectorException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.gargoylesoftware.css.parser.CSSException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.SgmlPage;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class HtmlUnitElementFinder {
public static WebElement findElement(HtmlUnitDriver driver, By locator) {
return ElementConverter.HtmlUnitElementConverter.getElementObject(driver, locator).findElement(locator);
}
public static List findElements(HtmlUnitDriver driver, By locator) {
return ElementConverter.HtmlUnitElementConverter.getElementObject(driver, locator).findElements(locator);
}
public static class FindByID extends ElementObject {
public FindByID(HtmlUnitDriver driver) {
super(driver);
}
@Override
public WebElement findElement(By locator) {
SgmlPage lastPage = getLastPage();
if (!(lastPage instanceof HtmlPage)) {
throw new IllegalStateException("Cannot find elements by id for " + lastPage);
}
By.Remotable remote = getRemotable(locator);
String id = (String) remote.getRemoteParameters().value();
DomElement element = ((HtmlPage) lastPage).getElementById(id);
if (element == null) {
throw new NoSuchElementException("Unable to locate element with ID: '" + id + "'");
}
return getDriver().toWebElement(element);
}
@Override
public List findElements(By locator) {
SgmlPage lastPage = getLastPage();
if (!(lastPage instanceof HtmlPage)) {
throw new IllegalStateException("Cannot find elements by id for " + lastPage);
}
final List allElements = ((HtmlPage) lastPage).getElementsById(getValue(locator));
return convertRawDomElementsToWebElements(getDriver(), allElements);
}
}
public static class FindByName extends ElementObject {
public FindByName(HtmlUnitDriver driver) {
super(driver);
}
@Override
public List findElements(By locator) {
SgmlPage lastPage = getLastPage();
if (!(lastPage instanceof HtmlPage)) {
throw new IllegalStateException("Cannot find elements by id for " + lastPage);
}
final List allElements = ((HtmlPage) lastPage).getElementsByName(getValue(locator));
return convertRawDomElementsToWebElements(getDriver(), allElements);
}
}
public static class FindByLinkText extends ElementObject {
public FindByLinkText(HtmlUnitDriver driver) {
super(driver);
}
@Override
public List findElements(By locator) {
SgmlPage lastPage = getLastPage();
if (!(lastPage instanceof HtmlPage)) {
throw new IllegalStateException("Cannot find links for " + lastPage);
}
List elements = new ArrayList<>();
List anchors = ((HtmlPage) lastPage).getAnchors();
String value = getValue(locator);
for (HtmlAnchor anchor : anchors) {
if (value.trim().equals(anchor.asNormalizedText().trim())) {
elements.add(getDriver().toWebElement(anchor));
}
}
return elements;
}
}
public static class FindByPartialLinkText extends ElementObject {
public FindByPartialLinkText(HtmlUnitDriver driver) {
super(driver);
}
@Override
public List findElements(By locator) {
SgmlPage lastPage = getLastPage();
if (!(lastPage instanceof HtmlPage)) {
throw new IllegalStateException("Cannot find links for " + lastPage);
}
List anchors = ((HtmlPage) lastPage).getAnchors();
List elements = new ArrayList<>();
for (HtmlAnchor anchor : anchors) {
if (anchor.asNormalizedText().contains(getValue(locator))) {
elements.add(getDriver().toWebElement(anchor));
}
}
return elements;
}
}
public static class FindByClassName extends ElementObject {
public FindByClassName(HtmlUnitDriver driver) {
super(driver);
}
private String checkValue(By locator) {
String value = getValue(locator);
if (value.indexOf(' ') != -1) {
throw new NoSuchElementException("Compound class names not permitted");
}
return value;
}
@Override
public WebElement findElement(By locator) {
return new FindByCssSelector(getDriver()).findElement(By.cssSelector("." + checkValue(locator)));
}
@Override
public List findElements(By locator) {
return new FindByCssSelector(getDriver()).findElements(By.cssSelector("." + checkValue(locator)));
}
}
public static class FindByCssSelector extends ElementObject {
public FindByCssSelector(HtmlUnitDriver driver) {
super(driver);
}
@Override
public WebElement findElement(By locator) {
DomNode node;
try {
node = getLastPage().querySelector(getValue(locator));
} catch (CSSException ex) {
throw new NoSuchElementException("Unable to locate element using css", ex);
}
if (node instanceof DomElement) {
return getDriver().toWebElement((DomElement) node);
}
throw new NoSuchElementException("Returned node (" + node + ") was not a DOM element");
}
@Override
public List findElements(By locator) {
DomNodeList allNodes;
try {
allNodes = getLastPage().querySelectorAll(getValue(locator));
} catch (CSSException ex) {
throw new NoSuchElementException("Unable to locate element using css", ex);
}
List toReturn = new ArrayList<>();
for (DomNode node : allNodes) {
if (node instanceof DomElement) {
toReturn.add(getDriver().toWebElement((DomElement) node));
} else {
throw new NoSuchElementException("Returned node was not a DOM element");
}
}
return toReturn;
}
}
public static class FindByTagName extends ElementObject {
public FindByTagName(HtmlUnitDriver driver) {
super(driver);
}
@Override
public WebElement findElement(By locator) {
NodeList allElements = getLastPage().getElementsByTagName(getValue(locator));
if (allElements.getLength() > 0) {
return getDriver().toWebElement((HtmlElement) allElements.item(0));
}
throw new NoSuchElementException("Unable to locate element with name: " + getValue(locator));
}
@Override
public List findElements(By locator) {
final String name = getValue(locator);
if ("".equals(name)) {
throw new InvalidSelectorException("Unable to locate element by xpath for " + getLastPage());
}
SgmlPage lastPage;
try {
lastPage = getLastPage();
} catch (IllegalStateException e) {
return Collections.emptyList();
}
NodeList allElements = lastPage.getElementsByTagName(name);
List toReturn = new ArrayList<>(allElements.getLength());
for (int i = 0; i < allElements.getLength(); i++) {
Node item = allElements.item(i);
if (item instanceof DomElement) {
toReturn.add(getDriver().toWebElement((DomElement) item));
}
}
return toReturn;
}
}
public static class FindByXPath extends ElementObject {
public FindByXPath(HtmlUnitDriver driver) {
super(driver);
}
@Override
public WebElement findElement(By locator) {
Object node;
final SgmlPage lastPage = getLastPage();
final String value = getValue(locator);
try {
node = lastPage.getFirstByXPath(value);
} catch (Exception ex) {
// The xpath expression cannot be evaluated, so the expression is invalid
throw new InvalidSelectorException(
String.format(INVALIDXPATHERROR, value),
ex);
}
if (node == null) {
throw new NoSuchElementException("Unable to locate a node using " + value);
}
if (node instanceof DomElement) {
return getDriver().toWebElement((DomElement) node);
}
// The xpath expression selected something different than a WebElement.
// The selector is therefore invalid
throw new InvalidSelectorException(
String.format(INVALIDSELECTIONERROR, value, node.getClass()));
}
@Override
public List findElements(By locator) {
SgmlPage lastPage;
try {
lastPage = getLastPage();
} catch (IllegalStateException e) {
return Collections.emptyList();
}
final String value = getValue(locator);
final List nodes;
try {
nodes = lastPage.getByXPath(value);
} catch (RuntimeException ex) {
// The xpath expression cannot be evaluated, so the expression is invalid
throw new InvalidSelectorException(String.format(INVALIDXPATHERROR, value), ex);
}
List elements = new ArrayList<>(nodes.size());
for (Object node : nodes) {
// There exist elements in the nodes list which could not be converted to WebElements.
// A valid xpath selector should only select WebElements.
if (!(node instanceof DomElement)) {
// We only want to know the type of one invalid element so that we can give this
// information in the exception. We can throw the exception immediately.
throw new InvalidSelectorException(String.format(INVALIDSELECTIONERROR, value, node.getClass()));
}
elements.add(getDriver().toWebElement((DomElement) node));
}
return elements;
}
}
public abstract static class ElementObject {
private final HtmlUnitDriver driver;
public ElementObject(HtmlUnitDriver driver) {
this.driver = driver;
}
protected HtmlUnitDriver getDriver() {
return driver;
}
public WebElement findElement(By locator) {
List elements = findElements(locator);
if (!elements.isEmpty()) {
return elements.get(0);
}
throw new NoSuchElementException("Unable to locate element");
}
abstract public List findElements(By locator);
protected static By.Remotable getRemotable(By locator) {
if (!(locator instanceof By.Remotable)) {
throw new IllegalStateException("Cannot convert locator to Remotable");
}
return (By.Remotable) locator;
}
protected SgmlPage getLastPage() {
Page lastPage = driver.getWindowManager().lastPage();
if (!(lastPage instanceof SgmlPage)) {
throw new IllegalStateException("Current page is not a SgmlPage");
}
return (SgmlPage) lastPage;
}
protected static String getValue(By locator) {
By.Remotable remote = getRemotable(locator);
return (String) remote.getRemoteParameters().value();
}
}
private static List convertRawDomElementsToWebElements(HtmlUnitDriver driver, List nodes) {
List elements = new ArrayList<>(nodes.size());
for (DomElement node : nodes) {
elements.add(driver.toWebElement(node));
}
return elements;
}
}