feat(接口测试): 新增导入更新加操作记录
--story=1011790 --user=郭雨琦 https://www.tapd.cn/55049933/prong/stories/view/1155049933001011790
This commit is contained in:
parent
0008fb5e74
commit
0368daed51
|
@ -4,6 +4,8 @@ import io.metersphere.api.dto.ApiTestImportRequest;
|
|||
import io.metersphere.api.dto.mock.config.MockConfigImportDTO;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||
import io.metersphere.base.mapper.OperatingLogMapper;
|
||||
import io.metersphere.base.mapper.OperatingLogResourceMapper;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -19,14 +21,11 @@ public class ApiDefinitionImportParamDTO {
|
|||
private List<ApiTestCaseWithBLOBs> caseList;
|
||||
|
||||
private List<ApiDefinitionWithBLOBs> repeatList;
|
||||
private String importType;
|
||||
private String scheduleId;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public ApiDefinitionImportParamDTO() {
|
||||
}
|
||||
private OperatingLogMapper operatingLogMapper;
|
||||
private OperatingLogResourceMapper operatingLogResourceMapper;
|
||||
|
||||
public ApiDefinitionImportParamDTO(ApiDefinitionWithBLOBs apiDefinition, ApiTestImportRequest apiTestImportRequest, List<MockConfigImportDTO> mocks, List<ApiDefinitionWithBLOBs> updateList, List<ApiTestCaseWithBLOBs> caseList) {
|
||||
this.apiDefinition = apiDefinition;
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
|||
import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.commons.constants.ElementConstants;
|
||||
import io.metersphere.log.utils.ApiDefinitionDiffUtil;
|
||||
import io.metersphere.log.utils.ReflexObjectUtil;
|
||||
|
@ -17,6 +18,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -94,11 +96,12 @@ public class ApiTestDefinitionDiffUtilImpl implements ApiDefinitionDiffUtil {
|
|||
|
||||
private static void diffHttp(MsHTTPSamplerProxy httpNew, MsHTTPSamplerProxy httpOld, JsonDiff jsonDiff, Map<String, String> diffMap) {
|
||||
// 请求头对比 old/new
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getHeaders()) && CollectionUtils.isNotEmpty(httpOld.getHeaders())) {
|
||||
httpNew.getHeaders().remove(httpNew.getHeaders().size() - 1);
|
||||
httpOld.getHeaders().remove(httpOld.getHeaders().size() - 1);
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getHeaders())) {
|
||||
removeSpaceName(httpNew.getHeaders());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(httpOld.getHeaders())) {
|
||||
removeSpaceName(httpOld.getHeaders());
|
||||
}
|
||||
|
||||
String headerNew = StringUtils.join(JSON_START, JSON.toJSONString(httpNew.getHeaders()), JSON_END);
|
||||
String headerOld = StringUtils.join(JSON_START, JSON.toJSONString(httpOld.getHeaders()), JSON_END);
|
||||
if (!StringUtils.equals(headerNew, headerOld)) {
|
||||
|
@ -109,9 +112,11 @@ public class ApiTestDefinitionDiffUtilImpl implements ApiDefinitionDiffUtil {
|
|||
}
|
||||
}
|
||||
// 对比QUERY参数
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getArguments()) && CollectionUtils.isNotEmpty(httpOld.getArguments())) {
|
||||
httpNew.getArguments().remove(httpNew.getArguments().size() - 1);
|
||||
httpOld.getArguments().remove(httpOld.getArguments().size() - 1);
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getArguments())) {
|
||||
removeSpaceName(httpNew.getArguments());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(httpOld.getArguments())) {
|
||||
removeSpaceName(httpOld.getArguments());
|
||||
}
|
||||
String queryNew = StringUtils.join(JSON_START, JSON.toJSONString(httpNew.getArguments()), JSON_END);
|
||||
String queryOld = StringUtils.join(JSON_START, JSON.toJSONString(httpOld.getArguments()), JSON_END);
|
||||
|
@ -123,9 +128,11 @@ public class ApiTestDefinitionDiffUtilImpl implements ApiDefinitionDiffUtil {
|
|||
}
|
||||
}
|
||||
// 对比REST参数
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getRest()) && CollectionUtils.isNotEmpty(httpOld.getRest())) {
|
||||
httpNew.getRest().remove(httpNew.getRest().size() - 1);
|
||||
httpOld.getRest().remove(httpOld.getRest().size() - 1);
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getRest())) {
|
||||
removeSpaceName(httpNew.getRest());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(httpOld.getRest())) {
|
||||
removeSpaceName(httpOld.getRest());
|
||||
}
|
||||
String restNew = StringUtils.join(JSON_START, JSON.toJSONString(httpNew.getRest()), JSON_END);
|
||||
String restOld = StringUtils.join(JSON_START, JSON.toJSONString(httpOld.getRest()), JSON_END);
|
||||
|
@ -142,21 +149,23 @@ public class ApiTestDefinitionDiffUtilImpl implements ApiDefinitionDiffUtil {
|
|||
String bodyOld = JSON.toJSONString(httpOld.getBody());
|
||||
if (!StringUtils.equals(bodyNew, bodyOld)) {
|
||||
String patch = jsonDiff.diff(bodyOld, bodyNew);
|
||||
String diff = jsonDiff.apply(bodyNew, patch);
|
||||
String diff = jsonDiff.apply(bodyOld, patch);
|
||||
if (StringUtils.isNotEmpty(diff)) {
|
||||
diffMap.put(BODY, diff);
|
||||
}
|
||||
}
|
||||
// 对比BODY-FORM参数
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getBody().getKvs()) && CollectionUtils.isNotEmpty(httpOld.getBody().getKvs())) {
|
||||
httpNew.getBody().getKvs().remove(httpNew.getBody().getKvs().size() - 1);
|
||||
httpOld.getBody().getKvs().remove(httpOld.getBody().getKvs().size() - 1);
|
||||
if (CollectionUtils.isNotEmpty(httpNew.getBody().getKvs())) {
|
||||
removeSpaceName(httpNew.getBody().getKvs());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(httpOld.getBody().getKvs())) {
|
||||
removeSpaceName(httpOld.getBody().getKvs());
|
||||
}
|
||||
String bodyFormNew = StringUtils.join(JSON_START, JSON.toJSONString(httpNew.getBody().getKvs()), JSON_END);
|
||||
String bodyFormOld = StringUtils.join(JSON_START, JSON.toJSONString(httpOld.getBody().getKvs()), JSON_END);
|
||||
if (!StringUtils.equals(bodyFormNew, bodyFormOld)) {
|
||||
String patch = jsonDiff.diff(bodyFormOld, bodyFormNew);
|
||||
String diff = jsonDiff.apply(bodyFormNew, patch);
|
||||
String diff = jsonDiff.apply(bodyFormOld, patch);
|
||||
if (StringUtils.isNotEmpty(diff)) {
|
||||
diffMap.put(BODY_FORM, diff);
|
||||
}
|
||||
|
@ -194,6 +203,16 @@ public class ApiTestDefinitionDiffUtilImpl implements ApiDefinitionDiffUtil {
|
|||
}
|
||||
}
|
||||
|
||||
private static void removeSpaceName(List<KeyValue> keyValues) {
|
||||
Iterator<KeyValue> iterator = keyValues.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
KeyValue next = iterator.next();
|
||||
if (StringUtils.isBlank(next.getName())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void diffHttpResponse(JSONObject httpNew, JSONObject httpOld, JsonDiff jsonDiff, Map<String, String> diffMap) {
|
||||
// 请求头对比 old/new
|
||||
if (httpNew.get(HEADS) != null && httpOld.get(HEADS) != null) {
|
||||
|
|
|
@ -8,20 +8,22 @@ import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
|||
import io.metersphere.api.dto.mock.config.MockConfigImportDTO;
|
||||
import io.metersphere.api.parse.api.ApiDefinitionImport;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiDefinitionMapper;
|
||||
import io.metersphere.base.mapper.ApiModuleMapper;
|
||||
import io.metersphere.base.mapper.ApiTestCaseMapper;
|
||||
import io.metersphere.base.mapper.ProjectMapper;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.BaseProjectVersionMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
|
||||
import io.metersphere.commons.constants.*;
|
||||
import io.metersphere.commons.enums.ApiTestDataStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.dto.ProjectConfig;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.log.utils.ReflexObjectUtil;
|
||||
import io.metersphere.log.vo.DetailColumn;
|
||||
import io.metersphere.log.vo.OperatingLogDetails;
|
||||
import io.metersphere.log.vo.api.DefinitionReference;
|
||||
import io.metersphere.notice.sender.NoticeModel;
|
||||
import io.metersphere.notice.service.NoticeSendService;
|
||||
import io.metersphere.service.BaseProjectApplicationService;
|
||||
|
@ -36,6 +38,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONObject;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -76,6 +79,8 @@ public class ApiDefinitionImportUtilService {
|
|||
private ApiTestCaseService apiTestCaseService;
|
||||
@Resource
|
||||
private BaseUserService baseUserService;
|
||||
@Resource
|
||||
private ScheduleMapper scheduleMapper;
|
||||
|
||||
|
||||
public void checkUrl(ApiTestImportRequest request, Project project) {
|
||||
|
@ -198,7 +203,8 @@ public class ApiDefinitionImportUtilService {
|
|||
ApiDefinitionMapper batchMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
|
||||
ExtApiDefinitionMapper extApiDefinitionMapper = sqlSession.getMapper(ExtApiDefinitionMapper.class);
|
||||
ApiModuleMapper apiModuleMapper = sqlSession.getMapper(ApiModuleMapper.class);
|
||||
|
||||
OperatingLogMapper operatingLogMapper = sqlSession.getMapper(OperatingLogMapper.class);
|
||||
OperatingLogResourceMapper operatingLogResourceMapper = sqlSession.getMapper(OperatingLogResourceMapper.class);
|
||||
//系统内需要做更新操作的数据
|
||||
List<ApiDefinitionWithBLOBs> toUpdateList = new ArrayList<>();
|
||||
//与当前导入接口重复的系统内所有数据
|
||||
|
@ -275,6 +281,10 @@ public class ApiDefinitionImportUtilService {
|
|||
|
||||
ApiDefinitionImportParamDTO apiDefinitionImportParam = new ApiDefinitionImportParamDTO(item, request, apiImport.getMocks(), toUpdateList, caseList);
|
||||
apiDefinitionImportParam.setRepeatList(sameRefIds);
|
||||
apiDefinitionImportParam.setImportType(request.getType());
|
||||
apiDefinitionImportParam.setScheduleId(request.getResourceId());
|
||||
apiDefinitionImportParam.setOperatingLogMapper(operatingLogMapper);
|
||||
apiDefinitionImportParam.setOperatingLogResourceMapper(operatingLogResourceMapper);
|
||||
ApiImportSendNoticeDTO apiImportSendNoticeDTO = importCreate(batchMapper, apiDefinitionImportParam);
|
||||
if (apiImportSendNoticeDTO != null) {
|
||||
apiImportSendNoticeDTOS.add(apiImportSendNoticeDTO);
|
||||
|
@ -1267,6 +1277,8 @@ public class ApiDefinitionImportUtilService {
|
|||
apiDefinition.setOrder(existApi.getOrder());
|
||||
reSetImportMocksApiId(mocks, originId, apiDefinition.getId(), apiDefinition.getNum());
|
||||
batchMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
|
||||
//记录导入使得数据产生变更的操作记录
|
||||
setOperatingLog(existApi, apiDefinition, apiDefinitionImportParamDTO);
|
||||
ApiDefinitionResult apiDefinitionResult = ApiDefinitionImportUtil.getApiDefinitionResult(apiDefinition, true);
|
||||
apiImportSendNoticeDTO.setApiDefinitionResult(apiDefinitionResult);
|
||||
List<ApiTestCaseDTO> apiTestCaseDTOS = importCase(apiDefinition, caseList);
|
||||
|
@ -1279,6 +1291,58 @@ public class ApiDefinitionImportUtilService {
|
|||
return apiImportSendNoticeDTO;
|
||||
}
|
||||
|
||||
private void setOperatingLog(ApiDefinitionWithBLOBs existApi, ApiDefinitionWithBLOBs apiDefinition, ApiDefinitionImportParamDTO apiDefinitionImportParamDTO) {
|
||||
OperatingLogWithBLOBs msOperLog = new OperatingLogWithBLOBs();
|
||||
msOperLog.setId(UUID.randomUUID().toString());
|
||||
msOperLog.setProjectId(existApi.getProjectId());
|
||||
msOperLog.setOperTitle(existApi.getName());
|
||||
msOperLog.setOperType(OperLogConstants.UPDATE.toString());
|
||||
setOperAndCreateUser(apiDefinitionImportParamDTO, msOperLog);
|
||||
msOperLog.setOperModule(OperLogModule.API_DEFINITION);
|
||||
msOperLog.setOperMethod("io.metersphere.api.controller.ApiDefinitionController.testCaseImport");
|
||||
msOperLog.setOperPath("/api/definition/import");
|
||||
OperatingLogDetails newDetails = getOperatingLogDetails(existApi, apiDefinition);
|
||||
msOperLog.setOperContent(JSON.toJSONString(newDetails));
|
||||
msOperLog.setCreateUser(newDetails.getCreateUser());
|
||||
msOperLog.setOperTime(System.currentTimeMillis());
|
||||
OperatingLogResource operatingLogResource = new OperatingLogResource();
|
||||
operatingLogResource.setOperatingLogId(msOperLog.getId());
|
||||
operatingLogResource.setId(UUID.randomUUID().toString());
|
||||
operatingLogResource.setSourceId(existApi.getId());
|
||||
apiDefinitionImportParamDTO.getOperatingLogResourceMapper().insert(operatingLogResource);
|
||||
apiDefinitionImportParamDTO.getOperatingLogMapper().insert(msOperLog);
|
||||
}
|
||||
|
||||
private void setOperAndCreateUser(ApiDefinitionImportParamDTO apiDefinitionImportParamDTO, OperatingLogWithBLOBs msOperLog) {
|
||||
if (StringUtils.equals(apiDefinitionImportParamDTO.getImportType(), SCHEDULE)) {
|
||||
ScheduleExample schedule = new ScheduleExample();
|
||||
schedule.createCriteria().andResourceIdEqualTo(apiDefinitionImportParamDTO.getScheduleId());
|
||||
List<Schedule> list = scheduleMapper.selectByExample(schedule);
|
||||
if (list.size() > 0) {
|
||||
User user = baseUserService.getUserDTO(list.get(0).getUserId());
|
||||
msOperLog.setOperUser(user.getName() + Translator.get("timing_synchronization"));
|
||||
msOperLog.setCreateUser(user.getId());
|
||||
} else {
|
||||
msOperLog.setOperUser(Translator.get("timing_synchronization"));
|
||||
}
|
||||
} else {
|
||||
SessionUser user = SessionUtils.getUser();
|
||||
msOperLog.setOperUser(user.getName() + Translator.get("import_file"));
|
||||
msOperLog.setCreateUser(user.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static OperatingLogDetails getOperatingLogDetails(ApiDefinitionWithBLOBs existApi, ApiDefinitionWithBLOBs apiDefinition) {
|
||||
List<DetailColumn> oldColumns = ReflexObjectUtil.getColumns(existApi, DefinitionReference.definitionColumns);
|
||||
OperatingLogDetails oldDetails = new OperatingLogDetails(JSON.toJSONString(existApi.getId()), existApi.getProjectId(), existApi.getName(), existApi.getCreateUser(), oldColumns);
|
||||
List<DetailColumn> newColumns = ReflexObjectUtil.getColumns(apiDefinition, DefinitionReference.definitionColumns);
|
||||
OperatingLogDetails newDetails = new OperatingLogDetails(JSON.toJSONString(apiDefinition.getId()), apiDefinition.getProjectId(), apiDefinition.getName(), apiDefinition.getCreateUser(), newColumns);
|
||||
List<DetailColumn> columns = ReflexObjectUtil.compared(oldDetails, newDetails, OperLogModule.API_DEFINITION);
|
||||
newDetails.setColumns(columns);
|
||||
return newDetails;
|
||||
}
|
||||
|
||||
|
||||
private static List<ApiTestCaseWithBLOBs> setRequestAndAddNewCase(ApiDefinitionWithBLOBs apiDefinition, List<ApiTestCaseWithBLOBs> caseList, boolean newCreate) {
|
||||
boolean createCase = false;
|
||||
|
|
|
@ -129,7 +129,9 @@ public class OperatingLogService {
|
|||
if (CollectionUtils.isEmpty(logWithBLOB.getDetails().getColumns())) {
|
||||
dtos.add(logWithBLOB);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(logWithBLOB.getUserName()) && StringUtils.isNotBlank(logWithBLOB.getOperUser())) {
|
||||
logWithBLOB.setUserName(logWithBLOB.getOperUser());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(dtos)) {
|
||||
|
|
|
@ -340,7 +340,7 @@ public class JsonDiff {
|
|||
if (childKey.startsWith("-")) {
|
||||
instruction.key = childKey.substring(1);
|
||||
//如果是删除多列 diff数据的key都是-1 ,会把数据给覆盖,所以这里 ke+下标 做新的index
|
||||
instruction.index = isIndexed(instruction.key) == 1 ? isIndexed(instruction.key) + i : isIndexed(instruction.key);
|
||||
instruction.index = isIndexed(instruction.key) == 1 ? isIndexed(instruction.key) : isIndexed(instruction.key) + i;
|
||||
instruction.oper = Oper.DELETE;
|
||||
} else if (childKey.startsWith("+")) {
|
||||
instruction.key = childKey.substring(1);
|
||||
|
|
|
@ -134,7 +134,7 @@ class Leaf implements Comparable<Leaf> {
|
|||
String key = child.parent.toString();
|
||||
String reIndexedKey = key;
|
||||
if (child.parent instanceof ArrNode) {
|
||||
((ArrNode) child.parent).index = i - deletes;
|
||||
//((ArrNode) child.parent).index = i - deletes;
|
||||
reIndexedKey = child.parent.toString();
|
||||
}
|
||||
JzonObject insert = factory.createJsonObject();
|
||||
|
|
|
@ -88,6 +88,8 @@ illegal_xml_format=illegal XML format
|
|||
api_report_is_null="Report is null, can't update"
|
||||
api_test_environment_already_exists="Api test environment already exists"
|
||||
api_test=API Test
|
||||
import_file=Import File
|
||||
timing_synchronization=Timing Synchronization
|
||||
#test case
|
||||
test_case_node_level=level
|
||||
test_case_node_level_tip=The node tree maximum depth is
|
||||
|
|
|
@ -88,6 +88,8 @@ illegal_xml_format=不合法的 XML 格式
|
|||
api_report_is_null="测试报告是未生成,无法更新"
|
||||
api_test_environment_already_exists="已存在该名称的环境配置"
|
||||
api_test=接口测试
|
||||
import_file=文件导入
|
||||
timing_synchronization=定时同步
|
||||
#test case
|
||||
test_case_node_level=层
|
||||
test_case_node_level_tip=模块树最大深度为
|
||||
|
|
|
@ -88,6 +88,8 @@ illegal_xml_format=不合法的 XML 格式
|
|||
api_report_is_null="測試報告是未生成,無法更新"
|
||||
api_test_environment_already_exists="已存在該名稱的環境配置"
|
||||
api_test=接口測試
|
||||
import_file=文件導入
|
||||
timing_synchronization=定時同步
|
||||
#test case
|
||||
test_case_node_level=層
|
||||
test_case_node_level_tip=模塊樹最大深度為
|
||||
|
|
Loading…
Reference in New Issue