添加TestNG数据驱动类及相应的单元测试类

This commit is contained in:
彭宇琦 2020-06-16 07:16:25 +08:00
parent f901f1b5e4
commit 4739333623
141 changed files with 937 additions and 5924 deletions

View File

@ -6,19 +6,7 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"> <classpathentry kind="src" path="src/test/java"/>
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-12">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
@ -27,5 +15,10 @@
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/> <classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="lib" path="lib/beautyeye_lnf.jar"/> <classpathentry kind="lib" path="lib/beautyeye_lnf.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -1,4 +1,5 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
encoding//src/main/java=UTF-8 encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8 encoding//src/test/java=UTF-8
encoding//src/test/java/pres/auxiliary/work/selenium/datadriven/Test.txt=GBK
encoding/<project>=UTF-8 encoding/<project>=UTF-8

View File

@ -1,11 +1,11 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=12 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=12 org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=12 org.eclipse.jdt.core.compiler.source=1.8

Binary file not shown.

View File

@ -1,253 +0,0 @@
package pres.auxiliary.selenium.browers;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
/**
* <p><b>文件名</b>AbstractBrower.java</p>
* <p><b>用途</b>该类定义启动浏览器时必要的方法以及打开浏览器创建WebDriver对象的操作由新添加的各个浏览器子类可进行继承</p>
* <p><b>编码时间</b>2020年4月6日 下午3:01:06</p>
* <p><b>修改时间</b>2020年4月6日 下午3:01:06</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
* @since selenium 3.0.0
*/
public abstract class AbstractBrower {
/**
* 用于接收用户需要进入的网站
*/
private String url = "";
/**
* 用于接收浏览器启动所需的文件路径
*/
private String browserRunPath = "";
/**
* 存储页面加载等待时间
*/
private int loadTime = 120;
/**
* 用于存储目标站点的title
*/
private StringBuilder pageTitle = new StringBuilder("");
/**
* 用于存储页面自动刷新的次数默认为0次
*/
private int rafreshCount = 0;
/**
* 用于存储获取到的浏览器对象
*/
WebDriver driver = null;
/**
* 该方法用于返回待链接的站点
*
* @return 返回待链接的站点
*/
public String getURL() {
return url.toString();
}
/**
* 该方法用于设置待链接的站点
*
* @param uRL
* 待链接的站点
*/
public void setURL(String uRL) {
//判断待测站点是否有发生改变若未发生改变则不重新设置
if (!url.equalsIgnoreCase(uRL)) {
// 由于改变了浏览器的条件故初始化driver变量以便于重新打开浏览器
driver = null;
url = uRL;
}
}
/**
* 用于返回浏览器的启动路径对于火狐则为浏览器可执行文件所在路径对于谷歌浏览器即浏览器驱动所在路径
*
* @return 浏览器的启动路径
*/
public String getBrowserRunPath() {
return browserRunPath;
}
/**
* 用于设置浏览器的启动路径对于火狐则为浏览器可执行文件所在路径对于谷歌浏览器即浏览器驱动所在路径
*
* @param startBrowserPath
* 浏览器的启动路径
*/
public void setBrowserRunPath(String browserRunPath) {
//判断待测站点是否有发生改变若未发生改变则不重新设置
if (!this.browserRunPath.equalsIgnoreCase(browserRunPath)) {
// 由于改变了浏览器的条件故初始化driver变量以便于重新打开浏览器
driver = null;
this.browserRunPath = browserRunPath;
}
}
/**
* 该方法用于返回设置的目标站点的title
*
* @return 返回设置的目标站点的title
*/
public String getPageTitle() {
return pageTitle.toString();
}
/**
* 该方法用于设置目标站点的title以便进行链接是否正确的判断
*
* @param pageTitle
* 设置的目标站点title
*/
public void setPageTitle(String pageTitle) {
this.pageTitle.delete(0, this.pageTitle.length());
this.pageTitle.append(pageTitle);
}
/**
* 该方法用于返回设置的页面等待时间默认时间为120秒
*
* @return 返回页面等待时间
*/
public int getLoadTime() {
return loadTime;
}
/**
* 该方法用于设置页面等待时间整形单位为秒
*
* @param LoadTime
* 传入的时间
*/
public void setLoadTime(int loadTime) {
this.loadTime = loadTime;
}
/**
* 该方法用于返回自动刷新的次数默认为0次
*
* @return 返回自动刷新的次数
*/
public int getRafreshCount() {
return rafreshCount;
}
/**
* 该方法用于设置页面的自动刷新次数当设置该值后则开启自动刷新
*
* @param rafreshCount
* 自动刷新的次数
*/
public void setRafreshCount(int rafreshCount) {
this.rafreshCount = rafreshCount;
}
/**
* 该方法用于启动浏览器并返回WebDriver对象
*
* @return 指向浏览器的WebDriver对象
*/
public abstract WebDriver getDriver();
/**
* 获取浏览器的名称
*
* @return 浏览器名称
*/
public abstract String getBrowerName();
/**
* 获取浏览器版本
*
* @return 浏览器版本
*/
public abstract String getBrowerVersion();
/**
* 获取操作系统信息
*
* @return 操作系统信息
*/
public abstract String getSystemInformation();
/**
* 用于初始化浏览器
*/
public WebDriver initialization() {
driver.close();
driver = null;
return getDriver();
}
/**
* 用于关闭浏览器
*/
public void close() {
driver.quit();
driver = null;
}
/**
* 该方法用于对浏览器的一系列操作包括全屏浏览器跳转相应的站点等待页面加载以及自动刷新
* 使用该方法时会抛出两个运行时异常分别为IncorrectPageTitleException和PageNotFoundException
*
* @param driver
* 通过start()方法创建的WebDriver对象
* @return 返回对浏览器进行操作后的得到的WebDriver对象
* @throws IncorrectPageTitleException
* 页面title与设置的title不一致时抛出的异常
* @throws PageNotFoundException
* 页面加载失败时抛出的异常
*/
protected WebDriver oprateBrower(WebDriver driver) {
// 将设置的自动刷新次数存储在临时变量中并加上1
// 加1的目的是自动刷新判断是用do...while循环实现若不事先加上1在会导致循环少1次
int rafresh = rafreshCount + 1;
String errorTitle = "页面载入出错";
// 进入站点
driver.get(url);
// 全屏浏览器
driver.manage().window().maximize();
// 循环执行页面加载判断判断其是否加载出目标站点若加载出来页面则结束循环若用户设置的自动刷新次数循环完还没加载出页面
// 抛出PageNotFoundException异常页面加载判断必须读取一次所以使用do...while循环
do {
// 读取并设置浏览器等待时间
driver.manage().timeouts().pageLoadTimeout(loadTime, TimeUnit.SECONDS);
// 判断进入站点后页面的title是否为页面载入出错若为该title则刷新页面重新加载
// 注意在火狐浏览器中凡是加载不出的页面其页面title都是页面载入出错所以该方法只适用于火狐浏览器
if (errorTitle.equals(driver.getTitle())) {
// 将刷新次数减1
rafresh--;
// 刷新网页
driver.navigate().refresh();
// 不执行后续代码继续循环
continue;
}
// 若页面加载成功则判断加载的页面是否与用户设置的一致若用户未设置目标站点的title则跳过判断
// 判断pageTitle中存储的信息是否为空若不为空则再判断页面的title是否与设置的title一致若不一致则抛出IncorrectPageTileException
if (!pageTitle.toString().equals("") && !driver.getTitle().equals(pageTitle.toString())) {
continue;
}
// 若页面能正常加载置空pageTitle并返回WebDriver对象
pageTitle.delete(0, pageTitle.length());
return driver;
// 判断的条件刷新次数rafresh为0时则结束循环
} while (rafresh != 0);
// 若循环结束则说明页面无法正常加载则置空pageTitle抛出PageNotFountException
pageTitle.delete(0, pageTitle.length());
throw new IncorrectPageTitleException("页面载入出错");
}
}

View File

@ -1,153 +0,0 @@
package pres.auxiliary.selenium.browers;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
/**
* <p><b>文件名</b>ChromeBrower.java</p>
* <p><b>用途</b>
* 该类用于启动谷歌浏览器并通过getDriver()方法获取当前浏览器的WebDriver对象调用本类时可通过
* set方法设置chromedriver的所在路径待测试的站点也可通过构造方法进行设置亦可通过在
* getDriver()方法直接设置参数以达到启动浏览器的目的
* </p>
* <p><b>修改时间</b>2019年6月5日下午4:24:23</p>
*
* @author 彭宇琦
* @version Ver1.0
* @since Selenium 2.53.0
* @since JDK 1.7
*/
public class ChromeBrower extends AbstractBrower {
/**
* 定义ChromeOptions类当需要控制已打开的浏览器时则定义该类
* */
ChromeOptions cp = null;
/**
* 双参构造用于设置谷歌浏览器启动驱动路径及待测试的站点并创建对象
*
* @param driverPath
* 谷歌浏览器启动驱动路径
* @param url
* 待测试的站点
*/
public ChromeBrower(String driverPath, String url) {
setBrowserRunPath(driverPath);
setURL(url);
}
/**
* 该构造用于使用已打开的浏览器对浏览器进行操作
* @param port 端口号
*/
public ChromeBrower(String driverPath, int port) {
setBrowserRunPath(driverPath);
//构造ChromeOptions类设置传入的浏览器打开的端口号
cp = new ChromeOptions();
cp.setExperimentalOption("debuggerAddress", "127.0.0.1:" + port);
}
@Override
public String getBrowerName() {
return ((ChromeDriver) driver).getCapabilities().getBrowserName();
}
@Override
public String getBrowerVersion() {
return ((ChromeDriver) driver).getCapabilities().getVersion();
}
@Override
public String getSystemInformation() {
String s = ((ChromeDriver) driver).getCapabilities().getPlatform().name();
s += ((ChromeDriver) driver).getCapabilities().getPlatform().getMajorVersion();
return s;
}
@Override
public void close() {
//若是控制已打开的浏览器时其quit()方法无法关闭浏览器故需要用close()方法来关闭
if (cp == null) {
driver.quit();
driver = null;
} else {
driver.close();
driver = null;
}
}
/**
* 该方法用于设置需要控制的已打开的浏览器端口<br>
* <b>注意为了安全调用该方法时会将传入的url待测站点值清空</b>
* @param port 端口
*/
public void setPort(int port) {
//构造ChromeOptions类设置传入的浏览器打开的端口号
cp = new ChromeOptions();
cp.setExperimentalOption("debuggerAddress", "127.0.0.1:" + port);
//将WebDriver对象置空以便于重新制定WebDriver对象
driver = null;
//将待测站点的信息也置空
setURL("");
}
/**
* 该方法用于解除对已打开的浏览器的控制调用该方法后重新获取的WebDriver对象将重新打开浏览器
*/
public void removeControl() {
cp = null;
driver = null;
}
/**
* 该方法通过类中的属性打开浏览器跳转相应的站点并创建WebDriver对象使用前需要通过类中的set()方法为属性进行赋值
* 在运行过程中可能会抛出两个运行时异常分别为IncorrectPageTitleException和PageNotFoundException <br/>
* <b><i>注意若未传入目标站点或者目标站点为空则返回null</i></b>
*
* @return 返回浏览器的WebDriver对象
* @throws IncorrectPageTitleException
* 页面title与设置的title不一致时抛出的异常
* @throws PageNotFoundException
* 页面加载失败时抛出的异常
*/
@Override
public WebDriver getDriver() {
// 判断类中的driver是否为null不为null则直接返回
if (driver != null) {
return driver;
}
// 判断传入的站点信息是否为空若为空则返回null
if ("".equals(getURL()) && cp == null) {
return null;
}
// 判断是否存在谷歌浏览器启动驱动的安装路径若存在则添加谷歌浏览器启动驱动启动路径若不存在则抛出ChromedriverNotFoundException异常
if (!"".equals(getBrowserRunPath())) {
System.setProperty("webdriver.chrome.driver", getBrowserRunPath());
} else {
throw new ChromedriverNotFoundException("chromedriver文件没有找到");
}
//判断当前是否通过已打开的浏览器来进行测试
if (cp != null) {
//通过已打开的浏览器参数来创建WebDiver对象
driver = new ChromeDriver(cp);
//判断当前是否有传入url若url为空则不改变页面的url若url不为空则进行更改
if (!"".equals(getURL())) {
//获取并判断浏览器当前站点是否与传入的站点一致若不一致则改变url
if (!getURL().equalsIgnoreCase(driver.getCurrentUrl())) {
driver.get(getURL());
}
}
return driver;
} else {
// 创造WebDriver对象
driver = new ChromeDriver();
// 调用OprateBrower()方法并返回其操作后的WebDriver对象
return oprateBrower(driver);
}
}
}

View File

@ -1,40 +0,0 @@
package pres.auxiliary.selenium.browers;
/**
* 该异常在没有找到Chromedriver路径时抛出的异常继承于RuntimeException
* @author 彭宇琦
* @version Ver1.0
*/
public class ChromedriverNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public ChromedriverNotFoundException() {
super();
// TODO Auto-generated constructor stub
}
public ChromedriverNotFoundException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public ChromedriverNotFoundException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public ChromedriverNotFoundException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public ChromedriverNotFoundException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}

View File

@ -1,147 +0,0 @@
package pres.auxiliary.selenium.browers;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.firefox.FirefoxDriver;
/**
* 该类用于启动火狐浏览器并通过getDriver()方法获取当前浏览器的WebDriver对象调用本类时可通过
* set方法设置火狐浏览器的启动路径待测试的站点和配置文件的位置也可通过构造方法进行设置亦可通过在
* getDriver()方法直接设置参数以达到启动浏览器的目的
*
* @author 彭宇琦
* @version Ver1.0
* @since Selenium 2.53.0
* @since JDK 1.7
*/
public class FirefoxBrower extends AbstractBrower {
// 存储配制文件名称
private String settingName = "";
/**
* 单参构造用于设置待测试的站点并创建对象
*
* @param url
* 待测试的站点
*/
public FirefoxBrower(String url) {
setURL(url);
}
/**
* 双参构造用于设置火狐浏览器安装路径及待测试的站点并创建对象
*
* @param firefoxPath
* 火狐浏览器的安装路径
* @param url
* 待测试的站点
*/
public FirefoxBrower(String firefoxPath, String url) {
setBrowserRunPath(firefoxPath);
setURL(url);
}
/**
* 叁参构造用于设置火狐浏览器安装路径及待测试的站点并创建对象
*
* @param firefoxPath
* 火狐浏览器的安装路径
* @param settingName
* 配置文件名称
* @param uRL
* 待测试的站点
*/
public FirefoxBrower(String firefoxPath, String settingName, String url) {
setBrowserRunPath(firefoxPath);
setSettingName(settingName);
setURL(url);
}
/**
* 该方法用于返回火狐浏览器配置文件的文件名
*
* @return 返回火狐浏览器配置文件的文件名
*/
public String getSettingName() {
return settingName;
}
/**
* 该方法用于设置火狐浏览器配置文件的文件名
*
* @param settingName
* 配置文件的文件名
*/
public void setSettingName(String settingName) {
//若配置文件名未改变则不重新赋值
if ( !this.settingName.equalsIgnoreCase(settingName) ) {
// 由于改变了浏览器的条件故初始化driver变量以便于重新打开浏览器
driver = null;
this.settingName = settingName;
}
}
@Override
public String getBrowerName() {
return ((FirefoxDriver) driver).getCapabilities().getBrowserName();
}
@Override
public String getBrowerVersion() {
return ((FirefoxDriver) driver).getCapabilities().getVersion();
}
@Override
public String getSystemInformation() {
String s = ((FirefoxDriver) driver).getCapabilities().getPlatform().name();
s += ((FirefoxDriver) driver).getCapabilities().getPlatform().getMajorVersion();
return s;
}
/**
* 该方法通过类中的属性打开浏览器跳转相应的站点并创建WebDriver对象使用前需要通过类中的set()方法为属性进行赋值
* 在运行过程中可能会抛出两个运行时异常分别为IncorrectPageTitleException和PageNotFoundException <br/>
* <b><i>注意若未传入目标站点或者目标站点为空则返回null</i></b>
*
* @return 返回浏览器的WebDriver对象
* @throws IncorrectPageTitleException
* 页面title与设置的title不一致时抛出的异常
* @throws PageNotFoundException
* 页面加载失败时抛出的异常
*/
@Override
public WebDriver getDriver() {
// 判断类中的driver是否为null不为null则直接返回
if (driver != null) {
return driver;
}
// 判断传入的站点信息是否为空若为空则返回null
if ("".equals(getURL())) {
return null;
}
// 判断是否存在火狐的安装路径若存在则添加火狐启动路径
if (!"".equals(getBrowserRunPath())) {
System.setProperty("webdriver.firefox.bin", getBrowserRunPath());
}
// 判断火狐的配置文件名是否为空若不为空则通过配置文件创建webdriver对象若为空则不使用配置文件创建对象
if (!"".equals(settingName)) {
// 通过配置文件创建webdriver对象并启动浏览器
//driver = new FirefoxDriver(new ProfilesIni().getProfile(settingName.toString()));
} else {
// 通过默认方式创建webdriver对象并启动浏览器
// 在创建对象时若火狐的路径不正确则会抛出WebDriverException异常捕捉该异常后再抛出FirefoxPathNotFountException的异常
try {
driver = new FirefoxDriver();
} catch (WebDriverException e) {
throw new FirefoxPathNotFoundException("指定的火狐浏览器安装路径不正确");
}
}
// 调用OprateBrower()方法并返回其操作后的WebDriver对象
return oprateBrower(driver);
}
}

View File

@ -1,39 +0,0 @@
package pres.auxiliary.selenium.browers;
/**
* 该异常在没有找到火狐路径时抛出的异常继承于RuntimeException
* @author 彭宇琦
* @version Ver1.0
*/
public class FirefoxPathNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public FirefoxPathNotFoundException() {
super();
// TODO Auto-generated constructor stub
}
public FirefoxPathNotFoundException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public FirefoxPathNotFoundException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public FirefoxPathNotFoundException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public FirefoxPathNotFoundException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}

View File

@ -1,39 +0,0 @@
package pres.auxiliary.selenium.browers;
/**
* 该异常在目标站点Title与设置的目标站点Title不一致的情况下抛出的异常继承于RuntimeException
*
* @author 彭宇琦
* @version Ver1.0
*/
public class IncorrectPageTitleException extends RuntimeException {
private static final long serialVersionUID = 1L;
public IncorrectPageTitleException() {
super();
// TODO Auto-generated constructor stub
}
public IncorrectPageTitleException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public IncorrectPageTitleException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public IncorrectPageTitleException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public IncorrectPageTitleException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}

View File

@ -1,39 +0,0 @@
package pres.auxiliary.selenium.browers;
/**
* 该异常为在页面无法加载出来时抛出的异常继承于RuntimeException
*
* @author 彭宇琦
* @version Ver1.0
*/
public class PageNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public PageNotFoundException() {
super();
// TODO Auto-generated constructor stub
}
public PageNotFoundException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public PageNotFoundException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public PageNotFoundException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public PageNotFoundException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}

View File

