gpt4 book ai didi

java - 我如何扩展 Selenium By.class 以创造更大的灵活性?

转载 作者:搜寻专家 更新时间:2023-10-31 19:33:40 25 4
gpt4 key购买 nike

我如何扩展 Selenium By.class 以创造更大的灵 active ?我看着 By.class我不太清楚如何处理这个问题。看来我需要创建一个接口(interface)类和一个静态 By 类,例如 ByJavascriptGetWebElement,才能创建这种包装器?

我希望能够这样调用它:

By.javascript("return document.querySelector(\"div#item div\");", el );

我也听说过一种更简单的方法,但我更愿意用更传统的方法:

public By byJavascriptGetElement( WebElement we ) {
return By. ???
}

有什么想法吗?

最佳答案

这其实很容易做到。

这个想法是访问 WebDriver 实例并在其上运行 JavaScript(如果它支持的话)。然后是大量的验证,因为我们需要确保只返回我们 promise 的内容。

ByJavaScript 类本身如下所示:

public class ByJavaScript extends By implements Serializable {
private final String script;

public ByJavaScript(String script) {
checkNotNull(script, "Cannot find elements with a null JavaScript expression.");
this.script = script;
}

@Override
public List<WebElement> findElements(SearchContext context) {
JavascriptExecutor js = getJavascriptExecutorFromSearchContext(context);

// call the JS, inspect and validate response
Object response = js.executeScript(script);
List<WebElement> elements = getElementListFromJsResponse(response);

// filter out the elements that aren't descendants of the context node
if (context instanceof WebElement) {
filterOutElementsWithoutCommonAncestor(elements, (WebElement)context);
}

return elements;
}

private static JavascriptExecutor getJavascriptExecutorFromSearchContext(SearchContext context) {
if (context instanceof JavascriptExecutor) {
// context is most likely the whole WebDriver
return (JavascriptExecutor)context;
}
if (context instanceof WrapsDriver) {
// context is most likely some WebElement
WebDriver driver = ((WrapsDriver)context).getWrappedDriver();
checkState(driver instanceof JavascriptExecutor, "This WebDriver doesn't support JavaScript.");
return (JavascriptExecutor)driver;
}
throw new IllegalStateException("We can't invoke JavaScript from this context.");
}

@SuppressWarnings("unchecked") // cast thoroughly checked
private static List<WebElement> getElementListFromJsResponse(Object response) {
if (response == null) {
// no element found
return Lists.newArrayList();
}
if (response instanceof WebElement) {
// a single element found
return Lists.newArrayList((WebElement)response);
}
if (response instanceof List) {
// found multiple things, check whether every one of them is a WebElement
checkArgument(
Iterables.all((List<?>)response, Predicates.instanceOf(WebElement.class)),
"The JavaScript query returned something that isn't a WebElement.");
return (List<WebElement>)response; // cast is checked as far as we can tell
}
throw new IllegalArgumentException("The JavaScript query returned something that isn't a WebElement.");
}

private static void filterOutElementsWithoutCommonAncestor(List<WebElement> elements, WebElement ancestor) {
for (Iterator<WebElement> iter = elements.iterator(); iter.hasNext(); ) {
WebElement elem = iter.next();

// iterate over ancestors
while (!elem.equals(ancestor) && !elem.getTagName().equals("html")) {
elem = elem.findElement(By.xpath("./.."));
}

if (!elem.equals(ancestor)) {
iter.remove();
}
}
}

@Override
public String toString() {
return "By.javaScript: \"" + script + "\"";
}

}

此代码使用 the Google Guava library .它是 Selenium 的依赖项,因此您应该将它放在类路径中。但如果有什么不明白的地方,请查看 Guava。

需要考虑的事项:

  1. 记录整个事情。
  2. 使用更好、更有帮助的异常。考虑 WebDriverException 的一些自定义子类。还可以添加更多有用的消息和信息。
  3. 限制类对包的可见性。或者将其嵌入静态工厂(如原始 By 类中所示),这样就无法直接访问它等。
  4. 编写测试。我已经尝试了最明显的用法(无法找到元素、从驱动程序中搜索、从某些上下文中搜索)并且一切似乎都正常,但我没有对其进行广泛测试。

用法:

WebElement elem = driver.findElement(new ByJavaScript("return document.querySelector('.haha');"));

现在,原来的 By 类是一个静态工厂,它给出了自己的各种实现。不幸的是,我们无法向它添加新的静态方法(不更改其源代码),因此我们将无法键入 By.javascript("return something;")。我们必须创建自己的静态工厂来获得类似的东西:

public class MyBy {
/**
* Returns a {@code By} which locates elements by the JavaScript expression passed to it.
*
* @param script The JavaScript expression to run and whose result to return
*/
public static By javascript(String script) {
return new ByJavaScript(script);
}
}

用法:

WebElement elem = driver.findElement(MyBy.javascript("return document.querySelector('.haha');"));

关于java - 我如何扩展 Selenium By.class 以创造更大的灵活性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19458305/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com