Merge branch 'main' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
848ec1780c
|
@ -1,21 +1,21 @@
|
||||||
package io.metersphere.listener;
|
package io.metersphere.listener;
|
||||||
|
|
||||||
import io.metersphere.base.domain.ApiModule;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.domain.ModuleNode;
|
|
||||||
import io.metersphere.base.domain.Project;
|
|
||||||
import io.metersphere.base.mapper.ApiModuleMapper;
|
import io.metersphere.base.mapper.ApiModuleMapper;
|
||||||
|
import io.metersphere.base.mapper.ApiScenarioModuleMapper;
|
||||||
import io.metersphere.base.mapper.ProjectMapper;
|
import io.metersphere.base.mapper.ProjectMapper;
|
||||||
import io.metersphere.base.mapper.ext.BaseModuleNodeMapper;
|
import io.metersphere.base.mapper.ext.BaseModuleNodeMapper;
|
||||||
import io.metersphere.commons.constants.KafkaTopicConstants;
|
import io.metersphere.commons.constants.KafkaTopicConstants;
|
||||||
import io.metersphere.commons.constants.ProjectModuleDefaultNodeEnum;
|
import io.metersphere.commons.constants.ProjectModuleDefaultNodeEnum;
|
||||||
import io.metersphere.commons.utils.BeanUtils;
|
import io.metersphere.commons.utils.BeanUtils;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||||
import org.springframework.kafka.annotation.KafkaListener;
|
import org.springframework.kafka.annotation.KafkaListener;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@ -28,6 +28,8 @@ public class ProjectCreatedListener {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiModuleMapper apiModuleMapper;
|
private ApiModuleMapper apiModuleMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
private ApiScenarioModuleMapper apiScenarioModuleMapper;
|
||||||
|
@Resource
|
||||||
private ProjectMapper projectMapper;
|
private ProjectMapper projectMapper;
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +54,12 @@ public class ProjectCreatedListener {
|
||||||
record.setUpdateTime(System.currentTimeMillis());
|
record.setUpdateTime(System.currentTimeMillis());
|
||||||
record.setProjectId(projectId);
|
record.setProjectId(projectId);
|
||||||
record.setName(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName());
|
record.setName(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName());
|
||||||
baseModuleNodeMapper.insert(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getTableName(), record);
|
ApiScenarioModuleExample scenarioModuleExample = new ApiScenarioModuleExample();
|
||||||
|
scenarioModuleExample.createCriteria().andProjectIdEqualTo(projectId).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName()).andParentIdIsNull();
|
||||||
|
List<ApiScenarioModule> scenarioModules = apiScenarioModuleMapper.selectByExample(scenarioModuleExample);
|
||||||
|
if (CollectionUtils.isEmpty(scenarioModules)) {
|
||||||
|
baseModuleNodeMapper.insert(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getTableName(), record);
|
||||||
|
}
|
||||||
ApiModule apiRecord = new ApiModule();
|
ApiModule apiRecord = new ApiModule();
|
||||||
BeanUtils.copyBean(apiRecord, record);
|
BeanUtils.copyBean(apiRecord, record);
|
||||||
apiRecord.setName(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName());
|
apiRecord.setName(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName());
|
||||||
|
@ -60,7 +67,12 @@ public class ProjectCreatedListener {
|
||||||
for (String protocol : protocols) {
|
for (String protocol : protocols) {
|
||||||
apiRecord.setProtocol(protocol);
|
apiRecord.setProtocol(protocol);
|
||||||
apiRecord.setId(UUID.randomUUID().toString());
|
apiRecord.setId(UUID.randomUUID().toString());
|
||||||
apiModuleMapper.insert(apiRecord);
|
ApiModuleExample apiExample = new ApiModuleExample();
|
||||||
|
apiExample.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName()).andParentIdIsNull();
|
||||||
|
List<ApiModule> apiList = apiModuleMapper.selectByExample(apiExample);
|
||||||
|
if (CollectionUtils.isEmpty(apiList)) {
|
||||||
|
apiModuleMapper.insert(apiRecord);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.ApiModuleMapper;
|
import io.metersphere.base.mapper.ApiModuleMapper;
|
||||||
import io.metersphere.base.mapper.ApiTestCaseMapper;
|
import io.metersphere.base.mapper.ApiTestCaseMapper;
|
||||||
import io.metersphere.commons.constants.NoticeConstants;
|
import io.metersphere.commons.constants.NoticeConstants;
|
||||||
|
import io.metersphere.commons.constants.ProjectModuleDefaultNodeEnum;
|
||||||
import io.metersphere.commons.constants.PropertyConstant;
|
import io.metersphere.commons.constants.PropertyConstant;
|
||||||
import io.metersphere.commons.enums.ApiTestDataStatus;
|
import io.metersphere.commons.enums.ApiTestDataStatus;
|
||||||
import io.metersphere.commons.utils.BeanUtils;
|
import io.metersphere.commons.utils.BeanUtils;
|
||||||
|
@ -355,7 +356,7 @@ public class ApiDefinitionImportUtil {
|
||||||
public static void setModule(ApiDefinitionWithBLOBs item, ApiModuleMapper apiModuleMapper) {
|
public static void setModule(ApiDefinitionWithBLOBs item, ApiModuleMapper apiModuleMapper) {
|
||||||
if (item != null && StringUtils.isEmpty(item.getModuleId()) || "default-module".equals(item.getModuleId())) {
|
if (item != null && StringUtils.isEmpty(item.getModuleId()) || "default-module".equals(item.getModuleId())) {
|
||||||
ApiModuleExample example = new ApiModuleExample();
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(item.getProjectId()).andProtocolEqualTo(item.getProtocol()).andNameEqualTo("未规划接口");
|
example.createCriteria().andProjectIdEqualTo(item.getProjectId()).andProtocolEqualTo(item.getProtocol()).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName());
|
||||||
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isNotEmpty(modules)) {
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
item.setModuleId(modules.get(0).getId());
|
item.setModuleId(modules.get(0).getId());
|
||||||
|
|
|
@ -1003,7 +1003,7 @@ public class ApiDefinitionService {
|
||||||
private void setModule(ApiDefinitionWithBLOBs item) {
|
private void setModule(ApiDefinitionWithBLOBs item) {
|
||||||
if (item != null && StringUtils.isEmpty(item.getModuleId()) || "default-module".equals(item.getModuleId())) {
|
if (item != null && StringUtils.isEmpty(item.getModuleId()) || "default-module".equals(item.getModuleId())) {
|
||||||
ApiModuleExample example = new ApiModuleExample();
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(item.getProjectId()).andProtocolEqualTo(item.getProtocol()).andNameEqualTo("未规划接口");
|
example.createCriteria().andProjectIdEqualTo(item.getProjectId()).andProtocolEqualTo(item.getProtocol()).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName());
|
||||||
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isNotEmpty(modules)) {
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
item.setModuleId(modules.get(0).getId());
|
item.setModuleId(modules.get(0).getId());
|
||||||
|
@ -1840,7 +1840,7 @@ public class ApiDefinitionService {
|
||||||
|
|
||||||
public void initModulePathAndId(String projectId, ApiDefinitionWithBLOBs test) {
|
public void initModulePathAndId(String projectId, ApiDefinitionWithBLOBs test) {
|
||||||
ApiModuleExample example = new ApiModuleExample();
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(test.getProtocol()).andNameEqualTo("未规划接口").andLevelEqualTo(1);
|
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(test.getProtocol()).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName()).andLevelEqualTo(1);
|
||||||
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isNotEmpty(modules)) {
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
test.setModuleId(modules.get(0).getId());
|
test.setModuleId(modules.get(0).getId());
|
||||||
|
|
|
@ -1,24 +1,15 @@
|
||||||
package io.metersphere.service.definition;
|
package io.metersphere.service.definition;
|
||||||
|
|
||||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionRequest;
|
import io.metersphere.api.dto.definition.*;
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
|
||||||
import io.metersphere.api.dto.definition.ApiModuleDTO;
|
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
|
||||||
import io.metersphere.api.dto.definition.DragModuleRequest;
|
|
||||||
import io.metersphere.api.dto.definition.UpdateApiModuleDTO;
|
|
||||||
import io.metersphere.api.parse.api.ApiDefinitionImport;
|
import io.metersphere.api.parse.api.ApiDefinitionImport;
|
||||||
import io.metersphere.base.domain.ApiDefinition;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.domain.ApiDefinitionExample;
|
|
||||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
|
||||||
import io.metersphere.base.domain.ApiModule;
|
|
||||||
import io.metersphere.base.domain.ApiModuleExample;
|
|
||||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
|
||||||
import io.metersphere.base.mapper.ApiDefinitionMapper;
|
import io.metersphere.base.mapper.ApiDefinitionMapper;
|
||||||
import io.metersphere.base.mapper.ApiModuleMapper;
|
import io.metersphere.base.mapper.ApiModuleMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper;
|
import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiModuleMapper;
|
import io.metersphere.base.mapper.ext.ExtApiModuleMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
|
||||||
|
import io.metersphere.commons.constants.ProjectModuleDefaultNodeEnum;
|
||||||
import io.metersphere.commons.constants.PropertyConstant;
|
import io.metersphere.commons.constants.PropertyConstant;
|
||||||
import io.metersphere.commons.constants.TestCaseConstants;
|
import io.metersphere.commons.constants.TestCaseConstants;
|
||||||
import io.metersphere.commons.enums.ApiTestDataStatus;
|
import io.metersphere.commons.enums.ApiTestDataStatus;
|
||||||
|
@ -40,19 +31,12 @@ import org.apache.ibatis.session.SqlSession;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.mybatis.spring.SqlSessionUtils;
|
import org.mybatis.spring.SqlSessionUtils;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -204,7 +188,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
return getNodeTrees(apiModules);
|
return getNodeTrees(apiModules);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ApiModuleDTO> getNodeTreeByCondition(String projectId, String protocol, String versionId, ApiDefinitionRequest request ) {
|
public List<ApiModuleDTO> getNodeTreeByCondition(String projectId, String protocol, String versionId, ApiDefinitionRequest request) {
|
||||||
// 判断当前项目下是否有默认模块,没有添加默认模块
|
// 判断当前项目下是否有默认模块,没有添加默认模块
|
||||||
this.getDefaultNode(projectId, protocol);
|
this.getDefaultNode(projectId, protocol);
|
||||||
List<ApiModuleDTO> apiModules = getApiModulesByProjectAndPro(projectId, protocol);
|
List<ApiModuleDTO> apiModules = getApiModulesByProjectAndPro(projectId, protocol);
|
||||||
|
@ -588,32 +572,33 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
|
|
||||||
public ApiModule getDefaultNode(String projectId, String protocol) {
|
public ApiModule getDefaultNode(String projectId, String protocol) {
|
||||||
ApiModuleExample example = new ApiModuleExample();
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol).andNameEqualTo("未规划接口").andParentIdIsNull();
|
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName()).andParentIdIsNull();
|
||||||
List<ApiModule> list = apiModuleMapper.selectByExample(example);
|
List<ApiModule> list = apiModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
ApiModule record = new ApiModule();
|
return saveDefault(projectId, protocol);
|
||||||
record.setId(UUID.randomUUID().toString());
|
|
||||||
record.setName("未规划接口");
|
|
||||||
record.setProtocol(protocol);
|
|
||||||
record.setPos(1.0);
|
|
||||||
record.setLevel(1);
|
|
||||||
record.setCreateTime(System.currentTimeMillis());
|
|
||||||
record.setUpdateTime(System.currentTimeMillis());
|
|
||||||
record.setProjectId(projectId);
|
|
||||||
record.setCreateUser(SessionUtils.getUserId());
|
|
||||||
apiModuleMapper.insert(record);
|
|
||||||
return record;
|
|
||||||
} else {
|
} else {
|
||||||
return list.get(0);
|
return list.get(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiModule getDefaultNodeUnCreateNew(String projectId, String protocol) {
|
@Async
|
||||||
|
public synchronized ApiModule saveDefault(String projectId, String protocol) {
|
||||||
ApiModuleExample example = new ApiModuleExample();
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol).andNameEqualTo("未规划接口").andParentIdIsNull();
|
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName()).andParentIdIsNull();
|
||||||
List<ApiModule> list = apiModuleMapper.selectByExample(example);
|
List<ApiModule> list = apiModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
return null;
|
ApiModule module = new ApiModule();
|
||||||
|
module.setId(UUID.randomUUID().toString());
|
||||||
|
module.setName(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName());
|
||||||
|
module.setProtocol(protocol);
|
||||||
|
module.setPos(1.0);
|
||||||
|
module.setLevel(1);
|
||||||
|
module.setCreateTime(System.currentTimeMillis());
|
||||||
|
module.setUpdateTime(System.currentTimeMillis());
|
||||||
|
module.setProjectId(projectId);
|
||||||
|
module.setCreateUser(SessionUtils.getUserId());
|
||||||
|
apiModuleMapper.insert(module);
|
||||||
|
return module;
|
||||||
} else {
|
} else {
|
||||||
return list.get(0);
|
return list.get(0);
|
||||||
}
|
}
|
||||||
|
@ -666,7 +651,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
if (protocol.equals("HTTP")) {
|
if (protocol.equals("HTTP")) {
|
||||||
return dealHttp(data, pidChildrenMap, idPathMap, idModuleMap, request, fullCoverage, urlRepeat, importCases);
|
return dealHttp(data, pidChildrenMap, idPathMap, idModuleMap, request, fullCoverage, urlRepeat, importCases);
|
||||||
} else {
|
} else {
|
||||||
return delOtherProtocol(data, pidChildrenMap, idPathMap, idModuleMap, request, fullCoverage, importCases);
|
return delOtherProtocol(data, pidChildrenMap, idPathMap, idModuleMap, request, fullCoverage, importCases);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -693,7 +678,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
//处理模块
|
//处理模块
|
||||||
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
|
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
|
||||||
|
|
||||||
return getUpdateApiModuleDTO(chooseModule,idPathMap,optionData,fullCoverage, moduleMap,optionDataCases);
|
return getUpdateApiModuleDTO(chooseModule, idPathMap, optionData, fullCoverage, moduleMap, optionDataCases);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UpdateApiModuleDTO dealHttp(List<ApiDefinitionWithBLOBs> data,
|
private UpdateApiModuleDTO dealHttp(List<ApiDefinitionWithBLOBs> data,
|
||||||
|
@ -722,8 +707,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
|
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
|
||||||
|
|
||||||
|
|
||||||
|
return getUpdateApiModuleDTO(chooseModule, idPathMap, optionData, fullCoverage, moduleMap, optionDataCases);
|
||||||
return getUpdateApiModuleDTO(chooseModule,idPathMap,optionData,fullCoverage, moduleMap,optionDataCases);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +736,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UpdateApiModuleDTO getUpdateApiModuleDTO(ApiModuleDTO chooseModule,Map<String, String> idPathMap,List<ApiDefinitionWithBLOBs> optionData,Boolean fullCoverage,Map<String, ApiModule> moduleMap, List<ApiTestCaseWithBLOBs> optionDataCases) {
|
private UpdateApiModuleDTO getUpdateApiModuleDTO(ApiModuleDTO chooseModule, Map<String, String> idPathMap, List<ApiDefinitionWithBLOBs> optionData, Boolean fullCoverage, Map<String, ApiModule> moduleMap, List<ApiTestCaseWithBLOBs> optionDataCases) {
|
||||||
UpdateApiModuleDTO updateApiModuleDTO = new UpdateApiModuleDTO();
|
UpdateApiModuleDTO updateApiModuleDTO = new UpdateApiModuleDTO();
|
||||||
updateApiModuleDTO.setChooseModule(chooseModule);
|
updateApiModuleDTO.setChooseModule(chooseModule);
|
||||||
updateApiModuleDTO.setIdPathMap(idPathMap);
|
updateApiModuleDTO.setIdPathMap(idPathMap);
|
||||||
|
@ -822,7 +806,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
//导入时即没选中模块,接口自身也没模块的,直接返会当前项目,当前协议下的默认模块
|
//导入时即没选中模块,接口自身也没模块的,直接返会当前项目,当前协议下的默认模块
|
||||||
List<ApiModule> moduleList = pidChildrenMap.get(PropertyConstant.ROOT);
|
List<ApiModule> moduleList = pidChildrenMap.get(PropertyConstant.ROOT);
|
||||||
for (ApiModule module : moduleList) {
|
for (ApiModule module : moduleList) {
|
||||||
if (module.getName().equals("未规划接口")) {
|
if (module.getName().equals(ProjectModuleDefaultNodeEnum.API_MODULE_DEFAULT_NODE.getNodeName())) {
|
||||||
datum.setModuleId(module.getId());
|
datum.setModuleId(module.getId());
|
||||||
datum.setModulePath("/" + module.getName());
|
datum.setModulePath("/" + module.getName());
|
||||||
}
|
}
|
||||||
|
@ -846,6 +830,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
datum.setModulePath(idPathMap.get(chooseModule.getId()));
|
datum.setModulePath(idPathMap.get(chooseModule.getId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getPathTree(String modulePath) {
|
public String[] getPathTree(String modulePath) {
|
||||||
String substring = modulePath.substring(0, 1);
|
String substring = modulePath.substring(0, 1);
|
||||||
if (substring.equals("/")) {
|
if (substring.equals("/")) {
|
||||||
|
|
|
@ -339,11 +339,19 @@ public class TestPlanScenarioCaseService {
|
||||||
if (envMap != null && !envMap.isEmpty()) {
|
if (envMap != null && !envMap.isEmpty()) {
|
||||||
env = JSON.toJSONString(envMap);
|
env = JSON.toJSONString(envMap);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Map<String, String> existMap = JSON.parseObject(env, Map.class);
|
||||||
|
if (existMap.isEmpty()) {
|
||||||
|
if (envMap != null && !envMap.isEmpty()) {
|
||||||
|
env = JSON.toJSONString(envMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Map<String, String> map = JSON.parseObject(env, Map.class);
|
Map<String, String> map = JSON.parseObject(env, Map.class);
|
||||||
if (map.isEmpty()) {
|
if (map.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> set = map.keySet();
|
Set<String> set = map.keySet();
|
||||||
for (String s : set) {
|
for (String s : set) {
|
||||||
if (StringUtils.isNotBlank(envMap.get(s))) {
|
if (StringUtils.isNotBlank(envMap.get(s))) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import io.metersphere.base.mapper.ApiScenarioMapper;
|
||||||
import io.metersphere.base.mapper.ApiScenarioModuleMapper;
|
import io.metersphere.base.mapper.ApiScenarioModuleMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
|
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiScenarioModuleMapper;
|
import io.metersphere.base.mapper.ext.ExtApiScenarioModuleMapper;
|
||||||
|
import io.metersphere.commons.constants.ProjectModuleDefaultNodeEnum;
|
||||||
import io.metersphere.commons.constants.PropertyConstant;
|
import io.metersphere.commons.constants.PropertyConstant;
|
||||||
import io.metersphere.commons.constants.TestCaseConstants;
|
import io.metersphere.commons.constants.TestCaseConstants;
|
||||||
import io.metersphere.commons.enums.ApiTestDataStatus;
|
import io.metersphere.commons.enums.ApiTestDataStatus;
|
||||||
|
@ -29,6 +30,7 @@ import org.apache.ibatis.session.ExecutorType;
|
||||||
import org.apache.ibatis.session.SqlSession;
|
import org.apache.ibatis.session.SqlSession;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.mybatis.spring.SqlSessionUtils;
|
import org.mybatis.spring.SqlSessionUtils;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
@ -157,7 +159,7 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
|
||||||
//回收站数据初始化:被删除了的数据挂在默认模块上
|
//回收站数据初始化:被删除了的数据挂在默认模块上
|
||||||
initTrashDataModule(projectId);
|
initTrashDataModule(projectId);
|
||||||
//通过回收站里的接口模块进行反显
|
//通过回收站里的接口模块进行反显
|
||||||
if(request.getFilters() != null && request.getFilters().get("status") != null){
|
if (request.getFilters() != null && request.getFilters().get("status") != null) {
|
||||||
List<String> statusList = new ArrayList<>();
|
List<String> statusList = new ArrayList<>();
|
||||||
statusList.add(ApiTestDataStatus.TRASH.getValue());
|
statusList.add(ApiTestDataStatus.TRASH.getValue());
|
||||||
request.getFilters().put("status", statusList);
|
request.getFilters().put("status", statusList);
|
||||||
|
@ -507,20 +509,32 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
|
||||||
|
|
||||||
public ApiScenarioModule getDefaultNode(String projectId) {
|
public ApiScenarioModule getDefaultNode(String projectId) {
|
||||||
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId).andNameEqualTo("未规划场景").andParentIdIsNull();
|
example.createCriteria().andProjectIdEqualTo(projectId).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName()).andParentIdIsNull();
|
||||||
List<ApiScenarioModule> list = apiScenarioModuleMapper.selectByExample(example);
|
List<ApiScenarioModule> list = apiScenarioModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
ApiScenarioModule record = new ApiScenarioModule();
|
return saveDefault(projectId);
|
||||||
record.setId(UUID.randomUUID().toString());
|
} else {
|
||||||
record.setName("未规划场景");
|
return list.get(0);
|
||||||
record.setPos(1.0);
|
}
|
||||||
record.setLevel(1);
|
}
|
||||||
record.setCreateTime(System.currentTimeMillis());
|
|
||||||
record.setUpdateTime(System.currentTimeMillis());
|
@Async
|
||||||
record.setProjectId(projectId);
|
public synchronized ApiScenarioModule saveDefault(String projectId) {
|
||||||
record.setCreateUser(SessionUtils.getUserId());
|
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
||||||
apiScenarioModuleMapper.insert(record);
|
example.createCriteria().andProjectIdEqualTo(projectId).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName()).andParentIdIsNull();
|
||||||
return record;
|
List<ApiScenarioModule> list = apiScenarioModuleMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
|
ApiScenarioModule module = new ApiScenarioModule();
|
||||||
|
module.setId(UUID.randomUUID().toString());
|
||||||
|
module.setName(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName());
|
||||||
|
module.setPos(1.0);
|
||||||
|
module.setLevel(1);
|
||||||
|
module.setCreateTime(System.currentTimeMillis());
|
||||||
|
module.setUpdateTime(System.currentTimeMillis());
|
||||||
|
module.setProjectId(projectId);
|
||||||
|
module.setCreateUser(SessionUtils.getUserId());
|
||||||
|
apiScenarioModuleMapper.insert(module);
|
||||||
|
return module;
|
||||||
} else {
|
} else {
|
||||||
return list.get(0);
|
return list.get(0);
|
||||||
}
|
}
|
||||||
|
@ -825,7 +839,7 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
|
||||||
//导入时即没选中模块,接口自身也没模块的,直接返会当前项目,当前协议下的默认模块
|
//导入时即没选中模块,接口自身也没模块的,直接返会当前项目,当前协议下的默认模块
|
||||||
List<ApiScenarioModule> moduleList = pidChildrenMap.get(PropertyConstant.ROOT);
|
List<ApiScenarioModule> moduleList = pidChildrenMap.get(PropertyConstant.ROOT);
|
||||||
for (ApiScenarioModule module : moduleList) {
|
for (ApiScenarioModule module : moduleList) {
|
||||||
if (module.getName().equals("未规划场景")) {
|
if (module.getName().equals(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName())) {
|
||||||
datum.setApiScenarioModuleId(module.getId());
|
datum.setApiScenarioModuleId(module.getId());
|
||||||
datum.setModulePath("/" + module.getName());
|
datum.setModulePath("/" + module.getName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1478,7 +1478,7 @@ public class ApiScenarioService {
|
||||||
|
|
||||||
private void replenishScenarioModuleIdPath(String request, ApiScenarioModuleMapper apiScenarioModuleMapper, ApiScenarioWithBLOBs item) {
|
private void replenishScenarioModuleIdPath(String request, ApiScenarioModuleMapper apiScenarioModuleMapper, ApiScenarioWithBLOBs item) {
|
||||||
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(request).andNameEqualTo("未规划场景");
|
example.createCriteria().andProjectIdEqualTo(request).andNameEqualTo(ProjectModuleDefaultNodeEnum.API_SCENARIO_DEFAULT_NODE.getNodeName());
|
||||||
List<ApiScenarioModule> modules = apiScenarioModuleMapper.selectByExample(example);
|
List<ApiScenarioModule> modules = apiScenarioModuleMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isNotEmpty(modules)) {
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
item.setApiScenarioModuleId(modules.get(0).getId());
|
item.setApiScenarioModuleId(modules.get(0).getId());
|
||||||
|
|
|
@ -78,6 +78,7 @@ export default {
|
||||||
jmxObj.attachFiles = jmxInfo.attachFiles;
|
jmxObj.attachFiles = jmxInfo.attachFiles;
|
||||||
jmxObj.attachByteFiles = jmxInfo.attachByteFiles;
|
jmxObj.attachByteFiles = jmxInfo.attachByteFiles;
|
||||||
jmxObj.scenarioId = row.id;
|
jmxObj.scenarioId = row.id;
|
||||||
|
jmxObj.caseId = null;
|
||||||
jmxObj.version = row.version;
|
jmxObj.version = row.version;
|
||||||
jmxObj.projectEnvMap = projectEnvMap;
|
jmxObj.projectEnvMap = projectEnvMap;
|
||||||
performanceStore.$patch({ test: { name: row.name, jmx: jmxObj } });
|
performanceStore.$patch({ test: { name: row.name, jmx: jmxObj } });
|
||||||
|
|
|
@ -545,8 +545,10 @@ export default {
|
||||||
if (this.httpForm.tags instanceof Array) {
|
if (this.httpForm.tags instanceof Array) {
|
||||||
this.httpForm.tags = JSON.stringify(this.httpForm.tags);
|
this.httpForm.tags = JSON.stringify(this.httpForm.tags);
|
||||||
}
|
}
|
||||||
if (this.beforeHttpForm.tags instanceof Array) {
|
if (this.beforeHttpForm) {
|
||||||
this.beforeHttpForm.tags = JSON.stringify(this.beforeHttpForm.tags);
|
if (this.beforeHttpForm.tags instanceof Array) {
|
||||||
|
this.beforeHttpForm.tags = JSON.stringify(this.beforeHttpForm.tags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
saveApi() {
|
saveApi() {
|
||||||
|
@ -808,11 +810,11 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.versionData = response.data;
|
this.versionData = response.data;
|
||||||
}
|
}
|
||||||
|
if (this.versionData[0]) {
|
||||||
this.beforeHttpForm = this.versionData[0];
|
this.beforeHttpForm = this.versionData[0];
|
||||||
this.beforeRequest = JSON.parse(this.versionData[0].request);
|
this.beforeRequest = JSON.parse(this.versionData[0].request);
|
||||||
this.beforeResponse = JSON.parse(this.versionData[0].response);
|
this.beforeResponse = JSON.parse(this.versionData[0].response);
|
||||||
|
}
|
||||||
let latestVersionData = response.data.filter((v) => v.versionId === this.latestVersionId);
|
let latestVersionData = response.data.filter((v) => v.versionId === this.latestVersionId);
|
||||||
if (latestVersionData.length > 0) {
|
if (latestVersionData.length > 0) {
|
||||||
this.hasLatest = false
|
this.hasLatest = false
|
||||||
|
|
|
@ -1433,6 +1433,7 @@ export default {
|
||||||
jmxObj.attachFiles = jmxInfo.attachFiles;
|
jmxObj.attachFiles = jmxInfo.attachFiles;
|
||||||
jmxObj.attachByteFiles = jmxInfo.attachByteFiles;
|
jmxObj.attachByteFiles = jmxInfo.attachByteFiles;
|
||||||
jmxObj.caseId = reqObj.id;
|
jmxObj.caseId = reqObj.id;
|
||||||
|
jmxObj.scenarioId = null;
|
||||||
jmxObj.version = row.version;
|
jmxObj.version = row.version;
|
||||||
jmxObj.envId = environment.id;
|
jmxObj.envId = environment.id;
|
||||||
jmxObj.projectEnvMap = projectEnvMap;
|
jmxObj.projectEnvMap = projectEnvMap;
|
||||||
|
@ -1442,7 +1443,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(() => {
|
||||||
this.$emit('runRefresh', {});
|
this.$emit('runRefresh', {});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,7 +36,11 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
|
<version>${redisson-starter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,5 @@ eureka.dashboard.enabled=true
|
||||||
# default eureka
|
# default eureka
|
||||||
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
|
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
|
||||||
|
|
||||||
logging.file.path=/opt/metersphere/logs/${spring.application.name}
|
logging.file.path=/opt/metersphere/logs/${spring.application.name}
|
||||||
|
spring.redis.redisson.file=file:/opt/metersphere/conf/redisson.yml
|
||||||
|
|
|
@ -45,11 +45,57 @@
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>{{ $t('api_test.request.headers') }}</p>
|
<!-- 接口测试配置 -->
|
||||||
<el-row>
|
<form-section :title="$t('commons.api')" :init-active=true>
|
||||||
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
|
<p>{{ $t('api_test.request.headers') }}</p>
|
||||||
</el-row>
|
<el-row>
|
||||||
<ms-api-key-value :items="condition.headers" :isShowEnable="true" :suggestions="headerSuggestions"/>
|
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{
|
||||||
|
$t("commons.batch_add")
|
||||||
|
}}
|
||||||
|
</el-link>
|
||||||
|
</el-row>
|
||||||
|
<ms-api-key-value :items="condition.headers" :isShowEnable="true" :suggestions="headerSuggestions"/>
|
||||||
|
</form-section>
|
||||||
|
|
||||||
|
<!-- UI 配置 -->
|
||||||
|
<form-section :title="$t('commons.ui_test')" :init-active=false v-if="condition.type !== 'MODULE'">
|
||||||
|
<el-row :gutter="10" style="padding-top: 10px;">
|
||||||
|
<el-col :span="6">
|
||||||
|
<!-- 浏览器驱动 -->
|
||||||
|
<span style="margin-right: 10px;">{{ $t("ui.browser") }}</span>
|
||||||
|
<el-select
|
||||||
|
size="mini"
|
||||||
|
v-model="httpConfig.browser"
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="b in browsers"
|
||||||
|
:key="b.value"
|
||||||
|
:value="b.value"
|
||||||
|
:label="b.label"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<!-- 性能模式 -->
|
||||||
|
<el-checkbox
|
||||||
|
v-model="httpConfig.headlessEnabled"
|
||||||
|
>
|
||||||
|
<span> {{ $t("ui.performance_mode") }}</span>
|
||||||
|
</el-checkbox>
|
||||||
|
<ms-instructions-icon size="10" :content="$t('ui.per_tip')"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 当前版本实现免登录是基于 cookie 的但是现在由于安全性问题绝大多数网站都不支持 cookie登录所以先屏蔽了-->
|
||||||
|
<!-- <el-row :gutter="10">-->
|
||||||
|
<!-- <el-col :span="24">-->
|
||||||
|
<!-- <ms-ui-scenario-cookie-table :items="httpConfig.cookie" ref="cookieTable"/>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- </el-row>-->
|
||||||
|
</form-section>
|
||||||
|
|
||||||
<div style="margin-top: 20px">
|
<div style="margin-top: 20px">
|
||||||
<el-button v-if="!condition.id" type="primary" style="float: right" size="mini" @click="add">
|
<el-button v-if="!condition.id" type="primary" style="float: right" size="mini" @click="add">
|
||||||
{{ $t('commons.add') }}
|
{{ $t('commons.add') }}
|
||||||
|
@ -121,10 +167,12 @@ import {getUUID} from "../../utils";
|
||||||
import {KeyValue} from "../../model/EnvTestModel";
|
import {KeyValue} from "../../model/EnvTestModel";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import BatchAddParameter from "./commons/BatchAddParameter";
|
import BatchAddParameter from "./commons/BatchAddParameter";
|
||||||
|
import FormSection from "metersphere-frontend/src/components/form/FormSection";
|
||||||
|
import MsInstructionsIcon from 'metersphere-frontend/src/components/MsInstructionsIcon';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsEnvironmentHttpConfig",
|
name: "MsEnvironmentHttpConfig",
|
||||||
components: {MsApiKeyValue, MsSelectTree, MsTableOperatorButton, BatchAddParameter},
|
components: {MsApiKeyValue, MsSelectTree, MsTableOperatorButton, BatchAddParameter, FormSection, MsInstructionsIcon},
|
||||||
props: {
|
props: {
|
||||||
httpConfig: new HttpConfig(),
|
httpConfig: new HttpConfig(),
|
||||||
projectId: String,
|
projectId: String,
|
||||||
|
@ -165,9 +213,21 @@ export default {
|
||||||
socket: "",
|
socket: "",
|
||||||
domain: "",
|
domain: "",
|
||||||
port: 0,
|
port: 0,
|
||||||
headers: [new KeyValue()]
|
headers: [new KeyValue()],
|
||||||
|
headlessEnabled: true,
|
||||||
|
browser: 'CHROME'
|
||||||
},
|
},
|
||||||
beforeCondition: {}
|
beforeCondition: {},
|
||||||
|
browsers: [
|
||||||
|
{
|
||||||
|
label: this.$t("chrome"),
|
||||||
|
value: "CHROME",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.$t("firefox"),
|
||||||
|
value: "FIREFOX",
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -289,7 +349,7 @@ export default {
|
||||||
list() {
|
list() {
|
||||||
if (this.projectId) {
|
if (this.projectId) {
|
||||||
this.result = getApiModuleByProjectIdAndProtocol(this.projectId, "HTTP").then((response) => {
|
this.result = getApiModuleByProjectIdAndProtocol(this.projectId, "HTTP").then((response) => {
|
||||||
if (response.data && response.data !== null) {
|
if (response.data && response.data !== null) {
|
||||||
this.moduleOptions = response.data;
|
this.moduleOptions = response.data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,12 +18,18 @@
|
||||||
:content="$t('commons.import')"
|
:content="$t('commons.import')"
|
||||||
@click="importJSON"
|
@click="importJSON"
|
||||||
/>
|
/>
|
||||||
<ms-table-button
|
<el-dropdown @command="handleExportCommand" class="scenario-ext-btn" trigger="hover"
|
||||||
v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']"
|
v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']">
|
||||||
icon="el-icon-box"
|
<ms-table-button
|
||||||
:content="$t('commons.export')"
|
style="margin-left: 10px"
|
||||||
@click="exportJSON"
|
icon="el-icon-box"
|
||||||
/>
|
:content="$t('commons.export')"
|
||||||
|
/>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="exportApi">{{ $t('envrionment.export_variable_tip') }}</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
<el-link
|
<el-link
|
||||||
style="margin-left: 10px"
|
style="margin-left: 10px"
|
||||||
@click="batchAdd"
|
@click="batchAdd"
|
||||||
|
@ -58,6 +64,31 @@
|
||||||
>
|
>
|
||||||
<ms-table-column prop="num" sortable label="ID" min-width="60">
|
<ms-table-column prop="num" sortable label="ID" min-width="60">
|
||||||
</ms-table-column>
|
</ms-table-column>
|
||||||
|
|
||||||
|
<ms-table-column
|
||||||
|
prop="scope"
|
||||||
|
sortable
|
||||||
|
:label="$t('commons.scope')"
|
||||||
|
:filters="scopeTypeFilters"
|
||||||
|
:filter-method="filterScope"
|
||||||
|
min-width="120">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-select
|
||||||
|
v-model="scope.row.scope"
|
||||||
|
:placeholder="$t('commons.please_select')"
|
||||||
|
size="mini"
|
||||||
|
@change="changeType(scope.row)"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in scopeTypeFilters"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.text"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</ms-table-column>
|
||||||
|
|
||||||
<ms-table-column
|
<ms-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
:label="$t('api_test.variable_name')"
|
:label="$t('api_test.variable_name')"
|
||||||
|
@ -84,9 +115,9 @@
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="scope.row.type"
|
v-model="scope.row.type"
|
||||||
|
v-if="!scope.row.scope || scope.row.scope == 'api'"
|
||||||
:placeholder="$t('commons.please_select')"
|
:placeholder="$t('commons.please_select')"
|
||||||
size="mini"
|
size="mini"
|
||||||
@change="changeType(scope.row)"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in typeSelectOptions"
|
v-for="item in typeSelectOptions"
|
||||||
|
@ -95,6 +126,20 @@
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
||||||
|
<el-select
|
||||||
|
v-else
|
||||||
|
v-model="scope.row.type"
|
||||||
|
:placeholder="$t('commons.please_select')"
|
||||||
|
size="mini"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in uiTypeSelectOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</ms-table-column>
|
</ms-table-column>
|
||||||
|
|
||||||
|
@ -128,14 +173,14 @@
|
||||||
sortable
|
sortable
|
||||||
>
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-input v-model="scope.row.description" size="mini" />
|
<el-input v-model="scope.row.description" size="mini"/>
|
||||||
</template>
|
</template>
|
||||||
</ms-table-column>
|
</ms-table-column>
|
||||||
|
|
||||||
<ms-table-column :label="$t('commons.operating')" width="150">
|
<ms-table-column :label="$t('commons.operating')" width="150">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span>
|
<span>
|
||||||
<el-switch v-model="scope.row.enable" size="mini" />
|
<el-switch v-model="scope.row.enable" size="mini"/>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
effect="dark"
|
effect="dark"
|
||||||
:content="$t('commons.remove')"
|
:content="$t('commons.remove')"
|
||||||
|
@ -171,7 +216,7 @@
|
||||||
</ms-table-column>
|
</ms-table-column>
|
||||||
</ms-table>
|
</ms-table>
|
||||||
</div>
|
</div>
|
||||||
<batch-add-parameter @batchSave="batchSave" ref="batchAdd" />
|
<batch-add-parameter @batchSave="batchSave" ref="batchAdd"/>
|
||||||
<api-variable-setting ref="apiVariableSetting"></api-variable-setting>
|
<api-variable-setting ref="apiVariableSetting"></api-variable-setting>
|
||||||
<variable-import
|
<variable-import
|
||||||
ref="variableImport"
|
ref="variableImport"
|
||||||
|
@ -181,7 +226,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { KeyValue } from "../../../model/EnvTestModel";
|
import {KeyValue} from "../../../model/EnvTestModel";
|
||||||
import MsApiVariableInput from "./ApiVariableInput";
|
import MsApiVariableInput from "./ApiVariableInput";
|
||||||
import BatchAddParameter from "./BatchAddParameter";
|
import BatchAddParameter from "./BatchAddParameter";
|
||||||
import MsTableButton from "../../MsTableButton";
|
import MsTableButton from "../../MsTableButton";
|
||||||
|
@ -189,8 +234,9 @@ import MsTable from "../../table/MsTable";
|
||||||
import MsTableColumn from "../../table/MsTableColumn";
|
import MsTableColumn from "../../table/MsTableColumn";
|
||||||
import ApiVariableSetting from "./ApiVariableSetting";
|
import ApiVariableSetting from "./ApiVariableSetting";
|
||||||
import CsvFileUpload from "./variable/CsvFileUpload";
|
import CsvFileUpload from "./variable/CsvFileUpload";
|
||||||
import { downloadFile, getUUID, operationConfirm } from "../../../utils";
|
import {downloadFile, getUUID, operationConfirm} from "../../../utils";
|
||||||
import VariableImport from "./variable/VariableImport";
|
import VariableImport from "./variable/VariableImport";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiScenarioVariables",
|
name: "MsApiScenarioVariables",
|
||||||
|
@ -230,15 +276,25 @@ export default {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
typeSelectOptions: [
|
typeSelectOptions: [
|
||||||
{ value: "CONSTANT", label: this.$t("api_test.automation.constant") },
|
{value: "CONSTANT", label: this.$t("api_test.automation.constant")},
|
||||||
{ value: "LIST", label: this.$t("test_track.case.list") },
|
{value: "LIST", label: this.$t("test_track.case.list")},
|
||||||
{ value: "CSV", label: "CSV" },
|
{value: "CSV", label: "CSV"},
|
||||||
{ value: "COUNTER", label: this.$t("api_test.automation.counter") },
|
{value: "COUNTER", label: this.$t("api_test.automation.counter")},
|
||||||
{ value: "RANDOM", label: this.$t("api_test.automation.random") },
|
{value: "RANDOM", label: this.$t("api_test.automation.random")},
|
||||||
|
],
|
||||||
|
uiTypeSelectOptions: [
|
||||||
|
{value: "STRING", label: this.$t("api_test.automation.string")},
|
||||||
|
{value: "ARRAY", label: this.$t("api_test.automation.array")},
|
||||||
|
{value: "JSON", label: this.$t("api_test.automation.json")},
|
||||||
|
{value: "NUMBER", label: this.$t("api_test.automation.number")},
|
||||||
],
|
],
|
||||||
variables: {},
|
variables: {},
|
||||||
selectVariable: "",
|
selectVariable: "",
|
||||||
editData: {},
|
editData: {},
|
||||||
|
scopeTypeFilters: [
|
||||||
|
{text: this.$t("commons.api"), value: "api"},
|
||||||
|
{text: this.$t("commons.ui_test"), value: "ui"},
|
||||||
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -279,15 +335,15 @@ export default {
|
||||||
if (repeatKey !== "") {
|
if (repeatKey !== "") {
|
||||||
this.$warning(
|
this.$warning(
|
||||||
this.$t("api_test.environment.common_config") +
|
this.$t("api_test.environment.common_config") +
|
||||||
"【" +
|
"【" +
|
||||||
repeatKey +
|
repeatKey +
|
||||||
"】" +
|
"】" +
|
||||||
this.$t("load_test.param_is_duplicate")
|
this.$t("load_test.param_is_duplicate")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (isNeedCreate) {
|
if (isNeedCreate) {
|
||||||
this.variables.push(
|
this.variables.push(
|
||||||
new KeyValue({ enable: true, id: getUUID(), type: "CONSTANT" })
|
new KeyValue({enable: true, id: getUUID(), type: "CONSTANT", scope: "api"})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.$emit("change", this.variables);
|
this.$emit("change", this.variables);
|
||||||
|
@ -304,6 +360,10 @@ export default {
|
||||||
data.files = [];
|
data.files = [];
|
||||||
data.quotedData = "false";
|
data.quotedData = "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data.scope || data.scope == "ui") {
|
||||||
|
data.type = 'STRING';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
valueText(data) {
|
valueText(data) {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
|
@ -320,11 +380,11 @@ export default {
|
||||||
},
|
},
|
||||||
querySearch(queryString, cb) {
|
querySearch(queryString, cb) {
|
||||||
let restaurants = [
|
let restaurants = [
|
||||||
{ value: "UTF-8" },
|
{value: "UTF-8"},
|
||||||
{ value: "UTF-16" },
|
{value: "UTF-16"},
|
||||||
{ value: "GB2312" },
|
{value: "GB2312"},
|
||||||
{ value: "ISO-8859-15" },
|
{value: "ISO-8859-15"},
|
||||||
{ value: "US-ASCll" },
|
{value: "US-ASCll"},
|
||||||
];
|
];
|
||||||
let results = queryString
|
let results = queryString
|
||||||
? restaurants.filter(this.createFilter(queryString))
|
? restaurants.filter(this.createFilter(queryString))
|
||||||
|
@ -346,6 +406,9 @@ export default {
|
||||||
this.$set(item, "description", item.remark);
|
this.$set(item, "description", item.remark);
|
||||||
item.remark = undefined;
|
item.remark = undefined;
|
||||||
}
|
}
|
||||||
|
if (!item.scope) {
|
||||||
|
this.$set(item, "scope", "api");
|
||||||
|
}
|
||||||
index++;
|
index++;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -369,7 +432,7 @@ export default {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
filter() {
|
filter(scope) {
|
||||||
let datas = [];
|
let datas = [];
|
||||||
this.variables.forEach((item) => {
|
this.variables.forEach((item) => {
|
||||||
if (this.selectVariable && this.selectVariable != "" && item.name) {
|
if (this.selectVariable && this.selectVariable != "" && item.name) {
|
||||||
|
@ -389,6 +452,12 @@ export default {
|
||||||
});
|
});
|
||||||
this.variables = datas;
|
this.variables = datas;
|
||||||
},
|
},
|
||||||
|
filterScope(value, row) {
|
||||||
|
if (value == "ui") {
|
||||||
|
return row.scope == "ui";
|
||||||
|
}
|
||||||
|
return !row.scope || row.scope == "api";
|
||||||
|
},
|
||||||
openSetting(data) {
|
openSetting(data) {
|
||||||
this.$refs.apiVariableSetting.open(data);
|
this.$refs.apiVariableSetting.open(data);
|
||||||
},
|
},
|
||||||
|
@ -449,8 +518,15 @@ export default {
|
||||||
this.sortParameters();
|
this.sortParameters();
|
||||||
},
|
},
|
||||||
exportJSON() {
|
exportJSON() {
|
||||||
if (this.$refs.variableTable.selectIds.length < 1) {
|
let apiVariable = [];
|
||||||
this.$warning(this.$t("api_test.environment.select_variable"));
|
this.$refs.variableTable.selectRows.forEach((r) => {
|
||||||
|
if (!r.scope || r.scope != "ui") {
|
||||||
|
apiVariable.push(r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (apiVariable.length < 1) {
|
||||||
|
this.$warning(this.$t("api_test.environment.select_api_variable"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let variablesJson = [];
|
let variablesJson = [];
|
||||||
|
@ -460,7 +536,7 @@ export default {
|
||||||
if (row.type === "CSV") {
|
if (row.type === "CSV") {
|
||||||
messages = this.$t("variables.csv_download");
|
messages = this.$t("variables.csv_download");
|
||||||
}
|
}
|
||||||
if (row.name) {
|
if (row.name && (!row.scope || row.scope == "api")) {
|
||||||
variablesJson.push(row);
|
variablesJson.push(row);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -493,10 +569,21 @@ export default {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleExportCommand(command){
|
||||||
|
this.exportJSON();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.items.length === 0) {
|
if (this.items.length === 0) {
|
||||||
this.items.push(new KeyValue({ enable: true }));
|
this.items.push(new KeyValue({enable: true, scope: "api"}));
|
||||||
|
} else {
|
||||||
|
//历史数据默认是 api 应用场景
|
||||||
|
_.forEach(this.items, item => {
|
||||||
|
if (!item.scope) {
|
||||||
|
this.$set(item, "scope", "api");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.variables = this.items;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -95,4 +95,6 @@ eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
|
||||||
eureka.instance.prefer-ip-address=true
|
eureka.instance.prefer-ip-address=true
|
||||||
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
|
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
|
||||||
#
|
#
|
||||||
|
# redisson
|
||||||
|
spring.redis.redisson.file=file:/opt/metersphere/conf/redisson.yml
|
||||||
|
spring.session.redis.repository-type=indexed
|
||||||
|
|
|
@ -463,6 +463,15 @@ public class GroupService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeGroupMember(String userId, String groupId) {
|
public void removeGroupMember(String userId, String groupId) {
|
||||||
|
Group group = groupMapper.selectByPrimaryKey(groupId);
|
||||||
|
if (group == null) {
|
||||||
|
MSException.throwException("group does not exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!StringUtils.equals(group.getType(), UserGroupType.PROJECT)) {
|
||||||
|
MSException.throwException("no permission to remove non-project type group users!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
UserGroupExample userGroupExample = new UserGroupExample();
|
UserGroupExample userGroupExample = new UserGroupExample();
|
||||||
userGroupExample.createCriteria()
|
userGroupExample.createCriteria()
|
||||||
.andGroupIdEqualTo(groupId)
|
.andGroupIdEqualTo(groupId)
|
||||||
|
|
|
@ -136,8 +136,8 @@ import MsTableOperator from "metersphere-frontend/src/components/MsTableOperator
|
||||||
import MsTableOperatorButton from "metersphere-frontend/src/components/MsTableOperatorButton";
|
import MsTableOperatorButton from "metersphere-frontend/src/components/MsTableOperatorButton";
|
||||||
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
|
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
|
||||||
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
|
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
|
||||||
import {Environment, parseEnvironment} from "metersphere-frontend/src/model/EnvironmentModel";
|
import {Environment, parseEnvironment, HttpConfig} from "metersphere-frontend/src/model/EnvironmentModel";
|
||||||
import EnvironmentEdit from "metersphere-frontend/src/components/environment/EnvironmentEdit";
|
import EnvironmentEdit from "./components/EnvironmentEdit";
|
||||||
import MsAsideItem from "metersphere-frontend/src/components/MsAsideItem";
|
import MsAsideItem from "metersphere-frontend/src/components/MsAsideItem";
|
||||||
import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer";
|
import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer";
|
||||||
import ProjectSwitch from "metersphere-frontend/src/components/head/ProjectSwitch";
|
import ProjectSwitch from "metersphere-frontend/src/components/head/ProjectSwitch";
|
||||||
|
@ -174,7 +174,7 @@ export default {
|
||||||
projectList: [],
|
projectList: [],
|
||||||
condition: {}, //封装传递给后端的查询条件
|
condition: {}, //封装传递给后端的查询条件
|
||||||
environments: [],
|
environments: [],
|
||||||
currentEnvironment: new Environment(),
|
currentEnvironment: new Environment({httpConfig: new HttpConfig()}),
|
||||||
result: {},
|
result: {},
|
||||||
loading: false,
|
loading: false,
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
|
@ -288,7 +288,7 @@ export default {
|
||||||
createEnv() {
|
createEnv() {
|
||||||
this.dialogTitle = this.$t('api_test.environment.create');
|
this.dialogTitle = this.$t('api_test.environment.create');
|
||||||
this.dialogVisible = true;
|
this.dialogVisible = true;
|
||||||
this.currentEnvironment = new Environment();
|
this.currentEnvironment = new Environment({httpConfig: new HttpConfig()});
|
||||||
this.currentEnvironment.projectId = this.currentProjectId;
|
this.currentEnvironment.projectId = this.currentProjectId;
|
||||||
this.currentEnvironment.currentProjectId = this.currentProjectId;
|
this.currentEnvironment.currentProjectId = this.currentProjectId;
|
||||||
this.ifCreate = true;
|
this.ifCreate = true;
|
||||||
|
|
|
@ -155,7 +155,7 @@ import {REQUEST_HEADERS} from "metersphere-frontend/src/utils/constants";
|
||||||
import {CommonConfig, Environment} from "metersphere-frontend/src/model/EnvironmentModel";
|
import {CommonConfig, Environment} from "metersphere-frontend/src/model/EnvironmentModel";
|
||||||
import MsApiHostTable from "metersphere-frontend/src/components/environment/commons/ApiHostTable";
|
import MsApiHostTable from "metersphere-frontend/src/components/environment/commons/ApiHostTable";
|
||||||
import MsDatabaseConfig from "metersphere-frontend/src/components/environment/database/DatabaseConfig";
|
import MsDatabaseConfig from "metersphere-frontend/src/components/environment/database/DatabaseConfig";
|
||||||
import MsEnvironmentHttpConfig from "metersphere-frontend/src/components/environment/EnvironmentHttpConfig";
|
import MsEnvironmentHttpConfig from "./EnvironmentHttpConfig";
|
||||||
import MsEnvironmentCommonConfig from "metersphere-frontend/src/components/environment/EnvironmentCommonConfig";
|
import MsEnvironmentCommonConfig from "metersphere-frontend/src/components/environment/EnvironmentCommonConfig";
|
||||||
import MsEnvironmentSSLConfig from "metersphere-frontend/src/components/environment/EnvironmentSSLConfig";
|
import MsEnvironmentSSLConfig from "metersphere-frontend/src/components/environment/EnvironmentSSLConfig";
|
||||||
import MsApiAuthConfig from "metersphere-frontend/src/components/environment/auth/ApiAuthConfig";
|
import MsApiAuthConfig from "metersphere-frontend/src/components/environment/auth/ApiAuthConfig";
|
||||||
|
|
|
@ -126,6 +126,7 @@ public class GroupController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/rm/{userId}/{groupId}")
|
@GetMapping("/rm/{userId}/{groupId}")
|
||||||
|
@RequiresPermissions(PermissionConstants.SYSTEM_GROUP_READ)
|
||||||
public void removeGroupMember(@PathVariable String userId, @PathVariable String groupId) {
|
public void removeGroupMember(@PathVariable String userId, @PathVariable String groupId) {
|
||||||
groupService.removeGroupMember(userId, groupId);
|
groupService.removeGroupMember(userId, groupId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,10 +162,11 @@ public class GroupService {
|
||||||
|
|
||||||
public void deleteGroup(String id) {
|
public void deleteGroup(String id) {
|
||||||
Group group = groupMapper.selectByPrimaryKey(id);
|
Group group = groupMapper.selectByPrimaryKey(id);
|
||||||
if (group != null) {
|
if (group == null) {
|
||||||
if (BooleanUtils.isTrue(group.getSystem())) {
|
MSException.throwException("group does not exist!");
|
||||||
MSException.throwException("系统用户组不支持删除!");
|
}
|
||||||
}
|
if (BooleanUtils.isTrue(group.getSystem())) {
|
||||||
|
MSException.throwException("系统用户组不支持删除!");
|
||||||
}
|
}
|
||||||
groupMapper.deleteByPrimaryKey(id);
|
groupMapper.deleteByPrimaryKey(id);
|
||||||
|
|
||||||
|
|
|
@ -385,12 +385,6 @@ public class TestPlanReportService {
|
||||||
TestPlanReportContentWithBLOBs testPlanReportContent = new TestPlanReportContentWithBLOBs();
|
TestPlanReportContentWithBLOBs testPlanReportContent = new TestPlanReportContentWithBLOBs();
|
||||||
testPlanReportContent.setId(UUID.randomUUID().toString());
|
testPlanReportContent.setId(UUID.randomUUID().toString());
|
||||||
testPlanReportContent.setTestPlanReportId(returnDTO.getTestPlanReport().getId());
|
testPlanReportContent.setTestPlanReportId(returnDTO.getTestPlanReport().getId());
|
||||||
if (testPlanReportContent.getStartTime() == null) {
|
|
||||||
testPlanReportContent.setStartTime(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
if (testPlanReportContent.getEndTime() == null) {
|
|
||||||
testPlanReportContent.setEndTime(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
testPlanReportContentMapper.insert(testPlanReportContent);
|
testPlanReportContentMapper.insert(testPlanReportContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,8 +643,10 @@ public class TestPlanReportService {
|
||||||
TestPlanReportContentWithBLOBs testPlanReportContent = null;
|
TestPlanReportContentWithBLOBs testPlanReportContent = null;
|
||||||
TestPlanSimpleReportDTO reportDTO = testPlanService.buildPlanReport(testPlan.getId(), false);
|
TestPlanSimpleReportDTO reportDTO = testPlanService.buildPlanReport(testPlan.getId(), false);
|
||||||
if (!testPlanReportContentList.isEmpty()) {
|
if (!testPlanReportContentList.isEmpty()) {
|
||||||
testPlanReportContent = testPlanReportContentList.get(0);
|
testPlanReportContent = parseReportDaoToReportContent(reportDTO, testPlanReportContentList.get(0));
|
||||||
testPlanReportContentMapper.updateByPrimaryKeySelective(parseReportDaoToReportContent(reportDTO, testPlanReportContent));
|
testPlanReportContent.setStartTime(null);
|
||||||
|
testPlanReportContent.setEndTime(null);
|
||||||
|
testPlanReportContentMapper.updateByPrimaryKeySelective(testPlanReportContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reportDTO.getStartTime() == null) {
|
if (reportDTO.getStartTime() == null) {
|
||||||
|
|
|
@ -65,8 +65,6 @@ import org.springframework.kafka.core.KafkaTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
|
@ -1554,6 +1552,10 @@ public class TestPlanService {
|
||||||
envMap = planTestPlanApiCaseService.getApiCaseEnv(planId);
|
envMap = planTestPlanApiCaseService.getApiCaseEnv(planId);
|
||||||
Map<String, List<String>> scenarioEnv = planTestPlanScenarioCaseService.getApiScenarioEnv(planId);
|
Map<String, List<String>> scenarioEnv = planTestPlanScenarioCaseService.getApiScenarioEnv(planId);
|
||||||
|
|
||||||
|
if (DiscoveryUtil.hasService(MicroServiceName.UI_TEST)) {
|
||||||
|
scenarioEnv = mergeUiScenarioEnv(planId, scenarioEnv);
|
||||||
|
}
|
||||||
|
|
||||||
Set<String> projectIds = scenarioEnv.keySet();
|
Set<String> projectIds = scenarioEnv.keySet();
|
||||||
for (String projectId : projectIds) {
|
for (String projectId : projectIds) {
|
||||||
if (envMap.containsKey(projectId)) {
|
if (envMap.containsKey(projectId)) {
|
||||||
|
@ -1576,6 +1578,32 @@ public class TestPlanService {
|
||||||
return envMap;
|
return envMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并ui场景的环境信息
|
||||||
|
* @param planId
|
||||||
|
* @param scenarioEnv
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String, List<String>> mergeUiScenarioEnv(String planId, Map<String, List<String>> scenarioEnv) {
|
||||||
|
Map<String, List<String>> uiScenarioEnv = planTestPlanUiScenarioCaseService.getUiScenarioEnv(planId);
|
||||||
|
if (MapUtils.isEmpty(scenarioEnv)) {
|
||||||
|
return uiScenarioEnv;
|
||||||
|
}
|
||||||
|
if (MapUtils.isNotEmpty(uiScenarioEnv)) {
|
||||||
|
uiScenarioEnv.entrySet().forEach(entry -> {
|
||||||
|
if (scenarioEnv.containsKey(entry.getKey())) {
|
||||||
|
List<String> environmentIds = scenarioEnv.get(entry.getKey());
|
||||||
|
entry.getValue().forEach(eId -> {
|
||||||
|
if (!environmentIds.contains(eId)) {
|
||||||
|
environmentIds.add(eId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return scenarioEnv;
|
||||||
|
}
|
||||||
|
|
||||||
public String runPlan(TestPlanRunRequest testplanRunRequest) {
|
public String runPlan(TestPlanRunRequest testplanRunRequest) {
|
||||||
//检查测试计划下有没有可以执行的用例;
|
//检查测试计划下有没有可以执行的用例;
|
||||||
if (!haveExecCase(testplanRunRequest.getTestPlanId(), false)) {
|
if (!haveExecCase(testplanRunRequest.getTestPlanId(), false)) {
|
||||||
|
|
|
@ -175,6 +175,9 @@ export default {
|
||||||
},
|
},
|
||||||
radioChange(val) {
|
radioChange(val) {
|
||||||
this.$emit("update:environmentType", val);
|
this.$emit("update:environmentType", val);
|
||||||
|
},
|
||||||
|
close(){
|
||||||
|
this.visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
|
<env-group-popover
|
||||||
|
:env-map="projectEnvMap"
|
||||||
|
:project-ids="projectIds"
|
||||||
|
:show-env-group="false"
|
||||||
|
@setProjectEnvMap="setProjectEnvMap"
|
||||||
|
:environment-type.sync="environmentType"
|
||||||
|
:group-id="envGroupId"
|
||||||
|
:is-scenario="false"
|
||||||
|
@setEnvGroup="setEnvGroup"
|
||||||
|
:show-config-button-with-out-permission="
|
||||||
|
showConfigButtonWithOutPermission
|
||||||
|
"
|
||||||
|
:project-list="projectList"
|
||||||
|
ref="envPopover"
|
||||||
|
class="env-popover"
|
||||||
|
/>
|
||||||
|
|
||||||
<ms-table-adv-search-bar :condition.sync="condition" class="adv-search-bar"
|
<ms-table-adv-search-bar :condition.sync="condition" class="adv-search-bar"
|
||||||
v-if="condition.components !== undefined && condition.components.length > 0"
|
v-if="condition.components !== undefined && condition.components.length > 0"
|
||||||
|
@ -99,6 +115,9 @@ import {
|
||||||
getCustomTableWidth
|
getCustomTableWidth
|
||||||
} from "metersphere-frontend/src/utils/tableUtils";
|
} from "metersphere-frontend/src/utils/tableUtils";
|
||||||
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
||||||
|
import EnvGroupPopover from "@/business/plan/env/EnvGroupPopover";
|
||||||
|
import {getApiScenarioEnvByProjectId} from "@/api/remote/api/api-automation";
|
||||||
|
import {getUiScenarioEnvByProjectId} from "@/api/remote/ui/ui-automation";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "RelevanceUiScenarioList",
|
name: "RelevanceUiScenarioList",
|
||||||
|
@ -112,6 +131,7 @@ export default {
|
||||||
MsTag,
|
MsTag,
|
||||||
MsTableAdvSearchBar,
|
MsTableAdvSearchBar,
|
||||||
MsTableColumn,
|
MsTableColumn,
|
||||||
|
EnvGroupPopover,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
referenced: {
|
referenced: {
|
||||||
|
@ -147,6 +167,7 @@ export default {
|
||||||
envGroupId: "",
|
envGroupId: "",
|
||||||
versionFilters: [],
|
versionFilters: [],
|
||||||
fieldsWidth: getCustomTableWidth('TEST_PLAN_UI_SCENARIO_CASE'),
|
fieldsWidth: getCustomTableWidth('TEST_PLAN_UI_SCENARIO_CASE'),
|
||||||
|
projectIds: new Set()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -244,9 +265,24 @@ export default {
|
||||||
selectCountChange(data) {
|
selectCountChange(data) {
|
||||||
this.selectRows = this.$refs.scenarioTable.selectRows;
|
this.selectRows = this.$refs.scenarioTable.selectRows;
|
||||||
this.$emit("selectCountChange", data);
|
this.$emit("selectCountChange", data);
|
||||||
|
this.initProjectIds();
|
||||||
},
|
},
|
||||||
showReport() {
|
showReport() {
|
||||||
|
|
||||||
|
},
|
||||||
|
initProjectIds() {
|
||||||
|
this.projectIds.clear();
|
||||||
|
// this.map.clear();
|
||||||
|
this.selectRows.forEach((row) => {
|
||||||
|
getUiScenarioEnvByProjectId(row.id).then((res) => {
|
||||||
|
let data = res.data;
|
||||||
|
data.projectIds.forEach((d) => this.projectIds.add(d));
|
||||||
|
// this.map.set(row.id, data.projectIds);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
closeEnv(){
|
||||||
|
this.$refs.envPopover.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,6 +87,8 @@ export default {
|
||||||
},
|
},
|
||||||
setProject(projectId) {
|
setProject(projectId) {
|
||||||
this.projectId = projectId;
|
this.projectId = projectId;
|
||||||
|
this.$refs.apiScenarioList.closeEnv();
|
||||||
|
this.$refs.apiScenarioList.initProjectIds();
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh(data) {
|
refresh(data) {
|
||||||
|
@ -148,6 +150,10 @@ export default {
|
||||||
let map = this.$refs.apiScenarioList.map;
|
let map = this.$refs.apiScenarioList.map;
|
||||||
let envGroupId = this.$refs.apiScenarioList.envGroupId;
|
let envGroupId = this.$refs.apiScenarioList.envGroupId;
|
||||||
|
|
||||||
|
if (!envMap || envMap.size == 0) {
|
||||||
|
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
selectRows.forEach(row => {
|
selectRows.forEach(row => {
|
||||||
selectIds.push(row.id);
|
selectIds.push(row.id);
|
||||||
})
|
})
|
||||||
|
@ -179,8 +185,6 @@ export default {
|
||||||
this.autoCheckStatus();
|
this.autoCheckStatus();
|
||||||
this.$refs.baseRelevance.close();
|
this.$refs.baseRelevance.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
autoCheckStatus() { // 检查执行结果,自动更新计划状态
|
autoCheckStatus() { // 检查执行结果,自动更新计划状态
|
||||||
if (!this.planId) {
|
if (!this.planId) {
|
||||||
|
|
|
@ -147,7 +147,8 @@
|
||||||
:filters="apiscenariofilters.RESULT_FILTERS"
|
:filters="apiscenariofilters.RESULT_FILTERS"
|
||||||
:label="$t('api_test.automation.last_result')">
|
:label="$t('api_test.automation.last_result')">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-link @click="showReport(row)" :disabled="!row.lastResult || row.lastResult==='PENDING' || row.lastResult==='UnExecute'">
|
<el-link @click="showReport(row)"
|
||||||
|
:disabled="!row.lastResult || row.lastResult==='PENDING' || row.lastResult==='UnExecute'">
|
||||||
<ms-test-plan-api-status :status="row.lastResult==='UnExecute' ? 'PENDING' : row.lastResult"/>
|
<ms-test-plan-api-status :status="row.lastResult==='UnExecute' ? 'PENDING' : row.lastResult"/>
|
||||||
</el-link>
|
</el-link>
|
||||||
</template>
|
</template>
|
||||||
|
@ -176,8 +177,8 @@
|
||||||
:select-row="this.$refs.table ? this.$refs.table.selectRows : new Set()" ref="batchEdit"
|
:select-row="this.$refs.table ? this.$refs.table.selectRows : new Set()" ref="batchEdit"
|
||||||
@batchEdit="batchEdit"/>
|
@batchEdit="batchEdit"/>
|
||||||
|
|
||||||
<ui-run-mode @handleRunBatch="handleRunBatch" ref="runMode" :custom-run-mode="true"
|
<ui-run-mode @handleRunBatch="handleRunBatch" ref="runMode" :custom-run-mode="true"
|
||||||
:custom-serial-on-sample-error="true"/>
|
:custom-serial-on-sample-error="true" :request="conditionRequest"/>
|
||||||
|
|
||||||
<ms-task-center ref="taskCenter" :show-menu="false"/>
|
<ms-task-center ref="taskCenter" :show-menu="false"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -327,6 +328,8 @@ export default {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
versionFilters: [],
|
versionFilters: [],
|
||||||
|
//
|
||||||
|
conditionRequest: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -358,14 +361,14 @@ export default {
|
||||||
},
|
},
|
||||||
search() {
|
search() {
|
||||||
initCondition(this.condition, this.condition.selectAll);
|
initCondition(this.condition, this.condition.selectAll);
|
||||||
if(this.condition && this.condition.filters && this.condition.filters.last_result){
|
if (this.condition && this.condition.filters && this.condition.filters.last_result) {
|
||||||
if(this.condition.filters.last_result.length > 0){
|
if (this.condition.filters.last_result.length > 0) {
|
||||||
//校验是否含有PENDING
|
//校验是否含有PENDING
|
||||||
if(this.condition.filters.last_result.includes("PENDING")){
|
if (this.condition.filters.last_result.includes("PENDING")) {
|
||||||
this.condition.filters.last_result = [...this.condition.filters.last_result, "UnExecute"]
|
this.condition.filters.last_result = [...this.condition.filters.last_result, "UnExecute"]
|
||||||
}
|
}
|
||||||
//校验是否含有ERROR
|
//校验是否含有ERROR
|
||||||
if(this.condition.filters.last_result.includes("ERROR")){
|
if (this.condition.filters.last_result.includes("ERROR")) {
|
||||||
this.condition.filters.last_result = [...this.condition.filters.last_result, "FAIL"]
|
this.condition.filters.last_result = [...this.condition.filters.last_result, "FAIL"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,12 +440,19 @@ export default {
|
||||||
let rows = this.orderBySelectRows(this.$refs.table.selectRows);
|
let rows = this.orderBySelectRows(this.$refs.table.selectRows);
|
||||||
this.planCaseIds = [];
|
this.planCaseIds = [];
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
this.planCaseIds.push(row.id);
|
this.planCaseIds.push(row.caseId);
|
||||||
})
|
})
|
||||||
|
this.conditionRequest.id = getUUID();
|
||||||
|
this.conditionRequest.ids = this.planCaseIds;
|
||||||
|
this.conditionRequest.projectId = this.projectId;
|
||||||
|
this.conditionRequest.condition = this.condition;
|
||||||
this.$refs.runMode.open();
|
this.$refs.runMode.open();
|
||||||
},
|
},
|
||||||
orderBySelectRows(rows) {
|
orderBySelectRows(rows) {
|
||||||
let selectIds = Array.from(rows).map(row => row.id);
|
let selectIds = this.$refs.table.selectIds;
|
||||||
|
if (rows) {
|
||||||
|
selectIds = Array.from(rows).map(row => row.id);
|
||||||
|
}
|
||||||
let array = [];
|
let array = [];
|
||||||
for (let i in this.tableData) {
|
for (let i in this.tableData) {
|
||||||
if (selectIds.indexOf(this.tableData[i].id) !== -1) {
|
if (selectIds.indexOf(this.tableData[i].id) !== -1) {
|
||||||
|
@ -499,8 +509,8 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
this.$t("ui.view_config")
|
this.$t("ui.view_config")
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
validate = false;
|
validate = false;
|
||||||
|
|
|
@ -7,6 +7,21 @@
|
||||||
:visible.sync="runModeVisible"
|
:visible.sync="runModeVisible"
|
||||||
>
|
>
|
||||||
<div class="mode-container">
|
<div class="mode-container">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>{{ $t("commons.environment") }}:</div>
|
||||||
|
<env-select-popover :project-ids="projectIds"
|
||||||
|
:project-list="projectList"
|
||||||
|
:project-env-map="projectEnvListMap"
|
||||||
|
:environment-type="'JSON'"
|
||||||
|
:has-option-group="false"
|
||||||
|
:group-id="runConfig.environmentGroupId"
|
||||||
|
@setProjectEnvMap="setProjectEnvMap"
|
||||||
|
ref="envSelectPopover"
|
||||||
|
class="mode-row"
|
||||||
|
></env-select-popover>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 浏览器 -->
|
<!-- 浏览器 -->
|
||||||
<div class="browser-row wrap">
|
<div class="browser-row wrap">
|
||||||
<div class="title">{{ $t("ui.browser") }}:</div>
|
<div class="title">{{ $t("ui.browser") }}:</div>
|
||||||
|
@ -175,11 +190,13 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter'
|
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter'
|
||||||
import {getOwnerProjects} from "@/business/utils/sdk-utils";
|
import {getCurrentProjectID, getOwnerProjects, strMapToObj} from "@/business/utils/sdk-utils";
|
||||||
|
import {uiScenarioEnvMap} from "@/api/remote/ui/ui-automation";
|
||||||
|
import EnvSelectPopover from "@/business/plan/env/EnvSelectPopover";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "UiRunMode",
|
name: "UiRunMode",
|
||||||
components: {MsDialogFooter},
|
components: {MsDialogFooter, EnvSelectPopover},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
runModeVisible: false,
|
runModeVisible: false,
|
||||||
|
@ -207,6 +224,8 @@ export default {
|
||||||
},
|
},
|
||||||
projectList: [],
|
projectList: [],
|
||||||
projectIds: new Set(),
|
projectIds: new Set(),
|
||||||
|
projectEnvListMap: {},
|
||||||
|
caseIdEnvNameMap: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -262,6 +281,7 @@ export default {
|
||||||
};
|
};
|
||||||
this.runModeVisible = true;
|
this.runModeVisible = true;
|
||||||
this.getWsProjects();
|
this.getWsProjects();
|
||||||
|
this.showPopover();
|
||||||
},
|
},
|
||||||
changeMode() {
|
changeMode() {
|
||||||
this.runConfig.runWithinResourcePool = false;
|
this.runConfig.runWithinResourcePool = false;
|
||||||
|
@ -296,6 +316,29 @@ export default {
|
||||||
this.$emit("handleRunBatch", this.runConfig);
|
this.$emit("handleRunBatch", this.runConfig);
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
setProjectEnvMap(projectEnvMap) {
|
||||||
|
this.runConfig.envMap = strMapToObj(projectEnvMap);
|
||||||
|
},
|
||||||
|
showPopover() {
|
||||||
|
this.showScenarioPopover();
|
||||||
|
},
|
||||||
|
showScenarioPopover() {
|
||||||
|
let currentProjectID = getCurrentProjectID();
|
||||||
|
this.projectIds.clear();
|
||||||
|
uiScenarioEnvMap(this.request).then((res) => {
|
||||||
|
let data = res.data;
|
||||||
|
this.projectEnvListMap = data;
|
||||||
|
if (data) {
|
||||||
|
for (let d in data) {
|
||||||
|
this.projectIds.add(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.projectIds.size === 0) {
|
||||||
|
this.projectIds.add(currentProjectID);
|
||||||
|
}
|
||||||
|
this.$refs.envSelectPopover.open();
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -88,6 +88,7 @@ const TRACK_HEADER = {
|
||||||
{id: 'name', key: '2', label: 'api_test.automation.scenario_name'},
|
{id: 'name', key: '2', label: 'api_test.automation.scenario_name'},
|
||||||
{id: 'versionId', key: 'd', label: 'commons.version'},
|
{id: 'versionId', key: 'd', label: 'commons.version'},
|
||||||
{id: 'level', key: '3', label: 'api_test.automation.case_level'},
|
{id: 'level', key: '3', label: 'api_test.automation.case_level'},
|
||||||
|
{id: 'envs', key: '8', label: 'commons.environment'},
|
||||||
{id: 'tagNames', key: '4', label: 'api_test.automation.tag'},
|
{id: 'tagNames', key: '4', label: 'api_test.automation.tag'},
|
||||||
{id: 'stepTotal', key: '7', label: 'api_test.automation.step'},
|
{id: 'stepTotal', key: '7', label: 'api_test.automation.step'},
|
||||||
{id: 'passRate', key: '9', label: 'api_test.automation.passing_rate'},
|
{id: 'passRate', key: '9', label: 'api_test.automation.passing_rate'},
|
||||||
|
|
Loading…
Reference in New Issue