feat(接口测试): 接口自动化场景导出再导入保留引用关系支持跨空间补充数据

--user=郭雨琦
接口自动化场景导出再导入保留引用关系 场景导入导出跨空间,增加数据
https://www.tapd.cn/55049933/prong/stories/view/1155049933001003780
This commit is contained in:
guoyuqi 2022-02-25 19:15:15 +08:00 committed by 刘瑞斌
parent 2f7f2ecf3d
commit de26483f74
12 changed files with 402 additions and 130 deletions

View File

@ -1,16 +1,28 @@
package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.automation.ApiScenarioModuleDTO;
import io.metersphere.api.dto.definition.ApiDefinitionRequest;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.SaveApiTestCaseRequest;
import io.metersphere.api.dto.definition.parse.ms.NodeTree;
import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiScenarioModuleService;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.service.ProjectService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Iterator;
import java.util.List;
import java.util.*;
public class ApiScenarioImportUtil {
@ -106,4 +118,189 @@ public class ApiScenarioImportUtil {
}
}
public static boolean checkWorkSpace(String projectId, String currentProjectId) {
if(!Objects.equals(projectId, currentProjectId)){
ProjectService projectService = CommonBeanFactory.getBean(ProjectService.class);
Project project = projectService.getProjectById(projectId);
return Objects.equals(project.getWorkspaceId(), SessionUtils.getCurrentWorkspaceId());
}
return true;
}
private static ApiDefinitionResult getApiDefinitionResult(JSONObject object, ApiDefinitionService apiDefinitionService) {
ApiDefinitionRequest apiDefinitionRequest = new ApiDefinitionRequest();
apiDefinitionRequest.setPath(object.getString("path"));
apiDefinitionRequest.setMethod(object.getString("method"));
apiDefinitionRequest.setPath(object.getString("protocol"));
return apiDefinitionService.getApiDefinitionResult(apiDefinitionRequest);
}
private static ApiTestCaseWithBLOBs getApiTestCase(JSONObject object, ApiTestCaseService testCaseService, ApiDefinitionResult apiDefinitionResult) {
SaveApiTestCaseRequest request = new SaveApiTestCaseRequest();
request.setName(object.getString("name"));
request.setApiDefinitionId(apiDefinitionResult.getId());
return testCaseService.getSameCaseWithBLOBs(request);
}
public static void checkCase(JSONObject object, String versionId, String projectId, ApiTestCaseMapper apiTestCaseMapper, ApiDefinitionMapper apiDefinitionMapper) {
ApiTestCaseService testCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ApiTestCaseWithBLOBs bloBs = testCaseService.get(object.getString("id"));
if (bloBs != null) {
boolean isSameWorkSpace = checkWorkSpace(bloBs.getProjectId(),projectId);
if(!isSameWorkSpace){
ApiDefinitionResult apiDefinition = apiDefinitionService.getById(bloBs.getApiDefinitionId());
String apiDefinitionId = checkDefinition(apiDefinitionService,apiDefinition, versionId,projectId,apiDefinitionMapper);
structureCaseData(bloBs,apiDefinitionId,versionId,projectId,apiTestCaseMapper);
object.put("projectId", projectId);
object.put("id", bloBs.getId());
}
}else{
ApiDefinitionResult apiDefinition = getApiDefinitionResult(object,apiDefinitionService);
ApiTestCaseWithBLOBs testCase;
if(apiDefinition!=null){
testCase= getApiTestCase(object, testCaseService, apiDefinition);
if (testCase != null) {
boolean isSameWorkSpace = checkWorkSpace(testCase.getProjectId(),projectId);
if(!isSameWorkSpace){
String apiDefinitionId = checkDefinition(apiDefinitionService, apiDefinition, versionId,projectId,apiDefinitionMapper);
structureCaseData(testCase,apiDefinitionId,versionId,projectId,apiTestCaseMapper);
}
}else{
String apiDefinitionId = checkDefinition(apiDefinitionService, apiDefinition, versionId,projectId,apiDefinitionMapper);
testCase= structureCaseByJson(object, versionId, projectId, apiDefinitionId,apiTestCaseMapper);
}
}else{
ApiDefinitionResult apiDefinitionResult = structureApiDefinitionByJson(apiDefinitionService, object, versionId, projectId, apiDefinitionMapper);
testCase = structureCaseByJson(object, versionId, projectId, apiDefinitionResult.getId(),apiTestCaseMapper);
}
object.put("projectId", projectId);
object.put("id", testCase.getId());
}
}
private static String checkDefinition(ApiDefinitionService apiDefinitionService, ApiDefinitionResult apiDefinition, String versionId, String projectId,ApiDefinitionMapper apiDefinitionMapper) {
boolean isSameWorkspace = checkWorkSpace(apiDefinition.getProjectId(),projectId);
if(!isSameWorkspace){
String requestStr = apiDefinition.getRequest();
JSONObject objectDefinition = JSONObject.parseObject(requestStr);
ApiDefinitionResult apiDefinitionResult1 = insertDefinitionByApiDefinition(apiDefinitionService,apiDefinition, objectDefinition, versionId, projectId,apiDefinitionMapper);
return apiDefinitionResult1.getId();
}else{
return apiDefinition.getId();
}
}
private static void structureCaseData(ApiTestCaseWithBLOBs testCase, String apiDefinitionId, String versionId, String projectId,ApiTestCaseMapper apiTestCaseMapper) {
String requestStr = testCase.getRequest();
JSONObject objectCase = JSONObject.parseObject(requestStr);
testCase.setApiDefinitionId(apiDefinitionId);
insertCaseByApiTestCase(testCase,objectCase,versionId,projectId,apiTestCaseMapper);
}
public static ApiDefinitionResult structureApiDefinitionByJson(ApiDefinitionService apiDefinitionService,JSONObject object, String versionId, String projectId,ApiDefinitionMapper apiDefinitionMapper) {
ApiDefinitionResult test = new ApiDefinitionResult();
apiDefinitionService.checkQuota();
String protocal = object.getString("protocal");
if (StringUtils.equals(protocal, "DUBBO")) {
test.setMethod("dubbo://");
}else{
test.setMethod(protocal);
}
apiDefinitionService.initModulePathAndId(projectId, test);
String id = UUID.randomUUID().toString();
test.setId(id);
test.setName(object.getString("name"));
test.setPath(object.getString("path"));
test.setCreateUser(SessionUtils.getUserId());
test.setProjectId(projectId);
test.setCreateTime(System.currentTimeMillis());
test.setUpdateTime(System.currentTimeMillis());
test.setStatus(APITestStatus.Underway.name());
test.setRefId(id);
test.setLatest(true);
test.setVersionId(versionId);
object.put("id", test.getId());
object.put("resourceId", test.getId());
object.put("projectId", projectId);
object.put("useEnvironment","");
test.setRequest(object.toJSONString());
test.setUserId(SessionUtils.getUserId());
test.setLatest(true);
test.setOrder(apiDefinitionService.getImportNextOrder(projectId));
apiDefinitionMapper.insert(test);
return test;
}
public static ApiDefinitionResult insertDefinitionByApiDefinition(ApiDefinitionService apiDefinitionService, ApiDefinitionResult apiDefinitionResult, JSONObject objectDefinition, String versionId, String projectId,ApiDefinitionMapper apiDefinitionMapper){
String id = UUID.randomUUID().toString();
apiDefinitionResult.setId(id);
apiDefinitionResult.setProjectId(projectId);
apiDefinitionResult.setVersionId(versionId);
apiDefinitionResult.setRefId(id);
apiDefinitionResult.setLatest(true);
objectDefinition.put("id", id);
objectDefinition.put("resourceId", id);
objectDefinition.put("projectId", projectId);
objectDefinition.put("useEnvironment","");
apiDefinitionService.initModulePathAndId(projectId, apiDefinitionResult);
apiDefinitionResult.setRequest(JSON.toJSONString(objectDefinition));
apiDefinitionResult.setOrder(apiDefinitionService.getImportNextOrder(projectId));
apiDefinitionMapper.insert(apiDefinitionResult);
return apiDefinitionResult;
}
public static ApiTestCaseWithBLOBs structureCaseByJson(JSONObject object, String versionId, String projectId, String apiDefinitionId,ApiTestCaseMapper apiTestCaseMapper) {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ApiTestCaseWithBLOBs apiTestCase = new ApiTestCaseWithBLOBs();
String id = UUID.randomUUID().toString();
apiTestCase.setId(id);
apiTestCase.setName(object.getString("name"));
apiTestCase.setCaseStatus(APITestStatus.Underway.name());
apiTestCase.setApiDefinitionId(apiDefinitionId);
apiTestCase.setCreateUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
apiTestCase.setUpdateUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
apiTestCase.setProjectId(projectId);
apiTestCase.setCreateTime(System.currentTimeMillis());
apiTestCase.setUpdateTime(System.currentTimeMillis());
apiTestCase.setVersionId(versionId);
object.put("id", apiTestCase.getId());
object.put("resourceId", apiTestCase.getId());
object.put("projectId", projectId);
object.put("useEnvironment","");
apiTestCase.setRequest(object.toJSONString());
apiTestCase.setOrder(apiDefinitionService.getImportNextCaseOrder(projectId));
apiTestCaseMapper.insert(apiTestCase);
return apiTestCase;
}
public static void insertCaseByApiTestCase(ApiTestCaseWithBLOBs bloBs, JSONObject objectCase, String versionId, String projectId,ApiTestCaseMapper apiTestCaseMapper){
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
String id = UUID.randomUUID().toString();
bloBs.setId(id);
bloBs.setProjectId(projectId);
bloBs.setVersionId(versionId);
objectCase.put("id", id);
objectCase.put("resourceId", id);
objectCase.put("projectId", projectId);
objectCase.put("useEnvironment","");
bloBs.setRequest(JSON.toJSONString(objectCase));
bloBs.setOrder(apiDefinitionService.getImportNextCaseOrder(projectId));
apiTestCaseMapper.insert(bloBs);
}
public static void formatHashTree(JSONArray hashTree) {
if (CollectionUtils.isNotEmpty(hashTree)) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject object = (JSONObject) hashTree.get(i);
object.put("index", i + 1);
object.put("resourceId", UUID.randomUUID().toString());
hashTree.set(i, object);
if (CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
formatHashTree(object.getJSONArray("hashTree"));
}
}
}
}
}

