UI执行接口

This commit is contained in:
2025-04-27 14:19:12 +08:00
parent 83109f3170
commit d71d5c070e
6 changed files with 1126 additions and 71 deletions

View File

@@ -52,11 +52,11 @@ public class UiSceneSteps extends BaseEntity
/** 元素库名称 */
@Excel(name = "元素库名称")
private Integer operateGroupId;
private Long operateGroupId;
/** 元素id */
@Excel(name = "元素id")
private Integer operateElementId;
private Long operateElementId;
/** 元素定位类型 */
@Excel(name = "元素定位类型")
@@ -76,7 +76,7 @@ public class UiSceneSteps extends BaseEntity
/** 窗口尺寸 */
@Excel(name = "窗口尺寸")
private Integer windowSize;
private String windowSize;
/** 子选项 */
@Excel(name = "子选项")
@@ -201,21 +201,21 @@ public class UiSceneSteps extends BaseEntity
{
return operateObject;
}
public void setOperateGroupId(Integer operateGroupId)
public void setOperateGroupId(Long operateGroupId)
{
this.operateGroupId = operateGroupId;
}
public Integer getOperateGroupId()
public Long getOperateGroupId()
{
return operateGroupId;
}
public void setOperateElementId(Integer operateElementId)
public void setOperateElementId(Long operateElementId)
{
this.operateElementId = operateElementId;
}
public Integer getOperateElementId()
public Long getOperateElementId()
{
return operateElementId;
}
@@ -255,12 +255,12 @@ public class UiSceneSteps extends BaseEntity
{
return inputValue;
}
public void setWindowSize(Integer windowSize)
public void setWindowSize(String windowSize)
{
this.windowSize = windowSize;
}
public Integer getWindowSize()
public String getWindowSize()
{
return windowSize;
}

View File

@@ -68,7 +68,7 @@ public class UiSceneStepsQO extends BaseEntity
private String inputValue;
/** 窗口尺寸 */
private Integer windowSize;
private String windowSize;
/** 子选项 */
private String subOptions;

View File

@@ -190,6 +190,7 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
uiAutomation.setStatus("1"); //未开始
uiAutomation.setDutyBy(SecurityUtils.getUsername());
uiAutomation.setDelFlag(0);
uiAutomation.setCrontabStatus(0); //未开启
uiAutomationMapper.insertUiAutomation(uiAutomation);
Long automationId = uiAutomation.getId();
//新增场景步骤

View File

