From 1f59d12f7b88e4c16285af743588fc02379d645c Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 9 Dec 2020 19:02:26 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E5=AE=8C=E5=96=84=E5=9B=9E=E6=94=B6=E7=AB=99?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/service/ApiAutomationService.java | 35 ++++--------------- .../api/service/ApiDefinitionService.java | 30 ++++++++-------- .../automation/scenario/ApiScenarioList.vue | 22 +++++++++--- .../automation/scenario/EditApiScenario.vue | 11 +++--- .../api/definition/components/ApiList.vue | 12 ++++++- 5 files changed, 58 insertions(+), 52 deletions(-) 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 006fbee84f..9120cd514f 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -22,7 +22,6 @@ import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ReportTriggerMode; import io.metersphere.commons.exception.MSException; -import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.i18n.Translator; import io.metersphere.track.dto.TestPlanDTO; @@ -34,13 +33,11 @@ import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.ListedHashTree; -import org.aspectj.util.FileUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.*; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -51,6 +48,8 @@ public class ApiAutomationService { @Resource private ApiScenarioMapper apiScenarioMapper; @Resource + private ApiDefinitionService apiDefinitionService; + @Resource private ExtApiScenarioMapper extApiScenarioMapper; @Resource private ApiTagMapper apiTagMapper; @@ -126,13 +125,13 @@ public class ApiAutomationService { apiScenarioMapper.insert(scenario); List bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); - createBodyFiles(bodyUploadIds, bodyFiles); + apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles); } public void update(SaveApiScenarioRequest request, List bodyFiles) { checkNameExist(request); - List bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); - createBodyFiles(bodyUploadIds, bodyFiles); + List bodyUploadIds = request.getBodyUploadIds(); + apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles); final ApiScenario scenario = new ApiScenario(); scenario.setId(request.getId()); @@ -177,7 +176,7 @@ public class ApiAutomationService { private void checkNameExist(SaveApiScenarioRequest request) { ApiScenarioExample example = new ApiScenarioExample(); - example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId()); + example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andStatusNotEqualTo("Trash").andIdNotEqualTo(request.getId()); if (apiScenarioMapper.countByExample(example) > 0) { MSException.throwException(Translator.get("automation_name_already_exists")); } @@ -194,26 +193,6 @@ public class ApiAutomationService { return new ArrayList<>(); } - private void createBodyFiles(List bodyUploadIds, List bodyFiles) { - if (!bodyUploadIds.isEmpty() && !bodyFiles.isEmpty()) { - File testDir = new File(BODY_FILE_DIR); - if (!testDir.exists()) { - testDir.mkdirs(); - } - for (int i = 0; i < bodyUploadIds.size(); i++) { - MultipartFile item = bodyFiles.get(i); - File file = new File(BODY_FILE_DIR + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename()); - try (InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(file)) { - file.createNewFile(); - FileUtil.copyStream(in, out); - } catch (IOException e) { - LogUtil.error(e); - MSException.throwException(Translator.get("upload_fail")); - } - } - } - } - public void deleteTag(String id) { List list = extApiScenarioMapper.selectByTagId(id); if (!list.isEmpty()) { @@ -297,7 +276,7 @@ public class ApiAutomationService { */ public String run(RunDefinitionRequest request, List bodyFiles) { List bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); - createBodyFiles(bodyUploadIds, bodyFiles); + apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles); EnvironmentConfig envConfig = null; if (request.getEnvironmentId() != null) { ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId()); 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 fef7732035..7aa80d95ef 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -25,7 +25,7 @@ import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.i18n.Translator; import io.metersphere.service.FileService; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.collections.CollectionUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; @@ -33,13 +33,15 @@ import org.apache.jorphan.collections.HashTree; import org.aspectj.util.FileUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import sun.security.util.Cache; import javax.annotation.Resource; import java.io.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; @@ -103,15 +105,17 @@ public class ApiDefinitionService { } public void update(SaveApiDefinitionRequest request, List bodyFiles) { - deleteFileByTestId(request.getRequest().getId()); - List bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); + if (request.getRequest() != null) { + deleteFileByTestId(request.getRequest().getId()); + } + List bodyUploadIds = request.getBodyUploadIds(); request.setBodyUploadIds(null); updateTest(request); createBodyFiles(bodyUploadIds, bodyFiles); } - private void createBodyFiles(List bodyUploadIds, List bodyFiles) { - if (bodyUploadIds.size() > 0) { + public void createBodyFiles(List bodyUploadIds, List bodyFiles) { + if (CollectionUtils.isNotEmpty(bodyUploadIds) && CollectionUtils.isNotEmpty(bodyFiles)) { File testDir = new File(BODY_FILE_DIR); if (!testDir.exists()) { testDir.mkdirs(); @@ -139,10 +143,9 @@ public class ApiDefinitionService { } public void deleteBatch(List apiIds) { - // 简单处理后续优化 - apiIds.forEach(item -> { - delete(item); - }); + ApiDefinitionExample example = new ApiDefinitionExample(); + example.createCriteria().andIdIn(apiIds); + apiDefinitionMapper.deleteByExample(example); } public void removeToGc(List apiIds) { @@ -160,14 +163,14 @@ public class ApiDefinitionService { private void checkNameExist(SaveApiDefinitionRequest request) { ApiDefinitionExample example = new ApiDefinitionExample(); if (request.getProtocol().equals(RequestType.HTTP)) { - example.createCriteria().andMethodEqualTo(request.getMethod()) + example.createCriteria().andMethodEqualTo(request.getMethod()).andStatusNotEqualTo("Trash") .andProtocolEqualTo(request.getProtocol()).andPathEqualTo(request.getPath()) .andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId()); if (apiDefinitionMapper.countByExample(example) > 0) { MSException.throwException(Translator.get("api_definition_url_not_repeating")); } } else { - example.createCriteria().andProtocolEqualTo(request.getProtocol()) + example.createCriteria().andProtocolEqualTo(request.getProtocol()).andStatusNotEqualTo("Trash") .andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()) .andIdNotEqualTo(request.getId()); if (apiDefinitionMapper.countByExample(example) > 0) { @@ -176,7 +179,6 @@ public class ApiDefinitionService { } } - private ApiDefinition updateTest(SaveApiDefinitionRequest request) { checkNameExist(request); final ApiDefinitionWithBLOBs test = new ApiDefinitionWithBLOBs(); diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index 78bd291342..438b2525b0 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -47,11 +47,16 @@ show-overflow-tooltip/> @@ -202,6 +207,13 @@ edit(row) { this.$emit('edit', row); }, + reductionApi(row) { + let obj = {id: row.id, projectId: row.projectId, name: row.name, status: 'Underway'} + this.$fileUpload("/api/automation/update", null, [], obj, () => { + this.$success(this.$t('commons.save_success')); + this.search(); + }) + }, execute(row) { this.infoDb = false; let url = "/api/automation/run"; diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index de392d5a95..968213f16b 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -240,7 +240,7 @@ - {{ $t('commons.copy') }} + {{ $t('commons.copy') }} @@ -326,6 +326,7 @@ userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}], apiScenarioModuleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}], status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}], + principal: [{required: true, message: this.$t('api_test.definition.request.responsible'), trigger: 'change'}], }, environments: [], tags: [], @@ -684,9 +685,11 @@ this.path = "/api/automation/update"; if (response.data.scenarioDefinition != null) { let obj = JSON.parse(response.data.scenarioDefinition); - this.currentEnvironmentId = obj.environmentId; - this.currentScenario.variables = obj.variables; - this.scenarioDefinition = obj.hashTree; + if (obj) { + this.currentEnvironmentId = obj.environmentId; + this.currentScenario.variables = obj.variables; + this.scenarioDefinition = obj.hashTree; + } } } }) diff --git a/frontend/src/business/components/api/definition/components/ApiList.vue b/frontend/src/business/components/api/definition/components/ApiList.vue index abf0d5352f..b9c7582656 100644 --- a/frontend/src/business/components/api/definition/components/ApiList.vue +++ b/frontend/src/business/components/api/definition/components/ApiList.vue @@ -77,7 +77,8 @@ 用例
- 编辑 + 恢复 + 编辑 用例 删除
@@ -256,6 +257,15 @@ editApi(row) { this.$emit('editApi', row); }, + reductionApi(row) { + row.status = 'Underway'; + row.request = null; + row.response = null; + this.$fileUpload("/api/definition/update", null, [], row, () => { + this.$success(this.$t('commons.save_success')); + this.search(); + }); + }, handleDeleteBatch() { if (this.currentModule != undefined && this.currentModule.id == "gc") { this.$alert(this.$t('api_test.definition.request.delete_confirm') + "?", '', { From 4f1f1c85d9e0fe2bf565f985c5412dabad7d2b48 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Thu, 10 Dec 2020 10:45:22 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E5=88=87=E6=8D=A2=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/head/SearchList.vue | 44 ++++++++++++------- .../components/common/head/ShowAll.vue | 10 ++++- frontend/src/business/components/xpack | 2 +- frontend/src/common/js/constants.js | 1 + frontend/src/i18n/zh-CN.js | 2 +- 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/frontend/src/business/components/common/head/SearchList.vue b/frontend/src/business/components/common/head/SearchList.vue index d399064435..b3f47d280f 100644 --- a/frontend/src/business/components/common/head/SearchList.vue +++ b/frontend/src/business/components/common/head/SearchList.vue @@ -12,7 +12,7 @@
- + @@ -23,8 +23,8 @@ diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 8a972a1987..a22a3005d9 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8 +Subproject commit a22a3005d9bd254793fcf634d72539cbdf31be3a diff --git a/frontend/src/common/js/constants.js b/frontend/src/common/js/constants.js index 8a09180ad9..a0cbf2420d 100644 --- a/frontend/src/common/js/constants.js +++ b/frontend/src/common/js/constants.js @@ -10,6 +10,7 @@ export const ROLE_TEST_VIEWER = 'test_viewer'; export const WORKSPACE_ID = 'workspace_id'; export const CURRENT_PROJECT = 'current_project'; +export const PROJECT_ID = 'project_id'; export const REFRESH_SESSION_USER_URL = 'user/refresh'; export const WORKSPACE = 'workspace'; diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 1d5ec370cb..d4dab4c28f 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -279,7 +279,7 @@ export default { verified: '验证通过' } }, - edit: { + project: { recent: '最近的项目', create: '创建项目', edit: '编辑项目', From afa7527738a170e677908a947311043810cdcf93 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Thu, 10 Dec 2020 11:03:34 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):?= =?UTF-8?q?=20=E5=AE=8C=E6=88=90=E6=9F=A5=E7=9C=8B=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E5=92=8C=E6=B7=BB=E5=8A=A0=E7=94=A8=E4=BE=8B=E5=88=B0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E8=AE=A1=E5=88=92=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiDefinitionController.java | 6 ++ .../api/service/ApiAutomationService.java | 2 + .../api/service/ApiDefinitionService.java | 18 ++++- .../base/mapper/ext/ExtApiScenarioMapper.xml | 1 - .../automation/scenario/ApiScenarioList.vue | 1 + .../api/definition/components/ApiCaseList.vue | 19 ++++-- .../components/reference/ApiExtendBtns.vue | 67 +++++++++++++++++++ .../components/reference/ReferenceView.vue | 66 ++++++++++++++++++ frontend/src/i18n/en-US.js | 52 +++++++++++--- frontend/src/i18n/zh-CN.js | 5 +- frontend/src/i18n/zh-TW.js | 38 ++++++++++- 11 files changed, 255 insertions(+), 20 deletions(-) create mode 100644 frontend/src/business/components/api/definition/components/reference/ApiExtendBtns.vue create mode 100644 frontend/src/business/components/api/definition/components/reference/ReferenceView.vue diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java index b3b06d6c39..b27b4737b6 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -4,6 +4,8 @@ import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.ApiTestImportRequest; +import io.metersphere.api.dto.automation.ApiScenarioRequest; +import io.metersphere.api.dto.automation.ReferenceDTO; import io.metersphere.api.dto.definition.ApiDefinitionRequest; import io.metersphere.api.dto.definition.ApiDefinitionResult; import io.metersphere.api.dto.definition.RunDefinitionRequest; @@ -93,5 +95,9 @@ public class ApiDefinitionController { return apiDefinitionService.apiTestImport(file, request); } + @PostMapping("/getReference") + public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) { + return apiDefinitionService.getReference(request); + } } 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 9120cd514f..50862bf5a0 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -322,6 +322,7 @@ public class ApiAutomationService { .flatMap(Collection::stream).distinct().collect(Collectors.toList()); item.setApiIds(JSON.toJSONString(result)); } + item.setScenarioIds(null); } } if (CollectionUtils.isNotEmpty(request.getScenarioIds())) { @@ -335,6 +336,7 @@ public class ApiAutomationService { .flatMap(Collection::stream).distinct().collect(Collectors.toList()); item.setScenarioIds(JSON.toJSONString(result)); } + item.setApiIds(null); } } mapper.updatePlan(item); 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 7aa80d95ef..ae38edc769 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -4,6 +4,8 @@ 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.ApiScenarioRequest; +import io.metersphere.api.dto.automation.ReferenceDTO; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.scenario.request.RequestType; @@ -16,6 +18,8 @@ import io.metersphere.base.mapper.ApiDefinitionMapper; import io.metersphere.base.mapper.ApiTestFileMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper; +import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; +import io.metersphere.base.mapper.ext.ExtTestPlanMapper; import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.exception.MSException; @@ -25,6 +29,7 @@ import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.i18n.Translator; import io.metersphere.service.FileService; +import io.metersphere.track.request.testcase.QueryTestPlanRequest; import org.apache.commons.collections.CollectionUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; @@ -65,7 +70,9 @@ public class ApiDefinitionService { @Resource private SqlSessionFactory sqlSessionFactory; @Resource - private ApiModuleService apiModuleService; + private ExtApiScenarioMapper extApiScenarioMapper; + @Resource + private ExtTestPlanMapper extTestPlanMapper; private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24); @@ -351,4 +358,13 @@ public class ApiDefinitionService { sqlSession.flushStatements(); } + public ReferenceDTO getReference(ApiScenarioRequest request) { + ReferenceDTO dto = new ReferenceDTO(); + dto.setScenarioList(extApiScenarioMapper.selectReference(request)); + QueryTestPlanRequest planRequest = new QueryTestPlanRequest(); + planRequest.setApiId(request.getId()); + planRequest.setProjectId(request.getProjectId()); + dto.setTestPlanList(extTestPlanMapper.selectReference(planRequest)); + return dto; + } } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml index b4f05a7bba..da36ff4df5 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml @@ -75,7 +75,6 @@