From 9b22917e8c0491aca2cec2888a68633547b92d25 Mon Sep 17 00:00:00 2001 From: "song.tianyang" Date: Wed, 6 Jan 2021 10:17:55 +0800 Subject: [PATCH 1/8] =?UTF-8?q?fix:=20=E9=A6=96=E9=A1=B5=E8=B7=B3=E8=BD=AC?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E4=BF=AE=E6=94=B9=E9=A1=B5=E9=9D=A2=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E5=A5=97=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复首页跳转场景修改页面控制套报错的问题 --- .../business/components/api/automation/ApiAutomation.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/automation/ApiAutomation.vue b/frontend/src/business/components/api/automation/ApiAutomation.vue index fcc2f45bea..fe9227773c 100644 --- a/frontend/src/business/components/api/automation/ApiAutomation.vue +++ b/frontend/src/business/components/api/automation/ApiAutomation.vue @@ -87,7 +87,7 @@ export default { isHide: true, activeName: 'default', currentModule: null, - moduleOptions: {}, + moduleOptions: [], tabs: [], trashEnable: false, selectNodeIds: [], @@ -114,7 +114,12 @@ export default { this.$post(url, {id:scenarioId,projectId:projectId}, response => { let data = response.data; if(data!=null){ + //如果树未加载 + if(JSON.stringify(this.moduleOptions) === '{}' ){ + this.$refs.nodeTree.list(); + } let row = data.listObject[0]; + row.tags = JSON.parse(row.tags); this.editScenario(row); } }); From 55e8d9fec67758bb392bd7403d84a7955aef31ea Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 6 Jan 2021 12:04:21 +0800 Subject: [PATCH 2/8] =?UTF-8?q?refactor:=20=E5=AF=BC=E5=85=A5=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=88=B0=E6=8C=87=E5=AE=9A=E7=9B=AE=E5=BD=95=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/parse/ApiImportAbstractParser.java | 29 +++++++++++++++ .../io/metersphere/api/parse/MsParser.java | 36 ++++++------------- .../metersphere/api/parse/PostmanParser.java | 21 ++--------- .../metersphere/api/parse/Swagger2Parser.java | 26 ++++---------- .../metersphere/api/parse/Swagger3Parser.java | 26 ++++---------- .../api/parse/SwaggerAbstractParser.java | 19 ++++++++++ 6 files changed, 73 insertions(+), 84 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java diff --git a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java index 0fde847e07..e5f05b7805 100644 --- a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java @@ -2,6 +2,7 @@ package io.metersphere.api.parse; import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.definition.ApiDefinitionResult; +import io.metersphere.api.dto.definition.ApiModuleDTO; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; @@ -11,6 +12,8 @@ import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.BeanUtils; +import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.SessionUtils; import org.apache.commons.collections.CollectionUtils; @@ -60,6 +63,32 @@ public abstract class ApiImportAbstractParser implements ApiImportParser { } } + protected ApiModule getSelectModule(String moduleId) { + apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + if (StringUtils.isNotBlank(moduleId)) { + ApiModule module = new ApiModule(); + ApiModuleDTO moduleDTO = apiModuleService.getNode(moduleId); + BeanUtils.copyBean(module, moduleDTO); + return module; + } + return null; + } + + protected ApiModule buildModule(ApiModule parentModule, String name, boolean isSaved) { + apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + ApiModule module; + if (parentModule != null) { + module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1); + module.setParentId(parentModule.getId()); + } else { + module = apiModuleService.getNewModule(name, this.projectId, 1); + } + if (isSaved) { + createModule(module); + } + return module; + } + protected void createModule(ApiModule module) { module.setProtocol(RequestType.HTTP); List apiModules = apiModuleService.selectSameModule(module); diff --git a/backend/src/main/java/io/metersphere/api/parse/MsParser.java b/backend/src/main/java/io/metersphere/api/parse/MsParser.java index 512965d760..0838445d12 100644 --- a/backend/src/main/java/io/metersphere/api/parse/MsParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/MsParser.java @@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.definition.ApiDefinitionResult; +import io.metersphere.api.dto.definition.ApiModuleDTO; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.scenario.Body; @@ -31,7 +32,7 @@ public class MsParser extends ApiImportAbstractParser { if (testObject.get("projectName") != null) { return parseMsFormat(testStr, request); } else { - return parsePluginFormat(testObject, request.isSaved()); + return parsePluginFormat(testObject, request); } } @@ -44,7 +45,7 @@ public class MsParser extends ApiImportAbstractParser { if (StringUtils.isBlank(apiDefinition.getModulePath())) { apiDefinition.setModuleId(null); } - parseModule(apiDefinition, importRequest.isSaved()); + parseModule(apiDefinition, importRequest); apiDefinition.setId(id); apiDefinition.setProjectId(this.projectId); String request = apiDefinition.getRequest(); @@ -55,16 +56,16 @@ public class MsParser extends ApiImportAbstractParser { return apiDefinitionImport; } - private ApiDefinitionImport parsePluginFormat(JSONObject testObject, boolean isSaved) { + private ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) { List results = new ArrayList<>(); ApiDefinitionImport apiImport = new ApiDefinitionImport(); apiImport.setProtocol(RequestType.HTTP); apiImport.setData(results); testObject.keySet().forEach(tag -> { - ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1); - if (isSaved) { - createModule(module); - } + + ApiModule parentModule = getSelectModule(importRequest.getModuleId()); + ApiModule module = buildModule(parentModule, tag, importRequest.isSaved()); + JSONObject requests = testObject.getJSONObject(tag); requests.keySet().forEach(requestName -> { @@ -125,7 +126,7 @@ public class MsParser extends ApiImportAbstractParser { } - private void parseModule(ApiDefinitionResult apiDefinition, Boolean isSaved) { + private void parseModule(ApiDefinitionResult apiDefinition, ApiTestImportRequest importRequest) { String modulePath = apiDefinition.getModulePath(); if (StringUtils.isBlank(modulePath)) { return; @@ -137,29 +138,14 @@ public class MsParser extends ApiImportAbstractParser { modulePath = modulePath.substring(0, modulePath.length() - 1); } List modules = Arrays.asList(modulePath.split("/")); - ApiModule parent = null; + ApiModule parent = getSelectModule(importRequest.getModuleId()); Iterator iterator = modules.iterator(); while (iterator.hasNext()) { String item = iterator.next(); - parent = buildModule(item, parent, isSaved); + parent = buildModule(parent, item, importRequest.isSaved()); if (!iterator.hasNext()) { apiDefinition.setModuleId(parent.getId()); } } } - - private ApiModule buildModule(String name, ApiModule parentModule, boolean isSaved) { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module; - if (parentModule != null) { - module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1); - module.setParentId(parentModule.getId()); - } else { - module = apiModuleService.getNewModule(name, this.projectId, 1); - } - if (isSaved) { - createModule(module); - } - return module; - } } diff --git a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java index 9809326b35..71d2379d3e 100644 --- a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java @@ -9,11 +9,9 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.parse.postman.*; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; -import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.constants.MsRequestBodyType; import io.metersphere.commons.constants.PostmanRequestBodyMode; -import io.metersphere.commons.utils.CommonBeanFactory; import org.apache.commons.lang3.StringUtils; import java.io.InputStream; @@ -30,7 +28,7 @@ public class PostmanParser extends ApiImportAbstractParser { List variables = postmanCollection.getVariable(); ApiDefinitionImport apiImport = new ApiDefinitionImport(); List results = new ArrayList<>(); - parseItem(postmanCollection.getItem(), variables, results, buildModule(postmanCollection.getInfo().getName(), null, request.isSaved()), request.isSaved()); + parseItem(postmanCollection.getItem(), variables, results, buildModule(getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName(), request.isSaved()), request.isSaved()); apiImport.setData(results); return apiImport; } @@ -39,7 +37,7 @@ public class PostmanParser extends ApiImportAbstractParser { for (PostmanItem item : items) { List childItems = item.getItem(); if (childItems != null) { - ApiModule module = buildModule(item.getName(), parentModule, isSaved); + ApiModule module = buildModule(parentModule, item.getName() , isSaved); parseItem(childItems, variables, results, module, isSaved); } else { ApiDefinitionResult request = parsePostman(item); @@ -53,21 +51,6 @@ public class PostmanParser extends ApiImportAbstractParser { } } - private ApiModule buildModule(String name, ApiModule parentModule, boolean isSaved) { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module; - if (parentModule != null) { - module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1); - module.setParentId(parentModule.getId()); - } else { - module = apiModuleService.getNewModule(name, this.projectId, 1); - } - if (isSaved) { - createModule(module); - } - return module; - } - private ApiDefinitionResult parsePostman(PostmanItem requestItem) { PostmanRequest requestDesc = requestItem.getRequest(); if (requestDesc == null) { diff --git a/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java b/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java index d61d9af101..b080aa2e23 100644 --- a/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java +++ b/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java @@ -11,10 +11,8 @@ import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.request.RequestType; -import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.constants.SwaggerParameterType; -import io.metersphere.commons.utils.CommonBeanFactory; import io.swagger.models.*; import io.swagger.models.parameters.*; import io.swagger.models.properties.*; @@ -25,7 +23,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.InputStream; import java.util.*; -public class Swagger2Parser extends ApiImportAbstractParser { +public class Swagger2Parser extends SwaggerAbstractParser { private Map definitions = null; @@ -47,11 +45,11 @@ public class Swagger2Parser extends ApiImportAbstractParser { ApiDefinitionImport definitionImport = new ApiDefinitionImport(); this.projectId = request.getProjectId(); - definitionImport.setData(parseRequests(swagger, request.isSaved())); + definitionImport.setData(parseRequests(swagger, request)); return definitionImport; } - private List parseRequests(Swagger swagger, boolean isSaved) { + private List parseRequests(Swagger swagger, ApiTestImportRequest importRequest) { Map paths = swagger.getPaths(); Set pathNames = paths.keySet(); @@ -59,6 +57,8 @@ public class Swagger2Parser extends ApiImportAbstractParser { List results = new ArrayList<>(); + ApiModule parentNode = getSelectModule(importRequest.getModuleId()); + for (String pathName : pathNames) { Path path = paths.get(pathName); Map operationMap = path.getOperationMap(); @@ -70,7 +70,7 @@ public class Swagger2Parser extends ApiImportAbstractParser { parseParameters(operation, request); apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses()))); - buildModule(apiDefinition, operation, isSaved); + buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved()); results.add(apiDefinition); } } @@ -79,20 +79,6 @@ public class Swagger2Parser extends ApiImportAbstractParser { return results; } - private void buildModule(ApiDefinitionResult apiDefinition, Operation operation, boolean isSaved) { - List tags = operation.getTags(); - if (tags != null) { - tags.forEach(tag -> { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1); - if (isSaved) { - createModule(module); - } - apiDefinition.setModuleId(module.getId()); - }); - } - } - private ApiDefinitionResult buildApiDefinition(String id, Operation operation, String path, String method) { String name = ""; if (StringUtils.isNotBlank(operation.getSummary())) { diff --git a/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java b/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java index 92edcfddf1..ac6ae883fa 100644 --- a/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java +++ b/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java @@ -11,10 +11,8 @@ import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.request.RequestType; -import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.exception.MSException; -import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.XMLUtils; import io.swagger.parser.OpenAPIParser; @@ -34,7 +32,7 @@ import java.io.InputStream; import java.util.*; -public class Swagger3Parser extends ApiImportAbstractParser { +public class Swagger3Parser extends SwaggerAbstractParser { private Components components; @@ -67,11 +65,11 @@ public class Swagger3Parser extends ApiImportAbstractParser { ApiDefinitionImport definitionImport = new ApiDefinitionImport(); this.projectId = request.getProjectId(); - definitionImport.setData(parseRequests(openAPI, request.isSaved())); + definitionImport.setData(parseRequests(openAPI, request)); return definitionImport; } - private List parseRequests(OpenAPI openAPI, boolean isSaved) { + private List parseRequests(OpenAPI openAPI, ApiTestImportRequest importRequest) { Paths paths = openAPI.getPaths(); Set pathNames = paths.keySet(); @@ -80,6 +78,8 @@ public class Swagger3Parser extends ApiImportAbstractParser { List results = new ArrayList<>(); + ApiModule parentNode = getSelectModule(importRequest.getModuleId()); + for (String pathName : pathNames) { PathItem pathItem = paths.get(pathName); @@ -102,7 +102,7 @@ public class Swagger3Parser extends ApiImportAbstractParser { parseRequestBody(operation.getRequestBody(), request.getBody()); apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses()))); - buildModule(apiDefinition, operation, isSaved); + buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved()); results.add(apiDefinition); } } @@ -111,20 +111,6 @@ public class Swagger3Parser extends ApiImportAbstractParser { return results; } - private void buildModule(ApiDefinitionResult apiDefinition, Operation operation, boolean isSaved) { - List tags = operation.getTags(); - if (tags != null) { - tags.forEach(tag -> { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1); - if (isSaved) { - createModule(module); - } - apiDefinition.setModuleId(module.getId()); - }); - } - } - private ApiDefinitionResult buildApiDefinition(String id, Operation operation, String path, String method) { String name = ""; if (StringUtils.isNotBlank(operation.getSummary())) { diff --git a/backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java b/backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java new file mode 100644 index 0000000000..1973109c54 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java @@ -0,0 +1,19 @@ +package io.metersphere.api.parse; + +import io.metersphere.api.dto.definition.ApiDefinitionResult; +import io.metersphere.base.domain.ApiModule; + +import java.util.List; + +public abstract class SwaggerAbstractParser extends ApiImportAbstractParser { + + protected void buildModule(ApiModule parentModule, ApiDefinitionResult apiDefinition, List tags, boolean isSaved) { + if (tags != null) { + tags.forEach(tag -> { + ApiModule module = buildModule(parentModule, tag, isSaved); + apiDefinition.setModuleId(module.getId()); + }); + } + } + +} From fc8c997716c4aa1369c5c80b8b9c37f2bfd7c623 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 6 Jan 2021 12:24:13 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E6=95=B0=E6=8D=AE=E8=BF=81=E7=A7=BB=E5=88=9D?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/APITestController.java | 82 +++-- .../controller/ApiAutomationController.java | 1 + .../api/dto/SaveHistoricalDataUpgrade.java | 18 + .../request/sampler/MsDubboSampler.java | 2 +- .../request/sampler/MsHTTPSamplerProxy.java | 6 +- .../service/HistoricalDataUpgradeService.java | 331 ++++++++++++++++++ .../api/automation/scenario/ApiComponent.vue | 4 +- .../assertion/ApiAssertionsEdit.vue | 2 +- .../request/database/BasisParameters.vue | 25 +- .../request/dubbo/BasisParameters.vue | 26 +- .../components/api/test/ApiTestList.vue | 15 +- .../business/components/api/test/Upgrade.vue | 109 ++++++ .../common/components/MsTableHeader.vue | 5 + 13 files changed, 555 insertions(+), 71 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/SaveHistoricalDataUpgrade.java create mode 100644 backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java create mode 100644 frontend/src/business/components/api/test/Upgrade.vue diff --git a/backend/src/main/java/io/metersphere/api/controller/APITestController.java b/backend/src/main/java/io/metersphere/api/controller/APITestController.java index 421eec048a..473793e47d 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -14,7 +14,6 @@ import io.metersphere.api.service.*; import io.metersphere.base.domain.ApiTest; import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.RoleConstants; -import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CronUtils; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; @@ -60,6 +59,8 @@ public class APITestController { private ScheduleService scheduleService; @Resource private APIReportService apiReportService; + @Resource + private HistoricalDataUpgradeService historicalDataUpgradeService; @GetMapping("recent/{count}") public List recentTest(@PathVariable int count) { @@ -109,6 +110,7 @@ public class APITestController { public void mergeCreate(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "selectIds") List selectIds) { apiTestService.mergeCreate(request, file, selectIds); } + @PostMapping(value = "/update", consumes = {"multipart/form-data"}) public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List bodyFiles) { checkownerService.checkApiTestOwner(request.getId()); @@ -189,19 +191,19 @@ public class APITestController { //查询完成率、进行中、已完成 List countResultByStatelList = apiDefinitionService.countStateByProjectID(projectId); apiCountResult.countStatus(countResultByStatelList); - long allCount = apiCountResult.getFinishedCount()+apiCountResult.getRunningCount()+apiCountResult.getNotStartedCount(); + long allCount = apiCountResult.getFinishedCount() + apiCountResult.getRunningCount() + apiCountResult.getNotStartedCount(); - if(allCount!=0){ - float complateRageNumber =(float)apiCountResult.getFinishedCount()*100/allCount; + if (allCount != 0) { + float complateRageNumber = (float) apiCountResult.getFinishedCount() * 100 / allCount; DecimalFormat df = new DecimalFormat("0.0"); - apiCountResult.setCompletionRage(df.format(complateRageNumber)+"%"); + apiCountResult.setCompletionRage(df.format(complateRageNumber) + "%"); } - apiCountResult.setHttpCountStr("HTTP  

"+apiCountResult.getHttpApiDataCountNumber()); - apiCountResult.setRpcCountStr("RPC  

"+apiCountResult.getRpcApiDataCountNumber()); - apiCountResult.setTcpCountStr("TCP  

"+apiCountResult.getTcpApiDataCountNumber()); - apiCountResult.setSqlCountStr("SQL  

"+apiCountResult.getSqlApiDataCountNumber()); - return apiCountResult; + apiCountResult.setHttpCountStr("HTTP  

" + apiCountResult.getHttpApiDataCountNumber()); + apiCountResult.setRpcCountStr("RPC  

" + apiCountResult.getRpcApiDataCountNumber()); + apiCountResult.setTcpCountStr("TCP  

" + apiCountResult.getTcpApiDataCountNumber()); + apiCountResult.setSqlCountStr("SQL  

" + apiCountResult.getSqlApiDataCountNumber()); + return apiCountResult; } @GetMapping("/testCaseInfoCount/{projectId}") @@ -222,21 +224,21 @@ public class APITestController { //未覆盖 已覆盖: 统计当前接口下是否含有案例 List countResultByApiCoverageList = apiDefinitionService.countApiCoverageByProjectID(projectId); apiCountResult.countApiCoverage(countResultByApiCoverageList); - long allCount = apiCountResult.getCoverageCount()+apiCountResult.getUncoverageCount(); + long allCount = apiCountResult.getCoverageCount() + apiCountResult.getUncoverageCount(); - if(allCount!=0){ - float coverageRageNumber =(float)apiCountResult.getCoverageCount()*100/allCount; + if (allCount != 0) { + float coverageRageNumber = (float) apiCountResult.getCoverageCount() * 100 / allCount; DecimalFormat df = new DecimalFormat("0.0"); - apiCountResult.setCoverageRage(df.format(coverageRageNumber)+"%"); + apiCountResult.setCoverageRage(df.format(coverageRageNumber) + "%"); } - apiCountResult.setHttpCountStr("HTTP  

"+apiCountResult.getHttpApiDataCountNumber()); - apiCountResult.setRpcCountStr("RPC  

"+apiCountResult.getRpcApiDataCountNumber()); - apiCountResult.setTcpCountStr("TCP  

"+apiCountResult.getTcpApiDataCountNumber()); - apiCountResult.setSqlCountStr("SQL  

"+apiCountResult.getSqlApiDataCountNumber()); + apiCountResult.setHttpCountStr("HTTP  

" + apiCountResult.getHttpApiDataCountNumber()); + apiCountResult.setRpcCountStr("RPC  

" + apiCountResult.getRpcApiDataCountNumber()); + apiCountResult.setTcpCountStr("TCP  

" + apiCountResult.getTcpApiDataCountNumber()); + apiCountResult.setSqlCountStr("SQL  

" + apiCountResult.getSqlApiDataCountNumber()); - return apiCountResult; + return apiCountResult; } @GetMapping("/testSceneInfoCount/{projectId}") @@ -263,15 +265,15 @@ public class APITestController { List countResultByRunResult = apiAutomationService.countRunResultByProjectID(projectId); apiCountResult.countRunResult(countResultByRunResult); - long allCount = apiCountResult.getUnexecuteCount()+apiCountResult.getExecutionPassCount()+apiCountResult.getExecutionFailedCount(); + long allCount = apiCountResult.getUnexecuteCount() + apiCountResult.getExecutionPassCount() + apiCountResult.getExecutionFailedCount(); - if(allCount!=0){ - float coverageRageNumber =(float)apiCountResult.getExecutionPassCount()*100/allCount; + if (allCount != 0) { + float coverageRageNumber = (float) apiCountResult.getExecutionPassCount() * 100 / allCount; DecimalFormat df = new DecimalFormat("0.0"); - apiCountResult.setPassRage(df.format(coverageRageNumber)+"%"); + apiCountResult.setPassRage(df.format(coverageRageNumber) + "%"); } - return apiCountResult; + return apiCountResult; } @@ -287,7 +289,7 @@ public class APITestController { apiCountResult.setThisWeekAddedCount(taskCountInThisWeek); long api_executedInThisWeekCountNumber = apiReportService.countByProjectIdAndCreateInThisWeek(projectId); long scene_executedInThisWeekCountNumber = apiScenarioReportService.countByProjectIdAndCreateAndByScheduleInThisWeek(projectId); - long executedInThisWeekCountNumber = api_executedInThisWeekCountNumber+scene_executedInThisWeekCountNumber; + long executedInThisWeekCountNumber = api_executedInThisWeekCountNumber + scene_executedInThisWeekCountNumber; apiCountResult.setThisWeekExecutedCount(executedInThisWeekCountNumber); //统计 失败 成功 以及总数 @@ -299,41 +301,41 @@ public class APITestController { apiCountResult.countScheduleExecute(allExecuteResult); long allCount = apiCountResult.getExecutedCount(); - if(allCount!=0){ - float coverageRageNumber =(float)apiCountResult.getSuccessCount()*100/allCount; + if (allCount != 0) { + float coverageRageNumber = (float) apiCountResult.getSuccessCount() * 100 / allCount; DecimalFormat df = new DecimalFormat("0.0"); - apiCountResult.setSuccessRage(df.format(coverageRageNumber)+"%"); + apiCountResult.setSuccessRage(df.format(coverageRageNumber) + "%"); } - return apiCountResult; + return apiCountResult; } @GetMapping("/faliureCaseAboutTestPlan/{projectId}/{limitNumber}") public List faliureCaseAboutTestPlan(@PathVariable String projectId, @PathVariable int limitNumber) { - List selectDataList = apiDefinitionExecResultService.findFaliureCaseInfoByProjectIDAndLimitNumberInSevenDays(projectId,limitNumber); + List selectDataList = apiDefinitionExecResultService.findFaliureCaseInfoByProjectIDAndLimitNumberInSevenDays(projectId, limitNumber); List returnList = new ArrayList<>(limitNumber); - for(int dataIndex = 0;dataIndex < limitNumber;dataIndex ++){ + for (int dataIndex = 0; dataIndex < limitNumber; dataIndex++) { ExecutedCaseInfoDTO dataDTO = new ExecutedCaseInfoDTO(); - dataDTO.setSortIndex(dataIndex+1); + dataDTO.setSortIndex(dataIndex + 1); - if(dataIndex testIds; + + private String projectId; + + private String modulePath; + + private String moduleId; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java index 6d97c94cc3..432d3e73e8 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java @@ -31,7 +31,7 @@ public class MsDubboSampler extends MsTestElement { private String type = "DubboSampler"; @JSONField(ordinal = 52) - private String protocol; + private String protocol = "DUBBO"; @JsonProperty(value = "interface") @JSONField(ordinal = 53, name = "interface") private String _interface; diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index 4770e79c04..dbfa8b8173 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -172,7 +172,7 @@ public class MsHTTPSamplerProxy extends MsTestElement { LogUtil.error(e); } // REST参数 - if (CollectionUtils.isNotEmpty(this.getArguments())) { + if (CollectionUtils.isNotEmpty(this.getRest())) { sampler.setArguments(httpArguments(this.getRest())); } // 请求参数 @@ -186,7 +186,9 @@ public class MsHTTPSamplerProxy extends MsTestElement { if (StringUtils.isNotEmpty(this.body.getType()) && this.body.getType().equals("Form Data")) { sampler.setDoMultipart(true); } - sampler.setArguments(httpArguments(bodyParams)); + if (CollectionUtils.isNotEmpty(bodyParams)) { + sampler.setArguments(httpArguments(bodyParams)); + } } } diff --git a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java new file mode 100644 index 0000000000..e29e74dc39 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java @@ -0,0 +1,331 @@ +package io.metersphere.api.service; + +import com.alibaba.fastjson.JSON; +import io.metersphere.api.dto.SaveHistoricalDataUpgrade; +import io.metersphere.api.dto.automation.ScenarioStatus; +import io.metersphere.api.dto.definition.request.MsScenario; +import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.assertions.MsAssertions; +import io.metersphere.api.dto.definition.request.controller.MsIfController; +import io.metersphere.api.dto.definition.request.extract.MsExtract; +import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor; +import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; +import io.metersphere.api.dto.definition.request.sampler.MsDubboSampler; +import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; +import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler; +import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; +import io.metersphere.api.dto.definition.request.timer.MsConstantTimer; +import io.metersphere.api.dto.scenario.Scenario; +import io.metersphere.api.dto.scenario.request.*; +import io.metersphere.base.domain.*; +import io.metersphere.base.mapper.ApiScenarioMapper; +import io.metersphere.base.mapper.ApiTestMapper; +import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; +import io.metersphere.commons.utils.BeanUtils; +import io.metersphere.commons.utils.DateUtils; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.commons.utils.SessionUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.io.*; +import java.net.URL; +import java.util.*; + +@Service +@Transactional(rollbackFor = Exception.class) +public class HistoricalDataUpgradeService { + @Resource + private ApiTestMapper apiTestMapper; + @Resource + private ExtApiScenarioMapper extApiScenarioMapper; + @Resource + SqlSessionFactory sqlSessionFactory; + + private int getNextNum(String projectId) { + ApiScenario apiScenario = extApiScenarioMapper.getNextNum(projectId); + if (apiScenario == null) { + return 100001; + } else { + return Optional.of(apiScenario.getNum() + 1).orElse(100001); + } + } + + private MsScenario createScenario(Scenario oldScenario) { + MsScenario scenario = new MsScenario(); + scenario.setVariables(oldScenario.getVariables()); + scenario.setName(oldScenario.getName()); + scenario.setEnableCookieShare(oldScenario.isEnableCookieShare()); + scenario.setEnvironmentId(oldScenario.getEnvironmentId()); + scenario.setReferenced("Upgrade"); + scenario.setId(oldScenario.getId()); + scenario.setResourceId(UUID.randomUUID().toString()); + LinkedList testElements = new LinkedList<>(); + int index = 1; + for (Request request : oldScenario.getRequests()) { + // 条件控制器 + MsIfController ifController = null; + if (request.getController() != null && StringUtils.isNotEmpty(request.getController().getValue()) + && StringUtils.isNotEmpty(request.getController().getVariable())) { + ifController = new MsIfController(); + BeanUtils.copyBean(ifController, request.getController()); + ifController.setType("IfController"); + ifController.setName("IfController"); + ifController.setIndex(index + ""); + ifController.setResourceId(UUID.randomUUID().toString()); + } + // 等待控制器 + if (request.getTimer() != null && StringUtils.isNotEmpty(request.getTimer().getDelay())) { + MsConstantTimer constantTimer = new MsConstantTimer(); + BeanUtils.copyBean(constantTimer, request.getTimer()); + constantTimer.setType("ConstantTimer"); + constantTimer.setIndex(index + ""); + constantTimer.setResourceId(UUID.randomUUID().toString()); + testElements.add(constantTimer); + } + + MsTestElement element = null; + if (request instanceof HttpRequest) { + element = new MsHTTPSamplerProxy(); + HttpRequest request1 = (HttpRequest) request; + if (StringUtils.isEmpty(request1.getPath()) && StringUtils.isNotEmpty(request1.getUrl())) { + try { + URL urlObject = new URL(request1.getUrl()); + String envPath = StringUtils.equals(urlObject.getPath(), "/") ? "" : urlObject.getPath(); + request1.setPath(envPath); + } catch (Exception ex) { + LogUtil.error(ex.getMessage()); + } + } + BeanUtils.copyBean(element, request1); + ((MsHTTPSamplerProxy) element).setProtocol(RequestType.HTTP); + ((MsHTTPSamplerProxy) element).setArguments(request1.getParameters()); + element.setType("HTTPSamplerProxy"); + } + if (request instanceof DubboRequest) { + String requestJson = JSON.toJSONString(request); + element = JSON.parseObject(requestJson, MsDubboSampler.class); + element.setType("DubboSampler"); + } + if (request instanceof SqlRequest) { + element = new MsJDBCSampler(); + SqlRequest request1 = (SqlRequest) request; + BeanUtils.copyBean(element, request1); + element.setType("JDBCSampler"); + } + if (request instanceof TCPRequest) { + element = new MsTCPSampler(); + TCPRequest request1 = (TCPRequest) request; + BeanUtils.copyBean(element, request1); + element.setType("TCPSampler"); + } + element.setIndex(index + ""); + element.setResourceId(UUID.randomUUID().toString()); + LinkedList msTestElements = new LinkedList<>(); + // 断言规则 + if (request.getAssertions() != null && ((request.getAssertions().getDuration() != null && request.getAssertions().getDuration().getValue() > 0) || + CollectionUtils.isNotEmpty(request.getAssertions().getJsonPath()) || CollectionUtils.isNotEmpty(request.getAssertions().getJsr223()) || + CollectionUtils.isNotEmpty(request.getAssertions().getRegex()) || CollectionUtils.isNotEmpty(request.getAssertions().getXpath2()))) { + String assertions = JSON.toJSONString(request.getAssertions()); + MsAssertions msAssertions = JSON.parseObject(assertions, MsAssertions.class); + msAssertions.setType("Assertions"); + msAssertions.setIndex(index + ""); + msAssertions.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(msAssertions); + } + // 提取规则 + if (request.getExtract() != null && (CollectionUtils.isNotEmpty(request.getExtract().getJson()) || + CollectionUtils.isNotEmpty(request.getExtract().getRegex()) || CollectionUtils.isNotEmpty(request.getExtract().getXpath()))) { + String extractJson = JSON.toJSONString(request.getExtract()); + MsExtract extract = JSON.parseObject(extractJson, MsExtract.class); + extract.setType("Extract"); + extract.setIndex(index + ""); + extract.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(extract); + } + // 前置脚本 + if (request.getJsr223PreProcessor() != null && StringUtils.isNotEmpty(request.getJsr223PreProcessor().getScript())) { + String preJson = JSON.toJSONString(request.getJsr223PreProcessor()); + MsJSR223PreProcessor preProcessor = JSON.parseObject(preJson, MsJSR223PreProcessor.class); + preProcessor.setType("JSR223PreProcessor"); + preProcessor.setIndex(index + ""); + preProcessor.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(preProcessor); + } + // 后置脚本 + if (request.getJsr223PostProcessor() != null && StringUtils.isNotEmpty(request.getJsr223PostProcessor().getScript())) { + String preJson = JSON.toJSONString(request.getJsr223PostProcessor()); + MsJSR223PostProcessor preProcessor = JSON.parseObject(preJson, MsJSR223PostProcessor.class); + preProcessor.setType("JSR223PostProcessor"); + preProcessor.setIndex(index + ""); + preProcessor.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(preProcessor); + } + if (CollectionUtils.isNotEmpty(msTestElements)) { + element.setHashTree(msTestElements); + } + if (ifController != null) { + LinkedList elements = new LinkedList<>(); + elements.add(element); + ifController.setHashTree(elements); + testElements.add(ifController); + } else { + testElements.add(element); + } + index++; + } + scenario.setHashTree(testElements); + return scenario; + } + + private ApiScenarioWithBLOBs checkNameExist(Scenario oldScenario, String projectId, ApiScenarioMapper mapper) { + ApiScenarioExample example = new ApiScenarioExample(); + example.createCriteria().andIdEqualTo(oldScenario.getId()); + List list = mapper.selectByExampleWithBLOBs(example); + if (list.size() > 0) { + return list.get(0); + } + return null; + } + + private static final String BODY_FILE_DIR = "/opt/metersphere/data/body"; + + //文件的拷贝 + private static void copyFile(String sourcePath, String newPath) { + File readfile = new File(sourcePath); + File newFile = new File(newPath); + BufferedWriter bufferedWriter = null; + Writer writer = null; + FileOutputStream fileOutputStream = null; + BufferedReader bufferedReader = null; + try { + fileOutputStream = new FileOutputStream(newFile, true); + writer = new OutputStreamWriter(fileOutputStream, "UTF-8"); + bufferedWriter = new BufferedWriter(writer); + + bufferedReader = new BufferedReader(new FileReader(readfile)); + + String line = null; + while ((line = bufferedReader.readLine()) != null) { + bufferedWriter.write(line); + bufferedWriter.newLine(); + bufferedWriter.flush(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bufferedWriter != null) { + bufferedWriter.close(); + } + if (bufferedReader != null) { + bufferedReader.close(); + } + if (writer != null) { + writer.close(); + } + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static void copyDir(String sourcePathDir, String newPathDir) { + File start = new File(sourcePathDir); + File end = new File(newPathDir); + String[] filePath = start.list(); + if (!end.exists()) { + end.mkdir(); + } + for (String temp : filePath) { + //添加满足情况的条件 + if (new File(sourcePathDir + File.separator + temp).isFile()) { + //为文件则进行拷贝 + copyFile(sourcePathDir + File.separator + temp, newPathDir + File.separator + temp); + } + } + } + + private void createBodyFiles(String testId) { + String dir = BODY_FILE_DIR + "/" + testId; + File testDir = new File(dir); + if (testDir.exists()) { + testDir.mkdirs(); + } + copyDir(dir, BODY_FILE_DIR); + } + + private void createApiScenarioWithBLOBs(SaveHistoricalDataUpgrade saveHistoricalDataUpgrade, Scenario oldScenario, String scenarioDefinition, ApiScenarioMapper mapper) { + if (StringUtils.isEmpty(oldScenario.getName())) { + oldScenario.setName("默认名称-" + DateUtils.getTimeStr(System.currentTimeMillis())); + } + ApiScenarioWithBLOBs scenario = checkNameExist(oldScenario, saveHistoricalDataUpgrade.getProjectId(), mapper); + if (scenario != null) { + scenario.setName(oldScenario.getName()); + scenario.setProjectId(saveHistoricalDataUpgrade.getProjectId()); + scenario.setTags(scenario.getTags()); + scenario.setLevel("P0"); + scenario.setModulePath(saveHistoricalDataUpgrade.getModulePath()); + scenario.setApiScenarioModuleId(saveHistoricalDataUpgrade.getModuleId()); + scenario.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId()); + scenario.setStepTotal(oldScenario.getRequests().size()); + scenario.setScenarioDefinition(scenarioDefinition); + scenario.setUpdateTime(System.currentTimeMillis()); + scenario.setStatus(ScenarioStatus.Underway.name()); + scenario.setUserId(SessionUtils.getUserId()); + scenario.setNum(getNextNum(saveHistoricalDataUpgrade.getProjectId())); + mapper.updateByPrimaryKeySelective(scenario); + } else { + scenario = new ApiScenarioWithBLOBs(); + scenario.setId(oldScenario.getId()); + scenario.setName(oldScenario.getName()); + scenario.setProjectId(saveHistoricalDataUpgrade.getProjectId()); + scenario.setTags(scenario.getTags()); + scenario.setLevel("P0"); + scenario.setModulePath(saveHistoricalDataUpgrade.getModulePath()); + scenario.setApiScenarioModuleId(saveHistoricalDataUpgrade.getModuleId()); + scenario.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId()); + scenario.setStepTotal(oldScenario.getRequests().size()); + scenario.setScenarioDefinition(scenarioDefinition); + scenario.setCreateTime(System.currentTimeMillis()); + scenario.setUpdateTime(System.currentTimeMillis()); + scenario.setStatus(ScenarioStatus.Underway.name()); + scenario.setUserId(SessionUtils.getUserId()); + scenario.setNum(getNextNum(saveHistoricalDataUpgrade.getProjectId())); + mapper.insert(scenario); + } + } + + public String upgrade(SaveHistoricalDataUpgrade saveHistoricalDataUpgrade) { + ApiTestExample example = new ApiTestExample(); + example.createCriteria().andIdIn(saveHistoricalDataUpgrade.getTestIds()); + List blobs = apiTestMapper.selectByExampleWithBLOBs(example); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class); + for (ApiTest test : blobs) { + // 附件迁移 + createBodyFiles(test.getId()); + + List scenarios = JSON.parseArray(test.getScenarioDefinition(), Scenario.class); + if (CollectionUtils.isNotEmpty(scenarios)) { + // 批量处理 + for (Scenario scenario : scenarios) { + MsScenario scenario1 = createScenario(scenario); + String scenarioDefinition = JSON.toJSONString(scenario1); + createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenario, scenarioDefinition, mapper); + } + } + } + sqlSession.flushStatements(); + return null; + } +} diff --git a/frontend/src/business/components/api/automation/scenario/ApiComponent.vue b/frontend/src/business/components/api/automation/scenario/ApiComponent.vue index 918abd1d24..7390d6edd0 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiComponent.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiComponent.vue @@ -58,8 +58,8 @@

{{$t('api_test.definition.request.req_param')}}

- - + +

{{$t('api_test.definition.request.res_param')}}

diff --git a/frontend/src/business/components/api/definition/components/assertion/ApiAssertionsEdit.vue b/frontend/src/business/components/api/definition/components/assertion/ApiAssertionsEdit.vue index b2fdd70c8c..3b6b8849e1 100644 --- a/frontend/src/business/components/api/definition/components/assertion/ApiAssertionsEdit.vue +++ b/frontend/src/business/components/api/definition/components/assertion/ApiAssertionsEdit.vue @@ -55,7 +55,7 @@ import MsApiAssertionRegex from "./ApiAssertionRegex"; import MsApiAssertionDuration from "./ApiAssertionDuration"; import MsApiAssertionJsonPath from "./ApiAssertionJsonPath"; - import MsApiAssertionJsr223 from "@/business/components/api/test/components/assertion/ApiAssertionJsr223"; + import MsApiAssertionJsr223 from "./ApiAssertionJsr223"; import MsApiAssertionXPath2 from "./ApiAssertionXPath2"; export default { diff --git a/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue b/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue index 3de55bde9a..9402456eee 100644 --- a/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue +++ b/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue @@ -63,18 +63,19 @@ -
- - - - - - - - - +
+
+ + + + + + + + +
diff --git a/frontend/src/business/components/api/definition/components/request/dubbo/BasisParameters.vue b/frontend/src/business/components/api/definition/components/request/dubbo/BasisParameters.vue index 9e3057827b..287cf0d22f 100644 --- a/frontend/src/business/components/api/definition/components/request/dubbo/BasisParameters.vue +++ b/frontend/src/business/components/api/definition/components/request/dubbo/BasisParameters.vue @@ -41,19 +41,19 @@
- -
- - - - - - - - - +
+
+ + + + + + + + +
diff --git a/frontend/src/business/components/api/test/ApiTestList.vue b/frontend/src/business/components/api/test/ApiTestList.vue index 35785fddbc..941b67b0aa 100644 --- a/frontend/src/business/components/api/test/ApiTestList.vue +++ b/frontend/src/business/components/api/test/ApiTestList.vue @@ -7,7 +7,7 @@ :title="$t('commons.test')" @create="create" :createTip="$t('load_test.create')" :runTip="$t('load_test.run')" :show-run="true" - @runTest="runTest"/> + @runTest="runTest" @historicalDataUpgrade="historicalDataUpgrade"/> @@ -54,7 +54,8 @@ - + @@ -72,13 +73,14 @@ import {TEST_CONFIGS} from "../../common/components/search/search-components"; import {ApiEvent, LIST_CHANGE} from "@/business/components/common/head/ListEvent"; import ApiCopyDialog from "./components/ApiCopyDialog"; + import MsUpgrade from "./Upgrade"; export default { components: { ApiCopyDialog, OneClickOperation, MsTableOperators, - MsApiTestStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination, MsTableOperator + MsApiTestStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination, MsTableOperator, MsUpgrade }, data() { return { @@ -204,6 +206,13 @@ _filter(filters, this.condition); this.init(); }, + historicalDataUpgrade() { + if (this.selectIds.size < 1) { + this.$warning(this.$t('test_track.plan_view.select_manipulate')); + } else { + this.$refs.upgrade.openOneClickOperation(); + } + } }, created() { this.init(); diff --git a/frontend/src/business/components/api/test/Upgrade.vue b/frontend/src/business/components/api/test/Upgrade.vue new file mode 100644 index 0000000000..5e0f9c2d92 --- /dev/null +++ b/frontend/src/business/components/api/test/Upgrade.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/frontend/src/business/components/common/components/MsTableHeader.vue b/frontend/src/business/components/common/components/MsTableHeader.vue index 09af2c28de..00c0f9d991 100644 --- a/frontend/src/business/components/common/components/MsTableHeader.vue +++ b/frontend/src/business/components/common/components/MsTableHeader.vue @@ -13,6 +13,8 @@ + @@ -84,6 +86,9 @@ }, runTest() { this.$emit('runTest') + }, + historicalDataUpgrade() { + this.$emit('historicalDataUpgrade'); } }, computed: { From f01c7f9d5919b8a1186cbeafc6cd18ffa564dbcb Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 6 Jan 2021 13:35:27 +0800 Subject: [PATCH 4/8] =?UTF-8?q?refator:=20=E9=A1=B9=E7=9B=AE=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=B7=BB=E5=8A=A0jar=E5=8C=85=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/settings/project/MsProject.vue | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/settings/project/MsProject.vue b/frontend/src/business/components/settings/project/MsProject.vue index 36f71ec385..36682a6fac 100644 --- a/frontend/src/business/components/settings/project/MsProject.vue +++ b/frontend/src/business/components/settings/project/MsProject.vue @@ -3,7 +3,12 @@ @@ -78,6 +83,8 @@ + +
@@ -96,10 +103,14 @@ import MsTableOperatorButton from "../../common/components/MsTableOperatorButton import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig"; import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent"; import {PROJECT_ID} from "@/common/js/constants"; +import MsJarConfig from "../../api/test/components/jar/JarConfig"; +import MsTableButton from "../../common/components/MsTableButton"; export default { name: "MsProject", components: { + MsTableButton, + MsJarConfig, TemplateComponent, ApiEnvironmentConfig, MsTableOperatorButton, @@ -206,6 +217,9 @@ export default { } }); }, + openJarConfig() { + this.$refs.jarConfig.open(); + }, handleDelete(project) { this.$refs.deleteConfirm.open(project); }, From 09fd2c2ab6ebed18c5b2d153ab3ec80ca9cf2e6a Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 6 Jan 2021 13:38:17 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E5=A2=9E=E5=8A=A0URL=E5=94=AF=E4=B8=80=E6=80=A7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=BC=80=E5=85=B3=EF=BC=8C=E6=8E=A7=E5=88=B6?= =?UTF-8?q?URL=E6=A0=A1=E9=AA=8C=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/service/ApiAutomationService.java | 7 +- .../api/service/ApiDefinitionService.java | 21 +- .../io/metersphere/base/domain/Project.java | 5 +- .../base/domain/ProjectExample.java | 60 +++ .../metersphere/base/mapper/ProjectMapper.xml | 29 +- .../base/mapper/ext/ExtProjectMapper.xml | 12 +- .../java/io/metersphere/dto/ProjectDTO.java | 2 + .../V60__modify_project_add_repeatable.sql | 1 + .../src/main/resources/generatorConfig.xml | 2 +- .../components/settings/project/MsProject.vue | 353 +++++++++--------- frontend/src/i18n/en-US.js | 3 +- frontend/src/i18n/zh-CN.js | 11 +- frontend/src/i18n/zh-TW.js | 3 +- 13 files changed, 301 insertions(+), 208 deletions(-) create mode 100644 backend/src/main/resources/db/migration/V60__modify_project_add_repeatable.sql diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 9465a3caea..2081b517ea 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -316,8 +316,11 @@ public class ApiAutomationService { boolean isFirst = true; for (ApiScenarioWithBLOBs item : apiScenarios) { if (item.getStepTotal() == 0) { - MSException.throwException(item.getName() + "," + Translator.get("automation_exec_info")); - break; + if (apiScenarios.size() == 1) { + MSException.throwException(item.getName() + "," + Translator.get("automation_exec_info")); + break; + } + continue; } MsThreadGroup group = new MsThreadGroup(); group.setLabel(item.getName()); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 5aa683ab4c..fe80e09751 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.ApiTestImportRequest; -import io.metersphere.api.dto.automation.ApiScenarioDTO; import io.metersphere.api.dto.automation.ApiScenarioRequest; import io.metersphere.api.dto.automation.ReferenceDTO; import io.metersphere.api.dto.datacount.ApiDataCountResult; @@ -18,6 +17,7 @@ import io.metersphere.api.parse.ApiImportParserFactory; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiDefinitionMapper; import io.metersphere.base.mapper.ApiTestFileMapper; +import io.metersphere.base.mapper.ProjectMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; @@ -71,6 +71,8 @@ public class ApiDefinitionService { private ExtApiScenarioMapper extApiScenarioMapper; @Resource private ExtTestPlanMapper extTestPlanMapper; + @Resource + private ProjectMapper projectMapper; private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24); @@ -168,7 +170,8 @@ public class ApiDefinitionService { example.createCriteria().andMethodEqualTo(request.getMethod()).andStatusNotEqualTo("Trash") .andProtocolEqualTo(request.getProtocol()).andPathEqualTo(request.getPath()) .andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId()); - if (apiDefinitionMapper.countByExample(example) > 0) { + Project project = projectMapper.selectByPrimaryKey(request.getProjectId()); + if (apiDefinitionMapper.countByExample(example) > 0 && !project.getRepeatable()) { MSException.throwException(Translator.get("api_definition_url_not_repeating")); } } else { @@ -429,8 +432,8 @@ public class ApiDefinitionService { public void editApiByParam(ApiBatchRequest request) { List ids = request.getIds(); - if(request.isSelectAllDate()){ - ids = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds()); + if (request.isSelectAllDate()) { + ids = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds()); } //name在这里只是查询参数 request.setName(null); @@ -493,15 +496,15 @@ public class ApiDefinitionService { public void deleteByParams(ApiDefinitionBatchProcessingRequest request) { List apiIds = request.getDataIds(); - if(request.isSelectAllDate()){ - apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds()); + if (request.isSelectAllDate()) { + apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds()); } ApiDefinitionExample example = new ApiDefinitionExample(); example.createCriteria().andIdIn(apiIds); apiDefinitionMapper.deleteByExample(example); } - private List getAllApiIdsByFontedSelect(List filter,String name,List moduleIds,String projectId,ListunSelectIds) { + private List getAllApiIdsByFontedSelect(List filter, String name, List moduleIds, String projectId, List unSelectIds) { ApiDefinitionRequest request = new ApiDefinitionRequest(); request.setFilters(filter); request.setName(name); @@ -519,8 +522,8 @@ public class ApiDefinitionService { public void removeToGcByParams(ApiDefinitionBatchProcessingRequest request) { List apiIds = request.getDataIds(); - if(request.isSelectAllDate()){ - apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds()); + if (request.isSelectAllDate()) { + apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds()); } extApiDefinitionMapper.removeToGc(apiIds); } diff --git a/backend/src/main/java/io/metersphere/base/domain/Project.java b/backend/src/main/java/io/metersphere/base/domain/Project.java index 25403e763e..a1ca062eee 100644 --- a/backend/src/main/java/io/metersphere/base/domain/Project.java +++ b/backend/src/main/java/io/metersphere/base/domain/Project.java @@ -1,8 +1,9 @@ package io.metersphere.base.domain; -import java.io.Serializable; import lombok.Data; +import java.io.Serializable; + @Data public class Project implements Serializable { private String id; @@ -23,5 +24,7 @@ public class Project implements Serializable { private String zentaoId; + private Boolean repeatable; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java b/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java index 8f83d6ad88..dd20602779 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java @@ -713,6 +713,66 @@ public class ProjectExample { addCriterion("zentao_id not between", value1, value2, "zentaoId"); return (Criteria) this; } + + public Criteria andRepeatableIsNull() { + addCriterion("`repeatable` is null"); + return (Criteria) this; + } + + public Criteria andRepeatableIsNotNull() { + addCriterion("`repeatable` is not null"); + return (Criteria) this; + } + + public Criteria andRepeatableEqualTo(Boolean value) { + addCriterion("`repeatable` =", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableNotEqualTo(Boolean value) { + addCriterion("`repeatable` <>", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableGreaterThan(Boolean value) { + addCriterion("`repeatable` >", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableGreaterThanOrEqualTo(Boolean value) { + addCriterion("`repeatable` >=", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableLessThan(Boolean value) { + addCriterion("`repeatable` <", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableLessThanOrEqualTo(Boolean value) { + addCriterion("`repeatable` <=", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableIn(List values) { + addCriterion("`repeatable` in", values, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableNotIn(List values) { + addCriterion("`repeatable` not in", values, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableBetween(Boolean value1, Boolean value2) { + addCriterion("`repeatable` between", value1, value2, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableNotBetween(Boolean value1, Boolean value2) { + addCriterion("`repeatable` not between", value1, value2, "repeatable"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml index 4ed30cebfe..7765a51e20 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml @@ -11,6 +11,7 @@ + @@ -72,7 +73,7 @@ id, workspace_id, `name`, description, create_time, update_time, tapd_id, jira_key, - zentao_id + zentao_id, `repeatable` @@ -211,6 +218,9 @@ zentao_id = #{record.zentaoId,jdbcType=VARCHAR}, + + `repeatable` = #{record.repeatable,jdbcType=BIT}, + @@ -226,7 +236,8 @@ update_time = #{record.updateTime,jdbcType=BIGINT}, tapd_id = #{record.tapdId,jdbcType=VARCHAR}, jira_key = #{record.jiraKey,jdbcType=VARCHAR}, - zentao_id = #{record.zentaoId,jdbcType=VARCHAR} + zentao_id = #{record.zentaoId,jdbcType=VARCHAR}, + `repeatable` = #{record.repeatable,jdbcType=BIT} @@ -258,6 +269,9 @@ zentao_id = #{zentaoId,jdbcType=VARCHAR}, + + `repeatable` = #{repeatable,jdbcType=BIT}, + where id = #{id,jdbcType=VARCHAR} @@ -270,7 +284,8 @@ update_time = #{updateTime,jdbcType=BIGINT}, tapd_id = #{tapdId,jdbcType=VARCHAR}, jira_key = #{jiraKey,jdbcType=VARCHAR}, - zentao_id = #{zentaoId,jdbcType=VARCHAR} + zentao_id = #{zentaoId,jdbcType=VARCHAR}, + `repeatable` = #{repeatable,jdbcType=BIT} where id = #{id,jdbcType=VARCHAR} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml index 66bb7c3588..af9787bece 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml @@ -4,7 +4,7 @@