View File

@ -1,21 +1,15 @@
package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.EnvironmentType;
import io.metersphere.api.dto.definition.parse.ms.NodeTree;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.base.domain.*;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.api.parse.MsAbstractParser;
import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.commons.utils.CommonBeanFactory;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -66,20 +60,6 @@ public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
return scenarioWithBLOBs;
}
private void formatHashTree(JSONArray hashTree) {
if (CollectionUtils.isNotEmpty(hashTree)) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject object = (JSONObject) hashTree.get(i);
object.put("index", i + 1);
object.put("resourceId", UUID.randomUUID().toString());
hashTree.set(i, object);
if (CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
formatHashTree(object.getJSONArray("hashTree"));
}
}
}
}
private ScenarioImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
ScenarioImport scenarioImport = JSON.parseObject(testStr, ScenarioImport.class);
List<ApiScenarioWithBLOBs> data = scenarioImport.getData();
@ -102,9 +82,6 @@ public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
if (StringUtils.isNotBlank(scenarioDefinitionStr)) {
JSONObject scenarioDefinition = JSONObject.parseObject(scenarioDefinitionStr);
if (scenarioDefinition != null) {
JSONArray hashTree = scenarioDefinition.getJSONArray("hashTree");
formatHashTree(hashTree);
setCopy(hashTree);
JSONObject environmentMap = scenarioDefinition.getJSONObject("environmentMap");
if (environmentMap != null) {
scenarioDefinition.put("environmentMap", new HashMap<>());
@ -127,61 +104,18 @@ public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
// 旧版本未导出模块
parseModule(item.getModulePath(), importRequest, item);
}
// item.setId(UUID.randomUUID().toString());
item.setProjectId(this.projectId);
});
}
return scenarioImport;
}
private void setCopy(JSONArray hashTree) {
// 将引用转成复制
if (CollectionUtils.isNotEmpty(hashTree)) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject object = (JSONObject) hashTree.get(i);
String referenced = object.getString("referenced");
if (StringUtils.isNotBlank(referenced) && StringUtils.equals(referenced, "REF")) {
// 检测引用对象是否存在若果不存在则改成复制对象
String refType = object.getString("refType");
boolean isCopy = true;
if (StringUtils.isNotEmpty(refType)) {
if (refType.equals("CASE")) {
ApiTestCaseService testCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiTestCaseWithBLOBs bloBs = testCaseService.get(object.getString("id"));
if (bloBs != null) {
isCopy = false;
}
} else {
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
ApiScenarioWithBLOBs bloBs = apiAutomationService.getDto(object.getString("id"));
if (bloBs != null) {
isCopy = false;
}
}
}
if (isCopy) {
object.put("referenced", "Copy");
}
}
object.put("projectId", "");
JSONObject environmentMap = object.getJSONObject("environmentMap");
if (environmentMap != null) {
object.put("environmentMap", new HashMap<>());
}
if (CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
setCopy(object.getJSONArray("hashTree"));
}
}
}
}
protected void parseModule(String modulePath, ApiTestImportRequest importRequest, ApiScenarioWithBLOBs apiScenarioWithBLOBs) {
if (StringUtils.isEmpty(modulePath)) {
return;
}
if (modulePath.startsWith("/")) {
modulePath = modulePath.substring(1, modulePath.length());
modulePath = modulePath.substring(1);
}
if (modulePath.endsWith("/")) {
modulePath = modulePath.substring(0, modulePath.length() - 1);

View File

@ -23,6 +23,8 @@ public class ApiDefinitionRequest extends BaseQueryRequest {
private String reviewId;
private String refId;
private String versionId;
private String path;
private String method;
// 测试计划是否允许重复
private boolean repeatCase;

View File

@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.*;
import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.automation.parse.ApiScenarioImportUtil;
import io.metersphere.api.dto.automation.parse.ScenarioImport;
import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
@ -240,7 +241,14 @@ public class ApiAutomationService {
request.setCustomNum(String.valueOf(nextNum));
}
checkScenarioNum(request);
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiTestCaseMapper apiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ApiDefinitionMapper apiDefinitionMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request,apiTestCaseMapper,apiDefinitionMapper);
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
scenario.setVersion(0);
scenario.setCreateTime(System.currentTimeMillis());
@ -346,7 +354,16 @@ public class ApiAutomationService {
//如果场景有TCP步骤的话也要做参数计算处理
tcpApiParamService.checkTestElement(request.getScenarioDefinition());
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request);
//检查是否要增加引用的步骤的CASE类型的数据
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiTestCaseMapper apiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ApiDefinitionMapper apiDefinitionMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request,apiTestCaseMapper,apiDefinitionMapper);
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
ApiScenarioWithBLOBs beforeScenario = apiScenarioMapper.selectByPrimaryKey(request.getId());
Integer version = beforeScenario.getVersion();
@ -387,6 +404,8 @@ public class ApiAutomationService {
extScheduleMapper.updateNameByResourceID(request.getId(), request.getName());// 修改场景name同步到修改首页定时任务
uploadFiles(request, bodyFiles, scenarioFiles);
// 存储依赖关系
ApiAutomationRelationshipEdgeService relationshipEdgeService = CommonBeanFactory.getBean(ApiAutomationRelationshipEdgeService.class);
if (relationshipEdgeService != null) {
@ -396,6 +415,19 @@ public class ApiAutomationService {
return scenario;
}
private void checkReferenceCase(ApiScenarioWithBLOBs scenario,ApiTestCaseMapper apiTestCaseMapper,ApiDefinitionMapper apiDefinitionMapper) {
if (scenario == null || StringUtils.isEmpty(scenario.getScenarioDefinition())) {
return;
}
if (scenario.getScenarioDefinition().contains("\"referenced\":\"REF\"")) {
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
JSONArray hashTree = element.getJSONArray("hashTree");
ApiScenarioImportUtil.formatHashTree(hashTree);
setReferenced(hashTree,scenario.getVersionId(),scenario.getProjectId(),apiTestCaseMapper,apiDefinitionMapper);
scenario.setScenarioDefinition(JSONObject.toJSONString(element));
}
}
private void checkAndSetLatestVersion(String refId) {
extApiScenarioMapper.clearLatestVersion(refId);
extApiScenarioMapper.addLatestVersion(refId);
@ -424,7 +456,7 @@ public class ApiAutomationService {
.map(MsHTTPSamplerProxy::getId).collect(Collectors.toSet());
}
public ApiScenarioWithBLOBs buildSaveScenario(SaveApiScenarioRequest request) {
public ApiScenarioWithBLOBs buildSaveScenario(SaveApiScenarioRequest request,ApiTestCaseMapper apiTestCaseMapper,ApiDefinitionMapper apiDefinitionMapper) {
ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
scenario.setId(request.getId());
scenario.setName(request.getName());
@ -473,6 +505,7 @@ public class ApiAutomationService {
} else {
scenario.setVersionId(request.getVersionId());
}
checkReferenceCase(scenario,apiTestCaseMapper,apiDefinitionMapper);
return scenario;
}
@ -1112,7 +1145,7 @@ public class ApiAutomationService {
}
private void _importCreate(List<ApiScenarioWithBLOBs> sameRequest, ApiScenarioMapper batchMapper, ExtApiScenarioMapper extApiScenarioMapper,
ApiScenarioWithBLOBs scenarioWithBLOBs, ApiTestImportRequest apiTestImportRequest) {
ApiScenarioWithBLOBs scenarioWithBLOBs, ApiTestImportRequest apiTestImportRequest,ApiTestCaseMapper apiTestCaseMapper, ApiDefinitionMapper apiDefinitionMapper) {
if (CollectionUtils.isEmpty(sameRequest)) {
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
List<ApiMethodUrlDTO> useUrl = this.parseUrl(scenarioWithBLOBs);
@ -1126,6 +1159,7 @@ public class ApiAutomationService {
scenarioWithBLOBs.setVersionId(apiTestImportRequest.getDefaultVersion());
}
scenarioWithBLOBs.setLatest(true);
checkReferenceCase(scenarioWithBLOBs,apiTestCaseMapper,apiDefinitionMapper);
batchMapper.insert(scenarioWithBLOBs);
apiScenarioReferenceIdService.saveByApiScenario(scenarioWithBLOBs);
} else {
@ -1156,6 +1190,7 @@ public class ApiAutomationService {
scenarioWithBLOBs.setUseUrl(JSONArray.toJSONString(useUrl));
batchMapper.updateByPrimaryKeyWithBLOBs(scenarioWithBLOBs);
}
checkReferenceCase(scenarioWithBLOBs,apiTestCaseMapper,apiDefinitionMapper);
apiScenarioReferenceIdService.saveByApiScenario(scenarioWithBLOBs);
extApiScenarioMapper.clearLatestVersion(scenarioWithBLOBs.getRefId());
extApiScenarioMapper.addLatestVersion(scenarioWithBLOBs.getRefId());
@ -1163,7 +1198,7 @@ public class ApiAutomationService {
}
private ApiScenarioWithBLOBs importCreate(ApiScenarioWithBLOBs request, ApiScenarioMapper batchMapper, ExtApiScenarioMapper extApiScenarioMapper,
ApiTestImportRequest apiTestImportRequest) {
ApiTestImportRequest apiTestImportRequest,ApiTestCaseMapper apiTestCaseMapper, ApiDefinitionMapper apiDefinitionMapper) {
final ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
BeanUtils.copyBean(scenarioWithBLOBs, request);
scenarioWithBLOBs.setCreateTime(System.currentTimeMillis());
@ -1212,7 +1247,7 @@ public class ApiAutomationService {
}
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
_importCreate(sameRequest, batchMapper, extApiScenarioMapper, scenarioWithBLOBs, apiTestImportRequest);
_importCreate(sameRequest, batchMapper, extApiScenarioMapper, scenarioWithBLOBs, apiTestImportRequest,apiTestCaseMapper,apiDefinitionMapper);
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
if (CollectionUtils.isEmpty(sameRequest)) {
List<ApiMethodUrlDTO> useUrl = this.parseUrl(scenarioWithBLOBs);
@ -1226,8 +1261,8 @@ public class ApiAutomationService {
scenarioWithBLOBs.setVersionId(apiTestImportRequest.getDefaultVersion());
}
scenarioWithBLOBs.setLatest(true);
checkReferenceCase(scenarioWithBLOBs,apiTestCaseMapper,apiDefinitionMapper);
batchMapper.insert(scenarioWithBLOBs);
// 存储依赖关系
ApiAutomationRelationshipEdgeService relationshipEdgeService = CommonBeanFactory.getBean(ApiAutomationRelationshipEdgeService.class);
if (relationshipEdgeService != null) {
@ -1237,7 +1272,7 @@ public class ApiAutomationService {
}
} else {
_importCreate(sameRequest, batchMapper, extApiScenarioMapper, scenarioWithBLOBs, apiTestImportRequest);
_importCreate(sameRequest, batchMapper, extApiScenarioMapper, scenarioWithBLOBs, apiTestImportRequest,apiTestCaseMapper,apiDefinitionMapper);
}
return scenarioWithBLOBs;
}
@ -1246,6 +1281,8 @@ public class ApiAutomationService {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioMapper batchMapper = sqlSession.getMapper(ApiScenarioMapper.class);
ExtApiScenarioMapper extApiScenarioMapper = sqlSession.getMapper(ExtApiScenarioMapper.class);
ApiTestCaseMapper apiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ApiDefinitionMapper apiDefinitionMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
List<ApiScenarioWithBLOBs> data = apiImport.getData();
currentScenarioOrder.remove();
int num = 0;
@ -1283,7 +1320,7 @@ public class ApiAutomationService {
item.setId(UUID.randomUUID().toString());
}
// 导入之后刷新latest
importCreate(item, batchMapper, extApiScenarioMapper, request);
importCreate(item, batchMapper, extApiScenarioMapper, request,apiTestCaseMapper,apiDefinitionMapper);
if (i % 300 == 0) {
sqlSession.flushStatements();
}
@ -1571,7 +1608,6 @@ public class ApiAutomationService {
return urlList;
}
public ScenarioEnv getApiScenarioProjectId(String id) {
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(id);
ScenarioEnv scenarioEnv = new ScenarioEnv();
@ -1953,4 +1989,45 @@ public class ApiAutomationService {
});
return strings;
}
private void setReferenced(JSONArray hashTree,String versionId,String projectId, ApiTestCaseMapper apiTestCaseMapper,ApiDefinitionMapper apiDefinitionMapper) {
// 将引用转成复制
if (CollectionUtils.isNotEmpty(hashTree)) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject object = (JSONObject) hashTree.get(i);
String referenced = object.getString("referenced");
if (StringUtils.isNotBlank(referenced) && StringUtils.equals(referenced, "REF")) {
// 检测引用对象是否存在若果不存在则改成复制对象
String refType = object.getString("refType");
if (StringUtils.isNotEmpty(refType)) {
if (refType.equals("CASE")) {
ApiScenarioImportUtil.checkCase(object,versionId,projectId,apiTestCaseMapper,apiDefinitionMapper);
} else {
checkAutomation(object,projectId);
}
}else{
object.put("referenced", "Copy");
}
}
JSONObject environmentMap = object.getJSONObject("environmentMap");
if (environmentMap != null) {
object.put("environmentMap", new HashMap<>());
}
if (CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
setReferenced(object.getJSONArray("hashTree"),versionId,projectId,apiTestCaseMapper,apiDefinitionMapper);
}
}
}
}
public void checkAutomation(JSONObject object, String projectId) {
ApiScenarioWithBLOBs bloBs = getDto(object.getString("id"));
if (bloBs != null) {
boolean isSameWorkSpace = ApiScenarioImportUtil.checkWorkSpace(bloBs.getProjectId(),projectId);
if(!isSameWorkSpace){
object.put("referenced", "Copy");
}
}
}
}

View File

@ -325,7 +325,7 @@ public class ApiDefinitionService {
return getBLOBs(returnModel.getId());
}
private void checkQuota() {
public void checkQuota() {
QuotaService quotaService = CommonBeanFactory.getBean(QuotaService.class);
if (quotaService != null) {
quotaService.checkAPIDefinitionQuota();
@ -688,13 +688,7 @@ public class ApiDefinitionService {
test.setVersionId(request.getVersionId());
test.setLatest(true); // 新建一定是最新的
if (StringUtils.isEmpty(request.getModuleId()) || "default-module".equals(request.getModuleId())) {
ApiModuleExample example = new ApiModuleExample();
example.createCriteria().andProjectIdEqualTo(test.getProjectId()).andProtocolEqualTo(test.getProtocol()).andNameEqualTo("未规划接口");
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(modules)) {
test.setModuleId(modules.get(0).getId());
test.setModulePath("/未规划接口");
}
initModulePathAndId(test.getProjectId(), test);
}
test.setResponse(JSONObject.toJSONString(request.getResponse()));
test.setEnvironmentId(request.getEnvironmentId());
@ -791,7 +785,7 @@ public class ApiDefinitionService {
return apiDefinition;
}
private Long getImportNextOrder(String projectId) {
public Long getImportNextOrder(String projectId) {
Long order = currentApiOrder.get();
if (order == null) {
order = ServiceUtils.getNextOrder(projectId, extApiDefinitionMapper::getLastOrder);
@ -801,7 +795,7 @@ public class ApiDefinitionService {
return order;
}
private Long getImportNextCaseOrder(String projectId) {
public Long getImportNextCaseOrder(String projectId) {
Long order = currentApiCaseOrder.get();
if (order == null) {
order = ServiceUtils.getNextOrder(projectId, extApiTestCaseMapper::getLastOrder);
@ -2002,4 +1996,23 @@ public class ApiDefinitionService {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
public ApiDefinitionResult getApiDefinitionResult(ApiDefinitionRequest request) {
List<ApiDefinitionResult> resList = extApiDefinitionMapper.list(request);
if(resList==null){
return null;
}
return resList.get(0);
}
public void initModulePathAndId(String projectId, ApiDefinitionWithBLOBs test) {
ApiModuleExample example = new ApiModuleExample();
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(test.getProtocol()).andNameEqualTo("未规划接口");
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(modules)) {
test.setModuleId(modules.get(0).getId());
test.setModulePath("/未规划接口");
}
}
}

View File

@ -129,7 +129,6 @@ public class ApiTestCaseService {
public List<ApiTestCaseDTO> listSimple(ApiTestCaseRequest request) {
request = this.initRequest(request, true, true);
List<ApiTestCaseDTO> apiTestCases = extApiTestCaseMapper.listSimple(request);
if (CollectionUtils.isEmpty(apiTestCases)) {
return apiTestCases;
@ -1059,4 +1058,22 @@ public class ApiTestCaseService {
List<ApiTestCaseFollow> follows = apiTestCaseFollowMapper.selectByExample(example);
return follows.stream().map(ApiTestCaseFollow::getFollowId).distinct().collect(Collectors.toList());
}
public ApiTestCaseWithBLOBs getSameCaseWithBLOBs(SaveApiTestCaseRequest request) {
ApiTestCaseExample example = new ApiTestCaseExample();
ApiTestCaseExample.Criteria criteria = example.createCriteria();
criteria.andStatusNotEqualTo("Trash").andNameEqualTo(request.getName()).andApiDefinitionIdEqualTo(request.getApiDefinitionId());
if (StringUtils.isNotBlank(request.getId())) {
criteria.andIdNotEqualTo(request.getId());
}
if (StringUtils.isNotBlank(request.getVersionId())) {
criteria.andVersionIdEqualTo(request.getVersionId());
}
List<ApiTestCaseWithBLOBs> apiTestCaseWithBLOBs = apiTestCaseMapper.selectByExampleWithBLOBs(example);
if (CollectionUtils.isNotEmpty(apiTestCaseWithBLOBs)) {
return apiTestCaseWithBLOBs.get(0);
}
return null;
}
}

View File

@ -38,4 +38,7 @@ END
DELIMITER ;
CALL project_api_appl();
DROP PROCEDURE IF EXISTS project_api_appl;
DROP PROCEDURE IF EXISTS project_api_appl;
ALTER TABLE `api_definition` ADD INDEX methodIndex ( `method` );
ALTER TABLE `api_definition` ADD INDEX protocolIndex ( `protocol` );

View File

@ -261,7 +261,7 @@
:scenario-definition="scenarioDefinition"/>
<!--接口列表-->
<scenario-api-relevance @save="pushApiOrCase" @close="setHideBtn" ref="scenarioApiRelevance" v-if="type!=='detail'"/>
<scenario-api-relevance @save="pushApiOrCase" @close="setHideBtn" ref="scenarioApiRelevance" :is-across-space="true" v-if="type!=='detail'"/>
<!--自定义接口-->
<el-drawer v-if="type!=='detail'" :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr"
@ -270,7 +270,7 @@
<ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/>
</el-drawer>
<!--场景导入 -->
<scenario-relevance v-if="type!=='detail'" @save="addScenario" @close="setHideBtn" ref="scenarioRelevance"/>
<scenario-relevance v-if="type!=='detail'" @save="addScenario" @close="setHideBtn" :is-across-space="true" ref="scenarioRelevance"/>
<!-- 环境 -->
<api-environment-config v-if="type!=='detail'" ref="environmentConfig" @close="environmentConfigClose"/>

View File

@ -1,5 +1,6 @@
<template>
<test-case-relevance-base
:is-across-space="isAcrossSpace"
@setProject="setProject"
:dialog-title="$t('api_test.definition.api_import')"
ref="baseRelevance">
@ -81,6 +82,14 @@ export default {
ScenarioRelevanceApiList,
MsMainContainer, MsAsideContainer, MsContainer, MsApiModule, ScenarioRelevanceCaseList
},
props:{
isAcrossSpace:{
type:Boolean,
default() {
return false;
}
}
},
data() {
return {
buttonIsWorking: false,

View File

@ -1,5 +1,6 @@
<template>
<test-case-relevance-base
:is-across-space="isAcrossSpace"
:dialog-title="$t('api_test.automation.scenario_import')"
@setProject="setProject"
ref="baseRelevance">
@ -56,6 +57,14 @@ const VersionSelect = requireComponent.keys().length > 0 ? requireComponent("./v
export default {
name: "ScenarioRelevance",
props:{
isAcrossSpace:{
type:Boolean,
default() {
return false;
}
}
},
components: {
'VersionSelect': VersionSelect.default,
TestCaseRelevanceBase,

View File

@ -20,7 +20,7 @@
:envMap="envMap"
:title="$t('commons.scenario')">
<template v-slot:afterTitle v-if="isSameSpace">
<template v-slot:afterTitle >
<span v-if="isShowNum" @click="clickResource(scenario)">{{ " ID: " + scenario.num + "" }}</span>
<span v-else>
<el-tooltip class="ms-num" effect="dark" :content="$t('api_test.automation.scenario.num_none')" placement="top">
@ -67,9 +67,8 @@ import MsTcpBasisParameters from "../../../definition/components/request/tcp/Tcp
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
import ApiBaseComponent from "../common/ApiBaseComponent";
import {getCurrentProjectID, getCurrentWorkspaceId, getUUID, strMapToObj} from "@/common/js/utils";
import {ELEMENT_TYPE, STEP, TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {KeyValue} from "@/business/components/api/definition/model/ApiTestModel";
import {getCurrentProjectID, getUUID, strMapToObj} from "@/common/js/utils";
import {STEP} from "@/business/components/api/automation/scenario/Setting";
export default {
name: "ApiScenarioComponent",
@ -113,15 +112,14 @@ export default {
},
},
created() {
if (this.scenario.num) {
this.isShowNum = true;
this.getWorkspaceId(this.scenario.projectId);
} else {
this.isShowNum = false;
}
if (!this.scenario.projectId) {
this.scenario.projectId = getCurrentProjectID();
}
if (this.scenario.num) {
this.isShowNum = true;
} else {
this.isShowNum = false;
}
if (this.scenario.id && this.scenario.referenced === 'REF' && !this.scenario.loaded && this.scenario.hashTree) {
this.setDisabled(this.scenario.hashTree, this.scenario.projectId);
}
@ -132,16 +130,14 @@ export default {
loading: false,
isShowInput: false,
isShowNum: false,
isSameSpace: true,
stepFilter: new STEP,
dataWorkspaceId:'',
}
},
computed: {
isDeletedOrRef() {
if (this.scenario.referenced != undefined && this.scenario.referenced === 'Deleted' || this.scenario.referenced === 'REF') {
return true;
}
return false;
return this.scenario.referenced !== undefined && this.scenario.referenced === 'Deleted' || this.scenario.referenced === 'REF';
},
projectId() {
return getCurrentProjectID();
@ -225,7 +221,7 @@ export default {
for (let i in arr) {
arr[i].disabled = true;
arr[i].projectId = this.calcProjectId(arr[i].projectId, id);
if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) {
if (arr[i].hashTree !== undefined && arr[i].hashTree.length > 0) {
this.recursive(arr[i].hashTree, arr[i].projectId);
}
}
@ -234,7 +230,7 @@ export default {
for (let i in scenarioDefinition) {
scenarioDefinition[i].disabled = true;
scenarioDefinition[i].projectId = this.calcProjectId(scenarioDefinition[i].projectId, id);
if (scenarioDefinition[i].hashTree != undefined && scenarioDefinition[i].hashTree.length > 0) {
if (scenarioDefinition[i].hashTree !== undefined && scenarioDefinition[i].hashTree.length > 0) {
this.recursive(scenarioDefinition[i].hashTree, scenarioDefinition[i].projectId);
}
}
@ -263,17 +259,6 @@ export default {
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + resource.id, projectId: resource.projectId}
});
window.open(automationData.href, '_blank');
},
getWorkspaceId(projectId) {
this.$get("/project/get/" + projectId, response => {
if (response.data) {
if (response.data.workspaceId === getCurrentWorkspaceId()) {
this.isShowNum = true;
} else {
this.isSameSpace = false;
}
}
});
}
}
}
@ -294,7 +279,7 @@ export default {
}
.ms-tag {
margin-left: 0px;
margin-left: 0;
}
.ms-req-error {

View File

@ -18,6 +18,10 @@
</template>
<template v-slot:aside>
<el-select v-if="isAcrossSpace" filterable slot="prepend" v-model="workspaceId" @change="changeWorkspace" style="width: 160px"
size="small">
<el-option v-for="(item,index) in workspaceList" :key="index" :label="item.name" :value="item.id"/>
</el-select>
<select-menu
:data="projects"
v-if="multipleProject"
@ -68,7 +72,9 @@ import SelectMenu from "../../../../common/SelectMenu";
projectId: '',
projectName: '',
projects: [],
workspaceId:'',
workspaceList:[],
currentWorkSpaceId:''
};
},
props: {
@ -91,16 +97,18 @@ import SelectMenu from "../../../../common/SelectMenu";
return false;
}
},
isAcrossSpace:{
type:Boolean,
default() {
return false;
}
},
multipleProject: {
type: Boolean,
default: true
}
},
watch: {
},
methods: {
refreshNode() {
this.$emit('refresh');
},
@ -119,7 +127,8 @@ import SelectMenu from "../../../../common/SelectMenu";
},
getProject() {
this.result = this.$post("/project/list/related", {userId: getCurrentUserId(), workspaceId: getCurrentWorkspaceId()}, res => {
let realWorkSpaceId = this.isAcrossSpace?this.workspaceId:this.currentWorkSpaceId;
this.result = this.$post("/project/list/related", {userId: getCurrentUserId(), workspaceId: realWorkSpaceId}, res => {
let data = res.data;
if (data) {
const index = data.findIndex(d => d.id === getCurrentProjectID());
@ -142,6 +151,23 @@ import SelectMenu from "../../../../common/SelectMenu";
this.$emit('setProject', project.id);
//
this.$emit('refreshNode');
},
getWorkSpaceList(){
this.$get("/workspace/list/userworkspace/" + encodeURIComponent(getCurrentUserId()), response => {
this.workspaceList = response.data;
});
},
changeWorkspace(){
this.getProject();
}
},
created() {
this.currentWorkSpaceId = getCurrentWorkspaceId();
this.workspaceId = this.currentWorkSpaceId;
if(this.isAcrossSpace){
this.getWorkSpaceList();
}
}
}