添加获取列表元素的多个方法

This commit is contained in:
彭宇琦 2020-05-09 17:54:44 +08:00
parent 898f539e9a
commit 8edc93119c
5 changed files with 334 additions and 76 deletions

View File

@ -152,7 +152,7 @@ public class DataListEvent extends ListElementEvent {
}
/**
* 用于对列中元素的文本进行筛选回符合筛选项序号
* 用于对列中元素的文本进行筛选qwa回符合筛选项序号
*
* @param name 列名
* @param index 筛选后所在的列下标下标从1开始1表示第一个元素

View File

@ -205,7 +205,7 @@ public abstract class AbstractElement {
* @param name 窗体的名称或xpath与css定位方式
*/
public void switchFrame(String name) {
switchFrame(name, null);
switchFrame(new ElementInformation(name, null));
}
/**
@ -218,18 +218,26 @@ public abstract class AbstractElement {
* @see #switchFrame(String)
*/
public void switchFrame(String name, ByType byType) {
switchFrame(new ElementInformation(name, byType));
}
/**
* 切换窗体的底层方法
* @param elementInformation 元素信息类对象
*/
private void switchFrame(ElementInformation elementInformation) {
List<String> nameList = new ArrayList<String>();
//判断传入的元素名称是否存在于xml文件中若存在则将该元素的父层名称存储至nameList
if (xml != null && xml.isElement(name) && isAutoSwitchIframe) {
nameList.addAll(getParentFrameName(name));
if (isXmlElement(elementInformation.name) && isAutoSwitchIframe) {
nameList.addAll(getParentFrameName(elementInformation.name));
}
//调用切换窗体的方法
switchFrame(nameList);
driver.switchTo().frame(recognitionElement(name, byType).get(0));
driver.switchTo().frame(recognitionElement(elementInformation).get(0));
//切换窗体
iframeNameList.add(name);
iframeNameList.add(elementInformation.name);
}
/**
@ -264,7 +272,7 @@ public abstract class AbstractElement {
}
} else {
//切换窗体
driver.switchTo().frame(recognitionElement(frameName, null).get(0));
driver.switchTo().frame(recognitionElement(new ElementInformation(frameName, null)).get(0));
iframeNameList.add(frameName);
}
});
@ -309,7 +317,7 @@ public abstract class AbstractElement {
driver.switchTo().window(newWinHandle);
try {
//构造信息因为在构造过程中会判断元素是否存在
recognitionElement(controlName, null);
recognitionElement(new ElementInformation(controlName, null));
return;
}catch (Exception e) {
continue;
@ -322,7 +330,7 @@ public abstract class AbstractElement {
//切换窗口并查找元素是否在窗口上若存在则结束切换
brower.switchWindow(page);
try {
recognitionElement(controlName, null);
recognitionElement(new ElementInformation(controlName, null));
return;
}catch (Exception e) {
continue;
@ -399,39 +407,44 @@ public abstract class AbstractElement {
* @throws TimeoutException 元素在指定时间内未查找到时抛出的异常
* @throws UnrecognizableLocationModeException 元素无法识别时抛出的异常
*/
/*
List<WebElement> recognitionElements(ElementInformation element) {
return driver.findElements(element.getBy());
}
*/
List<WebElement> recognitionElement(String name, ByType byType) {
List<WebElement> recognitionElement(ElementInformation elementInformation) {
By by;
//若未指定xml文件或者在xml文件中无法查到相应的元素时则将name的值赋给value且根据value判断相应定位方式
if (isXmlElement(name)) {
by = recognitionCommonElement(name, byType);
} else {
if (isXmlElement(elementInformation.name)) {
//若指定了xml文件且传入的元素名称存在与xml文件中则判断元素相应的定位方式及定位内容
by = recognitionXmlElement(name, byType);
by = recognitionXmlElement(elementInformation);
} else {
//若未指定xml文件或者在xml文件中无法查到相应的元素时则将name的值赋给value且根据value判断相应定位方式
by = recognitionCommonElement(elementInformation);
}
return driver.findElements(by);
}
private By recognitionCommonElement(String name, ByType byType) {
/**
* 获取普通元素的By对象
* @param elementInformation 元素信息类对象
* @return 元素信息指向的By对象
*/
private By recognitionCommonElement(ElementInformation elementInformation) {
//判断传入的ByType对象是否为null
if (byType == null) {
return judgeCommonElementBy(name);
if (elementInformation.byType == null) {
return judgeCommonElementBy(elementInformation.name);
} else {
return getBy(name, byType);
return getBy(elementInformation.name, elementInformation.byType);
}
}
private By recognitionXmlElement(String name, ByType byType) {
/**
* 获取xml文件内元素的By对象
* @param elementInformation 元素信息类对象
* @return 元素信息指向的By对象
*/
private By recognitionXmlElement(ElementInformation elementInformation) {
//判断传入的ByType对象是否为null
if (byType == null) {
return judgeXmlElementBy(name);
if (elementInformation.byType == null) {
return judgeXmlElementBy(elementInformation.name);
} else {
return xml.getBy(name, byType);
return xml.getBy(elementInformation.name, elementInformation.byType);
}
}
@ -587,7 +600,46 @@ public abstract class AbstractElement {
*/
abstract boolean isExistElement(By by, long waitTime);
/**
* 用于判断元素是否为xml文件内的元素
* @param name 元素名称
* @return 是否为xml文件内的元素
*/
boolean isXmlElement(String name) {
return (xml == null || !xml.isElement(name));
return (xml != null && xml.isElement(name));
}
/**
* <p><b>文件名</b>AbstractElement.java</p>
* <p><b>用途</b>
* 存储获取元素时的信息
* </p>
* <p><b>编码时间</b>2020年5月9日上午7:57:24</p>
* <p><b>修改时间</b>2020年5月9日上午7:57:24</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
class ElementInformation {
/**
* 存储元素的名称或定位内容
*/
public String name;
/**
* 存储元素的定位方式
*/
public ByType byType;
/**
* 初始化信息
* @param name 元素名称或定位内容
* @param byType 元素定位
*/
public ElementInformation(String name, ByType byType) {
super();
this.name = name;
this.byType = byType;
}
}
}

View File

@ -59,12 +59,21 @@ public class CommonElement extends AbstractElement {
* @return WebElement对象
*/
public WebElement getWebElement(String name, ByType byType) {
return getWebElement(new ElementInformation(name, byType));
}
/**
* 获取元素的底层方法
* @param elementInformation 元素信息类对象
* @return WebElement对象
*/
private WebElement getWebElement(ElementInformation elementInformation) {
//判断传入的元素是否在xml文件中若存在再判断是否自动切换窗体若需要则获取元素的所有父窗体并进行切换
if (xml != null && xml.isElement(name) && isAutoSwitchIframe) {
switchFrame(getParentFrameName(name));
if (xml != null && xml.isElement(elementInformation.name) && isAutoSwitchIframe) {
switchFrame(getParentFrameName(elementInformation.name));
}
return recognitionElement(name, byType).get(0);
return recognitionElement(elementInformation).get(0);
}
@Override

View File

@ -2,14 +2,18 @@ package pres.auxiliary.work.selenium.element;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;
import pres.auxiliary.selenium.event.DataListEvent.ListEvent;
import pres.auxiliary.selenium.xml.ByType;
import pres.auxiliary.work.selenium.brower.AbstractBrower;
@ -31,7 +35,7 @@ public class DataListElement extends AbstractElement {
/**
* 用于存储获取到的列表一列元素key为列表名称value为列表元素
*/
private HashMap<String, List<WebElement>> elementMap = new HashMap<>(16);
private LinkedHashMap<ElementInformation, List<WebElement>> elementMap = new LinkedHashMap<>(16);
/**
* 用于存储元素列累计的个数
@ -41,7 +45,7 @@ public class DataListElement extends AbstractElement {
/**
* 用于存储是否开始累加列表元素的个数
*/
private boolean isStartAddSize = false;
// private boolean isStartAddSize = false;
/**
* 用于判断列表的第一行元素是否为标题元素
@ -55,7 +59,7 @@ public class DataListElement extends AbstractElement {
/**
* 存储获取到的元素列表中最多元素列的名称
*/
private String maxColumnName = "";
private ArrayList<String> maxColumnNameList = new ArrayList<>();
/**
* 存储获取到的元素列表中最少元素列的元素个数
*/
@ -63,7 +67,7 @@ public class DataListElement extends AbstractElement {
/**
* 存储获取到的元素列表中最少元素列的名称
*/
private String minColumnName = "";
private ArrayList<String> minColumnNameList = new ArrayList<>();
/**
* 通过浏览器对象{@link AbstractBrower}进行构造
@ -94,9 +98,11 @@ public class DataListElement extends AbstractElement {
* 用于设置是否开始计算元素个数
* @param isStartAddSize 是否开始计算元素个数
*/
/*
public void setStartAddSize(boolean isStartAddSize) {
this.isStartAddSize = isStartAddSize;
}
*/
/**
* 返回元素最多列的元素个数
@ -110,8 +116,8 @@ public class DataListElement extends AbstractElement {
* 返回元素最多列的列名称
* @return 元素最多列的列名称
*/
public String getMaxColumnName() {
return maxColumnName;
public List<String> getMaxColumnName() {
return maxColumnNameList;
}
/**
@ -126,8 +132,8 @@ public class DataListElement extends AbstractElement {
* 返回元素最少列的列名称
* @return 元素最少列的列名称
*/
public String getMinColumnName() {
return minColumnName;
public List<String> getMinColumnName() {
return minColumnNameList;
}
/**
@ -136,66 +142,83 @@ public class DataListElement extends AbstractElement {
* @return 列名对应列的元素个数
*/
public int getColumnSize(String name) {
if (elementMap.containsKey(name)) {
return elementMap.get(name).size();
ElementInformation element = nameToElementInformation(name);
if (element != null) {
return elementMap.get(element).size();
} else {
return -1;
}
}
/**
* 该方法用于返回所有列的名称
* @return 所有列的名称
*/
public ArrayList<String> getColumnName() {
ArrayList<String> nameList = new ArrayList<>();
elementMap.forEach((key, value) -> {
nameList.add(key.name);
});
return nameList;
}
/**
* 用于根据传入的元素在xml文件中的名称或者元素的定位内容添加元素列由于该方法不指定元素的定位
* 方式若传入的参数不是xml元素且非xpath路径或绝对css路径时其识别效率较慢建议在该情况下
* 调用{@link #add(String, ByType)}方法指定元素定位方法
* @param name 元素在xml文件或者元素的定位内容
* @param isAddSize 是否对元素个数进行统计
// * @param isAddSize 是否对元素个数进行统计
* @see #add(String, ByType)
* @throws TimeoutException 元素在指定时间内无法找到时抛出的异常
*/
public void add(String name, boolean isAddSize) {
add(name, null, isAddSize);
public void add(String name) {
add(name, null);
}
/**
* 用于根据传入的元素在xml文件中的名称或者元素的定位内容以及元素的定位方式添加元素列
* @param name 元素在xml文件或者元素的定位内容
* @param byType 元素定位方式枚举对象{@link ByType}枚举
* @param isAddSize 是否对元素个数进行统计
// * @param isAddSize 是否对元素个数进行统计
* @see #add(String)
* @throws TimeoutException 元素在指定时间内无法找到时抛出的异常
*/
public void add(String name, ByType byType, boolean isAddSize) {
public void add(String name, ByType byType) {
}
/**
* 添加元素的底层方法
* @param elementInformation 元素信息类对象
* @param isAddSize 是否需要统计
*/
private void add(ElementInformation elementInformation) {
List<WebElement> elementList = new ArrayList<WebElement>();
//获取元素
elementList = recognitionElement(name, byType);
elementList = recognitionElement(elementInformation);
//添加元素
elementMap.put(name, elementList);
elementMap.put(elementInformation, elementList);
//判断当前获取到的元素是否大于当前存储的元素的最大值或小于当前存储的最小值若是则将最大值或最小值进行替换
int elementSize = elementList.size();
if (elementSize > maxColumnSize) {
maxColumnSize = elementSize;
maxColumnName = name;
} else if (elementSize < minColumnSize) {
minColumnSize = elementSize;
minColumnName = name;
} else {
}
findLimitColumn(elementInformation);
/*
//判断元素是否需统计若元素需要统计则对元素列表的个数加上当前获取到的元素个数若不需要统计则移除该元素
if (isAddSize) {
if (elementSizeMap.containsKey(name)) {
elementSizeMap.put(name, 0);
if (elementSizeMap.containsKey(elementInformation.name)) {
elementSizeMap.put(elementInformation.name, 0);
}
if (isStartAddSize) {
elementSizeMap.put(name, elementSizeMap.get(name) + elementSize);
elementSizeMap.put(elementInformation.name, elementSizeMap.get(elementInformation.name) + elementList.size());
}
} else {
if (elementSizeMap.containsKey(name)) {
elementSizeMap.remove(name);
if (elementSizeMap.containsKey(elementInformation.name)) {
elementSizeMap.remove(elementInformation.name);
}
}
*/
}
/**
@ -206,41 +229,215 @@ public class DataListElement extends AbstractElement {
* @return 被移除列中存储的所有元素
*/
public List<WebElement> clearColumn(String name, boolean isRemove) {
ElementInformation element = nameToElementInformation(name);
//若元素不存在则直接返回null
if (elementMap.containsKey(name)) {
if (element == null) {
return null;
}
//用于存储被移除的元素
List<WebElement> elementList = elementMap.get(name);
List<WebElement> elementList = elementMap.get(element);
//判断元素是否需要被完全移除
if (isRemove) {
//若元素需要被完全移除则直接移除元素
elementMap.remove(name);
elementMap.remove(element);
//由于元素被移除若该列存在元素个数统计则同样将该元素移除
if (elementSizeMap.containsKey(name)) {
elementSizeMap.remove(name);
}
} else {
//若元素无需移除则将元素存储的列表内容清空
elementMap.get(name).clear();
elementMap.get(element).clear();
}
return elementList;
}
private int findColumnLimitSize(boolean isMax) {
//根据传入的参数判断是获取最大值还是获取最小值根据不同的类型初始化不同的参数
int limit = isMax ? -1 : Integer.MAX_VALUE;
//TODO 获取极值
/**
* 该方法用于根据存入的元素名称或定位方式对元素进行重新获取的操作主要用于当列表数据翻页后
* 其原存入的数据将会失效必须重新获取注意调用该方法后会清空原存储的数据
*/
public void againGetElement() {
// 读取elements中的元素
elementMap.forEach((key, value) -> {
// 清空元素中的内容
clearColumn(key.name, false);
// 对页面内容重新进行获取
add(key);
});
return limit;
}
/**
* 该方法用于根据列名称查找到相应的列并返回与传入下标对应的元素下标支持从后向前获取传入的下标
* 与元素实际所在位置一致当传入0时则表示随机获取一个元素<br>
* {@code getWebElement("姓名", 1)}表示获取名称为姓名的列中的第1个元素<br>
* {@code getWebElement("姓名", 0)}表示获取名称为姓名的列中在长度范围内随机一个元素<br>
* {@code getWebElement("//*[@id='name']", -1)}表示获//*[@id='name']对应列中的倒数第1个元素<br>
*
* @param name 列名称
* @param index 元素下标即列表中对应的某一个元素
* @return 对应列指定的元素
* @throws NoSuchElementException 当未对name列进行获取数据或index的绝对值大于列表最大值时抛出的异常
*/
public WebElement getWebElement(String name, int index) {
//获取元素信息并判断元素是否存在不存在则抛出异常
ElementInformation element = nameToElementInformation(name);
if (element == null) {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
// 转义下标
index = getIndex(element, index);
// 转义下标后返回对应的元素
return elementMap.get(element).get(index);
}
/**
* 该方法用于根据列名称获取该列下所有的元素
*
* @param name 列名称
* @return 对应列元素
* @throws NoSuchElementException 当未对name列进行获取数据时抛出的异常
*/
public List<WebElement> getAllWebElement(String name) {
//获取元素信息并判断元素是否存在不存在则抛出异常
ElementInformation element = nameToElementInformation(name);
if (element == null) {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
return elementMap.get(element);
}
/**
* 用于返回列表多个指定的元素传入的下标可参见{@link #getWebElement(String, int)}
*
* @param name 列名称
* @param indexs 一组元素下标即列表中对应的某一个元素
* @return 对应列多个指定下标的元素
* @throws NoSuchElementException 当未对name列进行获取数据或index的绝对值大于列表最大值时抛出的异常
* @see #getWebElement(String, int)
*/
public List<WebElement> getWebElements(String name, int... indexs) {
// 存储所有获取到的事件
ArrayList<WebElement> events = new ArrayList<>();
// 循环解析所有的下标并调用getEvent()方法存储至events
for (int index : indexs) {
events.add(getWebElement(name, index));
}
return events;
}
/**
* 用于返回列表中指定随机个数的元素
*
* @param name 列名称
* @param length 需要返回列表事件的个数
* @return 列表事件组
*/
public List<WebElement> getRandomWebElements(String name, int length) {
// 判断传入的长度是否大于等于当前
if (length >= elements.get(name).size()) {
return getEvents(name);
}
// 存储通过随机得到的数字
ArrayList<Integer> indexsList = new ArrayList<Integer>();
// 循环随机获取下标数字
for (int i = 0; i < length; i++) {
int randomIndex = 0;
// 循环直到生成的随机数不在indexs中为止
while (indexsList.contains(randomIndex = new Random().nextInt(elements.get(name).size()) + 1)) {
}
indexsList.add(randomIndex);
}
// 将indexsList转换成int[]
int[] indexs = new int[indexsList.size()];
for (int i = 0; i < indexsList.size(); i++) {
indexs[i] = indexsList.get(i);
}
return getEvents(name, indexs);
}
/**
* 用于根据参数求取elementMap中最多或最少列表的元素个数以及列表的名称
* @param isMax 是否为求取最大值
* @return 极值以及极值所在的列
*/
private void findLimitColumn(ElementInformation key) {
//获取指向的元素列表的元素个数
int size = elementMap.get(key).size();
//根据参数判断获取的列是否为最大值所在的列并对极值做进一步判断
if (maxColumnSize < size) {
if (maxColumnSize < size) {
maxColumnNameList.clear();
maxColumnSize = size;
}
maxColumnNameList.add(key.name);
} else {
//对比当前存储的最小值与列的元素个数其操作与求取最大值相反
if (minColumnSize < size) {
return;
}
if (minColumnSize > size) {
minColumnNameList.clear();
minColumnSize = size;
}
minColumnNameList.add(key.name);
}
}
/**
* 由于方法允许传入负数和特殊数字0为下标并且下标的序号由1开始
* 故可通过该方法对下标的含义进行转义得到java能识别的下标
* @param element 元素信息类对象
* @param index 传入的下标
* @return 可识别的下标
* @throws NoSuchElementException 当元素无法查找到时抛出的异常
*/
int getIndex(ElementInformation element, int index) {
int length = elementMap.get(element).size();
//判断元素下标是否超出范围由于可以传入负数故需要使用绝对值
if (Math.abs(index) > length) {
throw new NoSuchElementException("指定的选项值大于选项的最大值。选项总个数:" + length + ",指定项:" + index);
}
//判断index的值若大于0则从前向后遍历若小于0则从后往前遍历若等于0则随机输入
if (index > 0) {
//选择元素正数的选项值从1开始故需要减小1
return index - 1;
} else if (index < 0) {
//选择元素由于index为负数则长度加上选项值即可得到需要选择的选项
return length + index;
} else {
//为0则随机进行选择
return new Random().nextInt(length);
}
}
/**
* 根据元素名称反推元素信息类对象用于根据列名称查找数据以及判断列是否存在若列名不存在则返回null
* @return ElementInformation对象
*/
ElementInformation nameToElementInformation(String name) {
//遍历elementMap若查找与name一致的名称则结束循环并返回相应的ElementInformation对象
for (ElementInformation element : elementMap.keySet()) {
if (element.name.equals(name)) {
return element;
}
}
return null;
}
@Override
boolean isExistElement(By by, long waitTime) {
//TODO 修改等待方法改为获取到元素后才返回相应的状态

View File

@ -23,7 +23,7 @@ import pres.auxiliary.work.selenium.brower.ChromeBrower.ChromeOptionType;
*
*/
public class CommonElementTest {
ChromeBrower cb = new ChromeBrower(new File("Resource/BrowersDriver/Chrom/80.0.3987.163/chromedriver.exe"));
ChromeBrower cb = new ChromeBrower(new File("Resource/BrowersDriver/Chrom/78.0394.70/chromedriver.exe"));
CommonElement ce;
@BeforeClass