添加外链xml功能
This commit is contained in:
parent
d56a49de5d
commit
a9ba0eb7c1
|
@ -2,6 +2,7 @@ package pres.auxiliary.work.selenium.element;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -462,9 +463,9 @@ public abstract class AbstractBy {
|
|||
private By recognitionXmlElement(ElementInformation elementInformation) {
|
||||
//判断传入的ByType对象是否为null
|
||||
if (elementInformation.byType == null) {
|
||||
return judgeXmlElementBy(elementInformation.name);
|
||||
return judgeXmlElementBy(elementInformation.name, elementInformation.linkKeyList);
|
||||
} else {
|
||||
By by = xml.getBy(elementInformation.name, elementInformation.byType);
|
||||
By by = xml.getBy(elementInformation.name, elementInformation.byType, elementInformation.linkKeyList);
|
||||
if (isExistElement(by, getWaitTime(elementInformation.name)))
|
||||
return by;
|
||||
else
|
||||
|
@ -556,11 +557,11 @@ public abstract class AbstractBy {
|
|||
/**
|
||||
* 用于设置xml文件内的元素的定位方式及定位内容
|
||||
*/
|
||||
By judgeXmlElementBy(String name) {
|
||||
By judgeXmlElementBy(String name, List<String> linkList) {
|
||||
By by;
|
||||
// 循环,逐个在页面上配对有效的标签对应的定位方式
|
||||
for (ByType mode : xml.getElementMode(name)) {
|
||||
by = getBy(xml.getValue(name, mode), mode);
|
||||
by = getBy(xml.getValue(name, mode, linkList), mode);
|
||||
|
||||
//若元素能被找到,则返回相应的By对象,若未找到,则再次循环
|
||||
if (isExistElement(by, getWaitTime(name))) {
|
||||
|
@ -626,7 +627,7 @@ public abstract class AbstractBy {
|
|||
* <p><b>修改时间:</b>2020年5月22日上午8:18:39</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.1
|
||||
* @since JDK 12
|
||||
* @since JDK 1.8
|
||||
*
|
||||
*/
|
||||
class ElementInformation {
|
||||
|
@ -642,6 +643,10 @@ public abstract class AbstractBy {
|
|||
* 用于标记元素的类型
|
||||
*/
|
||||
public ElementType elementType;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ArrayList<String> linkKeyList = new ArrayList<>();
|
||||
/**
|
||||
* 初始化信息
|
||||
* @param name 元素名称或定位内容
|
||||
|
@ -663,6 +668,20 @@ public abstract class AbstractBy {
|
|||
this.byType = byType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化信息
|
||||
* @param name 元素名称或定位内容
|
||||
* @param byType 元素定位
|
||||
* @param elementType 元素类型
|
||||
* @param links 元素外链信息
|
||||
*/
|
||||
public ElementInformation(String name, ByType byType, ElementType elementType, String...links) {
|
||||
this.name = name;
|
||||
this.byType = byType;
|
||||
|
||||
linkKeyList.addAll(Arrays.asList(links));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
|
|
|
@ -44,12 +44,12 @@ public class CommonBy extends AbstractBy {
|
|||
* 用于根据xml文件中元素的名称,返回对应的{@link Element}对象。该方法亦可传入元素
|
||||
* 定位内容,通过遍历所有的定位方式,在页面上查找元素,来获取元素的WebElement对象。
|
||||
* 建议传入的定位内容为xpath路径或绝对的css路径,若非这两路径,则在识别元素时会很慢,降低
|
||||
* 程序运行速度。若非xml文件中的元素,且不是xpath路径或绝对的css路径,建议使用{@link #getWebElement(String, ByType)}方法
|
||||
* 程序运行速度。若非xml文件中的元素,且不是xpath路径或绝对的css路径,建议使用{@link #getElement(String, ByType)}方法
|
||||
* @param name 元素的名称或元素定位内容
|
||||
* @return {@link Element}对象
|
||||
*/
|
||||
public Element getElement(String name) {
|
||||
return getElement(name, null);
|
||||
return getElement(new ElementInformation(name, null, ElementType.COMMON_ELEMENT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,23 +61,33 @@ public class CommonBy extends AbstractBy {
|
|||
public Element getElement(String name, ByType byType) {
|
||||
return getElement(new ElementInformation(name, byType, ElementType.COMMON_ELEMENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取元素的底层方法
|
||||
* @param elementInformation 元素信息类对象
|
||||
* @return WebElement对象
|
||||
*/
|
||||
/*
|
||||
private WebElement getWebElement(ElementInformation elementInformation) {
|
||||
//判断传入的元素是否在xml文件中,若存在再判断是否自动切换窗体,若需要,则获取元素的所有父窗体并进行切换
|
||||
if (xml != null && xml.isElement(elementInformation.name) && isAutoSwitchIframe) {
|
||||
switchFrame(getParentFrameName(elementInformation.name));
|
||||
}
|
||||
|
||||
return driver.findElement(recognitionElement(elementInformation));
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用于根据xml文件中元素的名称,与定位方式,返回对应的{@link Element}对象。该方法亦可传入元素
|
||||
* 定位内容,并根据定位方式,对页面数据进行查找。该方法可对由xml文件读取的内容进行词语替换,根据
|
||||
* 传参中词语的顺序,对需要替换的词语进行替换
|
||||
* @param name 元素名称或定位方式内容
|
||||
* @param byType 元素定位方式
|
||||
* @param links 替换词语
|
||||
* @return {@link Element}对象
|
||||
*/
|
||||
public Element getElement(String name, ByType byType, String...links) {
|
||||
return getElement(new ElementInformation(name, byType, ElementType.COMMON_ELEMENT, links));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据xml文件中元素的名称,返回对应的{@link Element}对象。该方法亦可传入元素
|
||||
* 定位内容,通过遍历所有的定位方式,在页面上查找元素,来获取元素的WebElement对象。
|
||||
* 建议传入的定位内容为xpath路径或绝对的css路径,若非这两路径,则在识别元素时会很慢,降低
|
||||
* 程序运行速度。若非xml文件中的元素,且不是xpath路径或绝对的css路径,建议使用{@link #getElement(String, ByType, String...)}方法
|
||||
* @param name 元素的名称或元素定位内容
|
||||
* @param links 替换词语
|
||||
* @return {@link Element}对象
|
||||
*/
|
||||
public Element getElement(String name, String...links) {
|
||||
return getElement(name, null, links);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取元素的底层方法
|
||||
* @param elementInformation 元素信息类对象
|
||||
|
|
|
@ -2,8 +2,10 @@ package pres.auxiliary.work.selenium.xml;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.dom4j.Attribute;
|
||||
|
@ -47,6 +49,10 @@ public class ReadXml {
|
|||
*/
|
||||
private Document dom;
|
||||
|
||||
/**
|
||||
* 切分公式标记
|
||||
*/
|
||||
private final String SPLIT_START = "\\$\\{";
|
||||
/**
|
||||
* 定义xml文件中,模板使用的替换符开始标志
|
||||
*/
|
||||
|
@ -142,8 +148,23 @@ public class ReadXml {
|
|||
* @throws NoSuchSignValueException 模板中存在为定义值的标志时抛出的异常
|
||||
*/
|
||||
public By getBy(String name, ByType mode) {
|
||||
return getBy(name, mode, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据元素名称,在指定的xml文件中查找到相应的元素,返回其元素的信息,以{@link By}类返回
|
||||
*
|
||||
* @param name 元素名称
|
||||
* @param mode 定位方式枚举类对象,参见{@link ByType}
|
||||
* @param linkKeyList 外链关键词集合
|
||||
* @return 元素对应的{@link By}类对象
|
||||
*
|
||||
* @throws UndefinedElementException 未找到相应的模板元素时抛出的异常
|
||||
* @throws NoSuchSignValueException 模板中存在为定义值的标志时抛出的异常
|
||||
*/
|
||||
public By getBy(String name, ByType mode, List<String> linkKeyList) {
|
||||
// 存储从xml文件中读取到的元素定位
|
||||
String elementPos = getValue(name, mode);
|
||||
String elementPos = getValue(name, mode, linkKeyList);
|
||||
|
||||
// 判断传入的参数是否符合使用By类的定位方式,如果符合,则拼接读取XML文件的xpath,若不符,则抛出异常
|
||||
try {
|
||||
|
@ -194,6 +215,53 @@ public class ReadXml {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于根据元素名称及定位方式查找其定位方式标签中的内容,并根据关键词组,对需要修改的关键词
|
||||
* 逐个进行修改。注意,该方法将根据需要修改的关键词顺序进行修改,与关键词名称无关
|
||||
*
|
||||
* @param name 元素名称
|
||||
* @param mode 定位方式枚举类对象,参见{@link ByType}
|
||||
* @return xml文件中的相应元素的定位值
|
||||
*
|
||||
* @throws UndefinedElementException 未找到相应的模板元素时抛出的异常
|
||||
* @throws NoSuchSignValueException 模板中存在为定义值的标志时抛出的异常
|
||||
*/
|
||||
public String getValue(String name, ByType mode, List<String> linkKeyList) {
|
||||
//获取到元素定位方式内容
|
||||
StringBuilder value = new StringBuilder(getValue(name, mode));
|
||||
|
||||
//判断linkKeyList是否为空或null,若为空或null,则直接返回
|
||||
if (linkKeyList == null || linkKeyList.isEmpty()) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
//按照公式起始符号对内容进行切分,遍历切分后的每一个元素
|
||||
String[] texts = value.toString().split(SPLIT_START);
|
||||
|
||||
//用于lambda中计算替换的词语位置
|
||||
AtomicInteger index = new AtomicInteger(0);
|
||||
//遍历texts
|
||||
Arrays.stream(texts)
|
||||
//过滤不包含END_SIGN的元素
|
||||
.filter(text -> text.indexOf(END_SIGN) > -1)
|
||||
//提取元素的有效替换词语(${XXX})
|
||||
.map(text -> START_SIGN + text.substring(0, text.indexOf(END_SIGN) + 1))
|
||||
//对词语进行替换
|
||||
.forEach(text -> {
|
||||
//判断当前下标是否超出linkKeyList最大元素个数,若超出,则结束当前执行
|
||||
if (index.get() >= linkKeyList.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//获取该字段在value中第一次出现的位置
|
||||
int signIndex = value.indexOf(text);
|
||||
// 将所有与该标志替换为元素属性中存储的内容(使用拼接的方式进行替换)
|
||||
value.replace(signIndex, signIndex + text.length(), linkKeyList.get(index.getAndAdd(1)));
|
||||
|
||||
});
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回元素的所在的窗体
|
||||
* @param name 元素在xml文件中的名称
|
||||
|
@ -253,7 +321,7 @@ public class ReadXml {
|
|||
"//templet/" + mode.getValue() + "[@id='" + element.attribute("temp_id").getValue() + "']");
|
||||
// 如果templetElement元素为null(无法查找到),则抛出UndefinedElementException
|
||||
if (templetElement == null) {
|
||||
throw new UndefinedElementException("未定义的模板。元素定位方式为:" + mode.getValue() + ",模板id为:"
|
||||
throw new UndefinedElementException("未定义的模板,元素定位方式为:" + mode.getValue() + ",模板id为:"
|
||||
+ element.attribute("temp_id").getValue() + ";该模板未定义");
|
||||
}
|
||||
|
||||
|
@ -265,18 +333,22 @@ public class ReadXml {
|
|||
attElements.put(att.getName(), att.getValue());
|
||||
}
|
||||
|
||||
// 存储存储模板的内容
|
||||
// 获取模板的内容
|
||||
String path = templetElement.getText();
|
||||
// 循环,遍历模板中的所有需要替换的属性
|
||||
while (path.indexOf(START_SIGN) > -1) {
|
||||
// 存储需要替换的标志名称
|
||||
String sign = path.substring(path.indexOf(START_SIGN) + START_SIGN.length(), path.indexOf(END_SIGN));
|
||||
// 判断该标志名称是否存储在attElements中,若不存在,则抛出异常
|
||||
if (!attElements.containsKey(sign)) {
|
||||
throw new NoSuchSignValueException(sign + "标志的值未记录为属性中;" + element.asXML());
|
||||
//按照公式起始符号对内容进行切分,遍历切分后的每一个元素
|
||||
String[] texts = path.split(SPLIT_START);
|
||||
for (int i = 0; i < texts.length; i++) {
|
||||
//判断切分的元素是否包含公式结束符号
|
||||
int index;
|
||||
if ((index = texts[i].indexOf(END_SIGN)) > -1) {
|
||||
//截取有效字符串,对关键词进行替换
|
||||
String sign = texts[i].substring(0, index);
|
||||
// 判断该标志名称是否存储在attElements中,若不存在,则抛出异常
|
||||
if (attElements.containsKey(sign)) {
|
||||
// 将所有与该标志相关的全部替换为元素属性中存储的内容
|
||||
path = path.replaceAll("\\$\\{" + sign + "\\}", attElements.get(sign));
|
||||
}
|
||||
}
|
||||
// 将所有与该标志相关的全部替换为元素属性中存储的内容
|
||||
path = path.replaceAll("\\$\\{" + sign + "\\}", attElements.get(sign));
|
||||
}
|
||||
|
||||
return path;
|
||||
|
|
|
@ -88,4 +88,14 @@ public class CommonByTest {
|
|||
//在获取元素前,会判断元素所在窗体,由于主窗体是爷爷辈窗体,获取元素前会切换工资发放详情窗体
|
||||
System.out.println(ce.getElement("单位名称").getWebElement().getText());
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于测试外链xml
|
||||
*/
|
||||
@Test
|
||||
public void getElementTest() {
|
||||
File xmlFile = new File("src/test/java/pres/auxiliary/work/selenium/element/测试文件.xml");
|
||||
ce.setXmlFile(xmlFile, false);
|
||||
System.out.println(ce.getElement("搜索条件", "工资单编号").getWebElement().getAttribute("type"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,27 @@
|
|||
package pres.auxiliary.selenium.xml.io;
|
||||
package pres.auxiliary.work.selenium.xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import pres.auxiliary.work.selenium.xml.ByType;
|
||||
import pres.auxiliary.work.selenium.xml.ReadXml;
|
||||
|
||||
/**
|
||||
* <p><b>文件名:</b>TestReadXml.java</p>
|
||||
* <p><b>用途:</b>用于测试ReadXml类</p>
|
||||
* <p><b>编码时间:</b>2019年10月25日下午3:14:25</p>
|
||||
* <p><b>修改时间:</b>2019年10月25日下午3:14:25</p>
|
||||
* @author 彭宇琦
|
||||
* @version Ver1.0
|
||||
* @since JDK 12
|
||||
*
|
||||
*/
|
||||
public class TestReadXml {
|
||||
ReadXml r;
|
||||
public class ReadXmlTest {
|
||||
ReadXml r;
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
@BeforeClass
|
||||
public void newReadXML() {
|
||||
r = new ReadXml(new File("src/test/java/pres/auxiliary/selenium/xml/io/测试用xml文件.xml"));
|
||||
r = new ReadXml(new File("src/test/java/pres/auxiliary/work/selenium/xml/测试用xml文件.xml"));
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
public void over(Method method) {
|
||||
System.out.println("*".repeat(5) + method.getName() + "运行完毕" + "*".repeat(5));
|
||||
System.out.println("*****" + method.getName() + "运行完毕" + "*****");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,4 +122,40 @@ public class TestReadXml {
|
|||
public void getIframeNameTest_RootElement() {
|
||||
System.out.println(r.getIframeName("XX控件1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于测试{@link ReadXml#getIframeName(String)}方法,获取模板元素
|
||||
*/
|
||||
@Test
|
||||
public void getIframeNameTest_NoPram() {
|
||||
System.out.println(r.getIframeName("XX控件12"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于测试{@link ReadXml#getValue(String, ByType)}方法,未查找到替换的属性
|
||||
*/
|
||||
@Test
|
||||
public void getValueTest_NoPram() {
|
||||
System.out.println(r.getValue("XX控件12", ByType.XPATH));
|
||||
System.out.println(r.getValue("窗体3", ByType.XPATH));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于测试{@link ReadXml#getValue(String, ByType)}方法,外链关键词
|
||||
*/
|
||||
@Test
|
||||
public void getValueTest_Link() {
|
||||
ArrayList<String> link = new ArrayList<>();
|
||||
link.add("测试1");
|
||||
link.add("测试2");
|
||||
link.add("测试3");
|
||||
|
||||
//XXX模板控件1[@X='${src}']/div[@name='${name}']
|
||||
System.out.println(r.getValue("XX控件13", ByType.XPATH, link));
|
||||
System.out.println(r.getValue("窗体3", ByType.XPATH, link));
|
||||
//XXX模板控件1[@X='${src}']/div[@name='${name}']/div[@is='${str1}' and text()='${str1}']
|
||||
System.out.println(r.getValue("XX控件14", ByType.XPATH, link));
|
||||
//XXX模板控件1[@X='${src}']/div[@name='${name}']/div[@is='${str1}' and text()='${src}']/span[text()='${str2}']/span[id='${aaaa}']
|
||||
System.out.println(r.getValue("XX控件15", ByType.XPATH, link));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue