feat(接口定义): 完成查看引用和添加用例到测试计划功能

This commit is contained in:
fit2-zhao 2020-12-10 11:03:34 +08:00
parent 1f59d12f7b
commit afa7527738
11 changed files with 255 additions and 20 deletions

View File

@ -4,6 +4,8 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.ApiTestImportRequest; 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.ApiDefinitionRequest;
import io.metersphere.api.dto.definition.ApiDefinitionResult; import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
@ -93,5 +95,9 @@ public class ApiDefinitionController {
return apiDefinitionService.apiTestImport(file, request); return apiDefinitionService.apiTestImport(file, request);
} }
@PostMapping("/getReference")
public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) {
return apiDefinitionService.getReference(request);
}
} }

View File

@ -322,6 +322,7 @@ public class ApiAutomationService {
.flatMap(Collection::stream).distinct().collect(Collectors.toList()); .flatMap(Collection::stream).distinct().collect(Collectors.toList());
item.setApiIds(JSON.toJSONString(result)); item.setApiIds(JSON.toJSONString(result));
} }
item.setScenarioIds(null);
} }
} }
if (CollectionUtils.isNotEmpty(request.getScenarioIds())) { if (CollectionUtils.isNotEmpty(request.getScenarioIds())) {
@ -335,6 +336,7 @@ public class ApiAutomationService {
.flatMap(Collection::stream).distinct().collect(Collectors.toList()); .flatMap(Collection::stream).distinct().collect(Collectors.toList());
item.setScenarioIds(JSON.toJSONString(result)); item.setScenarioIds(JSON.toJSONString(result));
} }
item.setApiIds(null);
} }
} }
mapper.updatePlan(item); mapper.updatePlan(item);

View File

@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.ApiTestImportRequest; 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.*;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.scenario.request.RequestType; 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.ApiTestFileMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper; 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.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException; 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.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import io.metersphere.service.FileService; import io.metersphere.service.FileService;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
@ -65,7 +70,9 @@ public class ApiDefinitionService {
@Resource @Resource
private SqlSessionFactory sqlSessionFactory; private SqlSessionFactory sqlSessionFactory;
@Resource @Resource
private ApiModuleService apiModuleService; private ExtApiScenarioMapper extApiScenarioMapper;
@Resource
private ExtTestPlanMapper extTestPlanMapper;
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24); private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
@ -351,4 +358,13 @@ public class ApiDefinitionService {
sqlSession.flushStatements(); 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;
}
} }

View File

@ -75,7 +75,6 @@
<select id="selectReference" resultType="io.metersphere.base.domain.ApiScenario"> <select id="selectReference" resultType="io.metersphere.base.domain.ApiScenario">
select * from api_scenario select * from api_scenario
<where> <where>
id != #{request.id}
<if test="request.workspaceId != null"> <if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId} AND project.workspace_id = #{request.workspaceId}
</if> </if>

View File

@ -49,6 +49,7 @@
<template v-slot:default="{row}"> <template v-slot:default="{row}">
<div v-if="currentModule!=undefined && currentModule.id === 'gc'"> <div v-if="currentModule!=undefined && currentModule.id === 'gc'">
<el-button type="text" @click="reductionApi(row)">恢复</el-button> <el-button type="text" @click="reductionApi(row)">恢复</el-button>
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button>
</div> </div>
<div v-else> <div v-else>
<el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button> <el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button>

View File