@@ -1,32 +1,26 @@
package com.test.test.service.impl;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import com.test.common.config.TestConfig;
import com.test.common.utils.DateUtils;
import com.test.common.utils.SecurityUtils;
import com.test.common.utils.SeleniumUtils;
import com.test.common.utils.StringUtils;
import com.test.test.domain.UiAutomation;
import com.test.test.domain.UiReport;
import com.test.test.domain.UiSceneSteps;
import com.test.test.domain.UiSceneStepsReport;
import com.test.test.domain.*;
import com.test.test.domain.qo.OtherSettingsQO;
import com.test.test.domain.vo.UiHighSettingVO;
import com.test.test.mapper.UiAutomationMapper;
import com.test.test.mapper.UiSceneStepsMapper;
import com.test.test.mapper.UiSceneStepsReportMapper;
import com.test.test.service.IUiAutomationService;
import com.test.test.service.IUiReportService;
import com.test.test.service.IUiSceneStepsService;
import com.test.test.service.StepExecution;
import com.test.test.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -46,18 +40,12 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
private UiSceneStepsReportMapper uiSceneStepsReportMapper;
@Resource
private IUiAutomationService uiAutomationService;
//场景成功数
private Integer scenesSucceedNumber = 0;
//场景失败数
private Integer scenesErrorNumber = 0;
//场景未执行数
private Integer scenesNotNumber = 0;
//步骤成功数
private Integer stepsSucceedNumber = 0;
//步骤失败数
private Integer stepsErrorNumber = 0;
//步骤未执行数
private Integer stepsNotNumber = 0;
@Resource
private IUiElementService uiElementService;
@Resource
private UiAutomationMapper uiAutomationMapper;
/**
@@ -72,7 +60,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
result.put("id", 0L);
// 1. 验证并获取步骤
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();
// 2. 创建执行报告
@@ -91,22 +86,48 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
// 3. 执行所有步骤
executeAllSteps(steps, reportId);
log.info("场景执行成功: {}", automationId);
scenesSucceedNumber++;
uiReport.setConsoleStr("OK");
uiReport.setStatus(3);
} catch (IllegalArgumentException e) {
result.put("msg", e.getMessage());
log.error("场景执行失败: {}", e.getMessage());
scenesErrorNumber++;
uiReport.setConsoleStr(e.toString());
uiReport.setStatus(2);
uiAutomation.setExecutionResult("2");
} finally {
endTime = DateUtils.getNowDate();
uiReport.setTake(DateUtils.calculateTimeDifference(startTime, 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.setScenesErrorNumber(scenesErrorNumber);
uiReport.setScenesNotNumber(scenesNotNumber);
uiReport.setScenesNotNumber(0);
uiReport.setStepsSucceedNumber(stepsSucceedNumber);
uiReport.setStepsErrorNumber(stepsErrorNumber);
uiReport.setStepsNotNumber(stepsNotNumber);
@@ -116,6 +137,16 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
);
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;
}
@@ -128,6 +159,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
*/
private List<UiSceneSteps> validateAndGetSteps(Long automationId) {
List<UiSceneSteps> steps = uiSceneStepsMapper.selectUiSceneStepsById(automationId);
steps = steps.stream().filter(e->e.getIsDisabled() == 0).collect(Collectors.toList());
if (CollectionUtils.isEmpty(steps)) {
throw new IllegalArgumentException("步骤不能为空");
}
@@ -186,30 +218,29 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
// 定义所有操作类型的执行方法映射
Map<String, Map<String, StepExecution>> operationStrategies = Map.of(
"1", Map.of( // 浏览器操作
"1", this::openWebPage
// "2", this::closeBrowser,
// "3", this::switchWindow,
// "4", this::resizeWindow,
// "5", this::selectEmbeddedPage
"1", this::openWebPage,
"2", this::closeBrowser,
"3", this::switchWindow,
"4", this::resizeWindow,
"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);
OtherSettingsQO otherSettingsQO = otherSetting.getOtherSettingsQO();
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. 准备报告对象
UiSceneStepsReport report = new UiSceneStepsReport();
report.setId(sceneStepsReportId);
@@ -261,28 +301,42 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
Date endTime = null;
boolean continueExecution = true; // 默认继续执行
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. 执行具体步骤
stepExecution.execute(step, seleniumUtils);
// 执行后置等待
if (afterAwaitTime > 0) {
log.info("执行后置等待: {}ms", afterAwaitTime);
Thread.sleep(afterAwaitTime);
}
report.setLogInfo("OK");
report.setExecutionFlag("1");
} catch (Exception e) {
// 4. 错误处理
stepsErrorNumber++;
stepsSucceedNumber--;
report.setLogInfo(e.toString());
report.setExecutionFlag("2");
// 根据错误处理设置决定是否继续
if ("1".equals(errorSetting.getErrorHandling())) {
continueExecution = false; // 不继续执行后续步骤
}
if (screenshotConfiguration == 2) {
report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
}
log.error("步骤执行失败: {}", e.getMessage());
} finally {
endTime = DateUtils.getNowDate();
stepsNotNumber--;
// 更新报告
report.setCreateTime(startTime);
report.setUpdateTime(endTime);
@@ -293,6 +347,52 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
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
@@ -305,6 +405,9 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
.orElse(new UiHighSettingVO()); // 返回默认设置
}
/**
* 提取错误处理设置
* @param settings
@@ -317,6 +420,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
.orElse(new UiHighSettingVO()); // 返回默认设置
}
//---------------------浏览器操作---------------------------
/**
* 打开网页
*
@@ -324,8 +435,465 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
* @param seleniumUtils Selenium工具类
*/
private void openWebPage(UiSceneSteps step, SeleniumUtils seleniumUtils) {
log.info("打开网页:{}",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){
}
}

View File

@@ -22,10 +22,12 @@
<result property="crontabStatus" column="crontab_status" />
<result property="delFlag" column="del_flag" />
<result property="description" column="description" />
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<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>
<select id="selectUiAutomationList" parameterType="UiAutomation" resultMap="UiAutomationResult">
@@ -126,6 +128,8 @@
<if test="crontabStatus != null">crontab_status,</if>
<if test="delFlag != null">del_flag,</if>
<if test="description != null">description,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="groupId != null">#{groupId},</if>
@@ -144,6 +148,8 @@
<if test="crontabStatus != null">#{crontabStatus},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="description != null">#{description},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
</trim>
</insert>
@@ -166,6 +172,8 @@
<if test="crontabStatus != null">crontab_status = #{crontabStatus},</if>
<if test="delFlag != null">del_flag = #{delFlag},</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>
where id = #{id}
</update>