如何在 Java Selenium 中创建包含多个连接定位器的工厂元素定位器

问题描述 投票:0回答:1

例如,页面有一个定位器 id =“test1”的容器字段和另一个定位器 id =“field1”的字段

加入的定位器应在定位器 id = "test1" 中搜索定位器 id = "field1": locator1.findElement().findElement((By) locator2)

如何在 Java Selenium 中创建包含多个合并定位器的元素定位器

代码中表示为mergeLocator,但我不知道该怎么做。

ElementLocator mergeLocator = locator1 + locator2;

我的代码:

import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.pagefactory.DefaultFieldDecorator;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class ElementsDecorator extends DefaultFieldDecorator {
    private WebDriver driver;

    public ElementsDecorator(ElementLocatorFactory factory, WebDriver driver) {
        super(factory);
        this.driver = driver;
    }

    @SneakyThrows
    @Override
    public Object decorate(ClassLoader loader, Field field) {
        ElementLocator locator1 = factory.createLocator(field);
        ElementLocator locator2 = factory.createLocator(field.getDeclaringClass().getDeclaredField("container"));
        ElementLocator mergeLocator = locator1 + locator2;
        return createElement(loader, mergeLocator, field.getType());
    }
    
    protected <T> T createElement(ClassLoader loader, ElementLocator locator, Class<?> tClass) {
        WebElement proxy = proxyForLocator(loader, locator);
        try {
            return (T) tClass.getConstructor(WebElement.class, WebDriver.class).newInstance(proxy, driver);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | InstantiationException |
                 InvocationTargetException e) {
            throw new AssertionError("WebElement can't be represented as " + tClass);
        }
    }
}
java selenium-webdriver page-factory
1个回答
0
投票

在 Selenium 中,不能直接添加两个 ElementLocator 对象(例如 locator1 + locator2),因为 ElementLocator 是接口类型,不支持相加。如果要查找嵌套元素(例如,在 id 为“test1”的元素内查找 id 为“field1”的元素),则需要为每个元素创建单独的 By 定位器,然后使用 WebDriver 的 findElement 方法来查找外部元素先元素,然后在返回的WebElement中找到嵌入的元素。

以下是如何修改代码来实现此目的:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.pagefactory.DefaultFieldDecorator;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;

import java.lang.reflect.Field;

public class ElementsDecorator extends DefaultFieldDecorator {
    private WebDriver driver;

    public ElementsDecorator(ElementLocatorFactory factory, WebDriver driver) {
        super(factory);
        this.driver = driver;
    }

    @Override
    public Object decorate(ClassLoader loader, Field field) {
        try {
            By outerBy = getFieldLocator(factory, field.getDeclaringClass().getDeclaredField("test1"));
            By innerBy = getFieldLocator(factory, field);
            WebElement mergedElement = findNestedElement(outerBy, innerBy);
            // Now you can use mergedElement to further manipulate the WebElement.
            // ...
            return null; // Or return the object you need
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
    
    private By getFieldLocator(ElementLocatorFactory factory, Field field) {
        ElementLocator locator = factory.createLocator(field);
        return ((ByElementLocator) locator).getBy();
    }
    
    private WebElement findNestedElement(By outerBy, By innerBy) {
        WebElement outerElement = driver.findElement(outerBy);
        return outerElement.findElement(innerBy);
    }

    // This is a hypothetical ByElementLocator class that you need to replace with the actual implementation to get the By object
    private static class ByElementLocator implements ElementLocator {
        public By getBy() { 
            // Implementing the logic for returning By objects
            return null;
        }

        @Override
        public WebElement findElement() {
            return null;
        }
    }
}

在此示例中,我添加了两个辅助方法:getFieldLocator 和 findNestedElement。 getFieldLocator 从 ElementLocatorFactory 和 Field 生成相应的 By 定位器,findNestedElement 使用这两个 By 对象来查找嵌套元素。 getFieldLocator 方法从 ElementLocatorFactory 和 Field 生成相应的 By 定位器,findNestedElement 使用这些 By 对象来查找嵌套元素。

请注意,我在这里使用一个名为 ByElementLocator 的假设类,因为 ElementLocator 接口本身不提供获取 By 对象的方法。您需要使您的代码适应您实际使用的 Selenium 绑定或扩展库,以便从 ElementLocator 正确获取 By 对象。

确保 ElementLocatorFactory 创建的 ElementLocator 实现了获取 By 对象的方法。如果您使用标准 Selenium 支持包,您可能需要采用不同的方法来实现获取 By 对象。

在这段代码中,decorate方法的返回值设置为null,您需要根据情况返回正确的对象,例如代理WebElement、自定义页面对象或您需要的任何其他对象装饰。

© www.soinside.com 2019 - 2024. All rights reserved.