@ -99,7 +99,6 @@
<el-col :span="10"> <el-col :span="10">
<i class="icon el-icon-arrow-right" :class="{'is-active': item.active}" <i class="icon el-icon-arrow-right" :class="{'is-active': item.active}"
@click="active(item)"/> @click="active(item)"/>
<el-input v-if="item.type==='create'" size="small" v-model="item.name" :name="index" :key="index" <el-input v-if="item.type==='create'" size="small" v-model="item.name" :name="index" :key="index"
class="ms-api-header-select" style="width: 180px" class="ms-api-header-select" style="width: 180px"
@blur="saveTestCase(item)"/> @blur="saveTestCase(item)"/>
@ -108,8 +107,14 @@
<i class="el-icon-edit" style="cursor:pointer" @click="showInput(item)"/> <i class="el-icon-edit" style="cursor:pointer" @click="showInput(item)"/>
</span> </span>
<div v-if="item.type!='create'" style="color: #999999;font-size: 12px"> <div v-if="item.type!='create'" style="color: #999999;font-size: 12px">
<span> {{item.createTime | timestampFormatDate }}</span> {{item.createUser}} 创建 <span>
<span> {{item.updateTime | timestampFormatDate }}</span> {{item.updateUser}} 更新 {{item.createTime | timestampFormatDate }}
{{item.createUser}} {{$t('api_test.definition.request.create_info')}}
</span>
<span>
{{item.updateTime | timestampFormatDate }}
{{item.updateUser}} {{$t('api_test.definition.request.update_info')}}
</span>
</div> </div>
</el-col> </el-col>
@ -119,8 +124,8 @@
<ms-tip-button @click="copyCase(item)" :tip="$t('commons.copy')" icon="el-icon-document-copy" <ms-tip-button @click="copyCase(item)" :tip="$t('commons.copy')" icon="el-icon-document-copy"
size="mini" circle/> size="mini" circle/>
<ms-tip-button @click="deleteCase(index,item)" :tip="$t('commons.delete')" icon="el-icon-delete" <ms-tip-button @click="deleteCase(index,item)" :tip="$t('commons.delete')" icon="el-icon-delete"
size="mini" size="mini" circle/>
circle/> <ms-api-extend-btns :row="item"/>
</el-col> </el-col>
<el-col :span="3"> <el-col :span="3">
@ -172,6 +177,7 @@
import MsSqlBasisParameters from "./request/database/BasisParameters"; import MsSqlBasisParameters from "./request/database/BasisParameters";
import MsTcpBasisParameters from "./request/tcp/BasisParameters"; import MsTcpBasisParameters from "./request/tcp/BasisParameters";
import MsDubboBasisParameters from "./request/dubbo/BasisParameters"; import MsDubboBasisParameters from "./request/dubbo/BasisParameters";
import MsApiExtendBtns from "./reference/ApiExtendBtns";
export default { export default {
name: 'ApiCaseList', name: 'ApiCaseList',
@ -184,7 +190,8 @@
MsSqlBasisParameters, MsSqlBasisParameters,
MsTcpBasisParameters, MsTcpBasisParameters,
MsDubboBasisParameters, MsDubboBasisParameters,
MsRun MsRun,
MsApiExtendBtns
}, },
props: { props: {
api: { api: {

View File

@ -0,0 +1,67 @@
<template>
<el-dropdown @command="handleCommand" class="scenario-ext-btn">
<el-link type="primary" :underline="false">
<el-icon class="el-icon-more"></el-icon>
</el-link>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
<el-dropdown-item command="add_plan">{{ $t('api_test.automation.batch_add_plan') }}</el-dropdown-item>
</el-dropdown-menu>
<ms-reference-view ref="viewRef"/>
<!--测试计划-->
<el-drawer :visible.sync="planVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
<ms-test-plan-list @addTestPlan="addTestPlan"/>
</el-drawer>
</el-dropdown>
</template>
<script>
import MsReferenceView from "./ReferenceView";
import MsTestPlanList from "../../../automation/scenario/testplan/TestPlanList";
export default {
name: "MsApiExtendBtns",
components: {MsReferenceView, MsTestPlanList},
props: {
row: Object
},
data() {
return {
planVisible: false,
}
},
methods: {
handleCommand(cmd) {
if (this.row.id) {
switch (cmd) {
case "ref":
this.$refs.viewRef.open(this.row);
break;
case "add_plan":
this.addCaseToPlan();
break;
}
} else {
this.$warning(this.$t('api_test.automation.save_case_info'))
}
},
addCaseToPlan() {
this.planVisible = true;
},
addTestPlan(plans) {
let obj = {planIds: plans, apiIds: [this.row.id]};
this.planVisible = false;
this.$post("/api/automation/scenario/plan", obj, response => {
this.$success(this.$t("commons.save_success"));
});
}
}
}
</script>
<style scoped>
.scenario-ext-btn {
margin-left: 10px;
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.case_ref')" :visible.sync="visible"
width="45%" :destroy-on-close="true">
<span>{{ $t('api_test.automation.scenario_ref') }}</span>
<div class="refs" v-loading="scenarioLoading">
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">{{ item.name }}</div>
</div>
<span>{{ $t('api_test.automation.plan_ref') }}</span>
<div class="refs">
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">{{ item.name }}</div>
</div>
<template v-slot:footer>
<div class="dialog-footer">
<el-button type="primary" @click="visible = false" @keydown.enter.native.prevent>
{{ $t('commons.confirm') }}
</el-button>
</div>
</template>
</el-dialog>
</template>
<script>
export default {
name: "MsReferenceView",
components: {},
data() {
return {
visible: false,
scenarioLoading: false,
scenarioRefs: [],
planRefs: []
}
},
methods: {
getReferenceData(row) {
if (row.id === undefined) {
return;
}
this.scenarioLoading = true;
this.scenarioRefs = [];
this.$post("/api/definition/getReference/", row, response => {
this.scenarioRefs = response.data.scenarioList;
this.planRefs = response.data.testPlanList;
this.scenarioLoading = false;
})
},
open(row) {
this.getReferenceData(row);
this.visible = true
}
}
}
</script>
<style scoped>
.refs {
min-height: 50px;
max-height: 200px;
overflow-y: auto;
font-size: 12px;
padding-bottom: 10px;
}
</style>

View File

@ -533,23 +533,57 @@ export default {
add_module: "Add module", add_module: "Add module",
edit_api: "Edit Api", edit_api: "Edit Api",
test_plan_select: "Please select test plan", test_plan_select: "Please select test plan",
create_info: 'Create',
update_info: 'Update',
} }
}, },
automation: { automation: {
follow_people: "Follow people", follow_people: "Follow people",
create_tag: "Create tag", create_tag: "Create tag",
scenario_step: "Scenario step", scenario_step: "Ccenario step",
step_total: "Step total", step_total: "Step total",
scenario_total: "Scene public parameters", scenario_total: "Scenario total",
api_list_import: "Interface list import", api_list_import: "Api list import",
external_import: "External import", external_import: "External import",
wait_controller: "Waiting for controller", wait_controller: "Wait controller",
if_controller: "Condition controller", if_controller: "If controller",
scenario_import: "Scene import", scenario_import: "Scenario import",
customize_script: "Custom script", customize_script: "Customize script",
customize_req: "Custom request", customize_req: "Customize req",
reference_info: "Please select interface or use case", reference_info: "Reference info",
scenario_test: "Scenario test",
add_scenario: "Add scenario",
scenario_name: "Scenario name",
case_level: "Case level",
tag: "Tag",
creator: "Creator",
update_time: "Update time",
step: "Step",
last_result: "Last result",
passing_rate: "Passing rate",
success: "Success",
fail: "Fail",
saved: "Saved",
trash: "Trash",
edit: "Edit",
execute: "Execute",
copy: "Copy",
remove: "Remove",
view_ref: "View ref",
case_ref: "Case ref",
scenario_ref: "Scenario ref",
plan_ref: "Plan ref",
batch_add_plan: "Add plan",
batch_execute: "Batch execute",
scenario: {
principal: "principal",
select_principal: "Select principal",
follow_people: "Follow people",
select_table: "Select table",
select_all: "Select all"
},
report_name_info: 'Please enter the registration name', report_name_info: 'Please enter the registration name',
save_case_info: 'Please save the use case first',
}, },
environment: { environment: {
name: "Environment Name", name: "Environment Name",

View File

@ -532,6 +532,8 @@ export default {
add_module: "创建模块", add_module: "创建模块",
edit_api: "编辑接口", edit_api: "编辑接口",
test_plan_select: "请选择测试计划", test_plan_select: "请选择测试计划",
create_info: '创建',
update_info: '更新',
} }
}, },
automation: { automation: {
@ -570,7 +572,7 @@ export default {
case_ref: "用例引用", case_ref: "用例引用",
scenario_ref: "场景引用", scenario_ref: "场景引用",
plan_ref: "测试计划引用", plan_ref: "测试计划引用",
batch_add_plan: "批量添加到测试计划", batch_add_plan: "添加到测试计划",
batch_execute: "批量执行", batch_execute: "批量执行",
scenario: { scenario: {
principal: "责任人", principal: "责任人",
@ -580,6 +582,7 @@ export default {
select_all: "选择全部数据" select_all: "选择全部数据"
}, },
report_name_info: '请输入报名名称', report_name_info: '请输入报名名称',
save_case_info: '请先保存用例',
}, },
environment: { environment: {
name: "环境名称", name: "环境名称",

View File

@ -532,6 +532,8 @@ export default {
add_module: "創建模塊", add_module: "創建模塊",
edit_api: "编辑接口", edit_api: "编辑接口",
test_plan_select: "請選擇測試計劃", test_plan_select: "請選擇測試計劃",
create_info: '創建',
update_info: '更新',
} }
}, },
automation: { automation: {
@ -545,10 +547,42 @@ export default {
wait_controller: "等待控制器", wait_controller: "等待控制器",
if_controller: "條件控制器", if_controller: "條件控制器",
scenario_import: "場景導入", scenario_import: "場景導入",
customize_script: "自定義本", customize_script: "自定義本",
customize_req: "自定義請求", customize_req: "自定義請求",
reference_info: "請選擇接口或用例", reference_info: "請選擇接口或用例",
report_name_info: '请输入报名名称', scenario_test: "場景",
add_scenario: "创建場景",
scenario_name: "場景名称",
case_level: "用例等级",
tag: "標簽",
creator: "創建人",
update_time: "最後更新時間",
step: "步驟數",
last_result: "最後結果",
passing_rate: "通過率",
success: "通過",
fail: "失敗",
saved: "保存",
trash: "回收",
edit: "編輯",
execute: "執行",
copy: "復制",
remove: "删除",
view_ref: "查看引用",
case_ref: "用例引用",
scenario_ref: "场景引用",
plan_ref: "测试计划引用",
batch_add_plan: "添加到测试计划",
batch_execute: "批量执行",
scenario: {
principal: "責任人",
select_principal: "請選擇責任人",
follow_people: "關註人",
select_table: "選擇可見數據",
select_all: "選擇全部數據"
},
report_name_info: '請輸入報名名稱',
save_case_info: '請先保存用例',
}, },
environment: { environment: {
name: "環境名稱", name: "環境名稱",