@ -1,602 +0,0 @@
package pres.auxiliary.selenium.event;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.dom4j.InvalidXPathException;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import pres.auxiliary.selenium.tool.RecordTool;
import pres.auxiliary.selenium.xml.ByType;
import pres.auxiliary.selenium.xml.ReadXml;
import pres.auxiliary.selenium.xml.UndefinedElementException;
/**
* <p><b>文件名</b>AbstractEvent.java</p>
* <p><b>用途</b>所有事件类的基类包含了事件类所用到的基础方法以及弹窗处理方法和窗体窗口的切换方法</p>
* <p><b>编码时间</b>2019年9月24日下午4:24:15</p>
* <p><b>修改时间</b>2019年11月29日上午9:53:37</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public abstract class AbstractEvent {
/**
* 用于存储浏览器的WebDriver对象设为静态保证所有的子类只使用一个WebDriver对象以避免造成WebDriver不正确导致的Bug
*/
private static WebDriver driver;
/**
* 用于指向存储控件定位方式的xml文件
*/
private static ReadXml xml;
/**
* 设置显示等待的超时时间默认3秒
*/
private long waitTime = 3;
/**
* 用于构造显示等待类对象
*/
private WebDriverWait wait;
/**
* 存储单个控件的等待时间
*/
private HashMap<String, Long> controlWaitTime = new HashMap<String, Long>();
/**
* 用于存储当前浏览器窗口的Handles值
*/
private String browserHandles;
/**
* 存储当前定位的窗体层级
*/
private static ArrayList<String> iframeNames = new ArrayList<>();
/**
* 控制是否自动切换窗体由于通过Event类调用时会构造另一个事件类但每个类都应共享一个开关故需要加上static
*/
private static boolean switchIframe = true;
/**
* 用于存储上一个获取到的元素
*/
private WebElement oldElement = null;
/**
* 用于存储上一个获取到的元素的style属性
*/
private String oldElementStyle = "";
/**
* 返回是否自动切换窗体
* @return 是否自动切换窗体
*/
public boolean isSwitchIframe() {
return switchIframe;
}
/**
* 设置是否自动切换窗体
* @param switchIframe 是否自动切换窗体
*/
public void setSwitchIframe(boolean switchIframe) {
this.switchIframe = switchIframe;
}
/**
* 构造对象并存储浏览器的WebDriver对象
*
* @param driver 浏览器的WebDriver对象
*/
public AbstractEvent(WebDriver driver) {
this.driver = driver;
browserHandles = this.driver.getWindowHandle();
wait = new WebDriverWait(driver, waitTime, EventConstants.FIND_TIME);
}
/**
* 用于返回等待时间
*
* @return 等待时间
*/
public long getWaitTime() {
return waitTime;
}
/**
* 用于设置等待时间
*
* @param waitTime 等待时间
*/
public void setWaitTime(long waitTime) {
this.waitTime = waitTime;
wait = new WebDriverWait(driver, this.waitTime, 200);
}
/**
* 该方法用于返回浏览器的WebDriver对象
*
* @return 浏览器的WebDriver对象
*/
public WebDriver getDriver() {
return driver;
}
/**
* 该方法用于设置浏览器的WebDriver对象
*
* @param driver 浏览器的WebDriver对象
*/
public void setDriver(WebDriver driver) {
// 判断传入WebDriver对象是否为空为空则抛出异常
if (driver == null) {
throw new WebDriverException("无效的WebDriver对象");
}
this.driver = driver;
browserHandles = this.driver.getWindowHandle();
}
/**
* 用于设置指向存储元素定位方式的xml文件对象
*
* @param xmlFile 存储元素定位方式的xml文件对象
*/
public void setXmlFile(File xmlFile) {
xml = new ReadXml(xmlFile);
}
/**
* 用于返回ReadXml类对象
* @return ReadXml类对象
*/
public ReadXml getXml() {
return xml;
}
/**
* 用于返回写入xml文件的或传入的元素定位方式mode=position的形式输出
*
* @param name 控件的名称或xpath与css定位方式
* @return 元素定位方式
*/
public String getElementPosition(String name) {
// 智能匹配方式
// 1.先对xml文件进行扫描若存在该元素对应的标签则读取xml文件的定位方式并识别有效的定位方式一一匹配直到正确为止
// 2.若在xml文件中查找不到该元素则按照xpath和css的规则进行匹配直到判断出该元素的定位方式位置
// 3.若仍找不到元素则抛出UnrecognizableLocationModeException
try {
ByType mode = readXml(name);
// 判断readXML()方法的返回值是否为空串若为空串则抛出TimeoutException
if (mode == null) {
// 将错误信息写入到记录工具的备注中
RecordTool.recordMark("元素查找超时或不存在请检查xml文件中“" + name + "”对应元素的定位方式");
throw new TimeoutException("元素查找超时或不存在请检查xml文件中“" + name + "”对应元素的定位方式");
} else {
// 页面查找元素并存储该元素
return mode + "=" + xml.getValue(name, mode);
}
} catch (UndefinedElementException | NullPointerException | InvalidXPathException e) {
ByType mode = readValue(driver, name);
// 判断readValue()方法的返回值是否为空串若为空串则抛出UnrecognizableLocationModeException
if (mode == null) {
// 将错误信息写入到记录工具的备注中
RecordTool.recordMark("元素定位方式类型无法识别:" + name);
// 若都不匹配则抛出异常
throw new UnrecognizableLocationModeException("元素定位方式类型无法识别:" + name);
} else {
//若有返回定位方式则根据定位方式类型获取其元素
switch (mode) {
case XPATH:
return ByType.XPATH.getValue() + "=" + name;
case CSS:
return ByType.CSS.getValue() + "=" + name;
default:
return "";
}
}
}
}
/**
* 用于对单个控件设置等待时间
*
* @param name 控件名称
* @param waitTime 等待时间
*/
public void setContorlWaitTime(String name, long waitTime) {
controlWaitTime.put(name, waitTime);
}
/**
* 该方法用于将窗体切回顶层当本身是在最顶层时则该方法将使用无效
*/
public void switchRootFrame() {
driver.switchTo().defaultContent();
iframeNames.clear();
}
/**
* 该方法用于将窗体切换到上一层父层当本身是在最顶层时则该方法将使用无效
*/
public void switchParentFrame() {
driver.switchTo().parentFrame();
iframeNames.remove(iframeNames.size() - 1);
}
/**
* 该方法用于通过悬浮窗名称使用xpath的定位方式将页面切换至悬浮窗iframe标签
*
* @param name 悬浮窗的名称
*/
public void switchFrame(String name) {
//获取父窗体的窗体名称
String parentIframeName = xml.getIframeName(name);
//判断窗体是否存在父窗体若不存在父窗体返回值为空则切换若有则递归调用该方法直到找到最顶层窗体为止
if (parentIframeName.isEmpty()) {
//清空iframeNames中的内容
iframeNames.clear();
//将窗体切换到顶层
driver.switchTo().defaultContent();
} else {
switchFrame(parentIframeName);
}
//记录当前自动切换的窗体的状态
boolean isSwitchFrame = isSwitchIframe();
//切换窗体前设置不自动切换窗体避免窗体的循环切换
setSwitchIframe(false);
//切换窗体
driver.switchTo().frame(judgeElementMode(name));
//切换窗体后还原原始的切换窗体状态
setSwitchIframe(isSwitchFrame);
//存储窗体切换记录
iframeNames.add(name);
}
/**
* 该方法可用于切换弹出的窗口新标签或新窗口并返回新窗口的WebDriver对象若无新窗口则返回当前的窗口的WebDriver对象
* 注意该方法只能切换弹出一个窗口的情况若有多个窗口通过该方法无法准确定位可参考方法{@link #switchWindow(String)}
*/
public void switchWindow() {
Set<String> handles = driver.getWindowHandles();
// 判断是否只存在一个窗体若只存在一个则直接返回当前浏览器的WebDriver对象
if (handles.size() == 1) {
return;
}
// 获取当前窗口的handle
String winHandle = driver.getWindowHandle();
// 循环获取所有的页面handle
for (String newWinHandle : handles) {
// 判断获取到的窗体handle是否为当前窗口的handle若不是则将其定位到获取的handle对应的窗体上
if (!newWinHandle.equals(winHandle)) {
driver.switchTo().window(newWinHandle);
}
}
throw new NoSuchWindownException("未找到相应的窗体");
}
/**
* 该方法用于将窗口切换回最原始的窗口上
*/
public void switchOldWindow() {
driver.switchTo().window(browserHandles);
}
/**
* 该方法可根据控件名称之后对比每一个弹窗若某一个弹窗上存在元素名对应的元素则返回相应
* 窗口的WebDriver对象,若无新窗口则返回当前的窗口的WebDriver对象当所有的窗体都
* 不包含相应的元素时则抛出NoSuchWindownException异常
*
* @param controlName 控件名称
* @throws NoSuchWindownException 窗口未找到时抛出的异常
*/
public void switchWindow(String controlName) {
Set<String> handles = driver.getWindowHandles();
// 判断是否只存在一个窗体若只存在一个则直接返回当前浏览器的WebDriver对象
if (handles.size() == 1) {
return;
}
// 循环获取所有的页面handle
for (String newWinHandle : handles) {
driver.switchTo().window(newWinHandle);
// 调用judgeElementMode()方法来判断元素是否存在如果元素存在则返回相应页面的WebDriver对象若抛出异常元素不存在则返回当前
try {
judgeElementMode(controlName);
} catch (TimeoutException e) {
continue;
}
}
throw new NoSuchWindownException("未找到存在元素" + controlName + "所在的窗体");
}
/**
* 定位到弹框上并且点击确定按钮并返回弹框上的文本
*
* @return 弹框上的文本
*/
public String alertAccept() {
String text = alertGetText();
driver.switchTo().alert().accept();
return text;
}
/**
* 定位到弹框上并且点击取消按钮并返回弹框上的文本
*
* @return 弹框上的文本
*/
public String alertDimiss() {
String text = alertGetText();
driver.switchTo().alert().dismiss();
return text;
}
/**
* 定位到弹框上并且在其文本框中输入信息
*
* @param content 需要输入的信息
* @return 弹框上的文本
*/
public String alertInput(String content) {
String text = alertGetText();
driver.switchTo().alert().sendKeys("");
return text;
}
/**
* 获取弹框上的文本
*
* @return 弹框上的文本
*/
public String alertGetText() {
return driver.switchTo().alert().getText();
}
/**
* <p>
* 用于根据传入的控件名称或定位方式对控件在页面上定位返回其WebElement对象形参可以传入在xml文件中元素的名称
* 亦可以传入页面元素的定位方式但目前识别只支持xpath和css两种方式
* 该方法获取的是单个元素但本质是调用了{@link #judgeElementModes(String)}方法只是将其容器中第一个元素进行返回
* 可用于普通元素事件获取页面元素中使用
* </p>
* <p>
* 元素识别判断方式按照以下步骤进行<br>
* 1.先对xml文件进行扫描若存在该元素对应的标签则读取xml文件的定位方式并识别有效的定位方式一一匹配直到正确为止<br>
* 2.若在xml文件中查找不到该元素则按照xpath和css的规则进行匹配直到判断出该元素的定位方式位置<br>
* 3.若仍找不到元素则抛出UnrecognizableLocationModeException
* </p>
*
* @param text 元素名称或元素的定位方式
* @return 返回页面元素WebElement对象
* @throws TimeoutException 元素在指定时间内未查找到时抛出的异常
* @throws UnrecognizableLocationModeException 元素无法识别时抛出的异常
*/
protected WebElement judgeElementMode(String name) {
return judgeElementModes(name).get(0);
}
/**
* <p>
* 用于根据传入的控件名称或定位方式对控件在页面上定位返回其WebElement对象形参可以传入在xml文件中元素的名称
* 亦可以传入页面元素的定位方式但目前识别只支持xpath和css两种方式
* 该方法获取的是一组元素可用于对列表元素事件中
* </p>
* <p>
* 元素识别判断方式按照以下步骤进行<br>
* 1.先对xml文件进行扫描若存在该元素对应的标签则读取xml文件的定位方式并识别有效的定位方式一一匹配直到正确为止<br>
* 2.若在xml文件中查找不到该元素则按照xpath和css的规则进行匹配直到判断出该元素的定位方式位置<br>
* 3.若仍找不到元素则抛出UnrecognizableLocationModeException
* </p>
*
* @param name 元素名称或元素的定位方式
* @return 返回页面一组元素WebElement的对象
* @throws TimeoutException 元素在指定时间内未查找到时抛出的异常
* @throws UnrecognizableLocationModeException 元素无法识别时抛出的异常
*/
protected List<WebElement> judgeElementModes(String name) {
// 获取当前的等待时间若有对单个控件设置等待时间时此处可以将等待时间设置回原来的时间
long time = getWaitTime();
// 判断是否有设置对单个控件增加等待时间若存在该控件则将等待时间设置为该控件设置的等待时间
if (controlWaitTime.containsKey(name)) {
setWaitTime(controlWaitTime.get(name));
}
// 存储最终识别得到元素
List<WebElement> elements = null;
// 智能匹配方式
// 1.先对xml文件进行扫描若存在该元素对应的标签则读取xml文件的定位方式并识别有效的定位方式一一匹配直到正确为止
// 2.若在xml文件中查找不到该元素则按照xpath和css的规则进行匹配直到判断出该元素的定位方式位置
// 3.若仍找不到元素则抛出UnrecognizableLocationModeException
try {
ByType mode = readXml(name);
// 判断readXML()方法的返回值是否为空串若为空串则抛出TimeoutException
if (mode == null) {
// 将错误信息写入到记录工具的备注中
RecordTool.recordMark("元素查找超时或不存在请检查xml文件中“" + name + "”对应元素的定位方式");
throw new TimeoutException("元素查找超时或不存在请检查xml文件中“" + name + "”对应元素的定位方式");
} else {
// 页面查找元素并存储该元素
elements = driver.findElements(xml.getBy(name, mode));
}
} catch (UndefinedElementException | NullPointerException | InvalidXPathException e) {
ByType mode = readValue(driver, name);
// 判断readValue()方法的返回值是否为空串若为空串则抛出UnrecognizableLocationModeException
if (mode == null) {
// 将错误信息写入到记录工具的备注中
RecordTool.recordMark("元素定位方式类型无法识别:" + name);
// 若都不匹配则抛出异常
throw new UnrecognizableLocationModeException("元素定位方式类型无法识别:" + name);
} else {
//若有返回定位方式则根据定位方式类型获取其元素
switch (mode) {
case XPATH:
elements = driver.findElements(By.xpath(name));
break;
case CSS:
elements = driver.findElements(By.cssSelector(name));
break;
default:
break;
}
}
}
// 设置等待时间为原来的等待时间
setWaitTime(time);
// 返回页面元素对象
return elements;
}
/**
* 该方法用于通过传入的控件名称在xml文件中查找其元素相应的定位方式并在页面上进行查找 若在相应的时间内查找到该元素则将其定位方式进行返回
*
* @param name 控件名称
* @return 查找到的定位方式名称
*/
protected ByType readXml(String name) {
// 循环逐个在页面上配对有效的标签对应的定位方式
for (ByType mode : xml.getElementMode(name)) {
// 在页面上查找元素定位方式
try {
//自动定位元素所在的窗体
if (isSwitchIframe()) {
autoSwitchIframe(xml.getIframeName(name));
}
//查找元素
wait.until(ExpectedConditions.presenceOfElementLocated(xml.getBy(name, mode)));
} catch (TimeoutException exception) {
// 若查找超时则重新查找
continue;
}
// 若在页面上找到该元素则将该元素的定位方式存储
return mode;
}
// 若循环结束后仍未能找到该元素则返回一个空串
return null;
}
/**
* 用于自动定位元素所在窗体
* @param iframeName 元素所在窗体名称
*/
protected void autoSwitchIframe(String iframeName) {
//判断传入的窗体名称是否为空若为空说明元素在主窗体上
if (iframeName.isEmpty()) {
//判断当前定位是否在主窗体上iframeNames无元素时若不在主窗体上则切换到主窗体若在则直接结束
if (iframeNames.size() != 0) {
//将窗体切换到顶层
switchRootFrame();
return;
} else {
return;
}
}
//判断当前元素所在的窗体是否与已切换的窗体列表中最后一个元素当前窗体的内容相同相同则直接返回无需操作
//获取最后一层窗体的名称若iframeNames为空则返回空串
String nowIframeName = (iframeNames.isEmpty() ? "" : iframeNames.get(iframeNames.size() - 1));
if (iframeName.equals(nowIframeName)) {
return;
}
//若传入的字符串不为空则表示当前窗体不在主窗体上则判断其是否在已切换的窗体列表中若在则通过层级返回
//无需再次重新定位避免等待时间太长若不在则重新定位窗体
int index = 0;
if ((index = iframeNames.indexOf(iframeName)) > -1) {
//循环将窗体一层一层返回
for(int i = 1; i < iframeNames.size() - index; i++) {
switchParentFrame();
}
} else {
//若当前元素的窗体不在当前窗体的父窗体则重新定位窗体
switchFrame(iframeName);
}
}
/**
* 该方法用于在xml文件查找不到对应的元素时则再对传入的参数进行xpath和css的比较
* 以确认是否为直接传值若不为xpath和css中的一种则抛出UnrecognizableLocationModeException
*
* @param driver WebDriver对象
* @param text 定位方式
* @return 定位方式的类型
*/
protected ByType readValue(WebDriver driver, String text) {
// 定义判断参数为xpath的字符
String judgeXpath = "/";
// 定义判断参数为css的字符
String judgeCss = "html";
try {
// 如果抛出元素名称查找不到的的异常则对应匹配xpath和css两种定位方式
// 匹配xpath定位判定方法判断text的第一个字符是否是/
if (text.indexOf(judgeXpath) == 0) {
// 查找该定位方式在有限的时间内是否内被查到
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(text)));
return ByType.XPATH;
// 将等待时间设置回原来的
} else if (text.indexOf(judgeCss) == 0) {
// 匹配css判断方法判断text的前四个字符是否是html
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(text)));
return ByType.CSS;
} else {
return null;
}
} catch (TimeoutException exception) {
// 将错误信息写入到记录工具的备注中
RecordTool.recordMark("元素查找超时或不存在,请检查“" + text + "”定位方式");
throw new TimeoutException("元素查找超时或不存在,请检查“" + text + "”定位方式");
}
}
/**
* 用于将页面控件元素高亮显示
* @param newElement 当前指向的元素
*/
protected void elementHight(WebElement newElement) {
//判断当前指向的元素是否与原来存储的元素一致若不一致且有之前有存储元素则解除之前元素的控件高亮
if (oldElement != newElement && oldElement != null) {
// 解除控件高亮若因为页面跳转导致页面过期时则不处理其异常
try {
((JavascriptExecutor) getDriver()).executeScript("arguments[0].setAttribute('style',arguments[1])",
oldElement, oldElementStyle);
} catch (StaleElementReferenceException exception) {
}
}
//获取当前指向的元素的style属性
String newElementStyle = newElement.getAttribute("style");
// 控件高亮
((JavascriptExecutor) getDriver()).executeScript("arguments[0].setAttribute('style',arguments[1])", newElement,
newElementStyle + "background:yellow;solid:red;");
//将当前指向的元素及其属性存储至属性中
oldElement = newElement;
oldElementStyle = newElementStyle;
}
}

View File

