UI执行接口
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.test.common.utils;
|
package com.test.common.utils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.openqa.selenium.*;
|
import org.openqa.selenium.*;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
import org.openqa.selenium.interactions.Actions;
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
@@ -13,6 +14,7 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* Selenium 工具类
|
* Selenium 工具类
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class SeleniumUtils {
|
public class SeleniumUtils {
|
||||||
|
|
||||||
private WebDriver driver;
|
private WebDriver driver;
|
||||||
@@ -238,9 +240,9 @@ public class SeleniumUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取alert文本
|
// 获取alert文本
|
||||||
public String getAlertText() {
|
// public String getAlertText() {
|
||||||
return switchToAlert().getText();
|
// return switchToAlert().getText();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 在alert中输入文本
|
// 在alert中输入文本
|
||||||
public void sendKeysToAlert(String text) {
|
public void sendKeysToAlert(String text) {
|
||||||
@@ -377,4 +379,480 @@ public class SeleniumUtils {
|
|||||||
driver.quit();
|
driver.quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Add SeleniumUtils -----
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据句柄ID切换到指定窗口
|
||||||
|
* @param handleId 窗口句柄ID
|
||||||
|
*/
|
||||||
|
public void switchToWindowByHandle(String handleId) {
|
||||||
|
driver.switchTo().window(handleId);
|
||||||
|
log.info("已切换到句柄ID为 {} 的窗口", handleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据网页索引号切换到指定窗口
|
||||||
|
* @param index 窗口索引(从0开始)
|
||||||
|
*/
|
||||||
|
public void switchToWindowByIndex(int index) {
|
||||||
|
Set<String> handles = driver.getWindowHandles();
|
||||||
|
if (index >= 0 && index < handles.size()) {
|
||||||
|
String handle = handles.toArray(new String[0])[index];
|
||||||
|
driver.switchTo().window(handle);
|
||||||
|
log.info("已切换到索引为 {} 的窗口", index);
|
||||||
|
} else {
|
||||||
|
throw new NoSuchWindowException("无效的窗口索引: " + index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换到初始窗口(第一个打开的窗口)
|
||||||
|
*/
|
||||||
|
public void switchToDefaultWindow() {
|
||||||
|
Set<String> handles = driver.getWindowHandles();
|
||||||
|
if (!handles.isEmpty()) {
|
||||||
|
String firstHandle = handles.iterator().next();
|
||||||
|
driver.switchTo().window(firstHandle);
|
||||||
|
log.info("已切换回初始窗口");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据索引切换到指定frame
|
||||||
|
* @param index frame索引(从0开始)
|
||||||
|
*/
|
||||||
|
public void switchToFrameByIndex(int index) {
|
||||||
|
try {
|
||||||
|
driver.switchTo().frame(index);
|
||||||
|
log.info("已切换到索引为 {} 的frame", index);
|
||||||
|
} catch (NoSuchFrameException e) {
|
||||||
|
log.error("按索引切换frame失败: {}", e.getMessage());
|
||||||
|
throw new RuntimeException("找不到索引为 " + index + " 的frame", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据定位方式切换到frame
|
||||||
|
* @param locatorType 定位类型(id/name/xpath/css等)
|
||||||
|
* @param locatorValue 定位值
|
||||||
|
*/
|
||||||
|
public void switchToFrameByLocator(String locatorType, String locatorValue) {
|
||||||
|
By locator = getLocator(locatorType, locatorValue);
|
||||||
|
try {
|
||||||
|
WebElement frameElement = wait.until(ExpectedConditions.presenceOfElementLocated(locator));
|
||||||
|
driver.switchTo().frame(frameElement);
|
||||||
|
log.info("已切换到 {} = '{}' 的frame", locatorType, locatorValue);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("等待frame元素超时: {} = '{}'", locatorType, locatorValue);
|
||||||
|
throw new RuntimeException("找不到 " + locatorType + " = '" + locatorValue + "' 的frame元素", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据定位类型和值获取Selenium定位器
|
||||||
|
* @param locatorType 定位类型(不区分大小写):
|
||||||
|
* id/name/className/tagName/linkText/partialLinkText/css/xpath/label/value/index
|
||||||
|
* @param locatorValue 定位值
|
||||||
|
* @return By 定位器对象
|
||||||
|
* @throws IllegalArgumentException 如果定位类型不支持
|
||||||
|
*/
|
||||||
|
public By getLocator(String locatorType, String locatorValue) {
|
||||||
|
if (locatorValue == null || locatorValue.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("定位值不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (locatorType.toLowerCase()) {
|
||||||
|
case "id":
|
||||||
|
return By.id(locatorValue);
|
||||||
|
case "name":
|
||||||
|
return By.name(locatorValue);
|
||||||
|
case "classname":
|
||||||
|
case "class":
|
||||||
|
return By.className(locatorValue);
|
||||||
|
case "tagname":
|
||||||
|
case "tag":
|
||||||
|
return By.tagName(locatorValue);
|
||||||
|
case "linktext":
|
||||||
|
case "link":
|
||||||
|
return By.linkText(locatorValue);
|
||||||
|
case "partiallinktext":
|
||||||
|
case "partiallink":
|
||||||
|
return By.partialLinkText(locatorValue);
|
||||||
|
case "css":
|
||||||
|
case "cssselector":
|
||||||
|
return By.cssSelector(locatorValue);
|
||||||
|
case "xpath":
|
||||||
|
return By.xpath(locatorValue);
|
||||||
|
case "label":
|
||||||
|
// 通过label文本定位对应的元素
|
||||||
|
return By.xpath(String.format("//label[contains(text(), '%s')]", locatorValue));
|
||||||
|
case "value":
|
||||||
|
// 通过value属性定位
|
||||||
|
return By.xpath(String.format("//*[@value='%s']", locatorValue));
|
||||||
|
case "index":
|
||||||
|
// 索引定位需要特殊处理,通常结合其他定位方式使用
|
||||||
|
try {
|
||||||
|
int index = Integer.parseInt(locatorValue);
|
||||||
|
return By.xpath(String.format("(//*)[%d]", index + 1)); // XPath索引从1开始
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalArgumentException("索引必须是数字: " + locatorValue);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("不支持的定位类型: " + locatorType +
|
||||||
|
"。支持的定位类型: id,name,className,tagName,linkText," +
|
||||||
|
"partialLinkText,css,xpath,label,value,index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理弹窗
|
||||||
|
* @param operationType 操作类型 (1=确定, 2=取消)
|
||||||
|
* @param inputText 需要输入的文本 (可为null表示不输入)
|
||||||
|
*/
|
||||||
|
public void handleAlert(int operationType, String inputText) {
|
||||||
|
try {
|
||||||
|
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
|
||||||
|
|
||||||
|
// 如果有输入文本
|
||||||
|
if (inputText != null && !inputText.isEmpty()) {
|
||||||
|
alert.sendKeys(inputText);
|
||||||
|
log.info("已在弹窗中输入文本: {}", inputText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行确认或取消操作
|
||||||
|
if (operationType == 1) {
|
||||||
|
alert.accept();
|
||||||
|
log.info("已确认弹窗");
|
||||||
|
} else if (operationType == 2) {
|
||||||
|
alert.dismiss();
|
||||||
|
log.info("已取消弹窗");
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("无效的弹窗操作类型: " + operationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NoAlertPresentException e) {
|
||||||
|
log.error("没有找到弹窗", e);
|
||||||
|
throw new RuntimeException("当前没有可操作的弹窗", e);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("等待弹窗超时", e);
|
||||||
|
throw new RuntimeException("等待弹窗出现超时", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取弹窗文本
|
||||||
|
* @return 弹窗显示的文本内容
|
||||||
|
*/
|
||||||
|
public String getAlertText() {
|
||||||
|
try {
|
||||||
|
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
|
||||||
|
String text = alert.getText();
|
||||||
|
log.info("获取到弹窗文本: {}", text);
|
||||||
|
return text;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取弹窗文本失败", e);
|
||||||
|
throw new RuntimeException("无法获取弹窗文本", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据定位方式和定位值查找元素
|
||||||
|
* @param locType 定位方式 (如 "id", "xpath", "cssSelector" 等)
|
||||||
|
* @param locValue 定位值
|
||||||
|
* @return 找到的WebElement
|
||||||
|
*/
|
||||||
|
public WebElement findElement(String locType, String locValue) {
|
||||||
|
try {
|
||||||
|
By by = getLocator(locType, locValue);
|
||||||
|
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(by));
|
||||||
|
return element;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("无法定位元素,定位方式:" + locType + ",定位值:" + locValue, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作下拉框
|
||||||
|
* @param element 下拉框元素
|
||||||
|
* @param optionType 选项类型 (1=选项文本, 2=索引, 3=值)
|
||||||
|
* @param optionValue 选项值
|
||||||
|
*/
|
||||||
|
public void selectDropdownOption(WebElement element, String optionType, String optionValue) {
|
||||||
|
Select select = new Select(element);
|
||||||
|
try {
|
||||||
|
switch (optionType) {
|
||||||
|
case "1": // 选项文本
|
||||||
|
select.selectByVisibleText(optionValue);
|
||||||
|
log.info("通过选项文本选择下拉框选项: {}", optionValue);
|
||||||
|
break;
|
||||||
|
case "2": // 索引
|
||||||
|
int index = Integer.parseInt(optionValue);
|
||||||
|
select.selectByIndex(index);
|
||||||
|
log.info("通过索引选择下拉框选项: {}", index);
|
||||||
|
break;
|
||||||
|
case "3": // 值
|
||||||
|
select.selectByValue(optionValue);
|
||||||
|
log.info("通过值选择下拉框选项: {}", optionValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("不支持的选项类型: " + optionType);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("操作下拉框失败", e);
|
||||||
|
throw new RuntimeException("操作下拉框失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待元素满足指定条件
|
||||||
|
* @param locator 元素定位器
|
||||||
|
* @param operate 操作类型:
|
||||||
|
* 1=等待元素文本等于给定值
|
||||||
|
* 2=等待元素存在
|
||||||
|
* 3=等待元素显示
|
||||||
|
* 4=等待元素不显示
|
||||||
|
* 5=等待元素不存在
|
||||||
|
* 6=等待元素可编辑
|
||||||
|
* 7=等待元素不可编辑
|
||||||
|
* @param awaitValue 等待的值(用于文本比较或自定义超时时间)
|
||||||
|
* @param timeoutInMillis 默认超时时间(毫秒)
|
||||||
|
*/
|
||||||
|
public void waitForElement(By locator, int operate, String awaitValue, long timeoutInMillis) {
|
||||||
|
WebDriverWait customWait = new WebDriverWait(driver, Duration.ofMillis(timeoutInMillis));
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch (operate) {
|
||||||
|
case 1: // 等待元素文本等于给定值
|
||||||
|
customWait.until(ExpectedConditions.textToBe(locator, awaitValue));
|
||||||
|
log.info("元素文本已等于: {}", awaitValue);
|
||||||
|
break;
|
||||||
|
case 2: // 等待元素存在
|
||||||
|
customWait.until(ExpectedConditions.presenceOfElementLocated(locator));
|
||||||
|
log.info("元素已存在");
|
||||||
|
break;
|
||||||
|
case 3: // 等待元素显示
|
||||||
|
customWait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
||||||
|
log.info("元素已显示");
|
||||||
|
break;
|
||||||
|
case 4: // 等待元素不显示
|
||||||
|
customWait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
|
||||||
|
log.info("元素已不显示");
|
||||||
|
break;
|
||||||
|
case 5: // 等待元素不存在
|
||||||
|
boolean isAbsent = customWait.until(ExpectedConditions.not(
|
||||||
|
ExpectedConditions.presenceOfElementLocated(locator)
|
||||||
|
));
|
||||||
|
log.info("元素已不存在");
|
||||||
|
break;
|
||||||
|
case 6: // 等待元素可编辑
|
||||||
|
customWait.until(driver -> {
|
||||||
|
WebElement element = driver.findElement(locator);
|
||||||
|
return element.isEnabled() && !element.getAttribute("readonly").equals("true");
|
||||||
|
});
|
||||||
|
log.info("元素已可编辑");
|
||||||
|
break;
|
||||||
|
case 7: // 等待元素不可编辑
|
||||||
|
customWait.until(driver -> {
|
||||||
|
WebElement element = driver.findElement(locator);
|
||||||
|
return !element.isEnabled() || element.getAttribute("readonly").equals("true");
|
||||||
|
});
|
||||||
|
log.info("元素已不可编辑");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("不支持的等待操作类型: " + operate);
|
||||||
|
}
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("等待元素超时,操作类型: {}, 定位器: {}", operate, locator);
|
||||||
|
throw new RuntimeException("等待元素条件未满足: " + getOperationDescription(operate), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取操作类型描述
|
||||||
|
private String getOperationDescription(int operate) {
|
||||||
|
switch (operate) {
|
||||||
|
case 1: return "文本等于给定值";
|
||||||
|
case 2: return "元素存在";
|
||||||
|
case 3: return "元素显示";
|
||||||
|
case 4: return "元素不显示";
|
||||||
|
case 5: return "元素不存在";
|
||||||
|
case 6: return "元素可编辑";
|
||||||
|
case 7: return "元素不可编辑";
|
||||||
|
default: return "未知操作";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行鼠标操作
|
||||||
|
* @param locator 元素定位器
|
||||||
|
* @param clickMethod 点击方式:
|
||||||
|
* 1=单击(左键)
|
||||||
|
* 2=单击(右键)
|
||||||
|
* 3=双击
|
||||||
|
* 4=按下
|
||||||
|
* 5=弹起
|
||||||
|
*/
|
||||||
|
public void performMouseAction(By locator, int clickMethod) {
|
||||||
|
try {
|
||||||
|
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator));
|
||||||
|
|
||||||
|
switch (clickMethod) {
|
||||||
|
case 1: // 左键单击
|
||||||
|
actions.click(element).perform();
|
||||||
|
log.info("已执行左键单击操作");
|
||||||
|
break;
|
||||||
|
case 2: // 右键单击
|
||||||
|
actions.contextClick(element).perform();
|
||||||
|
log.info("已执行右键单击操作");
|
||||||
|
break;
|
||||||
|
case 3: // 双击
|
||||||
|
actions.doubleClick(element).perform();
|
||||||
|
log.info("已执行双击操作");
|
||||||
|
break;
|
||||||
|
case 4: // 按下
|
||||||
|
actions.clickAndHold(element).perform();
|
||||||
|
log.info("已执行鼠标按下操作");
|
||||||
|
break;
|
||||||
|
case 5: // 弹起
|
||||||
|
actions.release(element).perform();
|
||||||
|
log.info("已执行鼠标弹起操作");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("不支持的鼠标操作类型: " + clickMethod);
|
||||||
|
}
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("等待元素可点击超时,定位器: {}", locator);
|
||||||
|
throw new RuntimeException("元素不可点击或未找到: " + locator, e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("鼠标操作执行失败", e);
|
||||||
|
throw new RuntimeException("鼠标操作失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行鼠标移动操作
|
||||||
|
* @param locator 元素定位器
|
||||||
|
* @param moveType 移动类型:
|
||||||
|
* 1=鼠标移出元素
|
||||||
|
* 2=鼠标移入元素
|
||||||
|
*/
|
||||||
|
public void performMouseMove(By locator, int moveType) {
|
||||||
|
try {
|
||||||
|
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
||||||
|
|
||||||
|
switch (moveType) {
|
||||||
|
case 1: // 鼠标移出元素
|
||||||
|
// 先移动到元素上,再移动到页面左上角
|
||||||
|
actions.moveToElement(element)
|
||||||
|
.moveByOffset(-element.getSize().getWidth(), -element.getSize().getHeight())
|
||||||
|
.perform();
|
||||||
|
log.info("已将鼠标从元素移出");
|
||||||
|
break;
|
||||||
|
case 2: // 鼠标移入元素(悬停)
|
||||||
|
actions.moveToElement(element).perform();
|
||||||
|
log.info("已将鼠标悬停在元素上");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("不支持的鼠标移动类型: " + moveType);
|
||||||
|
}
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("等待元素可见超时,定位器: {}", locator);
|
||||||
|
throw new RuntimeException("元素不可见或未找到: " + locator, e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("鼠标移动操作执行失败", e);
|
||||||
|
throw new RuntimeException("鼠标移动操作失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 在指定元素中输入文本
|
||||||
|
* @param locator 元素定位器
|
||||||
|
* @param text 要输入的文本
|
||||||
|
* @param clearFirst 是否先清空原有内容
|
||||||
|
* @param inputMethod 输入方式:
|
||||||
|
* 1=普通输入(sendKeys)
|
||||||
|
* 2=通过JavaScript设置值
|
||||||
|
* 3=模拟人工输入(带延迟)
|
||||||
|
*/
|
||||||
|
public void inputText(By locator, String text, boolean clearFirst, int inputMethod) {
|
||||||
|
try {
|
||||||
|
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
||||||
|
|
||||||
|
// 先清空内容(如果需要)
|
||||||
|
if (clearFirst) {
|
||||||
|
element.clear();
|
||||||
|
log.info("已清空输入框内容");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (inputMethod) {
|
||||||
|
case 1: // 普通输入
|
||||||
|
element.sendKeys(text);
|
||||||
|
log.info("已通过sendKeys输入文本: {}", text);
|
||||||
|
break;
|
||||||
|
case 2: // JavaScript输入
|
||||||
|
JavascriptExecutor js = (JavascriptExecutor) driver;
|
||||||
|
js.executeScript("arguments[0].value = arguments[1]", element, text);
|
||||||
|
log.info("已通过JavaScript设置文本: {}", text);
|
||||||
|
break;
|
||||||
|
case 3: // 模拟人工输入
|
||||||
|
for (char c : text.toCharArray()) {
|
||||||
|
element.sendKeys(String.valueOf(c));
|
||||||
|
Thread.sleep(50); // 每个字符间隔50ms
|
||||||
|
}
|
||||||
|
log.info("已模拟人工输入文本: {}", text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("不支持的输入方式: " + inputMethod);
|
||||||
|
}
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
log.error("等待输入元素可见超时,定位器: {}", locator);
|
||||||
|
throw new RuntimeException("输入元素不可见或未找到: " + locator, e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
log.error("模拟人工输入被中断");
|
||||||
|
throw new RuntimeException("输入操作被中断", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("输入操作执行失败", e);
|
||||||
|
throw new RuntimeException("输入操作失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在可编辑段落中输入文本(如富文本编辑器)
|
||||||
|
* @param locator 元素定位器
|
||||||
|
* @param text 要输入的文本
|
||||||
|
*/
|
||||||
|
public void inputToEditableDiv(By locator, String text) {
|
||||||
|
try {
|
||||||
|
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
||||||
|
element.click(); // 先点击激活
|
||||||
|
element.sendKeys(text);
|
||||||
|
log.info("已在可编辑段落中输入文本: {}", text);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("可编辑段落输入失败", e);
|
||||||
|
throw new RuntimeException("可编辑段落输入失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空输入框内容
|
||||||
|
* @param locator 元素定位器
|
||||||
|
*/
|
||||||
|
public void clearInput(By locator) {
|
||||||
|
try {
|
||||||
|
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
||||||
|
element.clear();
|
||||||
|
log.info("已清空输入框内容");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("清空输入框失败", e);
|
||||||
|
throw new RuntimeException("清空输入框失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ public class UiSceneSteps extends BaseEntity
|
|||||||
|
|
||||||
/** 元素库名称 */
|
/** 元素库名称 */
|
||||||
@Excel(name = "元素库名称")
|
@Excel(name = "元素库名称")
|
||||||
private Integer operateGroupId;
|
private Long operateGroupId;
|
||||||
|
|
||||||
/** 元素id */
|
/** 元素id */
|
||||||
@Excel(name = "元素id")
|
@Excel(name = "元素id")
|
||||||
private Integer operateElementId;
|
private Long operateElementId;
|
||||||
|
|
||||||
/** 元素定位类型 */
|
/** 元素定位类型 */
|
||||||
@Excel(name = "元素定位类型")
|
@Excel(name = "元素定位类型")
|
||||||
@@ -76,7 +76,7 @@ public class UiSceneSteps extends BaseEntity
|
|||||||
|
|
||||||
/** 窗口尺寸 */
|
/** 窗口尺寸 */
|
||||||
@Excel(name = "窗口尺寸")
|
@Excel(name = "窗口尺寸")
|
||||||
private Integer windowSize;
|
private String windowSize;
|
||||||
|
|
||||||
/** 子选项 */
|
/** 子选项 */
|
||||||
@Excel(name = "子选项")
|
@Excel(name = "子选项")
|
||||||
@@ -201,21 +201,21 @@ public class UiSceneSteps extends BaseEntity
|
|||||||
{
|
{
|
||||||
return operateObject;
|
return operateObject;
|
||||||
}
|
}
|
||||||
public void setOperateGroupId(Integer operateGroupId)
|
public void setOperateGroupId(Long operateGroupId)
|
||||||
{
|
{
|
||||||
this.operateGroupId = operateGroupId;
|
this.operateGroupId = operateGroupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getOperateGroupId()
|
public Long getOperateGroupId()
|
||||||
{
|
{
|
||||||
return operateGroupId;
|
return operateGroupId;
|
||||||
}
|
}
|
||||||
public void setOperateElementId(Integer operateElementId)
|
public void setOperateElementId(Long operateElementId)
|
||||||
{
|
{
|
||||||
this.operateElementId = operateElementId;
|
this.operateElementId = operateElementId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getOperateElementId()
|
public Long getOperateElementId()
|
||||||
{
|
{
|
||||||
return operateElementId;
|
return operateElementId;
|
||||||
}
|
}
|
||||||
@@ -255,12 +255,12 @@ public class UiSceneSteps extends BaseEntity
|
|||||||
{
|
{
|
||||||
return inputValue;
|
return inputValue;
|
||||||
}
|
}
|
||||||
public void setWindowSize(Integer windowSize)
|
public void setWindowSize(String windowSize)
|
||||||
{
|
{
|
||||||
this.windowSize = windowSize;
|
this.windowSize = windowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getWindowSize()
|
public String getWindowSize()
|
||||||
{
|
{
|
||||||
return windowSize;
|
return windowSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class UiSceneStepsQO extends BaseEntity
|
|||||||
private String inputValue;
|
private String inputValue;
|
||||||
|
|
||||||
/** 窗口尺寸 */
|
/** 窗口尺寸 */
|
||||||
private Integer windowSize;
|
private String windowSize;
|
||||||
|
|
||||||
/** 子选项 */
|
/** 子选项 */
|
||||||
private String subOptions;
|
private String subOptions;
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
|||||||
uiAutomation.setStatus("1"); //未开始
|
uiAutomation.setStatus("1"); //未开始
|
||||||
uiAutomation.setDutyBy(SecurityUtils.getUsername());
|
uiAutomation.setDutyBy(SecurityUtils.getUsername());
|
||||||
uiAutomation.setDelFlag(0);
|
uiAutomation.setDelFlag(0);
|
||||||
|
uiAutomation.setCrontabStatus(0); //未开启
|
||||||
uiAutomationMapper.insertUiAutomation(uiAutomation);
|
uiAutomationMapper.insertUiAutomation(uiAutomation);
|
||||||
Long automationId = uiAutomation.getId();
|
Long automationId = uiAutomation.getId();
|
||||||
//新增场景步骤
|
//新增场景步骤
|
||||||
|
|||||||
@@ -1,32 +1,26 @@
|
|||||||
package com.test.test.service.impl;
|
package com.test.test.service.impl;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.test.common.config.TestConfig;
|
||||||
import com.test.common.utils.DateUtils;
|
import com.test.common.utils.DateUtils;
|
||||||
import com.test.common.utils.SecurityUtils;
|
import com.test.common.utils.SecurityUtils;
|
||||||
import com.test.common.utils.SeleniumUtils;
|
import com.test.common.utils.SeleniumUtils;
|
||||||
import com.test.common.utils.StringUtils;
|
import com.test.common.utils.StringUtils;
|
||||||
import com.test.test.domain.UiAutomation;
|
import com.test.test.domain.*;
|
||||||
import com.test.test.domain.UiReport;
|
|
||||||
import com.test.test.domain.UiSceneSteps;
|
|
||||||
import com.test.test.domain.UiSceneStepsReport;
|
|
||||||
import com.test.test.domain.qo.OtherSettingsQO;
|
import com.test.test.domain.qo.OtherSettingsQO;
|
||||||
import com.test.test.domain.vo.UiHighSettingVO;
|
import com.test.test.domain.vo.UiHighSettingVO;
|
||||||
import com.test.test.mapper.UiAutomationMapper;
|
import com.test.test.mapper.UiAutomationMapper;
|
||||||
import com.test.test.mapper.UiSceneStepsMapper;
|
import com.test.test.mapper.UiSceneStepsMapper;
|
||||||
import com.test.test.mapper.UiSceneStepsReportMapper;
|
import com.test.test.mapper.UiSceneStepsReportMapper;
|
||||||
import com.test.test.service.IUiAutomationService;
|
import com.test.test.service.*;
|
||||||
import com.test.test.service.IUiReportService;
|
|
||||||
import com.test.test.service.IUiSceneStepsService;
|
|
||||||
import com.test.test.service.StepExecution;
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.checkerframework.checker.units.qual.C;
|
import org.checkerframework.checker.units.qual.C;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.chrome.ChromeDriver;
|
import org.openqa.selenium.chrome.ChromeDriver;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -46,18 +40,12 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
private UiSceneStepsReportMapper uiSceneStepsReportMapper;
|
private UiSceneStepsReportMapper uiSceneStepsReportMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private IUiAutomationService uiAutomationService;
|
private IUiAutomationService uiAutomationService;
|
||||||
//场景成功数
|
@Resource
|
||||||
private Integer scenesSucceedNumber = 0;
|
private IUiElementService uiElementService;
|
||||||
//场景失败数
|
@Resource
|
||||||
private Integer scenesErrorNumber = 0;
|
private UiAutomationMapper uiAutomationMapper;
|
||||||
//场景未执行数
|
|
||||||
private Integer scenesNotNumber = 0;
|
|
||||||
//步骤成功数
|
|
||||||
private Integer stepsSucceedNumber = 0;
|
|
||||||
//步骤失败数
|
|
||||||
private Integer stepsErrorNumber = 0;
|
|
||||||
//步骤未执行数
|
|
||||||
private Integer stepsNotNumber = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +60,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
result.put("id", 0L);
|
result.put("id", 0L);
|
||||||
// 1. 验证并获取步骤
|
// 1. 验证并获取步骤
|
||||||
List<UiSceneSteps> steps = validateAndGetSteps(automationId);
|
List<UiSceneSteps> steps = validateAndGetSteps(automationId);
|
||||||
stepsNotNumber = steps.size();
|
|
||||||
|
//修改ui_automation 状态为进行中 执行结果为running
|
||||||
|
UiAutomation uiAutomation = new UiAutomation();
|
||||||
|
uiAutomation.setStatus("2");
|
||||||
|
uiAutomation.setExecutionResult("1");
|
||||||
|
uiAutomation.setUpdateBy(DateUtils.getTime());
|
||||||
|
uiAutomationMapper.updateUiAutomation(uiAutomation);
|
||||||
|
|
||||||
|
|
||||||
Date startTime = DateUtils.getNowDate();
|
Date startTime = DateUtils.getNowDate();
|
||||||
// 2. 创建执行报告
|
// 2. 创建执行报告
|
||||||
@@ -91,22 +86,48 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
// 3. 执行所有步骤
|
// 3. 执行所有步骤
|
||||||
executeAllSteps(steps, reportId);
|
executeAllSteps(steps, reportId);
|
||||||
log.info("场景执行成功: {}", automationId);
|
log.info("场景执行成功: {}", automationId);
|
||||||
scenesSucceedNumber++;
|
|
||||||
uiReport.setConsoleStr("OK");
|
uiReport.setConsoleStr("OK");
|
||||||
uiReport.setStatus(3);
|
uiReport.setStatus(3);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
result.put("msg", e.getMessage());
|
result.put("msg", e.getMessage());
|
||||||
log.error("场景执行失败: {}", e.getMessage());
|
log.error("场景执行失败: {}", e.getMessage());
|
||||||
scenesErrorNumber++;
|
|
||||||
uiReport.setConsoleStr(e.toString());
|
uiReport.setConsoleStr(e.toString());
|
||||||
uiReport.setStatus(2);
|
uiReport.setStatus(2);
|
||||||
|
uiAutomation.setExecutionResult("2");
|
||||||
} finally {
|
} finally {
|
||||||
endTime = DateUtils.getNowDate();
|
endTime = DateUtils.getNowDate();
|
||||||
uiReport.setTake(DateUtils.calculateTimeDifference(startTime, endTime));
|
uiReport.setTake(DateUtils.calculateTimeDifference(startTime, endTime));
|
||||||
uiReport.setUpdateTime(endTime);
|
uiReport.setUpdateTime(endTime);
|
||||||
|
//查询report
|
||||||
|
UiSceneStepsReport uiStepsReport = new UiSceneStepsReport();
|
||||||
|
uiStepsReport.setReportId(reportId);
|
||||||
|
List<UiSceneStepsReport> uiSceneStepsReports = uiSceneStepsReportMapper.selectUiSceneStepsReportList(uiStepsReport);
|
||||||
|
int scenesSucceedNumber = 0;
|
||||||
|
int scenesErrorNumber = 0;
|
||||||
|
int stepsSucceedNumber = 0;
|
||||||
|
int stepsErrorNumber = 0;
|
||||||
|
int stepsNotNumber = 0;
|
||||||
|
if (uiSceneStepsReports != null && !uiSceneStepsReports.isEmpty()) {
|
||||||
|
boolean allSuccess = true;
|
||||||
|
for (UiSceneStepsReport report : uiSceneStepsReports) {
|
||||||
|
if (report.getExecutionFlag().equals("1")) {
|
||||||
|
stepsSucceedNumber++;
|
||||||
|
} else if (report.getExecutionFlag().equals("2")) {
|
||||||
|
stepsErrorNumber++;
|
||||||
|
allSuccess = false;
|
||||||
|
} else if (report.getExecutionFlag().equals("0")) {
|
||||||
|
stepsNotNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allSuccess) {
|
||||||
|
scenesSucceedNumber = 1;
|
||||||
|
} else {
|
||||||
|
scenesErrorNumber = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
uiReport.setScenesSucceedNumber(scenesSucceedNumber);
|
uiReport.setScenesSucceedNumber(scenesSucceedNumber);
|
||||||
uiReport.setScenesErrorNumber(scenesErrorNumber);
|
uiReport.setScenesErrorNumber(scenesErrorNumber);
|
||||||
uiReport.setScenesNotNumber(scenesNotNumber);
|
uiReport.setScenesNotNumber(0);
|
||||||
uiReport.setStepsSucceedNumber(stepsSucceedNumber);
|
uiReport.setStepsSucceedNumber(stepsSucceedNumber);
|
||||||
uiReport.setStepsErrorNumber(stepsErrorNumber);
|
uiReport.setStepsErrorNumber(stepsErrorNumber);
|
||||||
uiReport.setStepsNotNumber(stepsNotNumber);
|
uiReport.setStepsNotNumber(stepsNotNumber);
|
||||||
@@ -116,6 +137,16 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
);
|
);
|
||||||
uiReportService.updateUiReport(uiReport);
|
uiReportService.updateUiReport(uiReport);
|
||||||
|
|
||||||
|
//修改ui_automation
|
||||||
|
uiAutomation = new UiAutomation();
|
||||||
|
if (!uiAutomation.getExecutionResult().equals("2")){
|
||||||
|
uiAutomation.setExecutionResult("3");
|
||||||
|
uiAutomation.setStatus("3");
|
||||||
|
}
|
||||||
|
uiAutomation.setUpdateBy(DateUtils.getTime());
|
||||||
|
uiAutomation.setPassRate(stepsSucceedNumber == 0 ? "0%" :
|
||||||
|
String.format("%.2f%%", (double)stepsSucceedNumber / steps.size() * 100));
|
||||||
|
uiAutomationMapper.updateUiAutomation(uiAutomation);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -128,6 +159,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
*/
|
*/
|
||||||
private List<UiSceneSteps> validateAndGetSteps(Long automationId) {
|
private List<UiSceneSteps> validateAndGetSteps(Long automationId) {
|
||||||
List<UiSceneSteps> steps = uiSceneStepsMapper.selectUiSceneStepsById(automationId);
|
List<UiSceneSteps> steps = uiSceneStepsMapper.selectUiSceneStepsById(automationId);
|
||||||
|
steps = steps.stream().filter(e->e.getIsDisabled() == 0).collect(Collectors.toList());
|
||||||
if (CollectionUtils.isEmpty(steps)) {
|
if (CollectionUtils.isEmpty(steps)) {
|
||||||
throw new IllegalArgumentException("步骤不能为空");
|
throw new IllegalArgumentException("步骤不能为空");
|
||||||
}
|
}
|
||||||
@@ -186,30 +218,29 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
// 定义所有操作类型的执行方法映射
|
// 定义所有操作类型的执行方法映射
|
||||||
Map<String, Map<String, StepExecution>> operationStrategies = Map.of(
|
Map<String, Map<String, StepExecution>> operationStrategies = Map.of(
|
||||||
"1", Map.of( // 浏览器操作
|
"1", Map.of( // 浏览器操作
|
||||||
"1", this::openWebPage
|
"1", this::openWebPage,
|
||||||
// "2", this::closeBrowser,
|
"2", this::closeBrowser,
|
||||||
// "3", this::switchWindow,
|
"3", this::switchWindow,
|
||||||
// "4", this::resizeWindow,
|
"4", this::resizeWindow,
|
||||||
// "5", this::selectEmbeddedPage
|
"5", this::selectEmbeddedPage
|
||||||
|
),
|
||||||
|
"2", Map.of( // 弹窗操作
|
||||||
|
"1", this::handlePopup
|
||||||
|
),
|
||||||
|
"3", Map.of( // 元素操作
|
||||||
|
"1", this::submitForm,
|
||||||
|
"2", this::handleDropdown,
|
||||||
|
"3", this::setOption,
|
||||||
|
"4", this::waitForElement
|
||||||
|
),
|
||||||
|
"4", Map.of( // 鼠标操作
|
||||||
|
"1", this::mouseClick,
|
||||||
|
"2", this::mouseMove
|
||||||
|
),
|
||||||
|
"5", Map.of( // 输入操作
|
||||||
|
"1", this::inputText,
|
||||||
|
"2", this::uploadFile
|
||||||
)
|
)
|
||||||
// "2", Map.of( // 弹窗操作
|
|
||||||
// "1", this::handlePopup
|
|
||||||
// ),
|
|
||||||
// "3", Map.of( // 元素操作
|
|
||||||
// "1", this::submitForm,
|
|
||||||
// "2", this::handleDropdown,
|
|
||||||
// "3", this::setOption,
|
|
||||||
// "4", this::waitForElement
|
|
||||||
// ),
|
|
||||||
// "4", Map.of( // 鼠标操作
|
|
||||||
// "1", this::mouseClick,
|
|
||||||
// "2", this::mouseMove,
|
|
||||||
// "3", this::mouseDrag
|
|
||||||
// ),
|
|
||||||
// "5", Map.of( // 输入操作
|
|
||||||
// "1", this::inputText,
|
|
||||||
// "2", this::uploadFile
|
|
||||||
// )
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 获取对应的操作类型映射
|
// 获取对应的操作类型映射
|
||||||
@@ -253,7 +284,16 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
UiHighSettingVO otherSetting = extractOtherSetting(uiHighSettingVOList);
|
UiHighSettingVO otherSetting = extractOtherSetting(uiHighSettingVOList);
|
||||||
OtherSettingsQO otherSettingsQO = otherSetting.getOtherSettingsQO();
|
OtherSettingsQO otherSettingsQO = otherSetting.getOtherSettingsQO();
|
||||||
Integer screenshotConfiguration = otherSettingsQO.getScreenshotConfiguration(); //是否截图 1当前步骤截图 2异常截图 3 不截图
|
Integer screenshotConfiguration = otherSettingsQO.getScreenshotConfiguration(); //是否截图 1当前步骤截图 2异常截图 3 不截图
|
||||||
|
//等待元素超时时间
|
||||||
|
Integer waitElementTime = otherSettingsQO.getWaitElementTime()==null?0:otherSettingsQO.getWaitElementTime();
|
||||||
|
//前置操作设置
|
||||||
|
List<UiHighSettingVO> beforeSettingList = extractbeforeSetting(uiHighSettingVOList);
|
||||||
|
//后置操作设置
|
||||||
|
List<UiHighSettingVO> afterSettingList = extractafterSetting(uiHighSettingVOList);
|
||||||
|
//前置等待时间
|
||||||
|
int beforeAwaitTime = getAwaitTime(beforeSettingList);
|
||||||
|
//后置等待时间
|
||||||
|
int afterAwaitTime = getAwaitTime(afterSettingList);
|
||||||
// 2. 准备报告对象
|
// 2. 准备报告对象
|
||||||
UiSceneStepsReport report = new UiSceneStepsReport();
|
UiSceneStepsReport report = new UiSceneStepsReport();
|
||||||
report.setId(sceneStepsReportId);
|
report.setId(sceneStepsReportId);
|
||||||
@@ -261,28 +301,42 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
Date endTime = null;
|
Date endTime = null;
|
||||||
boolean continueExecution = true; // 默认继续执行
|
boolean continueExecution = true; // 默认继续执行
|
||||||
try {
|
try {
|
||||||
stepsSucceedNumber++;
|
// 执行前置等待
|
||||||
if (screenshotConfiguration == 1) {
|
if (beforeAwaitTime > 0) {
|
||||||
|
log.info("执行前置等待: {}ms", beforeAwaitTime);
|
||||||
|
Thread.sleep(beforeAwaitTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screenshotConfiguration == 1) {
|
||||||
|
report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
||||||
|
log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
||||||
}
|
}
|
||||||
// 3. 执行具体步骤
|
// 3. 执行具体步骤
|
||||||
stepExecution.execute(step, seleniumUtils);
|
stepExecution.execute(step, seleniumUtils);
|
||||||
|
|
||||||
|
// 执行后置等待
|
||||||
|
if (afterAwaitTime > 0) {
|
||||||
|
log.info("执行后置等待: {}ms", afterAwaitTime);
|
||||||
|
Thread.sleep(afterAwaitTime);
|
||||||
|
}
|
||||||
|
|
||||||
report.setLogInfo("OK");
|
report.setLogInfo("OK");
|
||||||
report.setExecutionFlag("1");
|
report.setExecutionFlag("1");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 4. 错误处理
|
// 4. 错误处理
|
||||||
stepsErrorNumber++;
|
|
||||||
stepsSucceedNumber--;
|
|
||||||
report.setLogInfo(e.toString());
|
report.setLogInfo(e.toString());
|
||||||
report.setExecutionFlag("2");
|
report.setExecutionFlag("2");
|
||||||
// 根据错误处理设置决定是否继续
|
// 根据错误处理设置决定是否继续
|
||||||
if ("1".equals(errorSetting.getErrorHandling())) {
|
if ("1".equals(errorSetting.getErrorHandling())) {
|
||||||
continueExecution = false; // 不继续执行后续步骤
|
continueExecution = false; // 不继续执行后续步骤
|
||||||
}
|
}
|
||||||
|
if (screenshotConfiguration == 2) {
|
||||||
|
report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
||||||
|
log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
||||||
|
}
|
||||||
log.error("步骤执行失败: {}", e.getMessage());
|
log.error("步骤执行失败: {}", e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
endTime = DateUtils.getNowDate();
|
endTime = DateUtils.getNowDate();
|
||||||
stepsNotNumber--;
|
|
||||||
// 更新报告
|
// 更新报告
|
||||||
report.setCreateTime(startTime);
|
report.setCreateTime(startTime);
|
||||||
report.setUpdateTime(endTime);
|
report.setUpdateTime(endTime);
|
||||||
@@ -293,6 +347,52 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
return continueExecution;
|
return continueExecution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取前置操作
|
||||||
|
* @param settings
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<UiHighSettingVO> extractbeforeSetting(List<UiHighSettingVO> settings) {
|
||||||
|
return settings.stream()
|
||||||
|
.filter(e -> "1".equals(e.getSettingType()) && e.getIsDisabled() == 0)
|
||||||
|
.collect(Collectors.toList()); // 返回默认设置
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取(前置//后置)等待时间
|
||||||
|
* @param settingList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int getAwaitTime(List<UiHighSettingVO> settingList){
|
||||||
|
//获取前置等待时间
|
||||||
|
int totalWaitTime = settingList.stream()
|
||||||
|
.map(UiHighSettingVO::getAwateTime)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(s -> !s.isEmpty())
|
||||||
|
.mapToInt(s -> {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(s);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
return totalWaitTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取后置操作
|
||||||
|
* @param settings
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<UiHighSettingVO> extractafterSetting(List<UiHighSettingVO> settings) {
|
||||||
|
return settings.stream()
|
||||||
|
.filter(e -> "2".equals(e.getSettingType()) && e.getIsDisabled() == 0)
|
||||||
|
.collect(Collectors.toList()); // 返回默认设置
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提取错误处理设置
|
* 提取错误处理设置
|
||||||
* @param settings
|
* @param settings
|
||||||
@@ -305,6 +405,9 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
.orElse(new UiHighSettingVO()); // 返回默认设置
|
.orElse(new UiHighSettingVO()); // 返回默认设置
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提取错误处理设置
|
* 提取错误处理设置
|
||||||
* @param settings
|
* @param settings
|
||||||
@@ -317,6 +420,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
.orElse(new UiHighSettingVO()); // 返回默认设置
|
.orElse(new UiHighSettingVO()); // 返回默认设置
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------浏览器操作---------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开网页
|
* 打开网页
|
||||||
*
|
*
|
||||||
@@ -324,8 +435,465 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
* @param seleniumUtils Selenium工具类
|
* @param seleniumUtils Selenium工具类
|
||||||
*/
|
*/
|
||||||
private void openWebPage(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
private void openWebPage(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
log.info("打开网页:{}",step.getUrl());
|
||||||
seleniumUtils.openUrl(step.getUrl());
|
seleniumUtils.openUrl(step.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭网页
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void closeBrowser(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
log.info("关闭网页");
|
||||||
|
seleniumUtils.quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换窗口
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void switchWindow(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
if (step.getOperate()==1){
|
||||||
|
log.info("根据句柄 ID 切换到指定窗口");
|
||||||
|
//句柄id
|
||||||
|
String handleId = step.getHandleId();
|
||||||
|
seleniumUtils.switchToWindowByHandle(handleId);
|
||||||
|
}else if (step.getOperate()==2){
|
||||||
|
log.info("根据网页索引号切换到指定窗口");
|
||||||
|
//网页索引号
|
||||||
|
Integer frameIndex = step.getFrameIndex();
|
||||||
|
seleniumUtils.switchToWindowByIndex(frameIndex);
|
||||||
|
}else if (step.getOperate()==3){
|
||||||
|
log.info("切换到初始窗口");
|
||||||
|
seleniumUtils.switchToDefaultWindow();
|
||||||
|
}else{
|
||||||
|
log.info("无效的窗口切换操作类型");
|
||||||
|
throw new IllegalArgumentException("无效的窗口切换操作类型");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置窗口大小
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void resizeWindow(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
if (step.getOperate()==1){
|
||||||
|
log.info("窗口最大化");
|
||||||
|
//窗口最大化
|
||||||
|
seleniumUtils.maximizeWindow();
|
||||||
|
}else if (step.getOperate()==2){
|
||||||
|
log.info("设置窗口大小");
|
||||||
|
String windowSize = step.getWindowSize();
|
||||||
|
String[] dimensions = windowSize.split("\\*");
|
||||||
|
int width = Integer.parseInt(dimensions[0]);
|
||||||
|
int height = Integer.parseInt(dimensions[1]);
|
||||||
|
seleniumUtils.setWindowSize(width, height);
|
||||||
|
}else{
|
||||||
|
log.info("无效的设置窗口大小");
|
||||||
|
throw new IllegalArgumentException("无效的设置窗口大小");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择内嵌网页
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void selectEmbeddedPage(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
if (step.getOperate()==1){
|
||||||
|
log.info("退出当前 frame(回到主页面)");
|
||||||
|
seleniumUtils.switchToDefaultContent();
|
||||||
|
}else if (step.getOperate()==2){
|
||||||
|
log.info("根据 frame 索引号切换到指定 frame");
|
||||||
|
//网页索引号
|
||||||
|
seleniumUtils.switchToFrameByIndex(step.getFrameIndex());
|
||||||
|
}else if (step.getOperate()==3){
|
||||||
|
log.info("根据定位方式切换 frame");
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
//元素对象
|
||||||
|
String operateLocType = step.getOperateLocType(); //属性
|
||||||
|
String operateLocValue = step.getOperateLocValue(); //值
|
||||||
|
seleniumUtils.switchToFrameByLocator(
|
||||||
|
operateLocType,
|
||||||
|
operateLocValue
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
//元素定位
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
|
||||||
|
}
|
||||||
|
String locType = uiElement.getLocType(); //属性
|
||||||
|
String elementLoc = uiElement.getElementLoc();//值
|
||||||
|
seleniumUtils.switchToFrameByLocator(
|
||||||
|
locType,
|
||||||
|
elementLoc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
log.info("无效的选择内嵌网页");
|
||||||
|
throw new IllegalArgumentException("无效的选择内嵌网页");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------弹窗操作--------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹窗操作
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void handlePopup(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
if (step.getOperate()==1){
|
||||||
|
log.info("弹窗操作");
|
||||||
|
// 获取输入内容(如果需要)
|
||||||
|
String inputValue = "1".equals(step.getIsEnter()) ? step.getInputValue() : null;
|
||||||
|
String operateWay = step.getOperateWay(); //操作方式 1确定 2取消
|
||||||
|
// 执行弹窗操作
|
||||||
|
seleniumUtils.handleAlert(
|
||||||
|
Integer.parseInt(operateWay), // 操作方式 (1=确定, 2=取消)
|
||||||
|
inputValue // 输入内容
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
log.info("无效的弹窗操作");
|
||||||
|
throw new IllegalArgumentException("无效的弹窗操作");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------元素操作----------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交表单
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void submitForm(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
//元素对象
|
||||||
|
String operateLocType = step.getOperateLocType(); //属性
|
||||||
|
String operateLocValue = step.getOperateLocValue(); //值
|
||||||
|
// 根据属性和值定位元素并提交表单
|
||||||
|
seleniumUtils.findElement(operateLocType, operateLocValue).submit();
|
||||||
|
log.info("通过元素对象提交表单,定位方式:{},定位值:{}", operateLocType, operateLocValue);
|
||||||
|
}else{
|
||||||
|
//元素定位
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
|
||||||
|
}
|
||||||
|
String locType = uiElement.getLocType(); //属性
|
||||||
|
String elementLoc = uiElement.getElementLoc();//值
|
||||||
|
seleniumUtils.findElement(locType, elementLoc).submit();
|
||||||
|
log.info("通过元素定位提交表单,定位方式:{},定位值:{}", locType, elementLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下拉框操作
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void handleDropdown(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
log.info("下拉框操作");
|
||||||
|
Integer operate = step.getOperate(); //操作 1选择 2取消
|
||||||
|
WebElement dropdownElement;
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
//元素对象
|
||||||
|
String operateLocType = step.getOperateLocType(); //属性
|
||||||
|
String operateLocValue = step.getOperateLocValue(); //值
|
||||||
|
dropdownElement = seleniumUtils.findElement(operateLocType, operateLocValue);
|
||||||
|
log.info("通过元素对象定位下拉框,定位方式:{},定位值:{}", operateLocType, operateLocValue);
|
||||||
|
}else{
|
||||||
|
//元素定位
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
|
||||||
|
}
|
||||||
|
String locType = uiElement.getLocType(); //属性
|
||||||
|
String elementLoc = uiElement.getElementLoc();//值
|
||||||
|
dropdownElement = seleniumUtils.findElement(locType, elementLoc);
|
||||||
|
log.info("通过元素定位定位下拉框,定位方式:{},定位值:{}", locType, elementLoc);
|
||||||
|
}
|
||||||
|
//子选项
|
||||||
|
String subOptions = step.getSubOptions(); //1 选项 2索引 3值
|
||||||
|
String subOptionsValue = step.getSubOptionsValue(); //值
|
||||||
|
|
||||||
|
if (operate == 1) {
|
||||||
|
// 选择操作
|
||||||
|
seleniumUtils.selectDropdownOption(dropdownElement, subOptions, subOptionsValue);
|
||||||
|
} else if (operate == 2) {
|
||||||
|
// 取消操作
|
||||||
|
// 如果需要取消下拉框的选择,可以使用默认选项或其他逻辑
|
||||||
|
log.info("取消下拉框选择");
|
||||||
|
// 示例:取消选择(假设下拉框的第一个选项是默认选项)
|
||||||
|
seleniumUtils.selectDropdownOption(dropdownElement, "2", "0");
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("无效的操作类型: " + operate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置选项
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void setOption(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
log.info("设置选项");
|
||||||
|
Integer operate = step.getOperate(); // 操作 1选择 2取消
|
||||||
|
WebElement element;
|
||||||
|
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
// 元素对象
|
||||||
|
String operateLocType = step.getOperateLocType(); // 属性
|
||||||
|
String operateLocValue = step.getOperateLocValue(); // 值
|
||||||
|
element = seleniumUtils.findElement(operateLocType, operateLocValue);
|
||||||
|
log.info("通过元素对象定位选项,定位方式:{},定位值:{}", operateLocType, operateLocValue);
|
||||||
|
} else {
|
||||||
|
// 元素定位
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
log.error("未找到指定的元素,元素ID:{}", step.getOperateElementId());
|
||||||
|
throw new IllegalArgumentException("未找到指定的元素");
|
||||||
|
}
|
||||||
|
String locType = uiElement.getLocType(); // 属性
|
||||||
|
String elementLoc = uiElement.getElementLoc(); // 值
|
||||||
|
element = seleniumUtils.findElement(locType, elementLoc);
|
||||||
|
log.info("通过元素定位定位选项,定位方式:{},定位值:{}", locType, elementLoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operate == 1) {
|
||||||
|
// 选择操作
|
||||||
|
if (!element.isSelected()) {
|
||||||
|
element.click();
|
||||||
|
log.info("设置选项为选中状态");
|
||||||
|
}
|
||||||
|
} else if (operate == 2) {
|
||||||
|
// 取消操作
|
||||||
|
if (element.isSelected()) {
|
||||||
|
element.click();
|
||||||
|
log.info("设置选项为未选中状态");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("无效的操作类型: " + operate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待元素
|
||||||
|
*
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void waitForElement(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
log.info("等待元素");
|
||||||
|
//操作 1等待元素等于给定的定值(Text) 2 等待元素存在 3等待元素显示 4等待元素不显示 5等待元素不存在 6等待元素可编辑 7等待元素不可编辑
|
||||||
|
By locator;
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
//元素对象
|
||||||
|
String operateLocType = step.getOperateLocType(); //属性
|
||||||
|
String operateLocValue = step.getOperateLocValue(); //值
|
||||||
|
// 使用直接指定的定位方式
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
operateLocType,
|
||||||
|
operateLocValue
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
//元素定位
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
String locType = uiElement.getLocType(); //属性
|
||||||
|
String elementLoc = uiElement.getElementLoc();//值
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
locType,
|
||||||
|
elementLoc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 解析等待时间(默认15000ms)
|
||||||
|
long timeout = 15000;
|
||||||
|
if (step.getOperate() != 1 && step.getAwaitValue() != null) {
|
||||||
|
try {
|
||||||
|
timeout = Long.parseLong(step.getAwaitValue());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.warn("等待时间格式错误,使用默认值15000ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 执行等待操作
|
||||||
|
seleniumUtils.waitForElement(
|
||||||
|
locator,
|
||||||
|
step.getOperate(),
|
||||||
|
step.getOperate() == 1 ? step.getAwaitValue() : null,
|
||||||
|
timeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------鼠标操作------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 鼠标点击操作
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void mouseClick(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
try {
|
||||||
|
log.info("执行鼠标操作,方式: {}", step.getClickMethod());
|
||||||
|
// 获取定位器
|
||||||
|
By locator;
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
// 使用直接指定的定位方式
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
step.getOperateLocType(),
|
||||||
|
step.getOperateLocValue()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 使用元素ID从数据库获取定位信息
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
|
||||||
|
}
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
uiElement.getLocType(),
|
||||||
|
uiElement.getElementLoc()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 执行鼠标操作
|
||||||
|
seleniumUtils.performMouseAction(
|
||||||
|
locator,
|
||||||
|
Integer.parseInt(step.getClickMethod())
|
||||||
|
);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.error("鼠标操作类型格式错误: {}", step.getClickMethod());
|
||||||
|
throw new RuntimeException("鼠标操作类型必须是数字(1-5)", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("鼠标操作执行失败", e);
|
||||||
|
throw new RuntimeException("鼠标操作失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 鼠标移动操作
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
private void mouseMove(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
try {
|
||||||
|
log.info("执行鼠标移动操作,方式: {}", step.getClickMethod());
|
||||||
|
// 获取定位器
|
||||||
|
By locator;
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
// 使用直接指定的定位方式
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
step.getOperateLocType(),
|
||||||
|
step.getOperateLocValue()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 使用元素ID从数据库获取定位信息
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
|
||||||
|
}
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
uiElement.getLocType(),
|
||||||
|
uiElement.getElementLoc()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 执行鼠标移动操作
|
||||||
|
seleniumUtils.performMouseMove(
|
||||||
|
locator,
|
||||||
|
Integer.parseInt(step.getClickMethod()) // 1=移出,2=移入
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.error("鼠标移动类型格式错误: {}", step.getClickMethod());
|
||||||
|
throw new RuntimeException("鼠标移动类型必须是数字(1-2)", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("鼠标移动操作执行失败", e);
|
||||||
|
throw new RuntimeException("鼠标移动操作失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入操作
|
||||||
|
* @param step 步骤对象
|
||||||
|
* @param seleniumUtils Selenium工具类
|
||||||
|
*/
|
||||||
|
public void inputText(UiSceneSteps step, SeleniumUtils seleniumUtils) {
|
||||||
|
try {
|
||||||
|
log.info("执行输入操作,类型: {}", step.getOperate());
|
||||||
|
|
||||||
|
// 获取定位器
|
||||||
|
By locator;
|
||||||
|
if ("2".equals(step.getOperateObject())) {
|
||||||
|
// 使用直接指定的定位方式
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
step.getOperateLocType(),
|
||||||
|
step.getOperateLocValue()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 使用元素ID从数据库获取定位信息
|
||||||
|
UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
|
||||||
|
if (uiElement == null) {
|
||||||
|
throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
|
||||||
|
}
|
||||||
|
locator = seleniumUtils.getLocator(
|
||||||
|
uiElement.getLocType(),
|
||||||
|
uiElement.getElementLoc()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取输入内容
|
||||||
|
String inputValue = step.getInputValue();
|
||||||
|
if (inputValue == null || inputValue.trim().isEmpty()) {
|
||||||
|
log.warn("输入内容为空,将执行清空操作");
|
||||||
|
seleniumUtils.clearInput(locator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 执行输入操作
|
||||||
|
if (step.getOperate() == 1) { // 普通输入框
|
||||||
|
seleniumUtils.inputText(
|
||||||
|
locator,
|
||||||
|
inputValue,
|
||||||
|
true, // 默认先清空
|
||||||
|
1 // 默认使用普通输入方式
|
||||||
|
);
|
||||||
|
} else if (step.getOperate() == 2) { // 可编辑段落
|
||||||
|
seleniumUtils.inputToEditableDiv(
|
||||||
|
locator,
|
||||||
|
inputValue
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("不支持的输入操作类型: " + step.getOperate());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("输入操作执行失败", e);
|
||||||
|
throw new RuntimeException("输入操作失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传
|
||||||
|
* @param step
|
||||||
|
* @param seleniumUtils
|
||||||
|
*/
|
||||||
|
public void uploadFile(UiSceneSteps step, SeleniumUtils seleniumUtils){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,10 +22,12 @@
|
|||||||
<result property="crontabStatus" column="crontab_status" />
|
<result property="crontabStatus" column="crontab_status" />
|
||||||
<result property="delFlag" column="del_flag" />
|
<result property="delFlag" column="del_flag" />
|
||||||
<result property="description" column="description" />
|
<result property="description" column="description" />
|
||||||
|
<result property="createTime" column="create_time"/>
|
||||||
|
<result property="updateBy" column="update_by"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectUiAutomationVo">
|
<sql id="selectUiAutomationVo">
|
||||||
select id, group_id, name, case_level, status, label, create_by, duty_by, run_environment, update_time, steps_number, execution_result, pass_rate, crontab, crontab_status, del_flag,description from ui_automation
|
select id, group_id, name, case_level, status, label, create_by, duty_by, run_environment, update_time, steps_number, execution_result, pass_rate, crontab, crontab_status, del_flag,create_time,update_by from ui_automation
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectUiAutomationList" parameterType="UiAutomation" resultMap="UiAutomationResult">
|
<select id="selectUiAutomationList" parameterType="UiAutomation" resultMap="UiAutomationResult">
|
||||||
@@ -126,6 +128,8 @@
|
|||||||
<if test="crontabStatus != null">crontab_status,</if>
|
<if test="crontabStatus != null">crontab_status,</if>
|
||||||
<if test="delFlag != null">del_flag,</if>
|
<if test="delFlag != null">del_flag,</if>
|
||||||
<if test="description != null">description,</if>
|
<if test="description != null">description,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateBy != null">update_by,</if>
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="groupId != null">#{groupId},</if>
|
<if test="groupId != null">#{groupId},</if>
|
||||||
@@ -144,6 +148,8 @@
|
|||||||
<if test="crontabStatus != null">#{crontabStatus},</if>
|
<if test="crontabStatus != null">#{crontabStatus},</if>
|
||||||
<if test="delFlag != null">#{delFlag},</if>
|
<if test="delFlag != null">#{delFlag},</if>
|
||||||
<if test="description != null">#{description},</if>
|
<if test="description != null">#{description},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="updateBy != null">#{updateBy},</if>
|
||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
@@ -166,6 +172,8 @@
|
|||||||
<if test="crontabStatus != null">crontab_status = #{crontabStatus},</if>
|
<if test="crontabStatus != null">crontab_status = #{crontabStatus},</if>
|
||||||
<if test="delFlag != null">del_flag = #{delFlag},</if>
|
<if test="delFlag != null">del_flag = #{delFlag},</if>
|
||||||
<if test="description != null">description = #{description},</if>
|
<if test="description != null">description = #{description},</if>
|
||||||
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
|
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||||
</trim>
|
</trim>
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|||||||
Reference in New Issue
Block a user