添加事件操作注入功能
This commit is contained in:
parent
bf549f3f32
commit
eb427a1b61
|
@ -107,7 +107,7 @@ public class CommonBy extends AbstractBy {
|
|||
switchFrame(getParentFrameName(elementInformation.name));
|
||||
}
|
||||
|
||||
return new Element(driver, ElementType.COMMON_ELEMENT, recognitionElement(elementInformation));
|
||||
return new Element(driver, ElementType.COMMON_ELEMENT, recognitionElement(elementInformation), elementInformation.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,6 +36,11 @@ public class Element {
|
|||
*/
|
||||
private WebDriver driver;
|
||||
|
||||
/**
|
||||
* 用于存储元素的名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 标记元素的类型,以用于重新获取时
|
||||
*/
|
||||
|
@ -46,12 +51,13 @@ public class Element {
|
|||
* @param name 元素名称或定位内容
|
||||
* @param byType 元素定位
|
||||
*/
|
||||
public Element(WebDriver driver, ElementType elementType, By by, int index) {
|
||||
public Element(WebDriver driver, ElementType elementType, By by, String name, int index) {
|
||||
super();
|
||||
this.by = by;
|
||||
this.index = index;
|
||||
this.driver = driver;
|
||||
this.elementType = elementType;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,8 +65,8 @@ public class Element {
|
|||
* @param name 元素名称或定位内容
|
||||
* @param byType 元素定位
|
||||
*/
|
||||
public Element(WebDriver driver, ElementType elementType, By by) {
|
||||
this(driver, elementType, by, 0);
|
||||
public Element(WebDriver driver, ElementType elementType, By by, String name) {
|
||||
this(driver, elementType, by, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,4 +100,29 @@ public class Element {
|
|||
throw new IllegalArgumentException("Unexpected value: " + elementType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回元素 的名称
|
||||
* @return 元素名称
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回元素信息,输出格式“元素名称 + “元素” + 列表选项”
|
||||
* @return 元素信息
|
||||
*/
|
||||
public String getLog() {
|
||||
switch (elementType) {
|
||||
case COMMON_ELEMENT:
|
||||
return name + "元素";
|
||||
case DATA_LIST_ELEMENT:
|
||||
case SELECT_DATAS_ELEMENT:
|
||||
case SELECT_OPTION_ELEMENT:
|
||||
return name + "元素第" + index + "个选项";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected value: " + elementType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public abstract class ListBy extends MultiBy {
|
|||
int size = driver.findElements(by).size();
|
||||
//构造Element对象
|
||||
for (int i = 0; i < size; i++) {
|
||||
elementList.add(new Element(driver, ElementType.DATA_LIST_ELEMENT, by, i));
|
||||
elementList.add(new Element(driver, ElementType.DATA_LIST_ELEMENT, by, elementInformation.name, i));
|
||||
}
|
||||
//elementList = driver.findElements(recognitionElement(elementInformation));
|
||||
//添加元素
|
||||
|
|
|
@ -198,7 +198,7 @@ public class SelectBy extends MultiBy {
|
|||
//构造Element对象
|
||||
for (int i = 0; i < size; i++) {
|
||||
//获取元素
|
||||
option.add(new Element(driver, elementType, by, i));
|
||||
option.add(new Element(driver, elementType, by, elementInformation.name, i));
|
||||
//获取元素的文本内容
|
||||
optionText.add(elementList.get(i).getText());
|
||||
}
|
||||
|
|
|
@ -2,16 +2,14 @@ package pres.auxiliary.work.selenium.event;
|
|||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.openqa.selenium.JavascriptExecutor;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>AbstractEvent.java</p>
|
||||
* <p><b>用途:</b>所有事件类的基类,包含了事件类所用到的基础方法以及弹窗处理方法和窗体、窗口的切换方法</p>
|
||||
* <p><b>编码时间:</b>2019年9月24日下午4:24:15</p>
|
||||
* <p><b>修改时间:</b>2020年5月10日 下午3:42:15</p>
|
||||
* <p><b>修改时间:</b>2020年7月10日上午16:49:37</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
|
@ -31,16 +29,6 @@ public abstract class AbstractEvent {
|
|||
*/
|
||||
long waitTime = 5;
|
||||
|
||||
/**
|
||||
* 用于在记录步骤时需要替换的元素名称文本
|
||||
*/
|
||||
public static final String ELEMENT_NAME = "&{元素名称}";
|
||||
|
||||
/**
|
||||
* 存储事件的操作说明
|
||||
*/
|
||||
String step = "";
|
||||
|
||||
/**
|
||||
* 构造对象并存储浏览器的WebDriver对象
|
||||
*
|
||||
|
@ -59,29 +47,4 @@ public abstract class AbstractEvent {
|
|||
public void setWaitTime(long waitTime) {
|
||||
wait.withTimeout(Duration.ofSeconds(waitTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于获取事件的文字说明,其文字存在一个可以替换元素名称的预留字段,可根据参数确定返回时是否需要保留该字段
|
||||
* @param clearElementName 是否清除预留字段
|
||||
* @return 操作的文本说明
|
||||
*/
|
||||
public String getStep(boolean clearElementName) {
|
||||
return clearElementName ? step.replaceAll(ELEMENT_NAME, "") : step;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于将页面控件元素高亮显示
|
||||
* @param element 当前指向的元素
|
||||
*/
|
||||
void elementHight(WebElement element) {
|
||||
//获取当前指向的元素的style属性
|
||||
String elementStyle = element.getAttribute("style");
|
||||
// 控件高亮
|
||||
((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('style',arguments[1])", element,
|
||||
elementStyle + "background:yellow;solid:red;");
|
||||
|
||||
//解除高亮
|
||||
((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('style',arguments[1])",
|
||||
element, elementStyle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import pres.auxiliary.work.selenium.element.Element;
|
|||
* 定义了对控件进行点击操作相关的方法,可通过该类,对页面进行基本的点击操作
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2019年8月29日下午3:24:34</p>
|
||||
* <p><b>修改时间:</b>2020年5月10日 下午3:42:36</p>
|
||||
* <p><b>修改时间:</b>2020年7月10日上午16:49:37</p>
|
||||
*
|
||||
* @author 彭宇琦
|
||||
* @version Ver2.0
|
||||
|
@ -55,8 +55,6 @@ public class ClickEvent extends AbstractEvent {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
step = "鼠标左键点击“" + ELEMENT_NAME + "”元素";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,8 +80,6 @@ public class ClickEvent extends AbstractEvent {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
step = "鼠标左键双击“" + ELEMENT_NAME + "”元素";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,8 +104,6 @@ public class ClickEvent extends AbstractEvent {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
step = "鼠标右键点击“" + ELEMENT_NAME + "”元素";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +122,5 @@ public class ClickEvent extends AbstractEvent {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
step = "鼠标左键连续" + clickCount + "次点击“" + ELEMENT_NAME + "”元素";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package pres.auxiliary.work.selenium.event;
|
||||
|
||||
import pres.auxiliary.work.selenium.element.Element;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>EventAction.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 用于执行事件增强的方法,方法中可通过{@link EventInformation}类对象,回调事件的操作的步骤
|
||||
* 以及传入到事件中的{@link Element}类对象
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年7月10日下午3:40:13</p>
|
||||
* <p><b>修改时间:</b>2020年7月10日下午3:40:13</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*
|
||||
*/
|
||||
public interface EventAction {
|
||||
/**
|
||||
* 事件增强的方法,可通过形参回调事件的操作步骤以及传入到事件中的{@link Element}类对象
|
||||
* @param name {@link EventInformation}类对象
|
||||
*/
|
||||
void action(EventInformation elemenetInformation);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package pres.auxiliary.work.selenium.event;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import pres.auxiliary.work.selenium.element.Element;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>EventInformation.java</p>
|
||||
* <p><b>用途:</b>
|
||||
* 用于存储事件的信息
|
||||
* </p>
|
||||
* <p><b>编码时间:</b>2020年7月10日下午3:47:58</p>
|
||||
* <p><b>修改时间:</b>2020年7月10日下午3:47:58</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
*
|
||||
*/
|
||||
public class EventInformation {
|
||||
/**
|
||||
* 存储事件操作的方法
|
||||
*/
|
||||
private Method method;
|
||||
/**
|
||||
* 传入到事件的参数
|
||||
*/
|
||||
private Object[] args;
|
||||
/**
|
||||
* 存储传入到方法中的元素类对象,由args进行分离
|
||||
*/
|
||||
private ArrayList<Element> elementList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 构造对象
|
||||
* @param method 事件方法的{@link Method}类对象
|
||||
* @param args 传入事件方法的参数
|
||||
*/
|
||||
public EventInformation(Method method, Object[] args) {
|
||||
super();
|
||||
this.method = method;
|
||||
this.args = args;
|
||||
//提取Element类对象
|
||||
getElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回事件操作方法类对象
|
||||
* @return 事件的{@link Method}类对象
|
||||
*/
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于返回传入事件方法的参数
|
||||
* @return 传入事件方法的参数
|
||||
*/
|
||||
public Object[] getParam() {
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于将args中为Element类对象的参数进行转换并存储至elementList中
|
||||
*/
|
||||
private void getElement() {
|
||||
Arrays.stream(args).forEach(arg -> {
|
||||
if (arg instanceof Element) {
|
||||
elementList.add((Element) arg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package pres.auxiliary.work.selenium.event;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
|
||||
import pres.auxiliary.work.selenium.element.Element;
|
||||
|
||||
public class EventProxy<T extends AbstractEvent> implements MethodInterceptor {
|
||||
/**
|
||||
* 用于存储方法前置通知,key表示方法名称匹配规则,value表示调用的方法
|
||||
*/
|
||||
private LinkedHashMap<String, ArrayList<EventAction>> functionBeforeActionMap = new LinkedHashMap<>(16);
|
||||
/**
|
||||
* 用于存储元素前置通知,key表示元素名称匹配规则,value表示调用的方法
|
||||
*/
|
||||
private LinkedHashMap<String, ArrayList<EventAction>> elementBeforeActionMap = new LinkedHashMap<>(16);
|
||||
/**
|
||||
* 用于存储元素后置通知
|
||||
*/
|
||||
private LinkedHashMap<String, ArrayList<EventAction>> elementAfterActionMap = new LinkedHashMap<>(16);
|
||||
/**
|
||||
* 用于存储方法执行成功通知
|
||||
*/
|
||||
private LinkedHashMap<String, ArrayList<EventAction>> functionSuccessActionMap = new LinkedHashMap<>(16);
|
||||
/**
|
||||
* 用于存储方法执行失败通知
|
||||
*/
|
||||
private LinkedHashMap<String, ArrayList<EventAction>> functionFailActionMap = new LinkedHashMap<>(16);
|
||||
/**
|
||||
* 用于存储方法最终通知
|
||||
*/
|
||||
private LinkedHashMap<String, ArrayList<EventAction>> functionFinalActionMap = new LinkedHashMap<>(16);
|
||||
|
||||
/**
|
||||
* 事件类对象
|
||||
*/
|
||||
private T target;
|
||||
|
||||
/**
|
||||
* 构造代理类
|
||||
* @param target {@link AbstractEvent}类或其子类
|
||||
*/
|
||||
public EventProxy(T target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建{@link AbstractEvent}类或其子类的代理类对象,通过该类可调用
|
||||
* {@link AbstractEvent}类或子类的所有方法
|
||||
* @return {@link AbstractEvent}类或子类的代理类对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T getProxyInstance(){
|
||||
//1.工具类
|
||||
Enhancer en = new Enhancer();
|
||||
//2.设置父类
|
||||
en.setSuperclass(target.getClass());
|
||||
//3.设置回调函数
|
||||
en.setCallback(this);
|
||||
//4.创建子类(代理对象)
|
||||
return (T) en.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||
//构造事件信息类对象
|
||||
EventInformation eventInformation = new EventInformation(method, args);
|
||||
|
||||
//按照方法名或元素名,匹配到相应的通知后,运行通知,若通知运行出现异常,则直接跳过
|
||||
//运行方法前置通知
|
||||
functionBeforeActionMap.forEach((key, value) -> {
|
||||
if (Pattern.compile(key).matcher(method.getName()).matches()) {
|
||||
value.forEach(action -> {
|
||||
//出现异常则不进行处理
|
||||
try {
|
||||
action.action(eventInformation);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//运行元素前置通知
|
||||
Arrays.stream(args).filter(arg -> arg instanceof Element).forEach(arg -> {
|
||||
elementBeforeActionMap.forEach((key, value) -> {
|
||||
if (Pattern.compile(key).matcher(((Element) arg).getName()).matches()) {
|
||||
value.forEach(action -> {
|
||||
try {
|
||||
action.action(eventInformation);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//执行目标对象的方法
|
||||
try {
|
||||
Object returnValue = method.invoke(target, args);
|
||||
//运行方法成功执行通知
|
||||
functionSuccessActionMap.forEach((key, value) -> {
|
||||
if (Pattern.compile(key).matcher(method.getName()).matches()) {
|
||||
value.forEach(action -> {
|
||||
//出现异常则不进行处理
|
||||
try {
|
||||
action.action(eventInformation);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return returnValue;
|
||||
} catch (Exception exception) {
|
||||
//运行方法失败执行通知
|
||||
functionFailActionMap.forEach((key, value) -> {
|
||||
if (Pattern.compile(key).matcher(method.getName()).matches()) {
|
||||
value.forEach(action -> {
|
||||
//出现异常则不进行处理
|
||||
try {
|
||||
action.action(eventInformation);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
throw exception;
|
||||
} finally {
|
||||
//运行元素后置通知
|
||||
Arrays.stream(args).filter(arg -> arg instanceof Element).forEach(arg -> {
|
||||
elementAfterActionMap.forEach((key, value) -> {
|
||||
if (Pattern.compile(key).matcher(((Element) arg).getName()).matches()) {
|
||||
value.forEach(action -> {
|
||||
try {
|
||||
action.action(eventInformation);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//运行方法最终通知
|
||||
functionFinalActionMap.forEach((key, value) -> {
|
||||
if (Pattern.compile(key).matcher(method.getName()).matches()) {
|
||||
value.forEach(action -> {
|
||||
//出现异常则不进行处理
|
||||
try {
|
||||
action.action(eventInformation);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -145,7 +145,7 @@ public class JsEvent extends AbstractEvent {
|
|||
// 获取新添加元素的xpath
|
||||
String xpath = addElement(element, elementName);
|
||||
// 查找新添加的元素(由于是新添加的元素,肯定能查找到,故无需编写等待)
|
||||
Element newElement = new Element(driver, ElementType.COMMON_ELEMENT, By.xpath(xpath));
|
||||
Element newElement = new Element(driver, ElementType.COMMON_ELEMENT, By.xpath(xpath), "TeamElement");
|
||||
|
||||
// 获取元素的所有属性
|
||||
JSONArray attributes = elementJson.getJSONArray("attributes");
|
||||
|
|
|
@ -21,10 +21,10 @@ import pres.auxiliary.work.selenium.tool.Screenshot;
|
|||
* <p><b>文件名:</b>TextEvent.java</p>
|
||||
* <p><b>用途:</b>定义了对控件文本操作相关的方法,可通过该类,对页面进行对控件输入,文本获取等操作</p>
|
||||
* <p><b>编码时间:</b>2019年9月6日上午9:28:59</p>
|
||||
* <p><b>修改时间:</b>2019年11月29日上午9:53:37</p>
|
||||
* <p><b>修改时间:</b>2020年7月10日上午16:49:37</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
* @since JDK 8
|
||||
*
|
||||
*/
|
||||
public class TextEvent extends AbstractEvent {
|
||||
|
@ -62,9 +62,6 @@ public class TextEvent extends AbstractEvent {
|
|||
}
|
||||
});
|
||||
|
||||
//记录操作
|
||||
step = "清空“" + ELEMENT_NAME + "”元素内的文本";
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -78,10 +75,6 @@ public class TextEvent extends AbstractEvent {
|
|||
//等待元素中attributeName指向的属性内容出现
|
||||
wait.until(ExpectedConditions.attributeToBeNotEmpty(element.getWebElement(), attributeName));
|
||||
|
||||
|
||||
//记录操作
|
||||
step = "获取“" + ELEMENT_NAME + "”元素的" + attributeName +"属性的内容";
|
||||
|
||||
//对元素进行操作,若元素过期,则重新获取
|
||||
return wait.until(driver -> {
|
||||
try {
|
||||
|
@ -99,9 +92,6 @@ public class TextEvent extends AbstractEvent {
|
|||
* @return 对应元素中的文本内容
|
||||
*/
|
||||
public String getText(Element element) {
|
||||
//记录操作
|
||||
step = "获取“" + ELEMENT_NAME + "”元素内的文本";
|
||||
|
||||
//对元素进行操作,若元素过期,则重新获取
|
||||
return wait.until(driver -> {
|
||||
try {
|
||||
|
@ -131,9 +121,6 @@ public class TextEvent extends AbstractEvent {
|
|||
}
|
||||
});
|
||||
|
||||
//记录操作
|
||||
step = "获取“" + ELEMENT_NAME + "”元素内的文本";
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -249,8 +236,6 @@ public class TextEvent extends AbstractEvent {
|
|||
* @return 上传的文件路径
|
||||
*/
|
||||
public String updataFile(Element element, File updataFile) {
|
||||
//记录操作
|
||||
step = "向“" + ELEMENT_NAME + "”元素中的上传文件";
|
||||
return input(element, updataFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue