From e228a8eb43f4c73cd1875b4293dbe3dd218b30a1 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Fri, 5 Mar 2021 14:21:16 +0800 Subject: [PATCH 01/12] =?UTF-8?q?refactor(=E6=B5=8B=E8=AF=95=E8=AE=A1?= =?UTF-8?q?=E5=88=92):=20=E4=BF=AE=E6=94=B9=E5=9C=BA=E6=99=AF=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E4=B8=8B=E7=8E=AF=E5=A2=83=E5=AD=97=E6=AE=B5=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/domain/TestPlanApiScenario.java | 4 +- .../domain/TestPlanApiScenarioExample.java | 70 ------------- .../mapper/TestPlanApiScenarioMapper.java | 6 ++ .../base/mapper/TestPlanApiScenarioMapper.xml | 98 ++++++++++++++----- .../ext/ExtTestPlanScenarioCaseMapper.xml | 2 +- .../db/migration/V78__v1.8_release.sql | 5 +- 6 files changed, 87 insertions(+), 98 deletions(-) diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenario.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenario.java index 7d347de5f9..652185c880 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenario.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenario.java @@ -13,8 +13,6 @@ public class TestPlanApiScenario implements Serializable { private String status; - private String environmentId; - private Long createTime; private Long updateTime; @@ -25,5 +23,7 @@ public class TestPlanApiScenario implements Serializable { private String reportId; + private String environment; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenarioExample.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenarioExample.java index a900880358..40d9e139f9 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenarioExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanApiScenarioExample.java @@ -384,76 +384,6 @@ public class TestPlanApiScenarioExample { return (Criteria) this; } - public Criteria andEnvironmentIdIsNull() { - addCriterion("environment_id is null"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdIsNotNull() { - addCriterion("environment_id is not null"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdEqualTo(String value) { - addCriterion("environment_id =", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdNotEqualTo(String value) { - addCriterion("environment_id <>", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdGreaterThan(String value) { - addCriterion("environment_id >", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdGreaterThanOrEqualTo(String value) { - addCriterion("environment_id >=", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdLessThan(String value) { - addCriterion("environment_id <", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdLessThanOrEqualTo(String value) { - addCriterion("environment_id <=", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdLike(String value) { - addCriterion("environment_id like", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdNotLike(String value) { - addCriterion("environment_id not like", value, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdIn(List values) { - addCriterion("environment_id in", values, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdNotIn(List values) { - addCriterion("environment_id not in", values, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdBetween(String value1, String value2) { - addCriterion("environment_id between", value1, value2, "environmentId"); - return (Criteria) this; - } - - public Criteria andEnvironmentIdNotBetween(String value1, String value2) { - addCriterion("environment_id not between", value1, value2, "environmentId"); - return (Criteria) this; - } - public Criteria andCreateTimeIsNull() { addCriterion("create_time is null"); return (Criteria) this; diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.java b/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.java index 63a39d7d6f..017d3a112e 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.java @@ -16,15 +16,21 @@ public interface TestPlanApiScenarioMapper { int insertSelective(TestPlanApiScenario record); + List selectByExampleWithBLOBs(TestPlanApiScenarioExample example); + List selectByExample(TestPlanApiScenarioExample example); TestPlanApiScenario selectByPrimaryKey(String id); int updateByExampleSelective(@Param("record") TestPlanApiScenario record, @Param("example") TestPlanApiScenarioExample example); + int updateByExampleWithBLOBs(@Param("record") TestPlanApiScenario record, @Param("example") TestPlanApiScenarioExample example); + int updateByExample(@Param("record") TestPlanApiScenario record, @Param("example") TestPlanApiScenarioExample example); int updateByPrimaryKeySelective(TestPlanApiScenario record); + int updateByPrimaryKeyWithBLOBs(TestPlanApiScenario record); + int updateByPrimaryKey(TestPlanApiScenario record); } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.xml index 08150fd137..9e6a517c29 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanApiScenarioMapper.xml @@ -6,13 +6,15 @@ - + + + @@ -72,9 +74,28 @@ - id, test_plan_id, api_scenario_id, `status`, environment_id, create_time, update_time, - pass_rate, last_result, report_id + id, test_plan_id, api_scenario_id, `status`, create_time, update_time, pass_rate, + last_result, report_id + + environment + + - select + , + from test_plan_api_scenario where id = #{id,jdbcType=VARCHAR} @@ -107,13 +130,13 @@ insert into test_plan_api_scenario (id, test_plan_id, api_scenario_id, - `status`, environment_id, create_time, - update_time, pass_rate, last_result, - report_id) + `status`, create_time, update_time, + pass_rate, last_result, report_id, + environment) values (#{id,jdbcType=VARCHAR}, #{testPlanId,jdbcType=VARCHAR}, #{apiScenarioId,jdbcType=VARCHAR}, - #{status,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, - #{updateTime,jdbcType=BIGINT}, #{passRate,jdbcType=VARCHAR}, #{lastResult,jdbcType=VARCHAR}, - #{reportId,jdbcType=VARCHAR}) + #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, + #{passRate,jdbcType=VARCHAR}, #{lastResult,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR}, + #{environment,jdbcType=LONGVARCHAR}) insert into test_plan_api_scenario @@ -130,9 +153,6 @@ `status`, - - environment_id, - create_time, @@ -148,6 +168,9 @@ report_id, + + environment, + @@ -162,9 +185,6 @@ #{status,jdbcType=VARCHAR}, - - #{environmentId,jdbcType=VARCHAR}, - #{createTime,jdbcType=BIGINT}, @@ -180,6 +200,9 @@ #{reportId,jdbcType=VARCHAR}, + + #{environment,jdbcType=LONGVARCHAR}, + select - t.id, t.environment_id, t.create_time, t.update_time, t.last_result, t.pass_rate, t.report_id, + t.id, t.environment, t.create_time, t.update_time, t.last_result, t.pass_rate, t.report_id, c.id as case_id, c.project_id, c.user_id,c.api_scenario_module_id, c.module_path, c.name, c.level, c.status, c.principal, c.step_total, c.follow_people, c.schedule, c.description, c.tags, c.num, p.name as project_name, p.id as project_id, u.name as user_name diff --git a/backend/src/main/resources/db/migration/V78__v1.8_release.sql b/backend/src/main/resources/db/migration/V78__v1.8_release.sql index 8e82f2d175..02c5752381 100644 --- a/backend/src/main/resources/db/migration/V78__v1.8_release.sql +++ b/backend/src/main/resources/db/migration/V78__v1.8_release.sql @@ -28,4 +28,7 @@ CREATE TABLE IF NOT EXISTS `api_document_share` ( ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- test_case_review add coloumn -ALTER TABLE test_case_review ADD tags VARCHAR(2000) NULL; \ No newline at end of file +ALTER TABLE test_case_review ADD tags VARCHAR(2000) NULL; + +-- alter test_plan_api_scenario +alter table test_plan_api_scenario change environment_id environment longtext null comment 'Relevance environment'; \ No newline at end of file From eed41fab067b50ef129ab3e4507ca92bfe61b5a4 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Fri, 5 Mar 2021 16:17:18 +0800 Subject: [PATCH 02/12] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92?= =?UTF-8?q?):=20=E5=85=B3=E8=81=94=E5=9C=BA=E6=99=AF=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E6=97=B6=E4=BF=9D=E5=AD=98=E6=89=A7=E8=A1=8C=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/automation/ApiScenarioDTO.java | 5 +++ .../api/service/ApiAutomationService.java | 25 ++++++----- .../base/mapper/ext/ExtApiScenarioMapper.xml | 1 + .../testcase/ApiCaseRelevanceRequest.java | 11 +++++ .../service/TestPlanScenarioCaseService.java | 29 ++++++++----- .../comonents/api/RelevanceScenarioList.vue | 41 ++++++++++++++++++- .../api/TestCaseScenarioRelevance.vue | 20 ++++++--- 7 files changed, 105 insertions(+), 27 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java index 358ca88ea3..b1f9e6e044 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java @@ -13,4 +13,9 @@ public class ApiScenarioDTO extends ApiScenarioWithBLOBs { private String projectName; private String userName; private List tagNames; + + /** + * 场景跨项目ID + */ + private List projectIds; } 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 88fc2242a2..5c99b63cd1 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -654,24 +654,29 @@ public class ApiAutomationService { } public void relevance(ApiCaseRelevanceRequest request) { - List ids = request.getSelectIds(); - if (CollectionUtils.isEmpty(ids)) { + Map> mapping = request.getMapping(); + Map envMap = request.getEnvMap(); + Set set = mapping.keySet(); + if (set.isEmpty()) { return; } - List apiScenarios = selectByIds(ids); - SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); - - ExtTestPlanScenarioCaseMapper batchMapper = sqlSession.getMapper(ExtTestPlanScenarioCaseMapper.class); - apiScenarios.forEach(scenario -> { + set.forEach(id -> { + Map newEnvMap = new HashMap<>(16); + if (envMap != null && !envMap.isEmpty()) { + List list = mapping.get(id); + list.forEach(l -> { + newEnvMap.put(l, envMap.get(l)); + }); + } TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario(); testPlanApiScenario.setId(UUID.randomUUID().toString()); - testPlanApiScenario.setApiScenarioId(scenario.getId()); + testPlanApiScenario.setApiScenarioId(id); testPlanApiScenario.setTestPlanId(request.getPlanId()); testPlanApiScenario.setCreateTime(System.currentTimeMillis()); testPlanApiScenario.setUpdateTime(System.currentTimeMillis()); - batchMapper.insertIfNotExists(testPlanApiScenario); + testPlanApiScenario.setEnvironment(JSON.toJSONString(newEnvMap)); + testPlanApiScenarioMapper.insert(testPlanApiScenario); }); - sqlSession.flushStatements(); } public List selectByIds(List ids) { 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 59e9100554..139de4d8d5 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 @@ -134,6 +134,7 @@ select - t.id, t.environment, t.create_time, t.update_time, t.last_result, t.pass_rate, t.report_id, + t.id, t.environment, t.create_time, t.update_time, t.last_result, t.pass_rate, t.report_id, c.scenario_definition, c.id as case_id, c.project_id, c.user_id,c.api_scenario_module_id, c.module_path, c.name, c.level, c.status, c.principal, c.step_total, c.follow_people, c.schedule, c.description, c.tags, c.num, p.name as project_name, p.id as project_id, u.name as user_name diff --git a/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java b/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java index 83bdf0ba9c..af7fe585e1 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java @@ -7,6 +7,7 @@ import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; +import io.metersphere.track.dto.RelevanceScenarioRequest; import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest; import io.metersphere.track.service.TestPlanScenarioCaseService; import org.apache.shiro.authz.annotation.Logical; @@ -53,4 +54,10 @@ public class TestPlanScenarioCaseController { request.setExecuteType(ExecuteType.Completed.name()); return testPlanScenarioCaseService.run(request); } + + @PostMapping("/batch/update/env") + @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) + public void batchUpdateEnv(@RequestBody RelevanceScenarioRequest request) { + testPlanScenarioCaseService.batchUpdateEnv(request); + } } diff --git a/backend/src/main/java/io/metersphere/track/dto/RelevanceScenarioRequest.java b/backend/src/main/java/io/metersphere/track/dto/RelevanceScenarioRequest.java new file mode 100644 index 0000000000..5504fb33aa --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/dto/RelevanceScenarioRequest.java @@ -0,0 +1,23 @@ +package io.metersphere.track.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +@Getter +@Setter +public class RelevanceScenarioRequest { + + /** + * 环境和项目对应关系 + */ + private Map envMap; + + /** + * 场景用例跨项目的关系 + */ + private Map> mapping; + +} diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java index 63c9d59467..b9a23d4301 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java @@ -14,6 +14,7 @@ import io.metersphere.base.mapper.TestPlanApiScenarioMapper; import io.metersphere.base.mapper.ext.ExtTestPlanScenarioCaseMapper; import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.utils.ServiceUtils; +import io.metersphere.track.dto.RelevanceScenarioRequest; import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,15 +41,15 @@ public class TestPlanScenarioCaseService { request.setProjectId(null); request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); List apiTestCases = extTestPlanScenarioCaseMapper.list(request); + setApiScenarioProjectIds(apiTestCases); if (CollectionUtils.isEmpty(apiTestCases)) { return apiTestCases; } return apiTestCases; } - public List relevanceList(ApiScenarioRequest request) { - request.setNotInTestPlan(true); - List list = apiAutomationService.list(request); + private void setApiScenarioProjectIds(List list) { + // 如果场景步骤涉及多项目,则把涉及到的项目ID保存在projectIds属性 list.forEach(data -> { String definition = data.getScenarioDefinition(); RunDefinitionRequest d = JSON.parseObject(definition, RunDefinitionRequest.class); @@ -64,6 +65,12 @@ public class TestPlanScenarioCaseService { } data.setProjectIds(idList); }); + } + + public List relevanceList(ApiScenarioRequest request) { + request.setNotInTestPlan(true); + List list = apiAutomationService.list(request); + setApiScenarioProjectIds(list); return list; } @@ -146,4 +153,28 @@ public class TestPlanScenarioCaseService { example.createCriteria().andApiScenarioIdEqualTo(id); testPlanApiScenarioMapper.deleteByExample(example); } + + public void batchUpdateEnv(RelevanceScenarioRequest request) { + Map envMap = request.getEnvMap(); + Map> mapping = request.getMapping(); + Set set = mapping.keySet(); + if (set.isEmpty()) { return; } + set.forEach(id -> { + Map newEnvMap = new HashMap<>(16); + if (envMap != null && !envMap.isEmpty()) { + List list = mapping.get(id); + list.forEach(l -> { + newEnvMap.put(l, envMap.get(l)); + }); + } + if (!newEnvMap.isEmpty()) { + TestPlanApiScenario scenario = new TestPlanApiScenario(); + scenario.setId(id); + scenario.setEnvironment(JSON.toJSONString(newEnvMap)); + testPlanApiScenarioMapper.updateByPrimaryKeySelective(scenario); + } + }); + + + } } diff --git a/frontend/src/business/components/track/case/components/BatchEdit.vue b/frontend/src/business/components/track/case/components/BatchEdit.vue index 421330b3ad..901e9f3dc1 100644 --- a/frontend/src/business/components/track/case/components/BatchEdit.vue +++ b/frontend/src/business/components/track/case/components/BatchEdit.vue @@ -112,6 +112,13 @@ this.projectIds.add(row.projectId) }) }, + setScenarioSelectRows(rows) { + this.selectRows = rows; + this.projectIds.clear(); + this.selectRows.forEach(row => { + row.projectIds.forEach(id => this.projectIds.add(id)); + }) + }, handleClose() { this.form = {}; this.options = []; diff --git a/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue b/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue index b803dc8bc0..0142730ff1 100644 --- a/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue +++ b/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue @@ -37,7 +37,8 @@ + + + @@ -98,7 +103,7 @@ import MsTableHeader from "@/business/components/common/components/MsTableHeader import MsTablePagination from "@/business/components/common/pagination/TablePagination"; import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn"; import MsTag from "../../../../../common/components/MsTag"; -import {getUUID, getCurrentProjectID, getCurrentUser} from "@/common/js/utils"; +import {getUUID, getCurrentProjectID, getCurrentUser, strMapToObj} from "@/common/js/utils"; import MsApiReportDetail from "../../../../../api/automation/report/ApiReportDetail"; import MsTableMoreBtn from "../../../../../api/automation/scenario/TableMoreBtn"; import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns"; @@ -110,6 +115,7 @@ import HeaderCustom from "@/business/components/common/head/HeaderCustom"; import {TEST_CASE_LIST, TEST_PLAN_SCENARIO_CASE} from "@/common/js/constants"; import {Test_Plan_Scenario_Case, Track_Test_Case} from "@/business/components/common/model/JsonData"; import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate"; +import BatchEdit from "@/business/components/track/case/components/BatchEdit"; export default { name: "MsTestPlanApiScenarioList", @@ -125,7 +131,8 @@ export default { MsTag, MsApiReportDetail, MsScenarioExtendButtons, - MsTestPlanList + MsTestPlanList, + BatchEdit }, props: { referenced: { @@ -162,9 +169,16 @@ export default { }, { name: this.$t('api_test.automation.batch_execute'), handleClick: this.handleBatchExecute - } + }, + {name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit} ], - selectRows: new Set() + selectRows: new Set(), + typeArr: [ + {id: 'projectEnv', name: this.$t('api_test.definition.request.run_env')}, + ], + valueArr: { + projectEnv: [] + }, } }, created() { @@ -284,7 +298,24 @@ export default { } } }); - } + }, + handleBatchEdit() { + this.$refs.batchEdit.open(this.selectRows.size); + this.$refs.batchEdit.setScenarioSelectRows(this.selectRows); + }, + batchEdit(form) { + let param = {}; + let map = new Map(); + this.selectRows.forEach(row => { + map.set(row.id, row.projectIds); + }) + param.mapping = strMapToObj(map); + param.envMap = strMapToObj(form.projectEnvMap); + this.$post('/test/plan/scenario/case/batch/update/env', param, () => { + this.$success(this.$t('commons.save_success')); + this.search(); + }) + }, } } From 58d4c226b87f7a45342cd24dff967b5b146e260d Mon Sep 17 00:00:00 2001 From: Coooder-X <55648333+Coooder-X@users.noreply.github.com> Date: Fri, 5 Mar 2021 17:28:14 +0800 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20(=E5=9C=BA=E6=99=AF=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4)=20=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=A4=8D=E9=80=89=E6=A1=86=E5=AE=9E=E7=8E=B0=E4=B8=80?= =?UTF-8?q?=E9=94=AE=E5=85=A8=E9=80=89=E5=92=8C=E5=8F=8D=E9=80=89=20(#1529?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/definition/components/ApiKeyValue.vue | 19 ++++++++++++++++++ .../api/definition/components/ApiVariable.vue | 20 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/definition/components/ApiKeyValue.vue b/frontend/src/business/components/api/definition/components/ApiKeyValue.vue index 34e5c4f103..9eeafbc4ce 100644 --- a/frontend/src/business/components/api/definition/components/ApiKeyValue.vue +++ b/frontend/src/business/components/api/definition/components/ApiKeyValue.vue @@ -3,6 +3,15 @@ {{ description }} + + + 全选/反选 + + + 全选 + 反选 + +
@@ -138,6 +147,16 @@ return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0); }; }, + selectAll() { + this.items.forEach(item => { + item.enable = true; + }); + }, + invertSelect() { + this.items.forEach(item => { + item.enable = !item.enable; + }); + }, }, created() { if (this.items.length === 0 || this.items[this.items.length - 1].name) { diff --git a/frontend/src/business/components/api/definition/components/ApiVariable.vue b/frontend/src/business/components/api/definition/components/ApiVariable.vue index b8f5830e7e..41806dd5d1 100644 --- a/frontend/src/business/components/api/definition/components/ApiVariable.vue +++ b/frontend/src/business/components/api/definition/components/ApiVariable.vue @@ -3,7 +3,15 @@ {{ description }} - + + + 全选/反选 + + + 全选 + 反选 + +
@@ -220,6 +228,16 @@ item.contentType = 'text/plain'; } }, + selectAll() { + this.parameters.forEach(item => { + item.enable = true; + }); + }, + invertSelect() { + this.parameters.forEach(item => { + item.enable = !item.enable; + }); + }, }, created() { if (this.parameters.length === 0 || this.parameters[this.parameters.length - 1].name) { From a5b03d1e121f72c28085ab71144b3d2e7512a843 Mon Sep 17 00:00:00 2001 From: Coooder-X <55648333+Coooder-X@users.noreply.github.com> Date: Fri, 5 Mar 2021 17:28:49 +0800 Subject: [PATCH 05/12] =?UTF-8?q?fix:(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92?= =?UTF-8?q?)=20=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E7=A9=BA=E6=8C=87?= =?UTF-8?q?=E9=92=88=E3=80=81=E8=AE=A1=E5=88=92=E5=BC=80=E5=A7=8B=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=9B=B4=E6=96=B0=20(#1543)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/api/service/ApiTestCaseService.java | 11 +++++++++++ .../track/service/TestPlanLoadCaseService.java | 13 ++++++++++++- .../metersphere/track/service/TestPlanService.java | 12 ++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java index fbad14793a..ee452d424a 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java @@ -22,6 +22,7 @@ import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; +import io.metersphere.commons.constants.TestPlanStatus; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.*; import io.metersphere.i18n.Translator; @@ -49,6 +50,8 @@ import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) public class ApiTestCaseService { + @Resource + TestPlanMapper testPlanMapper; @Resource private ApiTestCaseMapper apiTestCaseMapper; @Resource @@ -330,6 +333,14 @@ public class ApiTestCaseService { testPlanApiCase.setUpdateTime(System.currentTimeMillis()); batchMapper.insertIfNotExists(testPlanApiCase); }); + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId()); + if (StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Prepare.name()) + || StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Completed.name())) { + testPlan.setStatus(TestPlanStatus.Underway.name()); + testPlan.setActualStartTime(System.currentTimeMillis()); // 将状态更新为进行中时,开始时间也要更新 + testPlan.setActualEndTime(null); + testPlanMapper.updateByPrimaryKey(testPlan); + } sqlSession.flushStatements(); } diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java index 52ba444b26..18b2c63e15 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java @@ -4,7 +4,9 @@ import io.metersphere.base.domain.*; import io.metersphere.base.mapper.LoadTestMapper; import io.metersphere.base.mapper.LoadTestReportMapper; import io.metersphere.base.mapper.TestPlanLoadCaseMapper; +import io.metersphere.base.mapper.TestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanLoadCaseMapper; +import io.metersphere.commons.constants.TestPlanStatus; import io.metersphere.controller.request.OrderRequest; import io.metersphere.performance.request.RunTestPlanRequest; import io.metersphere.performance.service.PerformanceTestService; @@ -28,7 +30,8 @@ import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) public class TestPlanLoadCaseService { - + @Resource + TestPlanMapper testPlanMapper; @Resource private TestPlanLoadCaseMapper testPlanLoadCaseMapper; @Resource @@ -78,6 +81,14 @@ public class TestPlanLoadCaseService { t.setUpdateTime(System.currentTimeMillis()); testPlanLoadCaseMapper.insert(t); }); + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId()); + if (org.apache.commons.lang3.StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Prepare.name()) + || org.apache.commons.lang3.StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Completed.name())) { + testPlan.setStatus(TestPlanStatus.Underway.name()); + testPlan.setActualStartTime(System.currentTimeMillis()); // 将状态更新为进行中时,开始时间也要更新 + testPlan.setActualEndTime(null); + testPlanMapper.updateByPrimaryKey(testPlan); + } sqlSession.flushStatements(); } diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java index f6a7b00581..08b343ee43 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java @@ -159,8 +159,8 @@ public class TestPlanService { public int editTestPlan(TestPlanDTO testPlan) { checkTestPlanExist(testPlan); TestPlan res = testPlanMapper.selectByPrimaryKey(testPlan.getId()); // 先查一次库 + testPlan.setUpdateTime(System.currentTimeMillis()); if (!res.getStatus().equals(testPlan.getStatus())) { // 若有改变才更新时间 - testPlan.setUpdateTime(System.currentTimeMillis()); if (TestPlanStatus.Underway.name().equals(testPlan.getStatus())) { if (res.getStatus().equals(TestPlanStatus.Prepare.name())) { testPlan.setActualStartTime(System.currentTimeMillis()); @@ -183,7 +183,13 @@ public class TestPlanService { List userIds = new ArrayList<>(); userIds.add(testPlan.getPrincipal()); AddTestPlanRequest testPlans = new AddTestPlanRequest(); - int i = testPlanMapper.updateByPrimaryKeySelective(testPlan); // 更新 + int i; + if(testPlan.getName() == null) {// 若是点击该测试计划,则仅更新了updateTime,其它字段全为null,使用updateByPrimaryKeySelective + i = testPlanMapper.updateByPrimaryKeySelective(testPlan); + } + else { // 有修改字段的调用,为保证将某些时间置null的情况,使用updateByPrimaryKey + i = testPlanMapper.updateByPrimaryKey(testPlan); // 更新 + } if (!StringUtils.isBlank(testPlan.getStatus())) { BeanUtils.copyBean(testPlans, getTestPlan(testPlan.getId())); String context = getTestPlanContext(testPlans, NoticeConstants.Event.UPDATE); @@ -412,6 +418,8 @@ public class TestPlanService { if (StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Prepare.name()) || StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Completed.name())) { testPlan.setStatus(TestPlanStatus.Underway.name()); + testPlan.setActualStartTime(System.currentTimeMillis()); // 将状态更新为进行中时,开始时间也要更新 + testPlan.setActualEndTime(null); testPlanMapper.updateByPrimaryKey(testPlan); } } From dc6240c964086c15ad457b44b09212326c6c5e8f Mon Sep 17 00:00:00 2001 From: Coooder-X <55648333+Coooder-X@users.noreply.github.com> Date: Fri, 5 Mar 2021 17:29:17 +0800 Subject: [PATCH 06/12] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA?= =?UTF-8?q?):=20=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E6=A8=A1=E7=89=88=E5=A2=9E=E5=8A=A0=E6=A0=87=E7=AD=BE=E5=88=97?= =?UTF-8?q?=20(#1548)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(测试跟踪): 测试用例下载模版增加标签列 * fix(接口定义): 扩大请求头键长度 --- .../java/io/metersphere/excel/domain/TestCaseExcelData.java | 2 ++ .../io/metersphere/excel/domain/TestCaseExcelDataCn.java | 5 +++++ .../java/io/metersphere/track/service/TestCaseService.java | 1 + .../components/api/definition/components/ApiKeyValue.vue | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java index af8b17b529..8c344e6e3f 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java @@ -19,6 +19,8 @@ public class TestCaseExcelData { @ExcelIgnore private String priority; @ExcelIgnore + private String tags; + @ExcelIgnore private String method; @ExcelIgnore private String prerequisite; diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java index 7460deb555..2d98f10baf 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java @@ -38,6 +38,11 @@ public class TestCaseExcelDataCn extends TestCaseExcelData { @Pattern(regexp = "(^P0$)|(^P1$)|(^P2$)|(^P3$)", message = "{test_case_priority_validate}") private String priority; + @ColumnWidth(50) + @ExcelProperty("标签") + @Length(min = 0, max = 1000) + private String tags; + @NotBlank(message = "{cannot_be_null}") @ExcelProperty("测试方式") @Pattern(regexp = "(^manual$)|(^auto$)", message = "{test_case_method_validate}") diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java index 5b1c1772b7..b8ae792fe4 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -483,6 +483,7 @@ public class TestCaseService { data.setType(t.getType()); data.setMethod(t.getMethod()); data.setPrerequisite(t.getPrerequisite()); + data.setTags(t.getTags()); if (t.getMethod().equals("manual")) { String steps = t.getSteps(); String setp = ""; diff --git a/frontend/src/business/components/api/definition/components/ApiKeyValue.vue b/frontend/src/business/components/api/definition/components/ApiKeyValue.vue index 9eeafbc4ce..a2a8598afc 100644 --- a/frontend/src/business/components/api/definition/components/ApiKeyValue.vue +++ b/frontend/src/business/components/api/definition/components/ApiKeyValue.vue @@ -28,7 +28,7 @@ - From f1c021e9ccc3f4f3924412662e360db8a759fafb Mon Sep 17 00:00:00 2001 From: Coooder-X <55648333+Coooder-X@users.noreply.github.com> Date: Fri, 5 Mar 2021 17:30:01 +0800 Subject: [PATCH 07/12] Fix el input (#1559) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(测试跟踪): 测试用例下载模版增加标签列 * fix(接口定义): 扩大请求头键长度 * fix(环境配置): 解决 通用配置-变量名在屏幕缩小时无法显示 --- .../components/api/definition/components/ApiVariableInput.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/definition/components/ApiVariableInput.vue b/frontend/src/business/components/api/definition/components/ApiVariableInput.vue index f9319f713b..532116a3de 100644 --- a/frontend/src/business/components/api/definition/components/ApiVariableInput.vue +++ b/frontend/src/business/components/api/definition/components/ApiVariableInput.vue @@ -1,6 +1,6 @@