@ -1,162 +0,0 @@
package pres.auxiliary.selenium.event;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import pres.auxiliary.selenium.event.inter.ClickEventInter;
import pres.auxiliary.selenium.event.inter.ClickInter;
import pres.auxiliary.selenium.event.inter.DoubleClickInter;
import pres.auxiliary.selenium.event.inter.RightClickInter;
import pres.auxiliary.selenium.tool.RecordTool;
/**
* <p>
* <b>文件名</b>ClickEvent.java
* </p>
* <p>
* <b>用途</b>定义了对控件进行点击操作相关的方法可通过该类对页面进行基本的点击操作
* </p>
* <p>
* <b>编码时间</b>2019年8月29日下午3:24:34
* </p>
* <p>
* <b>修改时间</b>2019年11月29日上午9:53:37
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class ClickEvent extends CommenElementEvent implements ClickEventInter {
/**
* 构造ClickEvent类对象
*
* @param driver WebDriver类对象
*/
public ClickEvent(WebDriver driver) {
super(driver);
}
@Override
public Event click(String name) {
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
/*
// 获取原style属性
style = element.getAttribute("style");
// 控件高亮
((JavascriptExecutor) getDriver()).executeScript("arguments[0].setAttribute('style',arguments[1])", element,
style + "background:yellow;solid:red;");
*/
//修饰元素
elementHight(element);
//操作元素
ClickInter.click(element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
/*
// 解除控件高亮若因为页面跳转导致页面过期时则不处理其异常
try {
((JavascriptExecutor) getDriver()).executeScript("arguments[0].setAttribute('style',arguments[1])",
element, style);
} catch (StaleElementReferenceException exception) {
}
*/
} catch (TimeoutException timeException) {
RecordTool.recordException(new TimeoutException("元素查找超时或不存在,请检查“" + name + "”对应元素的定位方式"));
throw new TimeoutException("元素查找超时或不存在,请检查中“" + name + "”对应元素的定位方式");
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("点击“" + name + "”对应控件");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event doubleClick(String name) {
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
DoubleClickInter.doubleClick(getDriver(), element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (TimeoutException timeException) {
RecordTool.recordException(new TimeoutException("元素查找超时或不存在,请检查“" + name + "”对应元素的定位方式"));
throw new TimeoutException("元素查找超时或不存在,请检查中“" + name + "”对应元素的定位方式");
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("双击“" + name + "”对应控件");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event rightClick(String name) {
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
RightClickInter.rightClick(getDriver(), element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (TimeoutException timeException) {
RecordTool.recordException(new TimeoutException("元素查找超时或不存在,请检查“" + name + "”对应元素的定位方式"));
throw new TimeoutException("元素查找超时或不存在,请检查中“" + name + "”对应元素的定位方式");
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("右击“" + name + "”对应控件");
}
// 返回Event类
return Event.newInstance(getDriver());
}
}

View File

@ -1,34 +0,0 @@
package pres.auxiliary.selenium.event;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
/**
* <p><b>文件名</b>AbstractEvent.java</p>
* <p><b>用途</b>用于定义所有普通元素的事件类的基础方法所有普通元素的事件类必须继承该类</p>
* <p><b>编码时间</b>2019年8月29日下午3:23:30</p>
* <p><b>修改时间</b>2019年9月25日下午3:04:30</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public abstract class CommenElementEvent extends AbstractEvent {
/**
* 存储元素的原style属性用以控件高亮
*/
protected String style = "";
/**
* 存储获取到的元素
*/
protected WebElement element = null;
/**
* 构造对象并存储浏览器的WebDriver对象
*
* @param driver 浏览器的WebDriver对象
*/
public CommenElementEvent(WebDriver driver) {
super(driver);
}
}

View File

@ -1,723 +0,0 @@
package pres.auxiliary.selenium.event;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Random;
import java.util.Set;
import org.openqa.selenium.ElementClickInterceptedException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.inter.ClearInter;
import pres.auxiliary.selenium.event.inter.ClickInter;
import pres.auxiliary.selenium.event.inter.DataListEventInter;
import pres.auxiliary.selenium.event.inter.DoubleClickInter;
import pres.auxiliary.selenium.event.inter.GetAttributeValueInter;
import pres.auxiliary.selenium.event.inter.GetTextInter;
import pres.auxiliary.selenium.event.inter.InputInter;
import pres.auxiliary.selenium.event.inter.JudgeKeyInter;
import pres.auxiliary.selenium.event.inter.JudgeTextInter;
import pres.auxiliary.selenium.event.inter.RightClickInter;
import pres.auxiliary.selenium.tool.RecordTool;
/**
* <p>
* <b>文件名</b>WebElementList.java
* </p>
* <p>
* <b>用途</b>提供对页面多个使用相近定位方式的元素进行获取的方法并根据get方法返回获得每个 元素后可对其元素进行基本操作的方法
* </p>
* <p>
* <b>编码时间</b>2019年7月19日下午3:23:50
* </p>
* <p>
* <b>修改时间</b>2019年11月29日上午9:53:37
* </p>
*
* @author 彭宇琦
* @version Ver1.3
* @since JDK 12
*
*/
public class DataListEvent extends ListElementEvent {
/**
* 构造对象存储储浏览器的WebDriver对象
*
* @param driver 浏览器的WebDriver对象
*/
public DataListEvent(WebDriver driver) {
super(driver);
}
/**
* 该方法用于根据存入的元素名称或定位方式对元素进行重新获取的操作主要用于当列表数据翻页后
* 其原存入的数据将会失效必须重新获取注意调用该方法后会清空原存储的数据
*/
public void againGetElement() {
// 读取elements中的元素
elements.forEach((name, list) -> {
// 清空元素中的内容
clear(name);
// 对页面内容重新进行获取
add(name);
});
}
/**
* 用于根据下标移除下标所在行的整行元素下标允许传入负数意为由后向前遍历
*
* @param index 下标
*
* @throws NoSuchElementException 传入的元素列或元素不存在时抛出的异常
*/
public void removeLineElement(int index) {
// 遍历整行元素并调用removeElement方法删除对应列的元素若存在异常则跳过不处理
// 由于当传入0时会出现问题但lambda表达式不能为变量赋值故只能使用普通循环
for (String name : elements.keySet()) {
// 若下标为0则先进行下标获取操作并赋予index真实下标
index = index == 0 ? getIndex(name, index) : index;
// 判断是否能获取到元素若不能获取到元素则使用第二种构造方法
try {
removeElement(name, index);
} catch (NoSuchElementException e) {
throw e;
}
}
}
/**
* 用于返回最短列的长度
*
* @return 最短列的长度
*/
public String shortListName() {
// 初始化minSize为int的最大值
int minSize = Integer.MAX_VALUE;
String name = "";
// 循环遍历所有的key获取其长度查找最短的进行存储
for (String key : elements.keySet()) {
if (size(key) < minSize) {
minSize = size(key);
name = key;
}
}
return name;
}
/**
* 用于根据根据指定的列下标返回相应列元素的个数该方法根据存储时的顺序指定其列对应的下标
* 若需要通过列表返回元素个数可使用{@link #size(String)}进行返回
*
* @param columnNum 存储时相应列的下标
* @return 相应列元素的个数
*/
public int columnLength(int columnNum) {
//存储元素集合
Set<String> elemensSet = elements.keySet();
//存储最大下标
int maxListIndex = elemensSet.size();
//判断columnNum是否符合标准
if (columnNum < 0 || columnNum > maxListIndex) {
throw new ArrayIndexOutOfBoundsException("不存在的列下标:" + columnNum + "(列个数为:)" + maxListIndex);
}
//循环遍历元素下标返回其相应的列下标的元素个数
int i = 0;
for (String name : elements.keySet()) {
//判断当前循环的下标是否与columnNum相同若相同则返回相应的name
if (i == columnNum) {
return size(name);
}
//若不同则循环下标+1
i++;
}
return -1;
}
/**
* 用于返回添加列的个数即一行元素的个数若某一列元素不存在则每行元素个数同样将该行包含
* @return 添加列的个数
*/
public int rowLength() {
//存储元素集合
return elements.keySet().size();
}
/**
* 用于对列中元素的文本进行筛选返qwa回符合筛选项序号
*
* @param name 列名
* @param index 筛选后所在的列下标下标从1开始1表示第一个元素
*/
public int[] filterText(String name, String key, boolean keyFull) {
ArrayList<Integer> indexList = new ArrayList<>();
// 筛选文本
// 记录当前是否开启自动记录步骤的状态并设置关闭自动记录操作步骤加快操作进程
boolean recordStep = RecordTool.isRecordStep();
RecordTool.setRecordStep(false);
// 由于获取方法可能会出现异常故使用finally以保证无论获取方法是否有异常也能还原记录操作步骤的状态
try {
getEvents(name).forEach(event -> {
// 调用judgeText()方法进行判断若符合要求则indexList进行存储
if (event.judgeText(keyFull, key).getBooleanValue()) {
indexList.add(event.getIndex());
}
});
} catch (Exception e) {
// 抛出异常
throw e;
} finally {
// 还原自动记录操作步骤的状态
RecordTool.setRecordStep(recordStep);
}
// 将ArrayList转换成数组
int[] indexs = new int[indexList.size()];
for (int i = 0; i < indexs.length; i++) {
indexs[i] = indexList.get(i);
}
return indexs;
}
/**
* 根据指定的翻页按钮以及翻页次数对列表进行翻页操作该方法会自动判定是否翻页成功但以下场景下
* 将无法自动判定翻页是否成功
* <ol>
* <li>
* 当按钮的disable属性无法直接获取到其disable卸载css中或style中时
* 且列表的最后一页元素量与前一页一致时无法判断
* </li>
* <li>
* 当按钮在最后一页时仍能继续点击且且列表的最后一页元素量与前一页一致时无法判断
* </li>
* </ol>
* @param turnCount 翻页次数
* @param buttonName 翻页按钮
* @param sleepTime 翻页时间间隔单位为毫秒
*
* @throws TimeoutException 翻页按钮查找不到或数据加载时间过长导致翻页按钮无法点击时抛出
*/
public void pageTurning(int turnCount, String buttonName, long sleepTime) {
//判断翻页数是否小于等于0若小于等于0则直接返回不进行操作
if (turnCount <= 0) {
return;
}
//构造点击事件对象
ClickEvent ce = new ClickEvent(getDriver());
//记录当前步骤记录情况为节约翻页事件则先关闭自动记录步骤功能在循环结束后再还原
boolean recordStep = RecordTool.isRecordStep();
RecordTool.setRecordStep(false);
//记录实际翻页数
int actualPageCount = 0;
//循环对列表元素进行翻页
for (; actualPageCount < turnCount; actualPageCount++) {
//获取翻页前第一列的元素个数
int oldElementNum = columnLength(0);
//点击翻页按钮
//若抛出TimeoutException异常则表示翻页按钮的指向有问题则抛出该异常
//若抛出其他异常则表示下一页按钮可能无法点击则结束循环
//TODO 以上描述只表示已知的情况若存在其他异常且不是按钮无法点击的情况下则需要组织记录
try {
ce.click(buttonName);
} catch (ElementClickInterceptedException elementClickInterceptedException) {
RecordTool.recordException(new TimeoutException("页面未完全加载,翻页按钮点击超时"));
throw new TimeoutException("页面未完全加载,翻页按钮点击超时");
} catch (TimeoutException timeoutException) {
throw timeoutException;
} catch (Exception e) {
break;
}
//等待一定时间后再运行翻页
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
//重新获取列表元素
againGetElement();
//获取翻页后第一列的元素个数
int nowElementNum = columnLength(0);
//对比翻页前后第一列元素的个数若元素个数不同则表示当前以翻到最后一页则结束循环
if (nowElementNum != oldElementNum) {
break;
}
}
//还原之前的自动记录情况
RecordTool.setRecordStep(recordStep);
RecordTool.recordStep("点击" + buttonName + "指向的按钮,对列表进行" + turnCount + "翻页(实际翻页为" + actualPageCount + "页)");
}
/**
* 该方法用于根据控件名称或定位方式提供需要操作列表元素的下标对相应的元素进行操作
*
* @param name 控件的名称或xpath与css定位方式
* @param index 元素下标即列表中对应的某一个元素
* @return 元素的可执行的事件
* @throws NoSuchElementException 当未对name列进行获取数据或index的绝对值大于列表最大值时抛出的异常
*/
public ListEvent getEvent(String name, int index) {
// 转义下标
index = getIndex(name, index);
// 判断元素是否存在
if (elements.containsKey(name)) {
// 转义下标后返回对应的元素
return new ListEvent(elements.get(name).get(index), name, index + 1);
} else {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
}
/**
* 该方法用于根据控件名称或定位方式获取该列下所有的元素
*
* @param name 控件的名称或xpath与css定位方式
* @return 一组元素的可执行的事件
* @throws NoSuchElementException 当未对name列进行获取数据时抛出的异常
*/
public ArrayList<ListEvent> getEvents(String name) {
if (elements.containsKey(name)) {
ArrayList<ListEvent> events = new ArrayList<>();
int index = 1;
for (WebElement element : elements.get(name)) {
events.add(new ListEvent(element, name, index++));
}
return events;
} else {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
}
/**
* 用于返回多个指定的列表数据的事件
*
* @param name 控件的名称或xpath与css定位方式
* @param indexs 一组元素下标即列表中对应的某一个元素
* @return 指定下标的事件组
*/
public ArrayList<ListEvent> getEvents(String name, int... indexs) {
// 存储所有获取到的事件
ArrayList<ListEvent> events = new ArrayList<>();
// 循环解析所有的下标并调用getEvent()方法存储至events
for (int index : indexs) {
events.add(getEvent(name, index));
}
return events;
}
/**
* 用于返回指定个数列表事件其列表的行下标将随机生成
*
* @param name 控件的名称或xpath与css定位方式
* @param length 需要返回列表事件的个数
* @return 列表事件组
*/
public ArrayList<ListEvent> getRandomCountEvent(String name, int length) {
// 判断元素是否存在若元素不存在抛出异常
if (!elements.containsKey(name)) {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
// 判断传入的长度是否大于等于当前
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);
}
/**
* 该方法用于根据指定的行数获取一行元素当元素
*
* @param index 行数元素下标所在的行
* @return 指定行的事件组
*/
public LinkedHashMap<String, ListEvent> getLineEvent(int index) {
// 存储一行元素
LinkedHashMap<String, ListEvent> events = new LinkedHashMap<>(16);
// 由于当传入0时会出现问题但lambda表达式不能为变量赋值故只能使用普通循环
for (String name : elements.keySet()) {
// 若下标为0则先进行下标获取操作并赋予index真实下标
index = index == 0 ? getIndex(name, index) : index;
// 判断是否能获取到元素若不能获取到元素则使用第二种构造方法
ListEvent event;
try {
event = getEvent(name, index);
} catch (NoSuchElementException e) {
event = new ListEvent(name, index);
}
// 存储元素
events.put(name, event);
}
return events;
}
/**
* <p>
* <b>文件名</b>DataListEvent.java
* </p>
* <p>
* <b>用途</b>用于定义列表元素的操作事件
* </p>
* <p>
* <b>编码时间</b>2019年10月8日下午7:08:16
* </p>
* <p>
* <b>修改时间</b>2019年10月8日下午7:08:16
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class ListEvent implements DataListEventInter {
/**
* 用于存储当前获取的页面元素
*/
private WebElement element;
/**
* 用于存储当前元素的下标
*/
private int index;
/**
* 用于存储列表的名称
*/
private String name;
/**
* 构造对象
*
* @param elemnet WebElement对象
* @param name 列表的名称
* @param index 当前元素的下标
*/
public ListEvent(WebElement element, String name, int index) {
this.element = element;
this.index = index;
this.name = name;
}
public ListEvent(String name, int index) {
this.element = null;
this.index = index;
this.name = name;
}
/**
* 用于返回当前元素的下标
*
* @return 当前元素的下标
*/
public int getIndex() {
return index;
}
/**
* 用于判断元素是否为空若为空则抛出元素为空的异常
*/
private void isEmptyElement() {
if (element == null) {
throw new NoSuchElementException("不存在的元素;列名:" + name + ",行数:" + index);
}
}
@Override
public Event click() {
// 判断元素是否为空
isEmptyElement();
try {
// 修饰元素
elementHight(element);
// 操作元素
ClickInter.click(element);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("点击“" + name + "”对应列的第" + index + "条数据");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event doubleClick() {
// 判断元素是否为空
isEmptyElement();
try {
// 修饰元素
elementHight(element);
// 操作元素
DoubleClickInter.doubleClick(getDriver(), element);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("双击“" + name + "”对应列的第" + index + "条数据");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event rightClick() {
// 判断元素是否为空
isEmptyElement();
try {
// 修饰元素
elementHight(element);
// 操作元素
RightClickInter.rightClick(getDriver(), element);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("右击“" + name + "”对应列的第" + index + "条数据");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event getAttributeValue(String attributeName) {
// 判断元素是否为空
isEmptyElement();
// 自动记录异常
try {
// 修饰元素
elementHight(element);
// 操作元素
// 调用GetAttributeValueInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
GetAttributeValueInter.getAttributeValue(element, attributeName);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("获取“" + name + "”对应列的第" + index + "条数据" + attributeName + "属性的内容");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event getText() {
// 判断元素是否为空
isEmptyElement();
// 自动记录异常
try {
// 修饰元素
elementHight(element);
// 操作元素
// 调用GetTextInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
GetTextInter.getText(element);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("获取“" + name + "”对应列的第" + index + "条数据的内容");
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event judgeKey(boolean keyFull, String... keys) {
// 判断元素是否为空
isEmptyElement();
// 自动记录异常
try {
// 修饰元素
elementHight(element);
// 操作元素
// 调用JudgeKeyInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
JudgeKeyInter.judgeKey(element, keyFull, keys);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
// 记录步骤
// 拼接传入的关键词
String text = "";
for (String key : keys) {
text += (key + "");
}
text = text.substring(0, text.length() - 1);
// 根据keyFull的不同记录的文本将有改变
if (keyFull) {
RecordTool.recordStep("判断“" + name + "”对应列的第" + index + "条数据中的内容是否包含所有关键词(关键词为:" + text + "");
} else {
RecordTool.recordStep("判断“" + name + "”对应列的第" + index + "条数据中的内容是否包含部分关键词(关键词为:" + text + "");
}
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event judgeText(boolean keyFull, String key) {
// 判断元素是否为空
isEmptyElement();
// 自动记录异常
try {
// 修饰元素
elementHight(element);
// 操作元素
// 调用JudgeTextInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
JudgeTextInter.judgeText(element, keyFull, key);
} catch (Exception exception) {
// 捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
// 根据keyFull的不同记录的文本将有改变
if (keyFull) {
RecordTool.recordStep("判断“" + name + "”对应列的第" + index + "条数据中的内容是否与所有关键词“" + key + "”一致");
} else {
RecordTool.recordStep("判断“" + name + "”对应列的第" + index + "条数据中的内容是否包含关键词“" + key + "");
}
}
// 返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event clear() {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用ClearInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
ClearInter.clear(element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("清空“" + name + "”对应控件中的内容");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event input(String text) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用InputInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
InputInter.input(element, text);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("向“" + name + "”对应控件中输入“" + text + "");
}
//返回Event类
return Event.newInstance(getDriver());
}
}
}

View File

@ -1,202 +0,0 @@
package pres.auxiliary.selenium.event;
import org.openqa.selenium.WebDriver;
import pres.auxiliary.selenium.event.inter.CommenElementClearInter;
import pres.auxiliary.selenium.event.inter.CommenElementClickInter;
import pres.auxiliary.selenium.event.inter.CommenElementGetTextInter;
import pres.auxiliary.selenium.event.inter.CommenElementInputInter;
import pres.auxiliary.selenium.event.inter.CommenElementJudgeTextInter;
import pres.auxiliary.selenium.event.inter.CommenElementSelectInter;
/**
* <p>
* <b>文件名</b>Event.java
* </p>
* <p>
* <b>用途</b> 该类提供各个事件类的入口同时所有的事件方法的返回值保存在类中通过{@link #getStringValve()}
* {@link #getBooleanValue()}方法对返回值进行返回类中提供基本的事件包括鼠标左键单击事件输入事件获取文本事件
* 和清空事件以及选择下拉框事件在该类允许直接切换窗体及iframe和对alert的操作
* </p>
* <p>
* <b>编码时间</b>2019年8月28日下午5:01:33
* </p>
* <p>
* <b>修改时间</b>2019年9月25日下午3:03:33
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class Event extends AbstractEvent implements CommenElementClickInter, CommenElementClearInter,
CommenElementGetTextInter, CommenElementInputInter, CommenElementJudgeTextInter, CommenElementSelectInter {
/**
* 用于单例模式的设计
*/
private static Event event = null;
/**
* 存储可返回的TextEvent类对象
*/
private TextEvent textEvent;
/**
* 存储可返回的ClickEvent类对象
*/
private ClickEvent clickEvent;
/**
* 存储可返回的SelectEvent类对象
*/
private SelectEvent selectEvent;
/**
* 存储可返回的JudgeEvent类对象
*/
private JudgeEvent judgeEvent;
/**
* 存储可返回的JsEvent类对象
*/
private JsEvent jsEvent;
/**
* 用于存储各个事件的返回值
*/
private static EventResultEnum value;
// 私有所有的构造保证类对象唯一
/**
* 传入WebDriver对象构造Event类对象
*
* @param driver WebDriver对象
*/
private Event(WebDriver driver) {
super(driver);
}
/**
* 用于通过WebDriver对象来创建Event类对象当已创建过Event类对象时则返回上次创建的Event类对象
*
* @param driver WebDriver对象
* @return Event类对象
*/
public static Event newInstance(WebDriver driver) {
// 判断对象是否存储若不存在则进行构造
// 若对象存在则判断其当前WebDriver对象是否与传入的WebDriver对象相同若不相同则重新构造
return event == null ? (event = new Event(driver)) : (event.getDriver() == driver ? event : (event = new Event(driver)));
}
/**
* 用于返回一个TextEvent文本事件类对象
*
* @return TextEvent类对象
*/
public TextEvent getTextEvent() {
// 先判断是否存在对象若不存在则创建
return textEvent == null ? new TextEvent(getDriver()) : textEvent;
}
/**
* 用于返回一个ClickEvent点击事件类对象
*
* @return ClickEvent类对象
*/
public ClickEvent getClickEvent() {
// 先判断是否存在对象若不存在则创建
return clickEvent == null ? new ClickEvent(getDriver()) : clickEvent;
}
/**
* 用于返回一个SelectEvent下拉框选择事件类对象
*
* @return SelectEvent类对象
*/
public SelectEvent getSelectEvent() {
// 先判断是否存在对象若不存在则创建
return selectEvent == null ? new SelectEvent(getDriver()) : selectEvent;
}
/**
* 用于返回一个JudgeEvent文本判断事件类对象
*
* @return JudgeEvent类对象
*/
public JudgeEvent getJudgeEvent() {
// 先判断是否存在对象若不存在则创建
return judgeEvent == null ? new JudgeEvent(getDriver()) : judgeEvent;
}
/**
* 用于返回一个JsEventJavascript事件类对象
*
* @return JsEvent类对象
*/
public JsEvent getJsEvent() {
// 先判断是否存在对象若不存在则创建
return jsEvent == null ? new JsEvent(getDriver()) : jsEvent;
}
/**
* 用于设置事件类方法的返回值
*
* @param value 进行操作后得到的返回值
*/
public static void setValue(EventResultEnum value) {
Event.value = value;
}
/**
* 用于返回事件类方法的返回值
*
* @return 事件类方法的返回值
*/
public static String getStringValve() {
return value == null ? "" : value.getValue();
}
/**
* 用于当事件类方法的返回值为BOOLEAN_FALSE或BOOLEAN_TRUE类型时将返回值由字符串转为boolean类型返回
*
* @return 事件类方法的返回值
*/
public static boolean getBooleanValue() {
switch (value) {
case BOOLEAN_FALSE:
return false;
case BOOLEAN_TRUE:
return true;
default:
throw new IllegalArgumentException("该返回值类型不是boolean类型: " + value);
}
}
@Override
public Event select(String name, int option) {
return getSelectEvent().select(name, option);
}
@Override
public Event judgeText(String name, boolean keyFull, String key) {
return getJudgeEvent().judgeText(name, keyFull, key);
}
@Override
public Event input(String name, String text) {
return getTextEvent().input(name, text);
}
@Override
public Event getText(String name) {
return getTextEvent().getText(name);
}
@Override
public Event clear(String name) {
return getTextEvent().clear(name);
}
@Override
public Event click(String name) {
return getClickEvent().click(name);
}
}

View File

@ -1,13 +0,0 @@
package pres.auxiliary.selenium.event;
public class EventConstants {
/**
* 用于将秒转为毫秒
*/
public static final int CURR_SEC_MS_SCALED = 1000;
/**
* 用于每次到页面查找控件的时间
*/
public static final int FIND_TIME = 200;
}

View File

@ -1,84 +0,0 @@
package pres.auxiliary.selenium.event;
import java.util.regex.Pattern;
/**
* <p><b>文件名</b>EventResultEnum.java</p>
* <p><b>用途</b>用于枚举事件类的返回值类型并可以通过类中提供的{@link #getValue()}方法对返回值进行返回</p>
* <p><b>编码时间</b>2019年8月31日上午14:20:04</p>
* <p><b>修改时间</b>2019年9月2日上午8:41:04</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public enum EventResultEnum {
/**
* 返回值为boolean类型false
*/
BOOLEAN_FALSE("false"),
/**
* 返回值为boolean类型true
*/
BOOLEAN_TRUE("true"),
/**
* 无返回值类型
*/
VOID(""),
/**
* 数字返回值类型
*/
NUMBER("0"),
/**
* 字符串返回值类型
*/
STRING("");
/**
* 多组返回值时的分隔符
*/
public final static String TEXT_SEPARATOR = ",";
/**
* 存储枚举的值
*/
private String value;
/**
* 用于作为判断传值是否为数字的正则表达式
*/
private final String NUMBER_REGEX = "-?\\d+(\\.\\d+)?";
/**
* 初始化枚举中的值
* @param value 枚举值
*/
private EventResultEnum(String value) {
this.value = value;
}
/**
* 用于返回枚举中的值
* @return 枚举中的值
*/
public String getValue() {
return value;
}
/**
* 用于设置枚举中的值请注意只能修改STRING和符合正则的NUMBER类型的值其他的类型或不符合正则的数字修改无效依然是原始值
* @param value 需要修改的值
*/
public EventResultEnum setValue(String value) {
if (this == EventResultEnum.STRING) {
this.value = value;
} else if (this == EventResultEnum.NUMBER) {
if (Pattern.compile(NUMBER_REGEX).matcher(value).matches()) {
this.value = value;
}
}
return this;
}
}

View File

@ -1,37 +0,0 @@
package pres.auxiliary.selenium.event;
/**
* <p><b>文件名</b>IncorrectGrammarException.java</p>
* <p><b>用途</b>文本语法有误时抛出的异常</p>
* <p><b>编码时间</b>2019年10月9日下午5:34:34</p>
* <p><b>修改时间</b>2019年10月9日下午5:34:34</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class IncorrectGrammarException extends RuntimeException {
public IncorrectGrammarException() {
super();
}
public IncorrectGrammarException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
super(arg0, arg1, arg2, arg3);
}
public IncorrectGrammarException(String arg0, Throwable arg1) {
super(arg0, arg1);
}
public IncorrectGrammarException(String arg0) {
super(arg0);
}
public IncorrectGrammarException(Throwable arg0) {
super(arg0);
}
private static final long serialVersionUID = 1L;
}

View File

@ -1,175 +0,0 @@
package pres.auxiliary.selenium.event;
import java.util.UUID;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import pres.auxiliary.selenium.xml.ByType;
/**
* <p><b>文件名</b>JsEvent.java</p>
* <p><b>用途</b>提供通过Javascript来修改或者获取页面元素内容的方法</p>
* <p><b>编码时间</b>2018年12月2日 下午12:51:19</p>
* <p><b>修改时间</b>2019年10月7日下午4:54:52</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class JsEvent extends AbstractEvent {
/**
* 用于使用js
*/
private JavascriptExecutor js;
/**
* 构造对象
* @param driver 页面WebDriver对象
*/
public JsEvent(WebDriver driver) {
super(driver);
js = (JavascriptExecutor) getDriver();
}
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并获取元素的属性值若属性不存在时则返回空串
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为元素属性的值可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @param attributeName 元素属性名
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取
*/
public Event getAttribute(String name, String attributeName) {
try {
Event.setValue(EventResultEnum.STRING.setValue((String) (js.executeScript("return " + getScript(name) + ".getAttribute('" + attributeName + "')"))));
} catch ( WebDriverException e ) {
//当当前元素无此属性时则返回空
Event.setValue(EventResultEnum.STRING.setValue(""));
}
return Event.newInstance(getDriver());
}
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并设置元素的属性值或者添加属性
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为元素属性的原值可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @param attributeName 元素属性名
* @param value 需要设置的属性值
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取
*/
public Event setAttribute(String name, String attributeName, String value) {
// 存储脚本
String script = getScript(name);
// 获取原属性中的值
String oldValue = getAttribute(name, attributeName).getStringValve();
//判断传入的对象是否为null为null则执行删除命令
if ( value != null ) {
// 拼接脚本
script += (".setAttribute('" + attributeName + "','" + value + "');");
} else {
// 拼接脚本
script += (".removeAttribute('" + attributeName + "');");
}
// 执行代码
js.executeScript(script);
Event.setValue(EventResultEnum.STRING.setValue(oldValue));
return Event.newInstance(getDriver());
}
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并向元素下添加一个新的元素并返回其元素的查找xpath注意通过该方法创建的元素会自带
* 一个名为temp_attribute的属性其值为一个uuid以方便查找元素
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为新节点的xpath可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式
* @param elementName 待添加元素的标签名称
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取
*/
public Event addElement(String name, String elementName) {
// 获取并将其作为
String script = "var oldElement = " + getScript(name) + ";";
// 拼接添加元素的代码
script += "var newElement = document.createElement('" + elementName + "');";
// 给新的元素添加一个属性并将其值设为UUID使其可被搜索得到
String uuid = UUID.randomUUID().toString();
script += "newElement.setAttribute('temp_attribute', '" + uuid + "');";
// 向指定位置添加节点
script += "oldElement.appendChild(newElement);";
// 执行代码
js.executeScript(script);
Event.setValue(EventResultEnum.STRING.setValue("//" + elementName + "[@temp_attribute=\"" + uuid + "\"]"));
return Event.newInstance(getDriver());
}
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并删除该元素
* 本操作返回的枚举值是{@link EventResultEnum#VOID}可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取
*/
public Event deleteElement(String name) {
//获取节点
String script = "var deleteNode = " + getScript(name) + ";";
//获取节点的父节点
script += "var parentNode = deleteNode.parentNode;";
//通过父节点来删除子节点
script += "parentNode.removeChild(deleteNode)";
// 执行代码
js.executeScript(script);
return Event.newInstance(getDriver());
}
/**
* 用于执行已经写好的js脚本
* 本操作返回的枚举值是{@link EventResultEnum#VOID}可参见{@link EventResultEnum}
* @param script js脚本
*/
public Event runScript(String script) {
// 执行代码
js.executeScript(script);
return Event.newInstance(getDriver());
}
/**
* 用于识别传入的控件模型并将定位的代码的直接返回
*
* @param text 元素名称或元素的定位方式
* @return 返回页面元素WebElement对象
*/
private String getScript(String text) {
// 存储脚本
String script = "";
String[] element = getElementPosition(text).split("=");
// 判断定位方式若定位方式为css则按照querySelector()方式进行选择其他的方式均按照xpath来获取
if (ByType.XPATH.getValue().equalsIgnoreCase(element[0])) {
script = "document.evaluate('" + element[1]
+ "', document, null, XPathResult.ANY_TYPE, null).iterateNext()";
} else if (ByType.CSS.getValue().equalsIgnoreCase(element[0])) {
script = "document.querySelector(" + element[1] + ")";
} else {
script = "document.evaluate('//*[@" + element[0] + "=\"" + element[1]
+ "\"]', document, null, XPathResult.ANY_TYPE, null).iterateNext()";
}
// 返回页面元素对象
return script;
}
}

View File

@ -1,141 +0,0 @@
package pres.auxiliary.selenium.event;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import pres.auxiliary.selenium.event.inter.JudgeEventInter;
import pres.auxiliary.selenium.event.inter.JudgeKeyInter;
import pres.auxiliary.selenium.event.inter.JudgeTextInter;
import pres.auxiliary.selenium.tool.RecordTool;
/**
* <p><b>文件名</b>JudgeEvent.java</p>
* <p><b>用途</b>定义了对控件进行判断操作相关的方法可通过该类对页面数据进行基判断</p>
* <p><b>编码时间</b>2019年9月2日下午7:09:13</p>
* <p><b>修改时间</b>2019年11月29日上午9:53:37</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class JudgeEvent extends CommenElementEvent implements JudgeEventInter {
/**
* 构造JudgeEvent类对象
* @param driver WebDriver类对象
*/
public JudgeEvent(WebDriver driver) {
super(driver);
}
@Override
public Event judgeKey(String name, boolean keyFull, String... keys) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用JudgeKeyInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
JudgeKeyInter.judgeKey(element, keyFull, keys);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
//记录步骤
// 拼接传入的关键词
String text = "";
for (String key : keys) {
text += (key + "");
}
text = text.substring(0, text.length() - 1);
//根据keyFull的不同记录的文本将有改变
if (keyFull) {
RecordTool.recordStep("判断“" + name + "”对应的控件中的内容是否包含所有关键词(关键词为:" + text + "");
} else {
RecordTool.recordStep("判断“" + name + "”对应的控件中的内容是否包含部分关键词(关键词为:" + text + "");
}
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event judgeText(String name, boolean keyFull, String key) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用JudgeTextInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
JudgeTextInter.judgeText(element, keyFull, key);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
//根据keyFull的不同记录的文本将有改变
if (keyFull) {
RecordTool.recordStep("判断“" + name + "”对应的控件中的内容是否与所有关键词“" + key + "”一致");
} else {
RecordTool.recordStep("判断“" + name + "”对应的控件中的内容是否包含关键词“" + key + "");
}
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event judgeControl(String name) {
//自动记录异常
try {
// 判断页面上是否存在该元素,若抛出TimeoutException或UnrecognizableLocationModeException异常则说明元素不存在
try {
judgeElementMode(name);
Event.setValue(EventResultEnum.BOOLEAN_TRUE);
} catch (TimeoutException | UnrecognizableLocationModeException e) {
Event.setValue(EventResultEnum.BOOLEAN_FALSE);
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("判断页面是否包含“" + name + "”控件");
}
//返回Event类
return Event.newInstance(getDriver());
}
}

View File

@ -1,178 +0,0 @@
package pres.auxiliary.selenium.event;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Random;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.tool.RecordTool;
public abstract class ListElementEvent extends AbstractEvent {
/**
* 用于标记首行是否为标题行
*/
private boolean fristRowTitle = false;
/**
* 用于存储一列列表的数据并返回其相应的列表事件
*/
protected LinkedHashMap<String, ArrayList<WebElement>> elements = new LinkedHashMap<>(16);
/**
* 当列表元素获取为空时设置的重新获取次数
*/
private int toDataCount = 3;
/**
* 设置列表的首行是否为标题行
*
* @param isTitleRow 列表首行是否为标题行
*/
public void setFristRowTitle(boolean fristRowTitle) {
this.fristRowTitle = fristRowTitle;
}
/**
* 用于设置列表数据获取为空时重新获取的次数在限制次数内列表未获取到元素则重新对列表进行一次获取直到获取到列表元素或达到次数上限为止
* @param toDataCount 自动重新获取次数
*/
public void setToDataCount(int toDataCount) {
this.toDataCount = toDataCount;
}
/**
* 构造对象
* @param driver 页面WebDriver对象
*/
public ListElementEvent(WebDriver driver) {
super(driver);
}
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并将查到的一组元素进行存储该方法可传入多个元素定位参数
*
* @param names 一组控件的名称或xpath与css定位方式
*/
public void add(String... names) {
for (String name : names) {
RecordTool.recordStep("获取“" + name + "”定位方式对应的列");
//判断当前列名是否存在不存在则先存储其类名
if (!elements.containsKey(name)) {
elements.put(name, new ArrayList<WebElement>());
}
//循环直到获取到列表元素或者达到重获次数限制为止
for (int count = 0; count < toDataCount; count++) {
try {
//存储获取到的数据
elements.get(name).addAll(judgeElementModes(name));
//若首行为标题行则删除当前存储列的第一个元素
if (fristRowTitle) {
elements.get(name).remove(0);
}
} catch (TimeoutException excetion) {
}
//判断获取到的数据的个数是否为0若为0
if (elements.get(name).size() == 0) {
if (count == toDataCount - 1) {
//若在页面未找到元素则记录异常信息但不结束获取
RecordTool.recordMark("" + name + "”对应的定位方式获取超时");
} else {
continue;
}
}
//若获取到元素或次数达到限制上限则结束循环
break;
}
}
}
/**
* 清空指定的一列元素数据若未对传入的控件名称或定位方式进行获取时则该方法调用无效
* @param name 控件的名称或xpath与css定位方式
*/
public void clear(String name) {
if (elements.containsKey(name)) {
elements.get(name).clear();
}
}
/**
* 获取指定的一列元素的个数若未对传入的控件名称或定位方式进行获取时则该方法返回-1
* @param name 控件的名称或xpath与css定位方式
* @return 指定列的元素个数
*/
public int size(String name) {
if (elements.containsKey(name)) {
return elements.get(name).size();
} else {
return -1;
}
}
/**
* 用于根据元素下标移除当前列下标对应元素下标从1开始1表示第一个元素0表示随机选择一个元素进行移除
* 下标亦允许传入负数意为由后向前遍历
* @param name 元素列名称
* @param index 元素下标
*
* @throws NoSuchElementException 传入的元素列或元素不存在时抛出的异常
*/
public int removeElement(String name, int index) {
//判断元素是否存在若元素不存在抛出异常
if (!elements.containsKey(name)) {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
//若传入的数值大于当前列的总长度则跑出异常
int size = size(name);
if (size < Math.abs(index)) {
throw new NoSuchElementException("元素不存在,当前列总长度:" + size + ",传入的参数:" + index);
}
//转义下标删除相应的元素
index = getIndex(name, index);
elements.get(name).remove(index);
return index;
}
/**
* 由于方法允许传入负数和特殊数字0为下标并且下标的序号由1开始故可通过该方法对下标的含义进行转义得到java能识别的下标
* @param index
* @return
*/
protected int getIndex(String name, int index) {
//判断元素是否存在
if (elements.containsKey(name)) {
int length = elements.get(name).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);
}
} else {
throw new NoSuchElementException("不存在的定位方式:" + name);
}
}
}

View File

@ -1,28 +0,0 @@
package pres.auxiliary.selenium.event;
public class NoSuchWindownException extends RuntimeException {
private static final long serialVersionUID = 1L;
public NoSuchWindownException() {
super();
}
public NoSuchWindownException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
super(arg0, arg1, arg2, arg3);
}
public NoSuchWindownException(String arg0, Throwable arg1) {
super(arg0, arg1);
}
public NoSuchWindownException(String arg0) {
super(arg0);
}
public NoSuchWindownException(Throwable arg0) {
super(arg0);
}
}

View File

@ -1,227 +0,0 @@
package pres.auxiliary.selenium.event;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.UnexpectedTagNameException;
import pres.auxiliary.selenium.event.inter.SelectEventInter;
import pres.auxiliary.selenium.event.inter.SelectFirstInter;
import pres.auxiliary.selenium.event.inter.SelectInter;
import pres.auxiliary.selenium.event.inter.SelectLastInter;
import pres.auxiliary.selenium.tool.RecordTool;
/**
* <p><b>文件名</b>SelectEvent.java</p>
* <p><b>用途</b>定义了对控件进行点击操作相关的方法可通过该类对页面的下拉框控件进行选择操作</p>
* <p><b>编码时间</b>2019年9月29日下午3:55:34</p>
* <p><b>修改时间</b>2019年11月29日上午9:53:37</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class SelectEvent extends CommenElementEvent implements SelectEventInter {
/**
* 构造SelectEvent类对象
* @param driver WebDriver类对象
*/
public SelectEvent(WebDriver driver) {
super(driver);
}
@Override
public Event selectLast(String name) {
//自动记录异常
try {
//调用SelectLastInter接口的静态方法将对页面下拉框进行选择若下拉选项不是标准的下拉框则会抛出UnexpectedTagNameException
//异常则此时再选择应对非标准下拉框的方法
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
SelectLastInter.selectLast(judgeElementMode(name));
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (UnexpectedTagNameException e) {
//非标准下拉框无法代码高亮
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
SelectLastInter.selectLast(judgeElementModes(name));
break;
} catch (StaleElementReferenceException sere) {
continue;
}
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("选择“" + name + "”对应控件中的“" + Event.getStringValve() + "”选项");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event select(String name, int option) {
//自动记录异常
try {
//调用SelectInter接口的静态方法将对页面下拉框进行选择若下拉选项不是标准的下拉框则会抛出UnexpectedTagNameException
//异常则此时再选择应对非标准下拉框的方法
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
SelectInter.select(judgeElementMode(name), option);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (UnexpectedTagNameException e) {
//非标准下拉框无法代码高亮
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
SelectInter.select(judgeElementModes(name), option);
break;
} catch (StaleElementReferenceException sere) {
continue;
}
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("选择“" + name + "”对应控件中的“" + Event.getStringValve() + "”选项");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event selectFirst(String name) {
//自动记录异常
try {
//调用SelectFirstInter接口的静态方法将对页面下拉框进行选择若下拉选项不是标准的下拉框则会抛出UnexpectedTagNameException
//异常则此时再选择应对非标准下拉框的方法
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
SelectFirstInter.selectFirst(element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (UnexpectedTagNameException e) {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//非标准下拉框无法代码高亮
SelectFirstInter.selectFirst(judgeElementModes(name));
break;
} catch (StaleElementReferenceException sere) {
continue;
}
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("选择“" + name + "”对应控件中的“" + Event.getStringValve() + "”选项");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event select(String name, String optionStr) {
//自动记录异常
try {
//调用SelectFirstInter接口的静态方法将对页面下拉框进行选择若下拉选项不是标准的下拉框则会抛出UnexpectedTagNameException
//异常则此时再选择应对非标准下拉框的方法
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
SelectInter.select(element, optionStr);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (UnexpectedTagNameException e) {
//非标准下拉框无法代码高亮
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
SelectInter.select(judgeElementModes(name), optionStr);
break;
} catch (StaleElementReferenceException sere) {
continue;
}
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("选择“" + name + "”对应控件中的“" + Event.getStringValve() + "”选项");
}
//返回Event类
return Event.newInstance(getDriver());
}
}

View File

@ -1,309 +0,0 @@
package pres.auxiliary.selenium.event;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import org.openqa.selenium.Rectangle;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import pres.auxiliary.selenium.event.inter.ClearInter;
import pres.auxiliary.selenium.event.inter.GetAttributeValueInter;
import pres.auxiliary.selenium.event.inter.GetTextInter;
import pres.auxiliary.selenium.event.inter.InputInter;
import pres.auxiliary.selenium.event.inter.TextEventInter;
import pres.auxiliary.selenium.tool.RecognitionImage;
import pres.auxiliary.selenium.tool.RecordTool;
import pres.auxiliary.selenium.tool.Screenshot;
import pres.auxiliary.tool.randomstring.RandomString;
import pres.auxiliary.tool.randomstring.StringMode;
/**
* <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>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class TextEvent extends CommenElementEvent implements TextEventInter {
/**
* 定义验证码识别的制定文件夹名称
*/
private final String TESSDATA = "tessdata";
/**
* 构造TextEvent类对象
* @param driver WebDriver类对象
*/
public TextEvent(WebDriver driver) {
super(driver);
}
@Override
public Event clear(String name) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用ClearInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
ClearInter.clear(element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("清空“" + name + "”对应控件中的内容");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event getAttributeValue(String name, String attributeName) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用GetAttributeValueInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
GetAttributeValueInter.getAttributeValue(element, attributeName);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("获取“" + name + "”对应控件" + attributeName + "属性的内容");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event getText(String name) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用GetTextInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
GetTextInter.getText(element);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("获取“" + name + "”对应控件的内容");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event input(String name, String text) {
//自动记录异常
try {
// 为避免出现抛出StaleElementReferenceException页面过期异常则通过循环的方式
// 当抛出异常时则重新获取并操作若未抛出则结束循环
while (true) {
try {
//获取元素
element = judgeElementMode(name);
//修饰元素
elementHight(element);
//操作元素
//调用InputInter接口的静态方法将从页面上搜索到的控件元素对象传入其中
InputInter.input(element, text);
break;
} catch (StaleElementReferenceException e) {
continue;
}
}
} catch (Exception exception) {
//捕捉到异常后将异常信息记录在工具中并将异常抛出
RecordTool.recordException(exception);
throw exception;
} finally {
RecordTool.recordStep("向“" + name + "”对应控件中输入“" + text + "");
}
//返回Event类
return Event.newInstance(getDriver());
}
@Override
public Event codeInput(String textName, String codeName) {
// 判断验证码信息是否加载加载后获取其Rectang对象
Rectangle r = judgeElementMode(codeName).getRect();
// 构造截图对象并创建截图
Screenshot sc = new Screenshot(getDriver(), "Temp");
File image = null;
try {
image = sc.creatImage("code");
} catch (WebDriverException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 设置图片识别的语言包存放位置
RecognitionImage.setTessdataPath(new File(TESSDATA));
// 识别图片
String text = RecognitionImage.judgeImage(image, r.x, r.y, r.width, r.height);
// 删除生成的图片及文件夹
image.delete();
new File("Temp").delete();
return input(textName, text);
}
@Override
public Event avgIntergeInput(int num, String... names) {
//定义存储控件数量及需要随机的数量
int contrlNum = names.length;
String inputNumText = "";
String[] inputNum = new String[contrlNum];
// 向下取整获得平均数
int avgNum = num / contrlNum;
// 向上取整获得差值
int diffNum = (int) Math.ceil(avgNum / 10.0);
//求取通过随机得出的值之和用于计算最终其随机值之和与实际值的差值
int sum = 0;
//循环生成控件个数个随机值其随机值在给定数值的均值之前
for (int i = 0; i < contrlNum; i++) {
//注意2 * diffNum为以下算式的简写
//minNum = avgNum - diffNum;
//maxNum = avgNum + diffNum;
//int ranNum = new Random().nextInt(maxNum - minNum + 1) + minNum;
int ranNum = new Random().nextInt(2 * diffNum + 1) + (avgNum - diffNum);
sum += ranNum;
inputNum[i] = String.valueOf(ranNum);
}
//由于数值是随机的可能会出现随机值相加不为指定值故需要补上差值但由于差值通过算法后不会很大故可随机附加到一个控件值上
if ( (diffNum = sum - num) != 0 ) {
inputNum[new Random().nextInt(contrlNum)] = String.valueOf(Integer.valueOf(inputNum[new Random().nextInt(contrlNum)]) - diffNum);
}
//将随机值填写至控件中
for (int i = 0; i < contrlNum; i++) {
input(names[i], inputNum[i]);
inputNumText += (Event.getStringValve() + ",");
}
Event.setValue(EventResultEnum.STRING.setValue(inputNumText.substring(0, inputNumText.length() - 1)));
return Event.newInstance(getDriver());
}
@Override
public Event randomInput(String name, int minLength, int maxLength, StringMode... modes) {
// 判断传入的参数是否小于0小于0则将其都设置为1
if (minLength < 0 || maxLength < 0) {
minLength = 1;
maxLength = 1;
}
// 判断传入的随机字符串最小生成长度是否大于最大生成长度若大于则调换两数字的位置
if (minLength > maxLength) {
int tem = minLength;
minLength = maxLength;
maxLength = tem;
}
//根据参数生成随机字符串
String text = "";
if (minLength == maxLength) {
text = new RandomString(modes).toString(maxLength);
} else {
text = new RandomString(modes).toString(minLength, maxLength);
}
//调用input方法进行返回
return input(name, text);
}
@Override
public Event randomInput(String name, int minLength, int maxLength, String mode) {
// 判断传入的参数是否小于0小于0则将其都设置为1
if (minLength < 0 || maxLength < 0) {
minLength = 1;
maxLength = 1;
}
// 判断传入的随机字符串最小生成长度是否大于最大生成长度若大于则调换两数字的位置
if (minLength > maxLength) {
int tem = minLength;
minLength = maxLength;
maxLength = tem;
}
//根据参数生成随机字符串
String text = "";
if (minLength == maxLength) {
text = new RandomString(mode).toString(maxLength);
} else {
text = new RandomString(mode).toString(minLength, maxLength);
}
//调用input方法进行返回
return input(name, text);
}
@Override
public Event updataFile(String name, File updataFile) {
return input(name, updataFile.getAbsolutePath());
}
}

View File

@ -1,264 +0,0 @@
package pres.auxiliary.selenium.event;
import pres.auxiliary.tool.randomstring.RandomString;
import pres.auxiliary.tool.randomstring.StringMode;
/**
* 该类提供根据固定文本格式来选择相应的事件其相应的文本为
* <p>
* 1.输入事件<br>
* 1.1 XXX 输入 XXX<br>
* 1.2 XXX 随机 输入 6位 XXX 字符<br>
* 1.3 XXX 随机 输入 6位 XXXXXX 字符<br>
* 1.4 XXX 随机 输入 6-10位 XXX 字符<br>
* 1.5 XXX 随机 输入 6-10位 XXXXXX 字符<br>
* </p>
* <p>
* 2.清除事件<br>
* 2.1 清空 XXX 中的内容
* </p>
* <p>
* 3.获取事件<br>
* 3.1 获取 XXX 中的内容
* </p>
* <p>
* 4.选择事件<br>
* 4.1 选择 XXX 第X个 选项<br>
* 4.2 选择 XXX 最后 一个选项
* </p>
* <p>
* 5.点击事件<br>
* 5.1 点击 XXX<br>
* 5.2 右击 XXX<br>
* 5.3 双击 XXX
* </p>
* <p>
* 6.定位窗体事件<br>
* 6.1 定位 XXX 窗体<br>
* 6.2 定位顶层窗体
* </p>
* <p>
* 7.判断事件<br>
* 7.1 判断 XXX 中是否 包含 XXX<br>
* 7.2 判断 XXX 中是否 XXX<br>
* 7.3 判断 XXX 是否存在
* </p>
*
* @author 彭宇琦
*/
public class TextToOperation {
// 定义事件类
private Event event;
public TextToOperation(Event event) {
this.event = event;
}
/**
* 添加中文步骤
*
* @param text
* 步骤内容
* @return 执行返回值
*/
public String step(String text) {
return judgeEventType(text);
}
/**
* 用于判根据传入的信息判断其信息对应的是哪一种事件
*/
private String judgeEventType(String text) {
String name = null;
try {
// 处理控件名
name = text.substring(text.indexOf("") + 1, text.indexOf(""));
} catch (IndexOutOfBoundsException e) {
// 若抛出下标越界异常则抛出语法错误异常
throw new IncorrectGrammarException("控件名缺失");
}
// 对传入的text进行判断
if (text.indexOf("") == 0) {
return inputEvent(text.substring(text.indexOf("") + 1), name);
} else if (text.indexOf("清空") == 0) {
return clearEvent(name);
} else if (text.indexOf("获取") == 0) {
return getEvent(name);
} else if (text.indexOf("选择") == 0) {
return String.valueOf(selectEvent(text.substring(text.indexOf("") + 1), name));
} else if (text.indexOf("") == 1) {
return clickEvent(text.substring(0, text.indexOf("")), name);
} else if (text.indexOf("定位") == 0) {
return frameEvent(name);
} else if (text.indexOf("判断") == 0) {
//return judgeEvent(text.substring(text.indexOf("") + 1), name);
return "";
} else {
throw new IncorrectGrammarException("类型判断词无法识别");
}
}
/**
* 处理定位事件
*/
private String frameEvent(String name) {
String judeg_Text = "顶层窗体";
// 判断是否是定位到顶层窗体
if (judeg_Text.equals(name)) {
event.switchRootFrame();
} else {
event.switchFrame(name);
}
return "";
}
/**
* 处理判断事件
*/
/*
private String judgeEvent(String text, String name) {
// 处理方式先将text按照双引号进行切分若无内容则说明可能是判断元素是否存在若有内容则说明可能是文本判断
// 按照双引号的前部分对text的内容进行切分得到控件名和内容两部分之后再分别处理
String content = null;
try {
// 处理判断内容
content = text.substring(text.indexOf("") + 1, text.indexOf(""));
// 若未抛出下标越界异常则说明可能是文本判断
// 删除text判断内容的文本以避免误判断
text = new StringBuilder(text).delete(text.indexOf(""), text.indexOf("") + 1).toString();
// 用于判断文本是包含包含还是需要一致
boolean f = false;
// 判断是文本包含还是元素包含直接在if中加上对f变量的赋值若text包含则赋为true并可直接通过判断
if ((f = text.indexOf("") > -1 ? true : false) || text.indexOf("包含") > -1) {
// 添加事件
return String.valueOf(event.getJudgeEvent().judgeText(name, content, f));
} else {
// 若抛出下标越界异常则抛出语法错误异常
throw new IncorrectGrammarException("无效的判断词");
}
} catch (StringIndexOutOfBoundsException e) {
// 若抛出下标越界异常则说明可能是元素判断
if (text.indexOf("存在") > -1) {
// 添加事件
return String.valueOf(event.getJudgeEvent().judgeControl(name));
} else {
// 若未包含则说明其表述有误
throw new IncorrectGrammarException("无效的判断词");
}
}
}
*/
/**
* 处理点击事件
*/
private String clickEvent(String text, String name) {
// 判断需要使用哪一种点击事件
if (text.indexOf("点击") == 0) {
event.getClickEvent().click(name);
} else if (text.indexOf("双击") == 0) {
event.getClickEvent().doubleClick(name);
} else if (text.indexOf("右击") == 0) {
event.getClickEvent().rightClick(name);
} else {
throw new IncorrectGrammarException("选择下拉框选项语法缺失");
}
return "";
}
/**
* 处理选择事件
*/
private String selectEvent(String text, String name) {
// 判断text中包含或者最后若头不包含则抛出语法错误异常
if (text.indexOf("") > -1) {
// 根据语法获取需要的选项
int option = Integer.valueOf(text.substring(text.indexOf("") + 1, text.indexOf("")));
// 添加事件
return event.getSelectEvent().select(name, option).getStringValve();
} else if (text.indexOf("最后") > -1) {
return event.getSelectEvent().selectLast(name).getStringValve();
} else {
throw new IncorrectGrammarException("选择下拉框选项语法缺失");
}
}
/**
* 处理获取事件
*/
private String getEvent(String name) {
// 添加事件
return event.getTextEvent().getText(name).getStringValve();
}
/**
* 处理清空事件
*/
private String clearEvent(String name) {
// 添加事件
return event.getTextEvent().clear(name).getStringValve();
}
/**
* 处理输入事件
*/
private String inputEvent(String text, String name) {
// 按照双引号的前部分对text的内容进行切分得到控件名和内容两部分之后再分别处理
String content = null;
try {
// 处理输入内容
content = text.substring(text.indexOf("") + 1, text.indexOf(""));
} catch (ArrayIndexOutOfBoundsException e) {
// 若抛出下标越界异常则抛出语法错误异常
throw new IncorrectGrammarException("输入内容缺失");
}
// 判断是否包含随机二字则按照随机的方式进行处理
if (text.indexOf("随机") > -1) {
// 定义随机字符串类用于生成相应的随机字符串
RandomString rs = new RandomString();
// 循环读取所有的模型
for (String mode : content.split("")) {
// 判断需要加入到随机字符串中的模型
if (mode.equalsIgnoreCase("中文")) {
rs.addMode(StringMode.CH);
} else if (mode.equalsIgnoreCase("小写字母")) {
rs.addMode(StringMode.LOW);
} else if (mode.equalsIgnoreCase("大写字母")) {
rs.addMode(StringMode.CAP);
} else if (mode.equalsIgnoreCase("数字")) {
rs.addMode(StringMode.NUM);
}
}
// 判断模型是否未加载
if ("".equals(rs.getStringSeed())) {
throw new IncorrectGrammarException("输入的随机模型信息有误");
}
// 在判断是否有长度分隔符根据其结果来对事件进行处理
if (text.indexOf("-") > -1) {
// 获取间隔长度的最小值
int min = Integer.valueOf(text.substring(text.indexOf("输入") + 2, text.indexOf("-")));
// 获取间隔长度的最大值
int max = Integer.valueOf(text.substring(text.indexOf("-") + 1, text.indexOf("")));
// 添加事件
return event.getTextEvent().randomInput(name, min, max, rs.getStringSeed()).getStringValve();
} else {
// 获取需要输入的长度
int len = Integer.valueOf(text.substring(text.indexOf("输入") + 2, text.indexOf("")));
// 添加事件
return event.getTextEvent().randomInput(name, len, len, rs.getStringSeed()).getStringValve();
}
} else {
// 若不是随机输入则按照正常的输入方式添加事件
return event.getTextEvent().input(name, content).getStringValve();
}
}
}

View File

@ -1,38 +0,0 @@
package pres.auxiliary.selenium.event;
/**
* <p><b>文件名</b>UnrecognizableLocationModeException.java</p>
* <p><b>用途</b>在元素定位方式无法被识别的情况下抛出的异常</p>
* <p><b>编码时间</b>2019年9月24日下午3:19:43</p>
* <p><b>修改时间</b>2019年9月24日下午3:19:43</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public class UnrecognizableLocationModeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public UnrecognizableLocationModeException() {
super();
}
public UnrecognizableLocationModeException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public UnrecognizableLocationModeException(String message, Throwable cause) {
super(message, cause);
}
public UnrecognizableLocationModeException(String message) {
super(message);
}
public UnrecognizableLocationModeException(Throwable cause) {
super(cause);
}
}

View File

@ -1,39 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ClearInter.java</p>
* <p><b>用途</b>该接口定义控件内容清空事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月6日上午8:19:34</p>
* <p><b>修改时间</b>2019年9月6日上午8:19:34</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface ClearInter {
/**
* 用于判断标签名是否为input
*/
static final String TAGNAME_INPUT = "input";
/**
* 该方法通过控件名称或定位方式对页面元素进行定位来清空控件中的内容主要用于清空文本框中已有的数据
* 本操作的的返回值是{@link EventResultEnum#STRING}其枚举的值为输入到控件的内容参见{@link EventResultEnum}
* 该方法将返回值可通过类{@link Event}中的{@link Event#getStringValve()}方法进行返回
* @param element 通过查找页面得到的控件元素对象
*/
static void clear(WebElement element) {
// 判断元素是否为input元素如果是则获取其value值若不是则调用getText()方法
if (TAGNAME_INPUT.equalsIgnoreCase(element.getTagName())) {
Event.setValue(EventResultEnum.STRING.setValue(element.getAttribute("value")));
} else {
Event.setValue(EventResultEnum.STRING.setValue(element.getText()));
}
//清空元素中的内容
element.clear();
}
}

View File

@ -1,15 +0,0 @@
package pres.auxiliary.selenium.event.inter;
/**
* <p><b>文件名</b>ClickEventInter.java</p>
* <p><b>用途</b>该接口集合普通元素的所有点击相关的事件可在此处扩展新的方法</p>
* <p><b>编码时间</b>2019年8月29日下午3:15:39</p>
* <p><b>修改时间</b>2019年8月29日下午3:15:39</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface ClickEventInter
extends CommenElementClickInter, CommenElementDoubleClickInter, CommenElementRightClickInter {
}

View File

@ -1,32 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ClickInter.java</p>
* <p><b>用途</b>该接口定义鼠标左键单击事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年8月29日下午3:16:45</p>
* <p><b>修改时间</b>2019年12月29日下午1:41:45</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface ClickInter {
/**
* 鼠标左键单击事件的处理方法本操作的的返回值是{@link EventResultEnum#VOID}
* 其枚举的值为空串参见{@link EventResultEnum}该方法将返回值可通过类{@link Event}
* {@link Event#getStringValve()}方法进行返回
*
* @param element 通过查找页面得到的控件元素对象
*/
static void click(WebElement element) {
//进行元素的点击事件
element.click();
//设置返回值为空
Event.setValue(EventResultEnum.VOID);
}
}

View File

@ -1,37 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>CommenElementClearInter.java
* </p>
* <p>
* <b>用途</b>该接口定义了普通元素内容清空事件的实现标准
* </p>
* <p>
* <b>编码时间</b>2019年9月6日上午8:31:24
* </p>
* <p>
* <b>修改时间</b>2019年9月6日上午8:31:24
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementClearInter extends ClearInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并对控件中的内容进行清空操作主要用于清空文本框中已有的数据
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为控件中原有的内容可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*
*/
Event clear(String name);
}

View File

@ -1,36 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>CommenElementClickInter.java
* </p>
* <p>
* <b>用途</b>该接口定义了普通元素鼠标左键单击事件的实现标准
* </p>
* <p>
* <b>编码时间</b>2019年8月29日下午3:18:14
* </p>
* <p>
* <b>修改时间</b>2019年8月29日下午3:18:14
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementClickInter extends ClickInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并进行鼠标左键单击操作
* 本操作返回的枚举值是{@link EventResultEnum#VOID}其枚举的value值为空串可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event click(String name);
}

View File

@ -1,26 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementDoubleClickInter.java</p>
* <p><b>用途</b>该接口定义了普通元素鼠标左键双击事件的实现标准</p>
* <p><b>编码时间</b>2019年8月29日下午3:21:31</p>
* <p><b>修改时间</b>2019年8月29日下午3:21:31</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementDoubleClickInter extends DoubleClickInter {
/**
* 通过传入传入的控件名称到类中指向的xml文件中查找控件名称对应的定位方式进行鼠标左键双击操作
* 本操作返回的枚举值是{@link EventResultEnum#VOID}其枚举的value值为空串可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event doubleClick(String name);
}

View File

@ -1,28 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementGetAttributeValueInter.java</p>
* <p><b>用途</b>该接口定义了获取普通元素在html标签下属性值事件的实现标准</p>
* <p><b>编码时间</b>2019年9月6日上午8:45:54</p>
* <p><b>修改时间</b>2019年9月6日上午8:45:54</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementGetAttributeValueInter extends GetAttributeValueInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并获取元素的指定属性值的内容本操作返回的枚举值
* {@link EventResultEnum#STRING}其枚举的value值为获取到的控件指定属性的内容可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @param attributeName 属性名称
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event getAttributeValue(String name, String attributeName);
}

View File

@ -1,26 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementGetTextInter.java</p>
* <p><b>用途</b>该接口定义了获取普通元素内容事件事件的实现标准</p>
* <p><b>编码时间</b>2019年9月6日上午8:37:20</p>
* <p><b>修改时间</b>2019年9月6日上午8:37:20</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementGetTextInter extends GetTextInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并获取其中的内容
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为控件中的文本内容可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event getText(String name);
}

View File

@ -1,27 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementInputInter.java</p>
* <p><b>用途</b>该接口定义了普通元素输入事件的实现标准</p>
* <p><b>编码时间</b>2019年9月6日上午8:17:21</p>
* <p><b>修改时间</b>2019年9月6日上午8:17:21</p>
* @author
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementInputInter extends InputInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并在控件中输入指定的内容
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为输入到控件中的内容可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式
* @param text 待输入的内容
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event input(String name, String text);
}

View File

@ -1,56 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>CommenElementJudgeKeyInter.java
* </p>
* <p>
* <b>用途</b>该接口定义了普通元素对多个关键词判断事件的实现标准
* </p>
* <p>
* <b>编码时间</b>2019年9月2日下午2:28:59
* </p>
* <p>
* <b>修改时间</b>2019年9月2日下午2:28:59
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementJudgeKeyInter extends JudgeKeyInter {
/**
* <p>
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并获取控件中的文本判断文本中是否包含传入的关键词根据keyFull来判断是否需要所有的
* 关键词都包含在文本中例如有如下标签<br>
* &lt;p id="h"&gt;请输入正确填写关键词&lt;/p&gt;
* </p>
* <p>
* 则如下调用时结果为true<br>
* judgeKey("//p[@id='h']", true, "请输入", "关键词");<br>
* judgeKey("//p[@id='h']", false, "标题", "关键词");
* </p>
* <p>
* 如下调用时结果为false<br>
* judgeKey("//p[@id='h']", true, "标题", "关键词");<br>
* judgeKey("//p[@id='h']", false, "标题", "内容");
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的value值为判断的结果以字符串的形式存储"false""true"可参见{@link EventResultEnum}
* </p>
*
* @param name 控件的名称或xpath与css定位方式
* @param keyFull 是否需要所有关键词都包含
* @param keys 关键词组
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* 亦可通过{@link Event#getBooleanValve()}方法将枚举值转换为boolean进行返回
*/
Event judgeKey(String name, boolean keyFull, String... keys);
}

View File

@ -1,39 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>CommenElementJudgeTextInter.java
* </p>
* <p>
* <b>用途</b>该接口定义了普通元素对单个关键词判断事件的实现标准
* </p>
* <p>
* <b>编码时间</b>2019年9月2日下午2:39:26
* </p>
* <p>
* <b>修改时间</b>2019年9月2日下午2:39:26
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementJudgeTextInter extends JudgeTextInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并判断控件中的文本是否包含或者与关键词一致本操作返回的枚举值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的value值为判断的结果以字符串的形式存储"false""true"可参见{@link EventResultEnum}
*
* @param name 控件名称控件定位的xpath或者css路径
* @param textFull 是否需要与页面文本完全一致
* @param key 关键词
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* 亦可通过{@link Event#getBooleanValve()}方法将枚举值转换为boolean进行返回
*/
Event judgeText(String name, boolean keyFull, String key);
}

View File

@ -1,29 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementRightClickInter.java</p>
* <p><b>用途</b>该接口定义了普通元素鼠标右键单击事件的实现标准</p>
* <p><b>编码时间</b>2019年8月29日下午3:21:55</p>
* <p><b>修改时间</b>2019年8月29日下午3:21:55</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementRightClickInter extends RightClickInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并进行鼠标右键单击操作
* 本操作返回的枚举值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的value值为判断的结果以字符串的形式存储"false""true"可参见{@link EventResultEnum}
*
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* 亦可通过{@link Event#getBooleanValve()}方法将枚举值转换为boolean进行返回
*/
Event rightClick(String name);
}

View File

@ -1,49 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementSelectFirstInter.java</p>
* <p><b>用途</b>该接口定义了普通元素选择下拉框第一个选线事件的实现标准</p>
* <p><b>编码时间</b>2019年9月3日下午4:27:40</p>
* <p><b>修改时间</b>2019年9月3日下午4:27:40</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementSelectFirstInter extends SelectFirstInter {
/**
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并对标准的web下拉框由标签select和标签option构成选择其下拉框第一个选项
* 亦可以对非标准的下拉框由大量的div等标签组成进行操作但对于非标准的下拉框需要传入的是选项列表例如<br>
* 标准下拉框<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可但对于非标准的下拉框其下拉框是由input和button标签构成<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项<br>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为当前选择选项的内容可参见{@link EventResultEnum}
* </p>
*
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event selectFirst(String name);
}

View File

@ -1,60 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.NoSuchElementException;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementSelectInter.java</p>
* <p><b>用途</b>该接口定义了普通元素选择指定选项事件的实现标准</p>
* <p><b>编码时间</b>2019年9月3日下午4:32:25</p>
* <p><b>修改时间</b>2019年9月3日下午4:32:25</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementSelectInter extends SelectInter {
/**
* <p>
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并对标准的web下拉框由标签select和标签option构成进行选择亦可以对非标准的下拉框由大量的div等标签组成进行操作但对于非标准的
* 下拉框需要传入的是选项列表例如<br>
* 标准下拉框<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可但对于非标准的下拉框其下拉框是由input和button标签构成<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为当前选择选项的内容可参见{@link EventResultEnum}
* </p>
* <p>
* <b><i>注意</i></b>option序号从1开始1表示第一个选项亦可传入负数-1表示倒数第一个选项
* -2表示倒数第二个选项以此类推当传入的值为0时则表示随机选择一个选项但随机的值不包括第一个选项
* 以避免第一个元素为空或为请选择之类的选项
* </p>
*
* @param name 控件的名称或xpath与css定位方式
* @param option 选项的序号正数表示从前向后选负数表示从后往前选0表示随机选择
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* @throws NoSuchElementException 指定的选项值超过选项的最大值时抛出
*/
Event select(String name, int option);
}

View File

@ -1,51 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementSelectLastInter.java</p>
* <p><b>用途</b>该接口定义了普通元素选择下拉框最后一个选项事件的实现标准</p>
* <p><b>编码时间</b>2019年9月3日下午4:40:46</p>
* <p><b>修改时间</b>2019年9月3日下午4:40:46</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface CommenElementSelectLastInter extends SelectLastInter {
/**
* <p>
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并对标准的web下拉框由标签select和标签option构成选择其下拉框最后一个选项
* 亦可以对非标准的下拉框由大量的div等标签组成进行操作但对于非标准的下拉框需要传入的是选项列表例如<br>
* 标准下拉框<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可但对于非标准的下拉框其下拉框是由input和button标签构成<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为当前选择选项的内容可参见{@link EventResultEnum}
* </p>
*
* @param name 控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event selectLast(String name);
}

View File

@ -1,26 +0,0 @@
package pres.auxiliary.selenium.event.inter;
/**
* <p>
* <b>文件名</b>DataListEventInter.java
* </p>
* <p>
* <b>用途</b>该接口定义了列表元素需要使用的基本方法
* </p>
* <p>
* <b>编码时间</b>2019年10月8日下午6:50:43
* </p>
* <p>
* <b>修改时间</b>2019年10月8日下午6:50:43
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface DataListEventInter extends ListElementClickInter, ListElementDoubleClickInter,
ListElementRightClickInter, ListElementGetAttributeValueInter, ListElementGetTextInter,
ListElementJudgeKeyInter, ListElementJudgeTextInter, ListElementClearInter, ListElementInputInter {
}

View File

@ -1,35 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>DoubleClickInter.java</p>
* <p><b>用途</b>该接口定义鼠标左键双击事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年8月29日下午3:18:21</p>
* <p><b>修改时间</b>2019年12月29日下午1:41:45</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface DoubleClickInter {
/**
* 鼠标左键双击事件的处理方法本操作的的返回值是{@link EventResultEnum#VOID}
* 枚举的值为空串参见{@link EventResultEnum}该方法将返回值可通过类{@link Event}
* {@link Event#getStringValve()}方法进行返回
*
* @param driver 页面WebDriver对象
* @param element 通过查找页面得到的控件元素的WebElement对象
*/
static void doubleClick(WebDriver driver, WebElement element) {
//进行元素的点击事件
new Actions(driver).doubleClick(element).perform();
Event.setValue(EventResultEnum.VOID);
}
}

View File

@ -1,28 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>GetAttributeValueInter.java</p>
* <p><b>用途</b>该接口定义获取元素在html标签下属性值事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月6日上午8:39:57</p>
* <p><b>修改时间</b>2019年9月26日下午7:02:57</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface GetAttributeValueInter {
/**
* 用于获取页面元素的某一属性值的内容
* @param element 控件的名称或xpath与css定位方式
* @param attributeName 属性名称
*/
static void getAttributeValue(WebElement element, String attributeName) {
//获取元素的属性值将其存储至枚举中
Event.setValue(EventResultEnum.STRING.setValue(element.getAttribute(attributeName)));
}
}

View File

@ -1,36 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>GetTextInter.java</p>
* <p><b>用途</b>该接口定义获取元素内容事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月6日上午8:33:47</p>
* <p><b>修改时间</b>2019年9月26日下午7:02:57</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface GetTextInter {
/**
* 用于判断标签名是否为input
*/
static final String TAGNAME_INPUT = "input";
/**
* 该方法通过传入页面元素对象进行定位来获取其中的内容
* @param element 通过查找页面得到的控件元素对象
*/
static void getText(WebElement element) {
// 判断元素是否为input元素如果是则获取其value值若不是则调用getText()方法
if (TAGNAME_INPUT.equalsIgnoreCase(element.getTagName())) {
Event.setValue(EventResultEnum.STRING.setValue(element.getAttribute("value")));
} else {
Event.setValue(EventResultEnum.STRING.setValue(element.getText()));
}
}
}

View File

@ -1,30 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>InputInter.java</p>
* <p><b>用途</b>该接口定义键盘输入事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月4日上午8:19:53</p>
* <p><b>修改时间</b>2019年9月4日上午8:19:53</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface InputInter {
/**
* 根据定位得到的控件元素对象在其控件中进行输入指定的内容
* @param element 通过查找页面得到的控件元素对象
* @param text 待输入的内容
*/
static void input(WebElement element, String text) {
//控件中输入内容
element.sendKeys(text);
//将输入的内容存储至枚举中
Event.setValue(EventResultEnum.STRING.setValue(text));
}
}

View File

@ -1,26 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>JudgeEventInter.java</p>
* <p><b>用途</b>该接口集合普通元素的所有判断相关的事件可在此处扩展新的方法</p>
* <p><b>编码时间</b>2019年9月2日下午3:00:19</p>
* <p><b>修改时间</b>2019年9月2日下午3:00:19</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface JudgeEventInter
extends CommenElementJudgeKeyInter, CommenElementJudgeTextInter {
/**
* 判断页面上是否存在name对应的控件.本操作返回的枚举值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的value值为判断的结果以字符串的形式存储"false""true"可参见{@link EventResultEnum}
* @param name 控件名称控件定位的xpath或者css路径
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* 亦可通过{@link Event#getBooleanValve()}方法将枚举值转换为boolean进行返回
*/
Event judgeControl(String name);
}

View File

@ -1,78 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>JudgeKey.java
* </p>
* <p>
* <b>用途</b>该接口定义页面文本与指定文本的判断方法该方法可传入多个关键词对页面的数据进行逐一
* 比对根据传参判断是否要完全满足该关键词的对比为模糊对比 只需要关键词在页面文本中包含即可
* </p>
* <p>
* <b>编码时间</b>2019年9月1日上午9:52:04
* </p>
* <p>
* <b>修改时间</b>2019年9月1日上午9:52:04
* </p>
*
* @author
* @version Ver1.0
* @since JDK 12
*
*/
public interface JudgeKeyInter {
/**
* <p>
* 用于判断文本中是否包含传入的关键词根据keyFull来判断是否需要所有的关键词都包含在文本中例如有如下标签<br>
* &lt;p id="h"&gt;请输入正确填写关键词&lt;/p&gt;<br>
* <br>
* 则如下调用时结果为true<br>
* judgeKey("//p[@id='h']", true, "请输入", "关键词");<br>
* judgeKey("//p[@id='h']", false, "标题", "关键词");<br>
* <br>
* 如下调用时结果为false<br>
* judgeKey("//p[@id='h']", true, "标题", "关键词");<br>
* judgeKey("//p[@id='h']", false, "标题", "内容");<br>
* </p>
* <p>本操作的的返回值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的值为输入到控件的内容参见{@link EventResultEnum}
* 该方法将返回值可通过类{@link Event}中的{@link Event#getStringValve()}方法进行返回
* 亦可通过{@link Event#getBooleanValue()}方法进行返回
* </p>
*
* @param element 通过查找页面得到的控件元素的WebElement对象
* @param keyFull 是否需要所有关键词都包含
* @param keys 关键词组
*/
static void judgeKey(WebElement element, boolean keyFull, String... keys) {
//获取当前元素的文本
GetTextInter.getText(element);
// 将文本存储至text中
String text = Event.getStringValve();
// 循环判断文本是否包含所有关键词
for (String key : keys) {
// 判断文字是否包含关键词若未包含则设置为false若包含则设置为true
if (text.indexOf(key) == -1) {
//由于Event中存储的返回值是以最后一次存储的值为主故此处可以直接使用此方法以达到存储返回值的目的
Event.setValue(EventResultEnum.BOOLEAN_FALSE);
// 若未包含且需要关键词全包含时keyFull为true时可直接返回false
if (keyFull) {
return;
}
} else {
Event.setValue(EventResultEnum.BOOLEAN_TRUE);
// 若未包含且不需要关键词全包含时keyFull为false时可直接返回true
if (!keyFull) {
Event.setValue(EventResultEnum.BOOLEAN_TRUE);
return;
}
}
}
}
}

View File

@ -1,62 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebElement;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>JudgeKeyInter.java
* </p>
* <p>
* <b>用途</b>该接口定义页面文本与指定文本的判断方法该方法用传入的关键词与页面对比可精准对比亦可模糊对比
* </p>
* <p>
* <b>编码时间</b>2019年8月30日下午7:52:43
* </p>
* <p>
* <b>修改时间</b>2019年9月29日下午9:23:43
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface JudgeTextInter {
/**
* 判断控件中的文本是否包含或者与关键词一致
* <p>本操作的的返回值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的值为输入到控件的内容参见{@link EventResultEnum}
* 该方法将返回值可通过类{@link Event}中的{@link Event#getStringValve()}方法进行返回
* 亦可通过{@link Event#getBooleanValue()}方法进行返回
* </p>
*
* @param element 通过查找页面得到的控件元素的WebElement对象
* @param keyFull 是否需要与页面文本完全一致
* @param text 需要判断的字符号串
*/
static void judgeText(WebElement element, boolean keyFull, String key) {
// 获取元素指向的信息的内容文本
GetTextInter.getText(element);
String text = Event.getStringValve();
// 判断控件文本是否需要完整包含
if (keyFull) {
// 判断获取的文字一致
if (text.equals(key)) {
Event.setValue(EventResultEnum.BOOLEAN_TRUE);
} else {
Event.setValue(EventResultEnum.BOOLEAN_FALSE);
}
} else {
// 判断文字是否包含
if (text.indexOf(key) > -1) {
Event.setValue(EventResultEnum.BOOLEAN_TRUE);
} else {
Event.setValue(EventResultEnum.BOOLEAN_FALSE);
}
}
}
}

View File

@ -1,35 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p>
* <b>文件名</b>CommenElementClearInter.java
* </p>
* <p>
* <b>用途</b>该接口定义了列表元素内容清空事件的实现标准
* </p>
* <p>
* <b>编码时间</b>2019年9月6日上午8:31:24
* </p>
* <p>
* <b>修改时间</b>2019年10月8日上午8:31:24
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementClearInter extends ClearInter {
/**
* 该方法通过页面元素对象对页面元素进行清空内容的操作主要用于清空文本框中已有的数据
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为控件中原有的内容可参见{@link EventResultEnum}
*
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*
*/
Event clear();
}

View File

@ -1,25 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementClickInter.java</p>
* <p><b>用途</b>该接口定义了列表元素鼠标左键单击事件的实现标准</p>
* <p><b>编码时间</b>2019年8月29日下午3:22:22</p>
* <p><b>修改时间</b>2019年8月29日下午3:22:22</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementClickInter extends ClickInter {
/**
* 根据列表类返回的对象进行鼠标左键单击操作
*
* @return Event类对象可通过该类继续写操作以及获取返回值参见{@link Event}
* 本操作的的返回值是EventResultEnum.VOID参见{@link EventResultEnum}
*/
Event click();
}

View File

@ -1,25 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementDoubleClickInter.java</p>
* <p><b>用途</b>该接口定义了列表元素鼠标左键双击事件的实现标准</p>
* <p><b>编码时间</b>2019年8月29日下午3:22:49</p>
* <p><b>修改时间</b>2019年8月29日下午3:22:49</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementDoubleClickInter extends DoubleClickInter {
/**
* 根据列表类返回的对象进行鼠标左键双击操作
*
* @return Event类对象可通过该类继续写操作以及获取返回值参见{@link Event}
* 本操作的的返回值是EventResultEnum.VOID参见{@link EventResultEnum}
*/
Event doubleClick();
}

View File

@ -1,26 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>CommenElementGetAttributeValueInter.java</p>
* <p><b>用途</b>该接口定义了获取列表元素在html标签下属性值事件的实现标准</p>
* <p><b>编码时间</b>2019年9月6日上午8:45:54</p>
* <p><b>修改时间</b>2019年9月6日上午8:45:54</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementGetAttributeValueInter extends GetAttributeValueInter {
/**
* 用于获取页面元素的某一属性值的内容本操作返回的枚举值
* {@link EventResultEnum#STRING}其枚举的value值为获取到的控件指定属性的内容可参见{@link EventResultEnum}
*
* @param attributeName 属性名称
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event getAttributeValue(String attributeName);
}

View File

@ -1,24 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementGetTextInter.java</p>
* <p><b>用途</b>该接口定义了获取普通元素内容事件事件的实现标准</p>
* <p><b>编码时间</b>2019年9月6日上午8:37:20</p>
* <p><b>修改时间</b>2019年10月8日上午8:34:04</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementGetTextInter extends GetTextInter {
/**
* 该方法通过传入控件名称或定位方式对页面元素进行定位来获取其中的内容
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为控件中的文本内容可参见{@link EventResultEnum}
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event getText();
}

View File

@ -1,24 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementInputInter.java</p>
* <p><b>用途</b>该接口定义了普通元素输入事件的实现标准</p>
* <p><b>编码时间</b>2019年10月8日上午8:25:39</p>
* <p><b>修改时间</b>2019年10月8日上午8:25:39</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface ListElementInputInter extends InputInter {
/**
* 根据元素对象在其控件中进行输入指定的内容
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为输入到控件中的内容可参见{@link EventResultEnum}
* @param text 待输入的内容
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event input(String text);
}

View File

@ -1,44 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementJudgeKeyInter.java</p>
* <p><b>用途</b>该接口定义了列表元素对多个关键词判断事件的实现标准</p>
* <p><b>编码时间</b>2019年10月8日上午8:35:42</p>
* <p><b>修改时间</b>2019年10月8日上午8:35:42</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementJudgeKeyInter extends JudgeKeyInter {
/**
* <p>
* 用于判断文本中是否包含传入的关键词根据keyFull来判断是否需要所有的关键词都包含在文本中例如有如下标签<br>
* &lt;p id="h"&gt;请输入正确填写关键词&lt;/p&gt;
* </p>
* <p>
* 则如下调用时结果为true<br>
* judgeKey("//p[@id='h']", true, "请输入", "关键词");<br>
* judgeKey("//p[@id='h']", false, "标题", "关键词");
* </p>
* <p>
* 如下调用时结果为false<br>
* judgeKey("//p[@id='h']", true, "标题", "关键词");<br>
* judgeKey("//p[@id='h']", false, "标题", "内容");
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的value值为判断的结果以字符串的形式存储"false""true"可参见{@link EventResultEnum}
* </p>
*
* @param keyFull 是否需要所有关键词都包含
* @param keys 关键词组
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* 亦可通过{@link Event#getBooleanValve()}方法将枚举值转换为boolean进行返回
*/
Event judgeKey(boolean keyFull, String... keys);
}

View File

@ -1,28 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementJudgeTextInter.java</p>
* <p><b>用途</b>该接口定义了列表元素对单个关键词判断事件的实现标准</p>
* <p><b>编码时间</b>2019年10月8日上午8:37:35</p>
* <p><b>修改时间</b>2019年10月8日上午8:37:35</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementJudgeTextInter extends JudgeTextInter {
/**
* 判断控件中的文本是否包含或者与关键词一致本操作返回的枚举值是{@link EventResultEnum#BOOLEAN_FALSE}{@link EventResultEnum#BOOLEAN_TRUE}
* 其枚举的value值为判断的结果以字符串的形式存储"false""true"可参见{@link EventResultEnum}
*
* @param textFull 是否需要与页面文本完全一致
* @param key 关键词
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* 亦可通过{@link Event#getBooleanValve()}方法将枚举值转换为boolean进行返回
*/
Event judgeText(boolean keyFull, String key);
}

View File

@ -1,25 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>ListElementRightClickInter.java</p>
* <p><b>用途</b>该接口定义了列表元素鼠标右键单击事件的实现标准</p>
* <p><b>编码时间</b>2019年8月29日下午3:23:09</p>
* <p><b>修改时间</b>2019年8月29日下午3:23:09</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
@FunctionalInterface
public interface ListElementRightClickInter extends RightClickInter {
/**
* 根据列表类返回的对象进行鼠标右键单击操作
*
* @return Event类对象可通过该类继续写操作以及获取返回值参见{@link Event}
* 本操作的的返回值是EventResultEnum.VOID参见{@link EventResultEnum}
*/
Event rightClick();
}

View File

@ -1,34 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>RightClickInter.java</p>
* <p><b>用途</b>该接口定义鼠标右键单击事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年8月29日下午3:18:38</p>
* <p><b>修改时间</b>2019年12月29日下午1:41:45</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface RightClickInter {
/**
* 鼠标右键单击事件的处理方法本操作的的返回值是{@link EventResultEnum#VOID}
* 枚举的值为空串参见{@link EventResultEnum}该方法将返回值可通过类{@link Event}
* {@link Event#getStringValve()}方法进行返回
*
* @param driver 页面WebDriver对象
* @param element 通过查找页面得到的控件元素的WebElement对象
*/
static void rightClick(WebDriver driver, WebElement element) {
//进行元素的点击事件
new Actions(driver).contextClick(element).perform();
Event.setValue(EventResultEnum.VOID);
}
}

View File

@ -1,55 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import org.openqa.selenium.NoSuchElementException;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>SelectEventInter.java</p>
* <p><b>用途</b>该接口集合普通元素的所有选择相关的事件可在此处扩展新的方法</p>
* <p><b>编码时间</b>2019年9月3日下午5:00:07</p>
* <p><b>修改时间</b>2019年9月3日下午5:00:07</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface SelectEventInter
extends CommenElementSelectFirstInter, CommenElementSelectInter, CommenElementSelectLastInter {
/**
* <p>
* 通过传入在xml文件中的控件名称到类中指向的xml文件中查找控件名称对应的定位方式或直接传入xpath与css定位方式
* 根据定位方式在页面查找元素并对标准的web下拉框由标签select和标签option构成根据传入的选项进行选择亦可以对非标准的下拉框由大量的div等标签组成进行操作但对于非标准的
* 下拉框需要传入的是选项列表例如<br>
* 标准下拉框<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可但对于非标准的下拉框其下拉框是由input和button标签构成<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为当前选择选项的内容可参见{@link EventResultEnum}
* </p>
*
* @param name 控件的名称或xpath与css定位方式
* @param optionStr 选项的内容
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
* @throws NoSuchElementException 指定的选项值不存在时抛出
*/
Event select(String name, String optionStr);
}

View File

@ -1,64 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import java.util.List;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>SelectFirstInter.java</p>
* <p><b>用途</b>该接口定义下拉框选择事件选择第一个选项的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月3日下午2:33:11</p>
* <p><b>修改时间</b>2019年9月29日下午7:33:11</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface SelectFirstInter {
/**
* 该方法用于选择标准的web下拉框由标签select和标签option构成的第一个选项例如<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可
*
* @param element 通过查找页面得到的控件元素对象
*/
static void selectFirst(WebElement element) {
//定义Select类对象
Select select = new Select(element);
//选择元素
select.selectByIndex(0);
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(select.getOptions().get(0).getText()));
}
/**
* 该方法用于选择非标准的web标准下拉框由inputbutton和大量的div标签组成的第一个选项对于非标准的下拉框需要传入的是选项列表例如<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
*
* @param elements 通过查找页面得到的选项组对象
*/
static void selectFirst(List<WebElement> elements) {
elements.get(0).click();
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(elements.get(0).getText()));
}
}

View File

@ -1,200 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>SelectInter.java</p>
* <p><b>用途</b>该接口定义下拉框选择事件的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月3日上午8:38:34</p>
* <p><b>修改时间</b>2019年9月3日上午8:38:34</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface SelectInter {
/**
* <p>
* 该方法用于对标准的web下拉框由标签select和标签option构成进行选择例如<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可
* </p>
* <p>
* <b><i>注意</i></b>option序号从1开始1表示第一个选项亦可传入负数-1表示倒数第一个选项
* -2表示倒数第二个选项以此类推当传入的值为0时则表示随机选择一个选项但随机的值不包括第一个选项
* 以避免第一个元素为空或为请选择之类的选项
* </p>
* @param element 通过查找页面得到的控件元素对象
* @param option 选项的序号正数表示从前向后选负数表示从后往前选0表示随机选择
* @throws NoSuchElementException 指定的选项值超过选项的最大值时抛出
*/
static void select(WebElement element, int option) {
//定义Select类对象
Select select = new Select(element);
//获取选项的长度
int length = select.getOptions().size();
//判断传入的选项值的绝对值由于可传入负数故取绝对值是否大于选项的总长度若大于总长度则抛出NoSuchElementException
if (Math.abs(option) > length) {
throw new NoSuchElementException("指定的选项值大于选项的最大值。选项总个数:" + length + "指定项:" + option);
}
//判断option的值若大于0则从前向后遍历若小于0则从后往前遍历若等于0则随机输入
if (option > 0) {
//选择元素正数的选项值从1开始故需要减小1才是正确的选项值
select.selectByIndex(option - 1);
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(select.getOptions().get(option - 1).getText()));
} else if (option < 0) {
//选择元素由于option为负数则长度加上选项值即可得到需要选择的选项
select.selectByIndex(length + option);
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(select.getOptions().get(length + option).getText()));
} else {
//为0则在判断选项是否只有一个若有多个则随机抽取若选项只有一个则直接选择第一个
//进行随机选择但不选择第一个元素避免第一个元素为空或为请选择之类的选项
int index = length > 1 ? new Random().nextInt(length - 1) + 1 : 0;
select.selectByIndex(index);
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(select.getOptions().get(index).getText()));
}
}
/**
* <p>
* 该方法用于对非标准的web标准下拉框由inputbutton和大量的div标签组成进行选择对于非标准的下拉框需要传入的是选项列表例如<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
* </p>
* <p>
* <b><i>注意</i></b>option序号从1开始1表示第一个选项亦可传入负数-1表示倒数第一个选项
* -2表示倒数第二个选项以此类推当传入的值为0时则表示随机选择一个选项但随机的值不包括第一个选项
* 以避免第一个元素为空或为请选择之类的选项
* </p>
* @param elements 通过查找页面得到的选项组对象
* @param option 选项的序号正数表示从前向后选负数表示从后往前选0表示随机选择
* @throws NoSuchElementException 指定的选项值超过选项的最大值时抛出
*/
static void select(List<WebElement> elements, int option) {
//获取选项的长度
int length = elements.size();
//判断传入的选项值的绝对值由于可传入负数故取绝对值是否大于选项的总长度若大于总长度则抛出NoSuchElementException
if (Math.abs(option) > length) {
throw new NoSuchElementException("指定的选项值大于选项的最大值。选项总个数:" + length + ",指定项:" + option);
}
//判断option的值若大于0则从前向后遍历若小于0则从后往前遍历若等于0则随机输入
if (option > 0) {
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(elements.get(option - 1).getText()));
//选择元素正数的选项值从1开始故需要减小1才是正确的选项值
elements.get(option - 1).click();
} else if (option < 0) {
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(elements.get(length + option).getText()));
//选择元素由于option为负数则长度加上选项值即可得到需要选择的选项
elements.get(length + option).click();
} else {
//为0则在判断选项是否只有一个若有多个则随机抽取若选项只有一个则直接选择第一个
int index = length > 1 ? new Random().nextInt(length - 1) + 1 : 0;
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(elements.get(index).getText()));
//进行随机选择但不选择第一个元素避免第一个元素为空或为请选择之类的选项
elements.get(index).click();
}
}
/**
* <p>
* 该方法用于对标准的web下拉框由标签select和标签option构成根据选项的内容进行选择例如<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可
* </p>
* @param element 通过查找页面得到的控件元素对象
* @param optionStr 选项的内容
* @throws NoSuchElementException 指定的选项内容不存在时抛出
*/
static void select(WebElement element, String optionStr) {
//定义Select类对象
Select select = new Select(element);
//获取select的所有选项的选项值并判断哪个选项与传入的值对应
int index = select.getOptions().stream().map(e -> e.getText()).collect(Collectors.toList()).indexOf(optionStr);
//判断选项值是否有与传入的选项值对应的选项若没有则抛出异常
if (index == -1) {
throw new NoSuchElementException("不存在的选项内容:" + optionStr);
}
select.selectByIndex(index);
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(optionStr));
}
/**
* <p>
* 该方法用于对非标准的web标准下拉框由inputbutton和大量的div标签组成根据指定的选项内容进行选择对于非标准的下拉框需要传入的是选项列表例如<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
* </p>
*
* @param elements 通过查找页面得到的选项组对象
* @param optionStr 选项的内容
* @throws NoSuchElementException 指定的选项内容不存在时抛出
*/
static void select(List<WebElement> elements, String optionStr) {
//获取select的所有选项的选项值并判断哪个选项与传入的值对应
int index = elements.stream().map(e -> e.getText()).collect(Collectors.toList()).indexOf(optionStr);
//判断选项值是否有与传入的选项值对应的选项若没有则抛出异常
if (index == -1) {
throw new NoSuchElementException("不存在的选项内容:" + optionStr);
}
elements.get(index).click();
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(optionStr));
}
}

View File

@ -1,64 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import java.util.List;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
/**
* <p><b>文件名</b>SelectLastInter.java</p>
* <p><b>用途</b>该接口定义下拉框选择事件选择最后一个选项的实现方法可直接使用</p>
* <p><b>编码时间</b>2019年9月3日上午8:42:12</p>
* <p><b>修改时间</b>2019年9月29日下午7:35:12</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 12
*
*/
public interface SelectLastInter {
/**
* 该方法用于选择标准的web下拉框由标签select和标签option构成的最后一个选项例如<br>
* &lt;select&nbsp;id='test'&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;&lt;/option&gt;<br>
* &emsp;&lt;option&gt;其他&lt;/option&gt;<br>
* &lt;/select&gt;<br>
* 对于该标准的下拉框选项只需要定位到//select[@id='test']得到其WebElement对象即可
*
* @param element 通过查找页面得到的控件元素对象
*/
static void selectLast(WebElement element) {
//定义Select类对象
Select select = new Select(element);
//选择元素
select.selectByIndex(select.getOptions().size() - 1);
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(select.getOptions().get(select.getOptions().size() - 1).getText()));
}
/**
* 该方法用于选择非标准的web标准下拉框由inputbutton和大量的div标签组成的最后一个选项对于非标准的下拉框需要传入的是选项列表例如<br>
* &lt;div&gt;<br>
* &emsp;&lt;span&gt;&lt;input/&gt;&lt;/span&gt;<br>
* &emsp;&lt;span&gt;&lt;button/&gt;&lt;/span&gt;<br>
* &lt;/div&gt;<br>
* 点击button对应的按钮后其下也能弹出选项但其选项是由div标签写入text构成<br>
* &lt;div&nbsp;id='test'&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;&lt;/div&gt;<br>
* &emsp;&lt;div&gt;其他&lt;/div&gt;<br>
* &lt;/div&gt;<br>
* 对于这种非标准的下拉框选项需要传入选项所在的所有div标签对应的WebElement元素在上例则需要定位到//div[@id='test']/div
* 注意末尾的div不指定数字则可以代表整个选项
*
* @param elements 通过查找页面得到的选项组对象
*/
static void selectLast(List<WebElement> elements) {
elements.get(elements.size() - 1).click();
//将下拉框的选项的值设置为枚举值
Event.setValue(EventResultEnum.STRING.setValue(elements.get(elements.size() - 1).getText()));
}
}

View File

@ -1,81 +0,0 @@
package pres.auxiliary.selenium.event.inter;
import java.io.File;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.event.EventResultEnum;
import pres.auxiliary.tool.randomstring.RandomString;
import pres.auxiliary.tool.randomstring.StringMode;
/**
* <p><b>文件名</b>TextEventInter.java</p>
* <p><b>用途</b>该接口集合普通元素的所有文本相关的事件可在此处扩展新的方法</p>
* <p><b>编码时间</b>2019年9月6日上午8:52:33</p>
* <p><b>修改时间</b>2019年10月31日下午7:25:40</p>
* @author 彭宇琦
* @version Ver1.1
* @since JDK 12
*
*/
public interface TextEventInter extends CommenElementClearInter, CommenElementGetAttributeValueInter,
CommenElementGetTextInter, CommenElementInputInter {
/**
* <p>
* 通过图片识别的方法根据codeName查找验证码图片元素位置识别页面中的验证码并将结果填入textName对应
* 的文本框中注意该方法识别验证码成功的概率不高在数字+英文的验证码模式下经常将数字识别为英文
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为输入到控件的内容可参见{@link EventResultEnum}
* </p>
*
* @param textName 文本框控件的名称或xpath与css定位方式
* @param codeName 验证码图片控件的名称或xpath与css定位方式
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event codeInput(String textName, String codeName);
/**
* <p>
* 该方法用于将一个指定的整数随机填写到传入的控件组中<br>
* <b><i>建议在指定值远远大于控件的数量时再使用该方法否则将会出现不可预期的问题</i></b>
* </p>
* <p>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为输入到控件的内容
* 由于涉及到多个文本框故其返回值有多个将以值1,值2,值3...的形式进行存储可参见{@link EventResultEnum}
* </p>
* @param num 指定的整数
* @param names 控件的名称或xpath与css定位方式可传入多个控件名称
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event avgIntergeInput(int num, String...names);
/**
* 该方法通过指定的随机字符串长度与指定的随机字符串模型枚举{@link StringMode}枚举类向控件中随机输入字符串操作<br>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为输入到控件的内容可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式可传入多个控件名称
* @param minLength 字符串最小长度设为小于等于0的数值时则默认为1
* @param maxLength 字符串最大长度设为小于等于0的数值时则默认为1若需要指定字符串的输入长度可设置minLength数值与maxLength一致
* @param modes {@link StringMode}枚举指定字符串输入的类型可传入多种模型参见{@link RandomString#RandomString(StringMode...)}
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event randomInput(String name, int minLength, int maxLength, StringMode... modes);
/**
* 该方法通过指定的随机字符串长度与指定的随机字符串模型向控件中随机输入字符串操作<br>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为输入到控件的内容可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式可传入多个控件名称
* @param minLength 字符串最小长度设为小于等于0的数值时则默认为1
* @param maxLength 字符串最大长度设为小于等于0的数值时则默认为1若需要指定字符串的输入长度可设置minLength数值与maxLength一致
* @param mode 可用的随机字符串抽取范围参见{@link RandomString#RandomString(String)}
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event randomInput(String name, int minLength, int maxLength, String mode);
/**
* 该方法用于向控件中上传指定的文件<br>
* 本操作返回的枚举值是{@link EventResultEnum#STRING}其枚举的value值为文件在本地中的绝对路径可参见{@link EventResultEnum}
* @param name 控件的名称或xpath与css定位方式可传入多个控件名称
* @param updataFile 需要上传到控件中的文件
* @return {@link Event}类对象可通过{@link Event#getStringValve()}方法获取操作的返回值
*/
Event updataFile(String name, File updataFile);
}

View File

@ -46,8 +46,9 @@ public class Time {
/** /**
* 定义日期约束类型的传入格式 * 定义日期约束类型的传入格式
*/ */
private final String REGEX_DATE = "(\\d{4}[-\\.年\\\\\\/][01]?\\d[-\\.月\\\\\\/][0123]?\\d日?)?" private final String REGEX_DATE = "(\\d{4}[-\\.年\\\\/][01]?\\d[-\\.月\\\\/][0123]?\\d日?"
+ "( ?[012]?\\d[:时][0123456]?\\d分?([:分][0123456]?\\d秒?)?)?"; + "( [012]?\\d[:时][0123456]?\\d分?([:分][0123456]?\\d秒?)?)?)|"
+ "([012]?\\d[:时][0123456]?\\d分?([:分][0123456]?\\d秒?))";
/** /**
* 构造当前时间 * 构造当前时间
@ -111,6 +112,12 @@ public class Time {
* @throws IncorrectConditionException 时间转换错误时抛出的异常 * @throws IncorrectConditionException 时间转换错误时抛出的异常
*/ */
public void setTime(String formatTime) { public void setTime(String formatTime) {
//若formatTime传入为Null或为空串则设置为当前时间
if (formatTime == null || formatTime.isEmpty()) {
setNowTime();
return;
}
if (formatTime.matches(REGEX_DATE)) { if (formatTime.matches(REGEX_DATE)) {
try { try {
date = new SimpleDateFormat(getDateFormat(formatTime)).parse(formatTime); date = new SimpleDateFormat(getDateFormat(formatTime)).parse(formatTime);

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.datadriven; package pres.auxiliary.work.selenium.datadriven;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;

View File

@ -0,0 +1,50 @@
package pres.auxiliary.work.selenium.datadriven;
/**
* <p><b>文件名</b>DataDriverFunction.java</p>
* <p><b>用途</b>
* 用于存储数据驱动中处理数据的公式
* </p>
* <p><b>编码时间</b>2020年6月12日上午8:27:04</p>
* <p><b>修改时间</b>2020年6月12日上午8:27:04</p>
* @author 彭宇琦
* @version Ver1.0
*
*/
public class DataDriverFunction {
/**
* 用于存储正则表达式
*/
private String regex;
/**
* 用于存储处理数据的
*/
private DataFunction function;
/**
* 初始化数据
* @param regex 正则表达式
* @param function 数据对应的处理方法
*/
public DataDriverFunction(String regex, DataFunction function) {
this.regex = regex;
this.function = function;
}
/**
* 返回正则表达式
* @return 正则表达式
*/
public String getRegex() {
return regex;
}
/**
* 返回数据处理的方法
* @return 数据处理的方法
*/
public DataFunction getFunction() {
return function;
}
}

View File

@ -0,0 +1,17 @@
package pres.auxiliary.work.selenium.datadriven;
import java.util.function.Function;
/**
* <p><b>文件名</b>DataFunction.java</p>
* <p><b>用途</b>
* 用于定义在数据驱动文件中写入公式的处理方法
* </p>
* <p><b>编码时间</b>2020年6月10日上午7:11:09</p>
* <p><b>修改时间</b>2020年6月10日上午7:11:09</p>
* @author 彭宇琦
* @version Ver1.0
*
*/
public interface DataFunction extends Function<String, String> {
}

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.datadriven; package pres.auxiliary.work.selenium.datadriven;
/** /**
* 用于定义可向数据驱动中添加的预设模型 * 用于定义可向数据驱动中添加的预设模型

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.datadriven; package pres.auxiliary.work.selenium.datadriven;
public class DataNotFoundException extends Exception { public class DataNotFoundException extends Exception {

View File

@ -0,0 +1,138 @@
package pres.auxiliary.work.selenium.datadriven;
import pres.auxiliary.tool.date.Time;
import pres.auxiliary.tool.randomstring.RandomString;
import pres.auxiliary.tool.randomstring.StringMode;
public class Functions {
/**
* <p>
* 定义生成随机字符串函数用法<br>
* ${rs(字符串种子,生成字符串最短长度,生成字符串最大长度)}
* </p>
* <p>
* <b>参数解释</b><br>
* <ul>
* <li>字符串种子生成随机字符串的范围该范围可自定义也可以使用系统定义的特殊种子包括
* NUM数字CAP大写字母LOW小写字母CH中文AREA区域缩写SURNAME姓氏
* 使用自定义种子时需要使用双引号标识即传入"ASD"表示只在ASD中生成随机字符串
* </li>
* <li>生成字符串最短长度最终生成的随机字符串的最短长度</li>
* <li>生成字符串最大长度<b>该字段可不传入</b>用于指定最终生成的随机字符串的最大长度</li>
* </ul>
* </p>
* <p>
* <b>示例</b><br>
* ${rs("qwertyuiop", 10, 20)}表示生成qwertyuiop范围内10~20位随机长度的随机字符串<br>
* ${rs("qwertyuiop", 10)}表示生成qwertyuiop范围内10位长度的随机字符串<br>
* ${rs(CH,10)}表示生成中文1000个不重复的中文范围内10位长度的随机字符串<br>
* ${rs(num, 10,20)}表示生成数字0-9范围内10~20位随机长度的随机字符串<br>
* </p>
* <p>
* <b>注意</b>每个参数之间的分隔符号中允许存在一个空格该空格可写可不写
* </p>
* @return {@link DataDriverFunction}类对象
*/
public static DataDriverFunction randomString() {
//定义规则
String regex = "rs\\(((\".+\")|NUM|num|CAP|cap|LOW|low|CH|ch|AREA|area|SURNAME|surname), ?\\d+(, ?\\d+)?\\)";
return new DataDriverFunction(regex, text -> {
//获取公式中有效部分
String str = text.substring(text.indexOf("(") + 1, text.indexOf(")"));
//将公式有效部分按照分隔符号进行切分
String[] parameters = str.split(", ?");
//切分的第一个元素为字符串种子
String seed = parameters[0];
//第二个元素为随机字符串最小长度
int startIndex = Integer.valueOf(parameters[1]);
//判断parameters是否存在第三个元素若不存在则将字符串最长长度设置为与最小字符串长度一致
int endIndex = parameters.length > 2 ? Integer.valueOf(parameters[2]) : startIndex;
//判断字符串种子是否包含双引号若包含双引号则去掉双引号后将其转换若不包含
//表示字符串种子属于特殊种子按照枚举进行添加
if (seed.indexOf("\"") > -1) {
seed = seed.substring(seed.indexOf("\"") + 1, seed.lastIndexOf("\""));
} else {
switch (seed.toUpperCase()) {
case "NUM":
seed = StringMode.NUM.getSeed();
break;
case "CAP":
seed = StringMode.CAP.getSeed();
break;
case "LOW":
seed = StringMode.LOW.getSeed();
break;
case "CH":
seed = StringMode.CH.getSeed();
break;
case "AREA":
seed = StringMode.AREA.getSeed();
break;
case "SURNAME":
seed = StringMode.SURNAME.getSeed();
break;
default:
break;
}
}
//返回生成的随机字符串
return new RandomString(seed).toString(startIndex, endIndex);
});
}
/**
* <p>
* 定义对指定时间处理函数
* </p>
* @return 处理后的时间
*/
public static DataDriverFunction getTime() {
//定义规则
String regex = "time\\(((\\d{4}[-\\.年\\\\/][01]?\\d[-\\.月\\\\\\/][0123]?\\d日?"
+ "( [012]?\\d[:时][0123456]?\\d分?"
+ "([:分][0123456]?\\d秒?)?)?)|"
+ "([012]?\\d[:时][0123456]?\\d分?([:分][0123456]?\\d秒?))|"
+ "(\\d+)), ?(-?\\d+(\\.\\d+)?"
+ "([ymwdhs]|(min)))+\\)";
return new DataDriverFunction(regex, text -> {
//获取公式中有效部分
String str = text.substring(text.indexOf("(") + 1, text.indexOf(")"));
//将公式有效部分按照分隔符号进行切分
String[] parameters = str.split(", ?");
return disposeTime(parameters[0], parameters[1]);
});
}
/**
* 定义对当前时间处理函数
* @return 处理后的时间
*/
public static DataDriverFunction getNowTime() {
//定义规则
String regex = "time\\(((-?\\d+(\\.\\d+)?([ymwdhs]|(min)))+)?\\)";
return new DataDriverFunction(regex, text -> {
//获取公式中有效部分
String str = text.substring(text.indexOf("(") + 1, text.indexOf(")"));
return disposeTime("", str);
});
}
/**
* 用于对时间进行处理
* @param timeText 设置时间的文本
* @param pattern 时间处理规则
* @return 返回处理后的时间
*/
private static String disposeTime(String timeText, String pattern) {
Time time = new Time(timeText);
time.addTime(pattern);
return time.getFormatTime();
}
}

View File

@ -1,4 +1,4 @@
package pres.auxiliary.tool.readfile; package pres.auxiliary.work.selenium.datadriven;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -14,6 +14,9 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Paragraph; import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range; import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
@ -23,6 +26,7 @@ import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import com.opencsv.CSVReader; import com.opencsv.CSVReader;
import pres.auxiliary.tool.date.Time;
import pres.auxiliary.tool.file.UnsupportedFileException; import pres.auxiliary.tool.file.UnsupportedFileException;
/** /**
@ -38,43 +42,6 @@ import pres.auxiliary.tool.file.UnsupportedFileException;
* @since JDK 12 * @since JDK 12
*/ */
public class ListFileRead { public class ListFileRead {
/**
* 切分标记tap
*/
public static final String SPLIT_TAB = "\\t";
/**
* 切分标记空格
*/
public static final String SPLIT_SPACE = " ";
/**
* 切分标记中文逗号
*/
public static final String SPLIT_COMMA_CH = "";
/**
* 切分标记英文逗号
*/
public static final String SPLIT_COMMA_EN = ",";
/**
* 切分标记中文分号
*/
public static final String SPLIT_SEMICOLON_CH = "";
/**
* 切分标记英文分号
*/
public static final String SPLIT_SEMICOLON_EN = ";";
/**
* 切分标记中文顿号
*/
public static final String SPLIT_STOP_CH = "";
/**
* 切分标记斜杠
*/
public static final String SPLIT_SLASH = "/";
/**
* 切分标记反斜杠
*/
public static final String SPLIT_BACKSLASH = "\\\\";
/** /**
* 存储被切分的词语<br> * 存储被切分的词语<br>
* 外层ArrayList存在多列的情况存储每一列<br> * 外层ArrayList存在多列的情况存储每一列<br>
@ -109,13 +76,13 @@ public class ListFileRead {
* </ol> * </ol>
* 除上述两种文件类型外其他的文件调用该构造方法时则等同于调用{@link #ListFileRead(File, String)} * 除上述两种文件类型外其他的文件调用该构造方法时则等同于调用{@link #ListFileRead(File, String)}
* @param file 待读取的文件对象 * @param file 待读取的文件对象
* @param regex sheet名称或切分文本的规则 * @param pattern sheet名称或切分文本的规则
* @throws IOException 文件状态或路径不正确时抛出的异常 * @throws IOException 文件状态或路径不正确时抛出的异常
*/ */
public ListFileRead(File file, String regex) throws IOException { public ListFileRead(File file, String pattern) throws IOException {
//regex为null则赋为空 //pattern为null则赋为空
if (regex == null) { if (pattern == null) {
regex = ""; pattern = "";
} }
// 存储文件的名称 // 存储文件的名称
@ -124,16 +91,16 @@ public class ListFileRead {
switch ( fileName.substring(fileName.lastIndexOf(".") + 1)) { switch ( fileName.substring(fileName.lastIndexOf(".") + 1)) {
case "doc": case "doc":
case "docx": case "docx":
readWord(file, regex); readWord(file, pattern);
break; break;
case "xls": case "xls":
case "xlsx": case "xlsx":
readExcel(file, regex); readExcel(file, pattern);
break; break;
case "txt": case "txt":
readTxt(file, regex); readTxt(file, pattern);
break; break;
case "csv": case "csv":
@ -430,7 +397,7 @@ public class ListFileRead {
for (int cellNum = 0; cellNum < row.getLastCellNum(); cellNum++) { for (int cellNum = 0; cellNum < row.getLastCellNum(); cellNum++) {
//存储单元格的内容若单元格为null则存储空串 //存储单元格的内容若单元格为null则存储空串
try { try {
texts.add(row.getCell(cellNum).toString()); texts.add(getCellContent(row.getCell(cellNum)));
}catch (NullPointerException e) { }catch (NullPointerException e) {
texts.add(""); texts.add("");
} }
@ -532,4 +499,38 @@ public class ListFileRead {
fip.close(); fip.close();
} }
/**
* 根据单元格的类型对其内容进行输出
* @param cell 单元格类对象
* @return 单元格中的文本
*/
private String getCellContent(Cell cell) {
//判断单元格中的内容的格式
if (CellType.NUMERIC == cell.getCellTypeEnum()) {
//数值类型
//判断单元格内的数据是否为日期
if (DateUtil.isCellDateFormatted(cell)) {
//将单元格内容转换为Date后在time中进行存储
Time time = new Time(cell.getDateCellValue());
//根据存储的时间格式对时间进行转换输出格式化后的时间
return time.getFormatTime();
} else {
//若非日期格式则强转为字符串格式之后输出
cell.setCellType(CellType.STRING);
return cell.getStringCellValue();
}
} else if (CellType.FORMULA == cell.getCellTypeEnum()) {
//公式类型
//公式得到的值可能是一个字符串也可能是一个数字此时则需要进行区分转换错误会抛出异常
try {
return cell.getRichStringCellValue().getString();
} catch (IllegalStateException e) {
return String.valueOf(cell.getNumericCellValue());
}
} else {
//其他类型按照字符串进行读取
return cell.getStringCellValue();
}
}
} }

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.datadriven; package pres.auxiliary.work.selenium.datadriven;
public class NumberDataDriven extends DataDriven { public class NumberDataDriven extends DataDriven {
// /** // /**

View File

@ -0,0 +1,63 @@
package pres.auxiliary.work.selenium.datadriven;
public enum SplitType {
/**
* 切分标记tap
*/
SPLIT_TAB("\\t"),
/**
* 切分标记空格
*/
SPLIT_SPACE(" "),
/**
* 切分标记中文逗号
*/
SPLIT_COMMA_CH(""),
/**
* 切分标记英文逗号
*/
SPLIT_COMMA_EN(","),
/**
* 切分标记中文分号
*/
SPLIT_SEMICOLON_CH(""),
/**
* 切分标记英文分号
*/
SPLIT_SEMICOLON_EN(";"),
/**
* 切分标记中文顿号
*/
SPLIT_STOP_CH(""),
/**
* 切分标记斜杠
*/
SPLIT_SLASH("/"),
/**
* 切分标记反斜杠
*/
SPLIT_BACKSLASH("\\\\"),
;
/**
* 分隔符号
*/
String splitSign = "";
/**
* 初始化数据
* @param splitSign 分隔符号
*/
private SplitType(String splitSign) {
this.splitSign = splitSign;
}
/**
* 用于返回分隔文本的符号
* @return
*/
public String getSplitSign() {
return splitSign;
}
}

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.datadriven; package pres.auxiliary.work.selenium.datadriven;
public class StringDataDriven extends DataDriven { public class StringDataDriven extends DataDriven {

View File

@ -0,0 +1,423 @@
package pres.auxiliary.work.selenium.datadriven;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
import pres.auxiliary.tool.date.Time;
/**
* <p><b>文件名</b>TestNGDataDriver.java</p>
* <p><b>用途</b>
* 根据文件中的数据内容返回适配TestNG的数据驱动以便于在编写自动化脚本中使用源数据文件支持
* xls/xlsx/csv/txt/doc/docx支持自定义特殊关键词其自定义的关键词用${关键词}
* 进行标记系统根据在{@link #addFunction(String, DataFunction)}中定义的处理方式对数据进行处理
* 具体的用法可以参考
* </p>
* <p>
* 在类中可按照以下方法定义
* <pre>{@code
* dataDriver.addFunction("test", text -> "HelloWorld");
*dataDriver.addFunction("select(\\d+)", text -> {
* switch(Integer.value(text)) {
* case 1:
* return "function1"
* break;
* case 2:
* return "function2"
* break;
* }
*});
* </pre>
* 从数据驱动中读取到的数据有${test}${select(1)}则按照字符串的形式输出后分别得到HelloWorldfunction1
* </p>
* <p><b>编码时间</b>2020年6月3日上午7:04:51</p>
* <p><b>修改时间</b>2020年6月3日上午7:04:51</p>
* @author 彭宇琦
* @version Ver1.0
* @since JDK 8
*
*/
public class TestNGDataDriver {
/**
* 用于存储数据列的名称
*/
private ArrayList<String> titleList = new ArrayList<>();
/**
* 用于存储读取到的数据
*/
private ArrayList<Data> dataList = new ArrayList<>();
/**
* 用于存储自定义的公式
*/
private HashMap<String, DataFunction> dataFunctionMap = new HashMap<>(16);
/**
* 用于对日期格式或特殊字段输入的日期进行转换
*/
private Time time = new Time();
/**
* 用于返回数据驱动中列表的元素个数即当前数据驱动中最大行元素个数
* @return 列元素个数
*/
public int columnSize() {
//当前添加的数据中每一个元素都对应一个列名故通过列名可判断最大行的元素个数
return titleList.size();
}
/**
* 用于设置日期的输出格式该方法仅对由excel读取的日期格式或由特殊字段输出的日期生效
*/
public void setDateFromat(String pattern) {
time.setTimeFormat(pattern);
}
/**
* 用于添加自定义的公式支持传入正则表达式当数据驱动中的数据满足传入的正则时则会
* 将其按照在公式中定义的处理方式对数据进行处理生成对应的数据注意公式的返回值和
* 传参均为{@link String}类型
* @param regex 正则表达式
* @param function 数据处理方法
*/
public void addFunction(DataDriverFunction function) {
dataFunctionMap.put(function.getRegex(), function.getFunction());
}
/**
* 根据传入文件格式读取文件的内容添加至数据驱动中该方法可用于读取xls/xlsx/csv/doc/docx/txt格式的文件
* 根据不同的文件格式其pattern参数具有不同的意义
* <ol>
* <li>当读取的文件为Excel文件xls/xlsx格式其传入的pattern表示需要读取的sheet名称</li>
* <li>当读取的文件为文本文件doc/docx/txt格式其传入的pattern表示对每一行文本的切分规则以得到一个列表</li>
* <li>当读取的文件为csv文件csv格式其传入的pattern不生效无意义</li>
* </ol>
* @param dataFile 源数据文件类对象
* @param pattern 读取规则
* @param isFirstTitle 首行是否为标题
* @throws IOException 当文件读取有误时抛出的异常
*/
public void addDataDriver(File dataFile, String pattern, boolean isFirstTitle) throws IOException {
//读取文件内的数据
ListFileRead data = new ListFileRead(dataFile, pattern);
//由于数据按照列的形式读取故此处将数据转置
data.tableTransposition();
//若设定首行为标题行则根据首行元素读取标题
if (isFirstTitle) {
//定位到首行
List<String> dataTitleList = data.getColumn(0);
//记录当前标题的个数
for (int i = 0; i < data.getMaxRowNumber(); i++) {
//判断单元格是否为空或者为空串若为空串则存储为数据 + 列下标的形式
if (dataTitleList.get(i).isEmpty()) {
//rowSize() + 1表示在整个数据驱动中其实际下标加上1
titleList.add("数据" + (1 + columnSize()));
} else {
//为避免添加多个文件时出现重复数据此处做一个判断重复的工作若列名重复则添加序号
String title = dataTitleList.get(i);
int index = 1;
while(titleList.contains(title)) {
title += (++index);
}
titleList.add(title);
}
}
}
//遍历所有行读取所有的数据
for (int rowIndex = isFirstTitle ? 1 : 0; rowIndex < data.getMaxColumnNumber(); rowIndex++) {
addRowData(isFirstTitle ? rowIndex - 1 : rowIndex, data.getColumn(rowIndex));
}
}
/**
* 返回当前存储的所有标题
* @return 返回存储的标题
*/
public ArrayList<String> getTitle() {
return titleList;
}
/**
* 返回可以使用的TestNG数据驱动注意数组第一维代表获取到的数据驱动的行第二维只包含
* 一个{@link Data}类对象通过该对象对获取到的所有数据进行返回以简化在编写脚本时
* 的传参
*
* @return TestNG数据驱动
*/
public Object[][] getDataDriver() {
Object[][] objs = new Object[dataList.size()][1];
for (int i = 0; i < dataList.size(); i++) {
objs[i][0] = dataList.get(i);
}
return objs;
}
/**
* 用于将一行的数据转为Data类对象
* @param rowDataList 一行数据
* @return 返回一行数据的Data类对象
*/
private void addRowData(int rowInde, List<String> rowDataList) {
//当rowInde大于dataList的总列数时则表示未对该行进行存储此时存在两种情况
//1.第一次文件此时dataList并无数据调用方法时为初次添加数据则按照正常方式添加
//2.非第一次读取文件此时dataList已存在上次读取的数据当写入的数据行数大于存储的行数
//直接添加数据会造成数据向左移则需要读取原始列表的内容将原来没有的数据补全后再
//添加数据
if (rowInde > dataList.size() - 1) {
Data data = new Data();
//判断rowDataList元素与上一行元素个数一致若一致则表示当前为第一次读取
if (dataList.size() != 0 && dataList.get(rowInde - 1).dataList.size() != rowDataList.size()) {
//若上一行的元素个数与rowDataList的元素个数不一致则此时是非第一次读取文件rowDataList存在数据
//将rowDataList之前的列都置为空串
int oldListSize = dataList.get(rowInde - 1).dataList.size();
for (int index = 0; index < oldListSize - rowDataList.size(); index++) {
data.dataList.add("");
}
}
//存储数据
rowDataList.forEach(data.dataList :: add);
dataList.add(data);
} else {
rowDataList.forEach(dataList.get(rowInde).dataList :: add);
}
}
/**
* <p><b>文件名</b>TestNGDataDriver.java</p>
* <p><b>用途</b>
* 存储从文件中读取到的数据根据列名或列下标通过不同的get方法获取不同类型的数据当传入的
* 列名或下标不存在时则返回空串
* </p>
* <p><b>编码时间</b>2020年6月3日上午7:12:20</p>
* <p><b>修改时间</b>2020年6月3日上午7:12:20</p>
* @author 彭宇琦
* @version Ver1.0
*
*/
public class Data {
/**
* 切分公式标记
*/
private final String SPLIT_START = "\\$\\{";
/**
* 公式起始标记
*/
private final String FUNCTION_SIGN_START = "${";
/**
* 公式结束标记
*/
private final String FUNCTION_SIGN_END = "}";
/**
* 用于存储数据
*/
private ArrayList<String> dataList = new ArrayList<>();
/**
* 用于根据列名称以字符串的形式返回数据
* @param listName 列名称
* @return 字符串形式的数据
*/
public String getString(String listName) {
//判断列表是否存在若列名不存在则返回一个空串
return titleList.indexOf(listName) > -1 ? getString(titleList.indexOf(listName)) : "";
}
/**
* 用于根据列编号以字符串的形式返回数据
* @param index 列下标
* @return 字符串形式的数据
*/
public String getString(int index) {
return index < dataList.size() ? disposeContent(dataList.get(index)) : "";
}
/**
* 用于根据列名称以double的形式对数据进行返回
* @param listName 列表名称
* @return double类型的数据
* @throw NumberFormatException 数据无法转时抛出的异常
*/
public double getDouble(String listName) {
return Double.valueOf(getString(listName));
}
/**
* 用于根据列编号以double的形式对数据进行返回
* @param index 列下标
* @return double类型的数据
* @throw NumberFormatException 数据无法转时抛出的异常
*/
public double getDouble(int index) {
return Double.valueOf(getString(index));
}
/**
* 用于根据列名称以int的形式对数据进行返回
* @param listName 列表名称
* @return int类型的数据
* @throw NumberFormatException 数据无法转换时抛出的异常
*/
public int getInt(String listName) {
return Integer.valueOf(getString(listName));
}
/**
* 用于根据列编号以int的形式对数据进行返回
* @param index 列下标
* @return int类型的数据
* @throw NumberFormatException 数据无法转时抛出的异常
*/
public int getInt(int index) {
return Integer.valueOf(getString(index));
}
/**
* 用于根据列名称以long的形式对数据进行返回
* @param listName 列表名称
* @return long类型的数据
* @throw NumberFormatException 数据无法转换时抛出的异常
*/
public long getLong(String listName) {
return Long.valueOf(getString(listName));
}
/**
* 用于根据列编号以long的形式对数据进行返回
* @param index 列下标
* @return long类型的数据
* @throw NumberFormatException 数据无法转时抛出的异常
*/
public long getLong(int index) {
return Long.valueOf(getString(index));
}
/**
* 用于根据列名称以boolean的形式对数据进行返回
* @param listName 列表名称
* @return boolean类型的数据
*/
public boolean getBoolean(String listName) {
return Boolean.valueOf(getString(listName));
}
/**
* 用于根据列编号以boolean的形式对数据进行返回
* @param index 列下标
* @return boolean类型的数据
*/
public boolean getBoolean(int index) {
return Boolean.valueOf(getString(index));
}
/**
* 用于根据列编号{@link File}的形式对数据进行返回
* @param index 列下标
* @return {@link File}类型的数据
*/
public File getFile(int index) {
return new File(getString(index));
}
/**
* 用于根据列名称{@link File}的形式对数据进行返回
* @param listName 列表名称
* @return {@link File}类型的数据
*/
public File getFile(String listName) {
return new File(getString(listName));
}
/**
* 用于根据列编号{@link Time}的形式对数据进行返回
* @param index 列下标
* @return {@link Time}类型的数据
*/
public Time getTime(int index) {
return new Time(getString(index));
}
/**
* 用于根据列名称{@link Time}的形式对数据进行返回
* @param listName 列表名称
* @return {@link Time}类型的数据
*/
public Time getTime(String listName) {
return new Time(getString(listName));
}
/**
* 用于处理读取得到的内容并将处理后的内容进行返回
* @param content 读取的内容
* @return 处理后的内容
*/
private String disposeContent(String content) {
//判断传入的内容是否包含公式起始符号若不包含则返回原串
if (content.indexOf(FUNCTION_SIGN_START) < 0) {
return content;
}
//存储处理后的内容
StringBuilder newContent = new StringBuilder();
//按照公式起始符号对内容进行切分遍历切分后的每一个元素
String[] texts = content.split(SPLIT_START);
for (int i = 0; i < texts.length; i++) {
//判断切分的元素是否包含公式结束符号
int index;
if ((index = texts[i].indexOf(FUNCTION_SIGN_END)) > -1) {
//截取公式串处理公式
String disposeText = functionToData(texts[i].substring(0, index));
//判断处理后得到字符串是否为null不为null则拼接至newContent中
if (disposeText != null) {
newContent.append(disposeText + texts[i].substring(index + 1));
} else {
newContent.append(i == 0 ? texts[i] : (FUNCTION_SIGN_START + texts[i]));
}
} else {
//若不包含公式结束符号则直接拼接原串
newContent.append(i == 0 ? texts[i] : (FUNCTION_SIGN_START + texts[i]));
}
}
//若原串中最后一个元素是公式结束标记则将该标记拼接至新串的后面
if (content.lastIndexOf(FUNCTION_SIGN_START) + FUNCTION_SIGN_START.length() == content.length()) {
newContent.append(FUNCTION_SIGN_START);
}
return newContent.toString();
}
/**
* 用于对数据驱动中的公式进行处理返回处理得到的数据若数据不予存储的任何正则匹配
* 返回空串
* @param content 内容
* @return 处理后的内容
*/
private String functionToData(String content) {
//遍历所有的转译公式
for (String regex : dataFunctionMap.keySet()) {
//若传入的内容与正则匹配则将数据进行处理并返回处理结果
if (Pattern.compile(regex).matcher(content).matches()) {
return dataFunctionMap.get(regex).apply(content);
}
}
//若内容不与任何正则匹配则返回原始内容
return null;
}
}
}

View File

@ -1,107 +0,0 @@
package pres.auxiliary.work.selenium.event;
import java.util.Random;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
/**
* <p><b>文件名</b>SelectEvent.java</p>
* <p><b>用途</b>定义了对控件进行选择操作相关的方法可通过该类对页面的下拉框控件进行选择操作
* 注意该类中的方法仅对标准的下拉选项框<select><option>标签组成的下拉框进行操作对于非标准的
* 下拉框无法选择
* </p>
* <p><b>编码时间</b>2019年9月29日下午3:55:34</p>
* <p><b>修改时间</b>2020年5月11日上午7:55:26</p>
* @author 彭宇琦
* @version Ver2.0
* @since JDK 12
*
*/
public class SelectEvent extends AbstractEvent {
/**
* 构造SelectEvent类对象
* @param driver WebDriver类对象
*/
public SelectEvent(WebDriver driver) {
super(driver);
}
/**
* 选择下拉框中的最后一个元素
* @param element 下拉框控件对象
* @return 选择的选项内容
*/
public String selectLast(WebElement element) {
return select(element, -1);
}
/**
* 选择下拉框中的指定下标的元素下标支持从后向前获取传入的下标
* 与元素实际所在位置一致当传入0时则表示随机获取一个元素<br>
* {@code select(element, 1)}表示选择下拉框的第1个元素<br>
* {@code select(element, 0)}表示选择下拉框元素个数范围内随机一个元素<br>
* {@code select(element, -1)}表示选择下拉框的倒数第1个元素<br>
* @param element 下拉框控件对象
* @return 选择的选项内容
*/
public String select(WebElement element, int index) {
//元素高亮
elementHight(element);
//在等待时间内判断元素是否可以点击若可以点击元素则进行点击事件
String text = wait.until(driver -> {
try {
//定义Select类对象
Select select = new Select(element);
int newIndex = getIndex(select.getAllSelectedOptions().size(), index);
//选择元素
select.selectByIndex(newIndex);
return select.getOptions().get(newIndex).getText();
} catch (Exception e) {
return null;
}
});
step = "选择“" + ELEMENT_NAME + "”元素的第" + index + "个选项";
return text;
}
/**
* 选择下拉框中的第一个元素
* @param element 下拉框控件对象
* @return 选择的选项内容
*/
public String selectFirst(WebElement element) {
return select(element, 1);
}
/**
* 由于方法允许传入负数和特殊数字0为下标并且下标的序号由1开始
* 故可通过该方法对下标的含义进行转义得到java能识别的下标
* @param length 元素的总长度
* @param index 传入的下标
* @return 可识别的下标
* @throws NoSuchElementException 当元素无法查找到时抛出的异常
*/
private int getIndex(int length, int index) {
//判断元素下标是否超出范围由于可以传入负数故需要使用绝对值
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 - 1) + 1;
}
}
}

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -29,7 +29,7 @@ import org.dom4j.io.SAXReader;
import pres.auxiliary.directory.exception.IncorrectDirectoryException; import pres.auxiliary.directory.exception.IncorrectDirectoryException;
import pres.auxiliary.directory.operate.MakeDirectory; import pres.auxiliary.directory.operate.MakeDirectory;
import pres.auxiliary.selenium.browers.AbstractBrower; import pres.auxiliary.work.selenium.brower.AbstractBrower;
/** /**
* <p> * <p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
/** /**
* <p><b>文件名</b>RecordStateException.java</p> * <p><b>文件名</b>RecordStateException.java</p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -20,6 +20,7 @@ import java.util.zip.ZipOutputStream;
import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebDriverException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
@ -576,7 +577,7 @@ public class RecordTool {
bf.close(); bf.close();
//将模板中的json转换为JSONObject类并添加标题与id //将模板中的json转换为JSONObject类并添加标题与id
JSONObject json = JSONObject.parseObject(jsonScript); JSONObject json = JSON.parseObject(jsonScript);
json.getJSONObject("rootTopic").put("title", projectedName); json.getJSONObject("rootTopic").put("title", projectedName);
json.getJSONObject("rootTopic").put("id", UUID.randomUUID()); json.getJSONObject("rootTopic").put("id", UUID.randomUUID());
@ -584,7 +585,7 @@ public class RecordTool {
int moduleIndex = 0; int moduleIndex = 0;
for (String moduleName : module.keySet()) { for (String moduleName : module.keySet()) {
//读取模块信息的json //读取模块信息的json
JSONObject moduleJson = JSONObject.parseObject(RecordTool.getModuleJsonInformation(moduleName)); JSONObject moduleJson = JSON.parseObject(RecordTool.getModuleJsonInformation(moduleName));
//编写模块信息 //编写模块信息
addChildren(json.getJSONObject("rootTopic"), moduleName); addChildren(json.getJSONObject("rootTopic"), moduleName);
@ -593,7 +594,7 @@ public class RecordTool {
//循环读取所有的测试类信息 //循环读取所有的测试类信息
for (int testClassIndex = 0; testClassIndex < testClassList.size(); testClassIndex++) { for (int testClassIndex = 0; testClassIndex < testClassList.size(); testClassIndex++) {
//读取每一个测试类json //读取每一个测试类json
JSONObject testClassJson = JSONObject.parseObject(testClassList.get(testClassIndex).toString()); JSONObject testClassJson = JSON.parseObject(testClassList.get(testClassIndex).toString());
//编写测试类信息 //编写测试类信息
addChildren(json.getJSONObject("rootTopic"). addChildren(json.getJSONObject("rootTopic").
getJSONObject("children").getJSONArray("attached"). getJSONObject("children").getJSONArray("attached").
@ -604,7 +605,7 @@ public class RecordTool {
//循环读取测试类下所有的测试方法 //循环读取测试类下所有的测试方法
for (int methodIndex = 0; methodIndex < methodList.size(); methodIndex++) { for (int methodIndex = 0; methodIndex < methodList.size(); methodIndex++) {
//读取每一个测试方法的json //读取每一个测试方法的json
JSONObject methodJson = JSONObject.parseObject(methodList.get(methodIndex).toString()); JSONObject methodJson = JSON.parseObject(methodList.get(methodIndex).toString());
//写入测试方法信息 //写入测试方法信息
String methodInformation = "方法名:"; String methodInformation = "方法名:";
methodInformation += (methodJson.getString("name") + "\n"); methodInformation += (methodJson.getString("name") + "\n");

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
/** /**
* <p><b>文件名</b>RecordToolConfigException.java</p> * <p><b>文件名</b>RecordToolConfigException.java</p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
/** /**
* <p><b>文件名</b>RecordType.java</p> * <p><b>文件名</b>RecordType.java</p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.tool; package pres.auxiliary.work.selenium.tool;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -14,7 +14,6 @@ import org.openqa.selenium.WebDriverException;
import pres.auxiliary.directory.exception.IncorrectDirectoryException; import pres.auxiliary.directory.exception.IncorrectDirectoryException;
import pres.auxiliary.directory.exception.UndefinedDirectoryException; import pres.auxiliary.directory.exception.UndefinedDirectoryException;
import pres.auxiliary.directory.operate.MakeDirectory; import pres.auxiliary.directory.operate.MakeDirectory;
import pres.auxiliary.selenium.event.Event;
/** /**
* 该类用于在使用selenium进行自动化测试中进行截图的工具使用该类时可以指定截图保存的位置以及 * 该类用于在使用selenium进行自动化测试中进行截图的工具使用该类时可以指定截图保存的位置以及

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* <p> * <p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* 该异常在XML文件不正确或XML路径不存在时抛出 * 该异常在XML文件不正确或XML路径不存在时抛出

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* <p><b>文件名</b>NoSuchSignValueException.java</p> * <p><b>文件名</b>NoSuchSignValueException.java</p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* 该异常在查找到相同文件名时抛出的异常 * 该异常在查找到相同文件名时抛出的异常

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* <p><b>文件名</b>UndefinedElementException.java</p> * <p><b>文件名</b>UndefinedElementException.java</p>

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* 若传入的模型参数有误时抛出的异常 * 若传入的模型参数有误时抛出的异常

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;

View File

@ -1,4 +1,4 @@
package pres.auxiliary.selenium.xml; package pres.auxiliary.work.selenium.xml;
/** /**
* 该异常提示用户需要检查xml文件是否为空 * 该异常提示用户需要检查xml文件是否为空

View File

@ -9,10 +9,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import pres.auxiliary.selenium.browers.ChromeBrower; import pres.auxiliary.work.selenium.tool.RecordTool;
import pres.auxiliary.selenium.event.ClickEvent;
import pres.auxiliary.selenium.event.Event;
import pres.auxiliary.selenium.tool.RecordTool;
/** /**
* <p><b>文件名</b>ClickEventTest.java</p> * <p><b>文件名</b>ClickEventTest.java</p>

View File

@ -10,9 +10,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import pres.auxiliary.selenium.browers.ChromeBrower; import pres.auxiliary.work.selenium.tool.RecordTool;
import pres.auxiliary.selenium.event.DataListEvent.ListEvent;
import pres.auxiliary.selenium.tool.RecordTool;
/** /**
* <p> * <p>

Some files were not shown because too many files have changed in this diff Show More