This commit is contained in:
chenjianxing 2021-01-26 20:37:14 +08:00
commit 00eadc527f
29 changed files with 353 additions and 72 deletions

View File

@ -16,6 +16,7 @@ public class TestPlanScenarioRequest {
private String moduleId;
private List<String> moduleIds;
private String name;
private String status;
private String workspaceId;
private String userId;
private String planId;

View File

@ -356,6 +356,8 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
return protocol.toUpperCase();
}
return RequestType.DUBBO;
} else if (StringUtils.contains(result.getResponseHeaders(), "url:jdbc")) {
return "SQL";
} else {
// Http Method
String method = StringUtils.substringBefore(body, " ");

View File

@ -39,8 +39,17 @@
<when test="request.status == 'Trash'">
and a.status = 'Trash'
</when>
<otherwise>
<when test="request.status == null">
and a.status != 'Trash'
</when>
<when test="request.status == ''">
and a.status != 'Trash'
</when>
<when test="request.status == 'running'">
and t.status IS NULL
</when>
<otherwise>
and t.status = #{request.status}
</otherwise>
</choose>
where 1

View File

@ -40,6 +40,9 @@
<if test="request.name != null">
and (lt.name like CONCAT('%', #{request.name},'%') or lt.num like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.status != null">
and tplc.status like CONCAT('%', #{request.status},'%')
</if>
<if test="request.filters != null and request.filters.size() > 0">
<foreach collection="request.filters.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0">

View File

@ -46,6 +46,11 @@
<if test="request.name != null and request.name!=''">
and c.name like CONCAT('%', #{request.name},'%')
</if>
<if test="request.status != null and request.status!=''">
and t.last_result like CONCAT('%', #{request.status},'%')
</if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
and c.api_scenario_module_id in
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">

View File

@ -6,6 +6,7 @@ import io.metersphere.service.CheckPermissionService;
import io.metersphere.track.dto.TestCaseNodeDTO;
import io.metersphere.track.request.testcase.DragNodeRequest;
import io.metersphere.track.request.testcase.QueryNodeRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import io.metersphere.track.service.TestCaseNodeService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
@ -47,6 +48,15 @@ public class TestCaseNodeController {
return testCaseNodeService.getNodeByPlanId(planId);
}
@GetMapping("/list/plan/{planId}/{runResult}")
public List<TestCaseNodeDTO> getNodeByPlanIdAndRunResult(@PathVariable String planId,@PathVariable String runResult) {
checkPermissionService.checkTestPlanOwner(planId);
QueryTestPlanCaseRequest request = new QueryTestPlanCaseRequest();
request.setPlanId(planId);
request.setStatus(runResult);
return testCaseNodeService.getNodeByQueryRequest(request);
}
@GetMapping("/list/review/{reviewId}")
public List<TestCaseNodeDTO> getNodeByReviewId(@PathVariable String reviewId) {
checkPermissionService.checkTestReviewOwner(reviewId);

View File

@ -15,12 +15,14 @@ import java.util.List;
@Setter
public class TestPlanReportDTO {
private String id;
private String testPlanId;
private String name;
private String testPlanName;
private String creator;
private long createTime;
private String triggerMode;
private String status;
private String reportComponents;
private TestCaseReportAdvanceStatusResultDTO executeResult;
private List<TestCaseReportModuleResultDTO> moduleExecuteResult;

View File

@ -14,6 +14,7 @@ public class LoadCaseRequest extends TestPlanLoadCase {
private String projectId;
private List<String> caseIds;
private String name;
private String status;
private Map<String, List<String>> filters;
private List<OrderRequest> orders;
}

View File

@ -6,6 +6,7 @@ import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestCaseNodeMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.commons.constants.TestCaseConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.exception.ExcelException;
@ -13,9 +14,11 @@ import io.metersphere.i18n.Translator;
import io.metersphere.service.NodeTreeService;
import io.metersphere.track.dto.TestCaseDTO;
import io.metersphere.track.dto.TestCaseNodeDTO;
import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.request.testcase.DragNodeRequest;
import io.metersphere.track.request.testcase.QueryNodeRequest;
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
@ -43,6 +46,8 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
@Resource
TestPlanTestCaseMapper testPlanTestCaseMapper;
@Resource
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
@Resource
ExtTestCaseMapper extTestCaseMapper;
@Resource
SqlSessionFactory sqlSessionFactory;
@ -136,6 +141,32 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
return testCaseNodeMapper.deleteByExample(testCaseNodeExample);
}
/**
* 获取当前计划下
* 有关联数据的节点
*
* @param request
* @return List<TestCaseNodeDTO>
*/
public List<TestCaseNodeDTO> getNodeByQueryRequest(QueryTestPlanCaseRequest request) {
List<TestCaseNodeDTO> list = new ArrayList<>();
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(request.getPlanId());
projectIds.forEach(id -> {
Project project = projectMapper.selectByPrimaryKey(id);
String name = project.getName();
List<TestCaseNodeDTO> nodeList = getNodeDTO(id, request);
TestCaseNodeDTO testCaseNodeDTO = new TestCaseNodeDTO();
testCaseNodeDTO.setId(project.getId());
testCaseNodeDTO.setName(name);
testCaseNodeDTO.setLabel(name);
testCaseNodeDTO.setChildren(nodeList);
list.add(testCaseNodeDTO);
});
return list;
}
/**
* 获取当前计划下
* 有关联数据的节点
@ -187,6 +218,37 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
}
private List<TestCaseNodeDTO> getNodeDTO(String projectId, QueryTestPlanCaseRequest request) {
List<TestPlanCaseDTO> testPlanTestCases = extTestPlanTestCaseMapper.listByPlanId(request);
if (testPlanTestCases.isEmpty()) {
return null;
}
List<TestCaseNodeDTO> testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId);
List<String> caseIds = testPlanTestCases.stream()
.map(TestPlanCaseDTO::getCaseId)
.collect(Collectors.toList());
TestCaseExample testCaseExample = new TestCaseExample();
testCaseExample.createCriteria().andIdIn(caseIds);
List<String> dataNodeIds = testCaseMapper.selectByExample(testCaseExample).stream()
.map(TestCase::getNodeId)
.collect(Collectors.toList());
List<TestCaseNodeDTO> nodeTrees = getNodeTrees(testCaseNodes);
Iterator<TestCaseNodeDTO> iterator = nodeTrees.iterator();
while (iterator.hasNext()) {
TestCaseNodeDTO rootNode = iterator.next();
if (pruningTree(rootNode, dataNodeIds)) {
iterator.remove();
}
}
return nodeTrees;
}
private List<TestCaseNodeDTO> getNodeDTO(String projectId, String planId) {
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(planId);

View File

@ -27,6 +27,7 @@ import io.metersphere.track.request.report.QueryTestPlanReportRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.LoadCaseRequest;
import org.apache.commons.lang3.StringUtils;
import org.python.bouncycastle.pqc.math.linearalgebra.IntUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -194,6 +195,9 @@ public class TestPlanReportService {
returnDTO.setProjectName(testProject);
}
}
returnDTO.setId(report.getId());
returnDTO.setTestPlanId(report.getTestPlanId());
returnDTO.setReportComponents(report.getComponents());
return returnDTO;
}
@ -227,21 +231,33 @@ public class TestPlanReportService {
}
}
}else if(StringUtils.equals(ReportTriggerMode.TEST_PLAN_SCHEDULE.name(),triggerMode)){
issuesInfo = ReportTriggerMode.TEST_PLAN_SCHEDULE.name();
}
testPlanReport.setEndTime(System.currentTimeMillis());
testPlanReport.setUpdateTime(System.currentTimeMillis());
//手动触发的需要保存手工执行的信息
int [] componentIndexArr = null;
if(StringUtils.equals(ReportTriggerMode.MANUAL.name(),triggerMode)){
componentIndexArr = new int[]{1,2,3,4,5};
}else {
componentIndexArr = new int[]{1,3,4};
}
testPlanReport.setComponents(JSONArray.toJSONString(componentIndexArr));
JSONObject content = JSONObject.parseObject("{\"components\":[1,2,3,4,5]}");
JSONArray componentIds = content.getJSONArray("components");
// JSONObject content = JSONObject.parseObject("{\"components\":[1,2,3,4,5]}");
JSONArray componentIds = JSONArray.parseArray(testPlanReport.getComponents());
List<ReportComponent> components = ReportComponentFactory.createComponents(componentIds.toJavaList(String.class), testPlan);
testPlanService.buildApiCaseReport(testPlanReport.getTestPlanId(), components);
testPlanService.buildScenarioCaseReport(testPlanReport.getTestPlanId(), components);
testPlanService.buildLoadCaseReport(testPlanReport.getTestPlanId(), components);
if(StringUtils.equals(ReportTriggerMode.MANUAL.name(),triggerMode)){
List<Issues> issues = testPlanService.buildFunctionalCaseReport(testPlanReport.getTestPlanId(), components);
issuesInfo = JSONArray.toJSONString(issues);
}
//只针对定时任务做处理
if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
&&StringUtils.equals(resourceRunMode, ApiRunMode.SCHEDULE_API_PLAN.name())) {

@ -1 +1 @@
Subproject commit bb9ad600f10ff2dd9c3d364a7b30b1926dc2a74f
Subproject commit 792ace0c68d2b4ff42a74d8e6df32ca7f290ca1c

View File

@ -45,8 +45,8 @@
<el-tab-pane v-if="activeName == 'body'" :disabled="true" name="mode" class="pane assertions">
<template v-slot:label>
<ms-dropdown v-if="!isSqlType" :commands="modes" :default-command="mode" @command="modeChange"/>
<ms-dropdown v-if="isSqlType" :commands="sqlModes" :default-command="mode" @command="sqlModeChange"/>
<ms-dropdown v-if="request.method==='SQL'" :commands="sqlModes" :default-command="mode" @command="sqlModeChange"/>
<ms-dropdown v-else :commands="modes" :default-command="mode" @command="modeChange" ref="modeDropdown"/>
</template>
</el-tab-pane>
</el-tabs>
@ -110,7 +110,7 @@
computed: {
isSqlType() {
return (this.requestType === RequestFactory.TYPES.SQL && this.response.responseCode === '200');
return ((this.requestType === RequestFactory.TYPES.SQL || this.request.method === RequestFactory.TYPES.SQL) && this.response.responseCode === '200'&& this.mode === 'table');
}
}
}

View File

@ -95,7 +95,7 @@
<!-- HTTP 请求返回数据 -->
<p class="tip">{{$t('api_test.definition.request.res_param')}}</p>
<api-response-component :api-item="apiCase"/>
<api-response-component :currentProtocol="apiCase.request.protocol" :api-item="apiCase"/>
<ms-jmx-step :request="apiCase.request" :response="apiCase.responseData"/>
<!-- 保存操作 -->

View File

@ -20,19 +20,13 @@
<el-form :model="formData" :rules="rules" label-width="100px" v-loading="result.loading" ref="form">
<el-row>
<el-form-item :label="'Swagger URL'" prop="swaggerUrl" v-if="isSwagger2 && swaggerUrlEable" class="swagger-url">
<el-input size="small" v-model="formData.swaggerUrl" clearable show-word-limit/>
</el-form-item>
<el-col :span="11">
<el-form-item :label="$t('commons.import_module')"
v-if="selectedPlatformValue != 'Swagger2' || (selectedPlatformValue == 'Swagger2' && !swaggerUrlEable)">
<el-form-item :label="$t('commons.import_module')">
<el-select size="small" v-model="formData.moduleId" class="project-select" clearable>
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
</el-select>
</el-form-item>
<el-form-item :label="$t('commons.import_mode')"
v-if="selectedPlatformValue != 'Swagger2' || (selectedPlatformValue == 'Swagger2' && !swaggerUrlEable)">
<el-form-item :label="$t('commons.import_mode')">
<el-select size="small" v-model="formData.modeId" class="project-select" clearable>
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
</el-select>
@ -43,7 +37,16 @@
:active-text="$t('api_test.api_import.swagger_url_import')">
</el-switch>
</el-form-item>
<el-form-item v-show="isSwagger2 && swaggerUrlEable">
</el-col>
<el-col :span="1">
<el-divider direction="vertical"/>
</el-col>
<el-col :span="12" v-show="isSwagger2 && swaggerUrlEable" style="margin-top: 40px">
<el-form-item :label="'Swagger URL'" prop="swaggerUrl" class="swagger-url">
<el-input size="small" v-model="formData.swaggerUrl" clearable show-word-limit/>
</el-form-item>
<el-form-item>
<el-switch
v-model="swaggerSynchronization"
@click.native="scheduleEdit"
@ -51,10 +54,6 @@
</el-switch>
</el-form-item>
</el-col>
<el-col :span="1"
v-if="selectedPlatformValue != 'Swagger2' || (selectedPlatformValue == 'Swagger2' && !swaggerUrlEable)">
<el-divider direction="vertical"/>
</el-col>
<el-col :span="12"
v-if="selectedPlatformValue != 'Swagger2' || (selectedPlatformValue == 'Swagger2' && !swaggerUrlEable)">
<el-upload

View File

@ -4,6 +4,7 @@
:options="options"
:theme="theme"
:group="group"
@click="onClick"
:watch-shallow="watchShallow"
:manual-update="manualUpdate"
:autoresize="autoresize"/>
@ -27,12 +28,18 @@ export default {
}
},
mounted() {
this.defaultInitOptions = this.defaultInitOptions || {};
// svg
// BUG: svg legend
// if (!this.defaultInitOptions.renderer) {
// this.defaultInitOptions.renderer = 'svg';
// }
},
methods: {
onClick(params){
this.$emit('onClick', params.data)
},
}
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<div>
<ms-chart :options="options">
<ms-chart :options="options" @onClick="onClick">
</ms-chart>
</div>
@ -107,7 +107,10 @@ export default {
itemNames.push(item.name);
});
this.dataNames = itemNames;
}
},
onClick(params){
this.$emit('onClick', params);
},
}
}
</script>

View File

@ -19,9 +19,9 @@
</el-menu>
</template>
</ms-test-plan-header-bar>
<test-plan-functional v-if="activeIndex === 'functional'" :plan-id="planId"/>
<test-plan-api v-if="activeIndex === 'api'" :plan-id="planId"/>
<test-plan-load v-if="activeIndex === 'load'" :plan-id="planId"/>
<test-plan-functional v-if="activeIndex === 'functional'" :redirectCharType="redirectCharType" :clickType="clickType" :plan-id="planId"/>
<test-plan-api v-if="activeIndex === 'api'" :redirectCharType="redirectCharType" :clickType="clickType" :plan-id="planId"/>
<test-plan-load v-if="activeIndex === 'load'" :redirectCharType="redirectCharType" :clickType="clickType" :plan-id="planId"/>
<test-case-statistics-report-view :test-plan="currentPlan" v-if="activeIndex === 'report'"/>
<test-report-template-list @openReport="openReport" ref="testReportTemplateList"/>
@ -61,7 +61,11 @@
testPlans: [],
currentPlan: {},
activeIndex: "functional",
isMenuShow: true
isMenuShow: true,
//-
redirectCharType:'',
//-
clickType:'',
}
},
computed: {
@ -71,14 +75,30 @@
},
watch: {
'$route.params.planId'() {
this.activeIndex = "functional";
this.genRedirectParam();
this.getTestPlans();
}
},
mounted() {
this.getTestPlans();
},
activated() {
this.genRedirectParam();
},
methods: {
genRedirectParam(){
this.redirectCharType = this.$route.params.charType;
this.clickType = this.$route.params.clickType;
if(this.redirectCharType != ""){
if(this.redirectCharType=='scenario'){
this.activeIndex = 'api';
}else if(this.redirectCharType != null && this.redirectCharType != ''){
this.activeIndex = this.redirectCharType;
}
}else{
this.activeIndex = "functional";
}
},
getTestPlans() {
this.$post('/test/plan/list/all', {}, response => {
this.testPlans = response.data;

View File

@ -10,6 +10,7 @@
@setModuleOptions="setModuleOptions"
:plan-id="planId"
:is-read-only="true"
:redirectCharType="redirectCharType"
ref="apiNodeTree">
<template v-slot:header>
<div class="model-change-radio">
@ -48,6 +49,7 @@
:is-case-relevance="true"
:model="'plan'"
:plan-id="planId"
:clickType="clickType"
@refresh="refreshTree"
@relevanceCase="openTestCaseRelevanceDialog"
ref="apiCaseList"/>
@ -57,6 +59,7 @@
:select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
:plan-id="planId"
:clickType="clickType"
@refresh="refreshTree"
@relevanceCase="openTestCaseRelevanceDialog"
ref="apiScenarioList"/>
@ -119,18 +122,34 @@
}
},
props: [
'planId'
'planId',
'redirectCharType',
'clickType'
],
mounted() {
this.checkRedirectCharType();
},
watch: {
model() {
this.selectNodeIds = [];
this.moduleOptions = {};
},
redirectCharType(){
if(this.redirectCharType=='scenario'){
this.model = 'scenario';
}else{
this.model = 'api';
}
}
},
methods: {
checkRedirectCharType(){
if(this.redirectCharType=='scenario'){
this.model = 'scenario';
}else{
this.model = 'api';
}
},
refresh() {
this.refreshTree();
this.refreshTable();

View File

@ -165,6 +165,7 @@ export default {
selectCase: {},
result: {},
moduleId: "",
status:'default',
deletePath: "/test/case/delete",
selectRows: new Set(),
buttons: [
@ -224,12 +225,16 @@ export default {
'api'
}
},
planId: String
planId: String,
clickType:String
},
created: function () {
this.getMaintainerOptions();
this.initTable();
},
activated() {
this.status ='default'
},
watch: {
selectNodeIds() {
this.initTable();
@ -278,6 +283,14 @@ export default {
if (this.currentProtocol != null) {
this.condition.protocol = this.currentProtocol;
}
if(this.clickType){
if(this.status =='default'){
this.condition.status = this.clickType;
}else{
this.condition.status = null;
}
this.status = 'all';
}
this.result = this.$post('/test/plan/api/case/list/' + this.currentPage + "/" + this.pageSize, this.condition, response => {
this.total = response.data.itemCount;
this.tableData = response.data.listObject;

View File

@ -97,7 +97,8 @@
default: false,
},
selectNodeIds: Array,
planId: String
planId: String,
clickType:String
},
data() {
return {
@ -111,6 +112,7 @@
pageSize: 10,
total: 0,
reportId: "",
status:'default',
infoDb: false,
runVisible: false,
projectId: "",
@ -144,7 +146,14 @@
this.loading = true;
this.condition.moduleIds = this.selectNodeIds;
this.condition.planId = this.planId;
if(this.clickType){
if(this.status =='default'){
this.condition.status = this.clickType;
}else{
this.condition.status = null;
}
this.status = 'all';
}
let url = "/test/plan/scenario/case/list/" + this.currentPage + "/" + this.pageSize;
this.$post(url, this.condition, response => {
let data = response.data;

View File

@ -257,6 +257,7 @@ export default {
currentPage: 1,
pageSize: 10,
total: 0,
status:'default',
selectRows: new Set(),
testPlan: {},
isReadOnly: false,
@ -318,6 +319,7 @@ export default {
planId: {
type: String
},
clickType:String,
selectNodeIds: {
type: Array
},
@ -352,6 +354,14 @@ export default {
// param.planId = this.planId;
this.condition.planId = this.planId;
}
if(this.clickType){
if(this.status =='default'){
this.condition.status = this.clickType;
}else{
this.condition.status = null;
}
this.status = 'all';
}
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
// param.nodeIds = this.selectNodeIds;
this.condition.nodeIds = this.selectNodeIds;

View File

@ -14,6 +14,7 @@
@openTestCaseRelevanceDialog="openTestCaseRelevanceDialog"
@refresh="refresh"
:plan-id="planId"
:clickType="clickType"
:select-node-ids="selectNodeIds"
:select-parent-nodes="selectParentNodes"
ref="testPlanTestCaseList"/>
@ -52,9 +53,16 @@
}
},
props: [
'planId'
'planId',
'redirectCharType',
'clickType'
],
mounted() {
// activated() {
// this.search();
// this.checkTipsType();
// },
// mounted() {
activated(){
this.initData();
this.openTestCaseEdit(this.$route.path);
},
@ -88,7 +96,11 @@
},
getNodeTreeByPlanId() {
if (this.planId) {
this.result = this.$get("/case/node/list/plan/" + this.planId, response => {
let url = "/case/node/list/plan/" + this.planId;
if(this.clickType){
url = url+"/"+this.clickType;
}
this.result = this.$get(url, response => {
this.treeNodes = response.data;
});
}

View File

@ -12,6 +12,7 @@
class="table-list"
@refresh="refresh"
:plan-id="planId"
:clickType="clickType"
:select-project-id="selectProjectId"
:select-parent-nodes="selectParentNodes"
@relevanceCase="openTestCaseRelevanceDialog"
@ -51,7 +52,9 @@ export default {
}
},
props: [
'planId'
'planId',
'redirectCharType',
'clickType'
],
watch: {
planId() {

View File

@ -140,6 +140,7 @@ export default {
currentPage: 1,
pageSize: 10,
total: 0,
status: 'default',
screenHeight: document.documentElement.clientHeight - 330,//
buttons: [
// {
@ -171,7 +172,8 @@ export default {
type: Boolean,
default: false
},
planId: String
planId: String,
clickType: String,
},
created() {
this.initTable();
@ -187,12 +189,19 @@ export default {
},
methods: {
initTable() {
console.log('init')
this.selectRows = new Set();
this.condition.testPlanId = this.planId;
if (this.selectProjectId && this.selectProjectId !== 'root') {
this.condition.projectId = this.selectProjectId;
}
if (this.clickType) {
if (this.status == 'default') {
this.condition.status = this.clickType;
}else{
this.condition.status = null;
}
this.status = 'all';
}
this.$post("/test/plan/load/case/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
let data = response.data;
let {itemCount, listObject} = data;
@ -278,7 +287,7 @@ export default {
},
updateStatus(loadCase, status) {
this.$post('/test/plan/load/case/update', {id: loadCase.id, status: status}, () => {
this.$post('/test/plan/edit/status/' + loadCase.testPlanId, {},() => {
this.$post('/test/plan/edit/status/' + loadCase.testPlanId, {}, () => {
this.initTable();
});
});

View File

@ -18,7 +18,7 @@
<base-info-component id="baseInfoComponent" :report-info="metric" v-if="preview.id == 1"/>
<test-result-component id="testResultComponent" :test-results="metric.moduleExecuteResult" v-if="preview.id == 2"/>
<!--<test-result-chart-component id="resultChartComponent" :execute-result="metric.executeResult" v-if="preview.id == 3"/>-->
<test-result-advance-chart-component id="resultChartComponent" :execute-result="metric.executeResult" v-if="preview.id == 3"/>
<test-result-advance-chart-component id="resultChartComponent" :execute-result="metric.executeResult" :source="source" :planId="planId" v-if="preview.id == 3"/>
<!--<failure-result-component id="failureResultComponent" :failure-test-cases="metric.failureTestCases" v-if="preview.id == 4"/>-->
<failure-result-advance-component id="failureResultComponent" :failure-test-cases="metric.failureTestCases" v-if="preview.id == 4"/>
<defect-list-component id="defectListComponent" :defect-list="metric.issues" v-if="preview.id == 5"/>
@ -53,6 +53,8 @@
metric: {
type: Object
},
source:String,
planId:String,
isReport: {
type: Boolean,
default: true

View File

@ -4,22 +4,22 @@
<div class="char-component">
<div class="char-item" v-if="showFunctional">
<ms-pie-chart v-if="isShow" :text="'功能测试用例'"
<ms-pie-chart v-if="isShow" :text="'功能测试用例'" @onClick="onFuncCharClick"
:name="$t('test_track.plan_view.test_result')" :data="functionalCharData"/>
</div>
<div class="char-item" v-if="showApi">
<ms-pie-chart v-if="isShow" :text="'接口测试用例'"
<ms-pie-chart v-if="isShow" :text="'接口测试用例'" @onClick="onApiCharClick"
:name="$t('test_track.plan_view.test_result')" :data="apiCharData"/>
</div>
<div class="char-item" v-if="showScenario">
<ms-pie-chart v-if="isShow" :text="'场景测试用例'"
<ms-pie-chart v-if="isShow" :text="'场景测试用例'" @onClick="onScenarioCharClick"
:name="$t('test_track.plan_view.test_result')" :data="scenarioCharData"/>
</div>
<div class="char-item" v-if="showLoad">
<ms-pie-chart v-if="isShow" :text="'性能测试用例'"
<ms-pie-chart v-if="isShow" :text="'性能测试用例'" @onClick="onLoadCharClick"
:name="$t('test_track.plan_view.test_result')" :data="loadCharData"/>
</div>
</div>
@ -53,36 +53,38 @@
}
},
props: {
planId:String,
source:String,
executeResult: {
type: Object,
default() {
return {
functionalResult: [
{status: 'Pass', count: '235'},
{status: 'Failure', count: '310'},
{status: 'Blocking', count: '274'},
{status: 'Skip', count: '335'},
{status: 'Underway', count: '245'},
{status: 'Prepare', count: '265'},
{status: 'Pass', count: '0'},
{status: 'Failure', count: '0'},
{status: 'Blocking', count: '0'},
{status: 'Skip', count: '0'},
{status: 'Underway', count: '0'},
{status: 'Prepare', count: '0'},
],
apiResult: [
{status: 'Pass', count: '235'},
{status: 'Failure', count: '310'},
{status: 'Underway', count: '245'},
{status: 'Pass', count: '0'},
{status: 'Failure', count: '0'},
{status: 'Underway', count: '0'},
],
scenarioResult: [
{status: 'Pass', count: '205'},
{status: 'Failure', count: '350'},
{status: 'Underway', count: '110'},
{status: 'Pass', count: '0'},
{status: 'Failure', count: '0'},
{status: 'Underway', count: '0'},
],
loadResult: [
{status: 'Pass', count: '205'},
{status: 'Failure', count: '350'},
{status: 'Underway', count: '110'},
{status: 'Pass', count: '0'},
{status: 'Failure', count: '0'},
{status: 'Underway', count: '0'},
],
}
}
}
},
},
computed: {
showFunctional() {
@ -163,6 +165,59 @@
this.$nextTick(function () {
this.isShow = true;
})
},
onvertDataStatus(status){
if(status == this.$t('test_track.plan_view.pass')){
status = "Pass";
}else if(status == this.$t('test_track.plan_view.failure')){
status = "Failure";
}else if(status == this.$t('test_track.plan_view.blocking')){
status = "Blocking";
}else if(status == this.$t('test_track.plan.plan_status_prepare')){
status = "Prepare";
}else if (status == this.$t('test_track.plan.plan_status_running')){
status = "running";
}
return status;
},
onFuncCharClick(params){
let clickType = params['name'];
clickType = this.onvertDataStatus(clickType);
this.redirectPage('functional',clickType);
},
onApiCharClick(params){
let clickType = params['name'];
clickType = this.onvertDataStatus(clickType);
if(clickType=="Failure"){
clickType = "error";
}else if(clickType=="Pass"){
clickType = "success";
}
this.redirectPage('api',clickType);
},
onScenarioCharClick(params){
let clickType = params['name'];
clickType = this.onvertDataStatus(clickType);
if(clickType=="Failure"){
clickType = "Fail";
}else if(clickType=="Pass"){
clickType = "Success";
}
this.redirectPage('scenario',clickType);
},
onLoadCharClick(params){
let clickType = params['name'];
clickType = this.onvertDataStatus(clickType);
if(clickType=="Failure"){
clickType = "error";
}
this.redirectPage('load',clickType);
},
redirectPage(charType,clickType){
if(this.source == "ReportView"){
this.$router.push({name:'planView',params:{planId:this.planId,charType:charType,clickType:clickType}});
}
}
}
}

View File

@ -74,7 +74,10 @@
this.$nextTick(function () {
this.isShow = true;
})
}
},
onClick(params){
this.$emit('onClick', params)
},
}
}
</script>

View File

@ -22,7 +22,7 @@ export default {
return {}
},
activated() {
// this.refreshTestPlanList();
this.refreshTestPlanList();
},
mounted() {
this.refreshTestPlanList();

View File

@ -34,7 +34,7 @@
<div class="container" ref="resume" id="app">
<el-main>
<div v-for="(item, index) in previews" :key="item.id">
<template-component :isReportView="true" :metric="metric" :preview="item" :index="index" ref="templateComponent"/>
<template-component :source="source" :isReportView="true" :metric="metric" :planId="planId" :preview="item" :index="index" ref="templateComponent"/>
</div>
</el-main>
</div>
@ -80,6 +80,7 @@
previews: [],
report: {},
reportId: '',
source:"ReportView",
reportComponents:[1,3,4],
metric: {},
planId: '',
@ -100,6 +101,11 @@
mounted() {
this.isTestManagerOrTestUser = checkoutTestManagerOrTestUser();
},
watch: {
reportComponents() {
this.initPreviews();
}
},
methods: {
listenGoBack() {
//
@ -118,13 +124,6 @@
this.listenGoBack();
},
getReport() {
// this.result = this.$get('/case/report/get/' + this.reportId, response => {
// this.report = response.data;
// this.report.content = JSON.parse(response.data.content);
// if (this.report.content.customComponent) {
// this.report.content.customComponent = jsonToMap(this.report.content.customComponent);
// }
// });
this.getMetric();
this.initPreviews();
},
@ -185,6 +184,13 @@
getMetric() {
this.result = this.$get('/test/plan/report/getMetric/' + this.reportId, response => {
this.metric = response.data;
let components = response.data.reportComponents;
this.planId = response.data.testPlanId;
if(components === null || components === ''){
this.reportComponents = [1,3,4];
}else {
this.reportComponents = JSON.parse(components);
}
if (!this.metric.failureTestCases) {
this.metric.failureTestCases = [];