Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
dd8de4e277
|
@ -26,6 +26,7 @@ import io.metersphere.dto.ScheduleDao;
|
|||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
import io.metersphere.service.CheckPermissionService;
|
||||
import io.metersphere.service.ScheduleService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.apache.shiro.authz.annotation.Logical;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
|
@ -342,12 +343,16 @@ public class APITestController {
|
|||
return returnList;
|
||||
}
|
||||
|
||||
@GetMapping("/runningTask/{projectID}")
|
||||
public List<TaskInfoResult> runningTask(@PathVariable String projectID) {
|
||||
List<String> typeFilter = Arrays.asList( // 首页显示的运行中定时任务,只要这3种,不需要 性能测试、api_test(旧版)
|
||||
ScheduleGroup.API_SCENARIO_TEST.name(),
|
||||
ScheduleGroup.SWAGGER_IMPORT.name(),
|
||||
ScheduleGroup.TEST_PLAN_TEST.name());
|
||||
@GetMapping("/runningTask/{projectID}/{callFrom}")
|
||||
public List<TaskInfoResult> runningTask(@PathVariable String projectID, @PathVariable String callFrom) {
|
||||
List<String> typeFilter = new ArrayList<>();
|
||||
if(StringUtils.equals(callFrom, "api_test")) { // 接口测试首页显示的运行中定时任务,只要这3种,不需要 性能测试、api_test(旧版)
|
||||
typeFilter.add(ScheduleGroup.API_SCENARIO_TEST.name());
|
||||
typeFilter.add(ScheduleGroup.SWAGGER_IMPORT.name());
|
||||
typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name());
|
||||
} else if(StringUtils.equals(callFrom, "track_home")) { // 测试跟踪首页只显示测试计划的定时任务
|
||||
typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name());
|
||||
}
|
||||
List<TaskInfoResult> resultList = scheduleService.findRunningTaskInfoByProjectID(projectID, typeFilter);
|
||||
int dataIndex = 1;
|
||||
for (TaskInfoResult taskInfo :
|
||||
|
|
|
@ -22,9 +22,9 @@ public class MsDefinitionParser extends MsAbstractParser<ApiDefinitionImport> {
|
|||
String testStr = getApiTestStr(source);
|
||||
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
|
||||
this.projectId = request.getProjectId();
|
||||
if (testObject.get("projectName") != null || testObject.get("projectId") != null ) {
|
||||
if (testObject.get("projectName") != null || testObject.get("projectId") != null ) {// metersphere 格式导入
|
||||
return parseMsFormat(testStr, request);
|
||||
} else {
|
||||
} else { // chrome 插件录制格式导入
|
||||
request.setPlatform(ApiImportPlatform.Plugin.name());
|
||||
ApiDefinitionImport apiImport = new ApiDefinitionImport();
|
||||
apiImport.setProtocol(RequestType.HTTP);
|
||||
|
|
|
@ -216,6 +216,7 @@ public class ApiDefinitionService {
|
|||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
if (request.getProtocol().equals(RequestType.HTTP)) {
|
||||
example.createCriteria().andMethodEqualTo(request.getMethod()).andStatusNotEqualTo("Trash")
|
||||
.andPathEqualTo(request.getPath())
|
||||
.andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId());
|
||||
return apiDefinitionMapper.selectByExample(example);
|
||||
} else {
|
||||
|
|
|
@ -69,17 +69,18 @@
|
|||
sch.id AS taskID,
|
||||
sch.`value` AS rule,
|
||||
sch.`enable` AS `taskStatus`,
|
||||
u.name AS creator,
|
||||
u.`name` AS creator,
|
||||
sch.update_time AS updateTime,
|
||||
sch.type AS taskType,
|
||||
sch.group AS taskGroup
|
||||
sch.`group` AS taskGroup,
|
||||
sch.resource_id AS scenarioId
|
||||
FROM (
|
||||
schedule sch left join user u
|
||||
ON sch.user_id = u.id
|
||||
)
|
||||
WHERE sch.`enable` = true
|
||||
AND sch.project_id = #{projectId,jdbcType=VARCHAR}
|
||||
and sch.group in
|
||||
and sch.`group` in
|
||||
<foreach collection="types" item="item" separator="," open="(" close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
|
|
|
@ -8,7 +8,7 @@ import java.util.List;
|
|||
|
||||
public interface ExtTestPlanLoadCaseMapper {
|
||||
|
||||
List<String> selectIdsNotInPlan(@Param("projectId") String projectId, @Param("planId") String planId);
|
||||
List<String> selectIdsNotInPlan(@Param("request") LoadCaseRequest request);
|
||||
List<TestPlanLoadCaseDTO> selectTestPlanLoadCaseList(@Param("request") LoadCaseRequest request);
|
||||
void updateCaseStatus(@Param("reportId") String reportId, @Param("status") String status);
|
||||
List<String> getStatusByTestPlanId(@Param("planId") String planId);
|
||||
|
|
|
@ -10,9 +10,12 @@
|
|||
<select id="selectIdsNotInPlan" resultType="java.lang.String">
|
||||
select load_test.id
|
||||
from load_test
|
||||
where load_test.project_id = #{projectId}
|
||||
where load_test.project_id = #{request.projectId}
|
||||
<if test="request.name != null and request.name != ''">
|
||||
and load_test.name like CONCAT('%', #{request.name},'%')
|
||||
</if>
|
||||
and load_test.id not in (
|
||||
select tplc.load_case_id from test_plan_load_case tplc where tplc.test_plan_id = #{planId}
|
||||
select tplc.load_case_id from test_plan_load_case tplc where tplc.test_plan_id = #{request.testPlanId}
|
||||
)
|
||||
</select>
|
||||
<select id="selectTestPlanLoadCaseList" resultType="io.metersphere.track.dto.TestPlanLoadCaseDTO">
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.controller.handler;
|
|||
|
||||
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.controller.ResultHolder;
|
||||
import org.apache.shiro.ShiroException;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
|
@ -34,6 +35,7 @@ public class RestControllerExceptionHandler {
|
|||
@ExceptionHandler(SQLException.class)
|
||||
public ResultHolder sqlExceptionHandler(HttpServletRequest request, HttpServletResponse response, SQLException e) {
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
LogUtil.error(e);
|
||||
return ResultHolder.error("SQL error happened, please check logs.");
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class TestPlanLoadCaseService {
|
|||
private LoadTestMapper loadTestMapper;
|
||||
|
||||
public List<LoadTest> relevanceList(LoadCaseRequest request) {
|
||||
List<String> ids = extTestPlanLoadCaseMapper.selectIdsNotInPlan(request.getProjectId(), request.getTestPlanId());
|
||||
List<String> ids = extTestPlanLoadCaseMapper.selectIdsNotInPlan(request);
|
||||
if (CollectionUtils.isEmpty(ids)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
|
|
@ -194,7 +194,6 @@ public class TestPlanService {
|
|||
testPlan.setActualEndTime(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
extScheduleMapper.updateNameByResourceID(testPlan.getId(), testPlan.getName());// 同步更新该测试的定时任务的name
|
||||
|
||||
List<String> userIds = new ArrayList<>();
|
||||
userIds.add(testPlan.getPrincipal());
|
||||
|
@ -204,6 +203,7 @@ public class TestPlanService {
|
|||
i = testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
||||
}
|
||||
else { // 有修改字段的调用,为保证将某些时间置null的情况,使用updateByPrimaryKey
|
||||
extScheduleMapper.updateNameByResourceID(testPlan.getId(), testPlan.getName());// 同步更新该测试的定时任务的name
|
||||
i = testPlanMapper.updateByPrimaryKey(testPlan); // 更新
|
||||
}
|
||||
if (!StringUtils.isBlank(testPlan.getStatus())) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit adefde265ff12d4ea909353c3f46008f8a8e17e7
|
||||
Subproject commit efd6af73b7c5cc53cd4515772000bc1436c49837
|
|
@ -12,7 +12,7 @@
|
|||
<span>
|
||||
<slot name="headerLeft">
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': data.active}"
|
||||
@click="active(data)" v-if="data.type!='scenario' && data.type!='JmeterElement' && !isMax " @click.stop/>
|
||||
@click="active(data)" v-if="data.type!='scenario' && !isMax " @click.stop/>
|
||||
<span @click.stop v-if="isShowInput && isShowNameInput">
|
||||
<el-input :draggable="draggable" size="mini" v-model="data.name" class="name-input"
|
||||
@blur="isShowInput = false" :placeholder="$t('commons.input_name')" ref="nameEdit" :disabled="data.disabled"/>
|
||||
|
@ -113,9 +113,6 @@
|
|||
this.$refs.nameEdit.focus();
|
||||
});
|
||||
}
|
||||
if (this.data && this.data.type === "JmeterElement") {
|
||||
this.data.active = false;
|
||||
}
|
||||
if (this.data && ELEMENTS.get("AllSamplerProxy").indexOf(this.data.type) != -1) {
|
||||
if (!this.data.method) {
|
||||
this.data.method = this.data.protocol;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<api-base-component
|
||||
@copy="copyRow"
|
||||
@remove="remove"
|
||||
@active="active"
|
||||
:data="request"
|
||||
:draggable="draggable"
|
||||
:color="defColor"
|
||||
|
@ -9,7 +10,9 @@
|
|||
:show-btn="showBtn"
|
||||
:background-color="defBackgroundColor"
|
||||
:title="request.elementType">
|
||||
|
||||
<div style="height: 300px;width: 100%">
|
||||
<ms-code-edit mode="xml" :data.sync="request.jmeterElement" theme="eclipse" ref="codeEdit"/>
|
||||
</div>
|
||||
</api-base-component>
|
||||
</template>
|
||||
|
||||
|
@ -56,6 +59,9 @@
|
|||
copyRow() {
|
||||
this.$emit('copyRow', this.jsr223Processor, this.node);
|
||||
},
|
||||
active() {
|
||||
this.request.active = !this.request.active;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -459,11 +459,11 @@
|
|||
} else {
|
||||
this.operatingElements = [];
|
||||
}
|
||||
if (data && data.type != "JmeterElement") {
|
||||
if (data) {
|
||||
data.active = true;
|
||||
if (data.hashTree) {
|
||||
data.hashTree.forEach(item => {
|
||||
if (item && item.type != "JmeterElement") {
|
||||
if (item) {
|
||||
item.active = true;
|
||||
}
|
||||
})
|
||||
|
@ -915,7 +915,7 @@
|
|||
setProjectEnvMap(projectEnvMap) {
|
||||
this.projectEnvMap = projectEnvMap;
|
||||
},
|
||||
refReload(data,node) {
|
||||
refReload(data, node) {
|
||||
this.selectedTreeNode = data;
|
||||
this.selectedNode = node;
|
||||
this.initProjectIds();
|
||||
|
|
|
@ -127,11 +127,18 @@ export default {
|
|||
let param = {};
|
||||
param.taskID = this.schedule.id;
|
||||
param.enable = flag;
|
||||
let that = this;
|
||||
if(flag == false) {
|
||||
this.$confirm(this.$t('api_test.home_page.running_task_list.confirm.close_title'), this.$t('commons.prompt'), {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
beforeClose(action, instance, done) {
|
||||
if(action == 'cancel') { // 否则在 messageBox 点击取消后,switch 按钮仍然会被关闭
|
||||
that.schedule.enable = param.enable = true;
|
||||
}
|
||||
done(); // done 是关闭 messageBox 的行为
|
||||
},
|
||||
}).then(() => {
|
||||
this.updateTask(param);
|
||||
}).catch(() => {
|
||||
|
|
|
@ -240,7 +240,6 @@ import MsTabButton from "@/business/components/common/components/MsTabButton";
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
changeRedirectParam(redirectIDParam) {
|
||||
this.redirectID = redirectIDParam;
|
||||
},
|
||||
|
@ -349,7 +348,7 @@ import MsTabButton from "@/business/components/common/components/MsTabButton";
|
|||
this.showCasePage = true;
|
||||
},
|
||||
exportAPI(type) {
|
||||
if (!this.isApiListEnable) {
|
||||
if (this.activeDom !== 'left') {
|
||||
this.$warning('用例列表暂不支持导出,请切换成接口列表');
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -222,7 +222,9 @@
|
|||
}
|
||||
|
||||
this.result = this.$post("/api/testcase/list", this.condition, response => {
|
||||
this.apiCaseList = response.data;
|
||||
if(response.data){
|
||||
this.apiCaseList = response.data;
|
||||
}
|
||||
this.apiCaseList.forEach(apiCase => {
|
||||
if (apiCase.tags && apiCase.tags.length > 0) {
|
||||
apiCase.tags = JSON.parse(apiCase.tags);
|
||||
|
@ -236,7 +238,7 @@
|
|||
}
|
||||
|
||||
})
|
||||
if (!this.useEnvironment && this.apiCaseList[0].request && this.apiCaseList[0].request.useEnvironment) {
|
||||
if (!this.useEnvironment && this.apiCaseList[0] && this.apiCaseList[0].request && this.apiCaseList[0].request.useEnvironment) {
|
||||
this.useEnvironment = this.apiCaseList[0].request.useEnvironment;
|
||||
this.environment = this.useEnvironment;
|
||||
}
|
||||
|
|
|
@ -524,7 +524,8 @@ export default {
|
|||
this.$emit('editApi', row);
|
||||
},
|
||||
runApi(row) {
|
||||
let request = JSON.parse(row.request);
|
||||
|
||||
let request = row ? JSON.parse(row.request) : {};
|
||||
if (row.tags instanceof Array) {
|
||||
row.tags = JSON.stringify(row.tags);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
<ms-failure-test-case-list @redirectPage="redirectPage"/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ms-running-task-list @redirectPage="redirectPage"/>
|
||||
<ms-running-task-list :call-from="'api_test'" @redirectPage="redirectPage"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
|
|
@ -64,7 +64,9 @@ export default {
|
|||
components: {
|
||||
MsTag
|
||||
},
|
||||
|
||||
props: {
|
||||
callFrom: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '100',
|
||||
|
@ -84,7 +86,7 @@ export default {
|
|||
methods: {
|
||||
search() {
|
||||
let projectID = getCurrentProjectID();
|
||||
this.result = this.$get("/api/runningTask/"+projectID, response => {
|
||||
this.result = this.$get("/api/runningTask/"+projectID+"/"+this.callFrom, response => {
|
||||
this.tableData = response.data;
|
||||
});
|
||||
},
|
||||
|
@ -109,9 +111,9 @@ export default {
|
|||
});
|
||||
},
|
||||
redirect(param){
|
||||
if(param.taskType === 'testPlan'){
|
||||
if(param.taskGroup === 'TEST_PLAN_TEST'){
|
||||
this.$emit('redirectPage','testPlanEdit','', param.scenarioId);
|
||||
}else{
|
||||
}else if(param.taskGroup === 'API_SCENARIO_TEST') {
|
||||
this.$emit('redirectPage','scenario','scenario', 'edit:'+param.scenarioId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
<review-list class="track-card"/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ms-running-task-list class="track-card"/>
|
||||
<ms-running-task-list :call-from="'track_home'" class="track-card" @redirectPage="redirectPage"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
@ -73,7 +73,7 @@ import MsMainContainer from "@/business/components/common/components/MsMainConta
|
|||
import MsContainer from "@/business/components/common/components/MsContainer";
|
||||
import CaseCountCard from "@/business/components/track/home/components/CaseCountCard";
|
||||
import RelevanceCaseCard from "@/business/components/track/home/components/RelevanceCaseCard";
|
||||
import {getCurrentProjectID, getUUID} from "@/common/js/utils";
|
||||
import {getCurrentProjectID,getUUID} from "@/common/js/utils";
|
||||
import CaseMaintenance from "@/business/components/track/home/components/CaseMaintenance";
|
||||
import {COUNT_NUMBER, COUNT_NUMBER_SHALLOW} from "@/common/js/constants";
|
||||
import BugCountCard from "@/business/components/track/home/components/BugCountCard";
|
||||
|
@ -187,6 +187,8 @@ export default {
|
|||
this.caseOption = option;
|
||||
},
|
||||
redirectPage(page,dataType,selectType){
|
||||
//test_plan 页面跳转
|
||||
this.$router.push('/track/plan/view/'+selectType);
|
||||
switch (page){
|
||||
case "case":
|
||||
this.$router.push({name:'testCase',params:{dataType:dataType,dataSelectRange:selectType, projectId: getCurrentProjectID()}});
|
||||
|
|
|
@ -2,8 +2,17 @@
|
|||
<div>
|
||||
<el-card class="table-card" v-loading="result.loading">
|
||||
|
||||
<env-popover :env-map="projectEnvMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
|
||||
:project-list="projectList" ref="envPopover" class="env-popover"/>
|
||||
<template v-slot:header>
|
||||
<el-row>
|
||||
<el-col :span="8" :offset="11">
|
||||
<el-input :placeholder="$t('api_test.definition.request.select_case')" @blur="search"
|
||||
@keyup.enter.native="search" class="search-input" size="small" v-model="condition.name"/>
|
||||
</el-col>
|
||||
|
||||
<env-popover :env-map="projectEnvMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
|
||||
:project-list="projectList" ref="envPopover" class="env-popover"/>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="handleSelectAll" @select="handleSelect">
|
||||
<el-table-column type="selection"/>
|
||||
|
|
|
@ -13,48 +13,59 @@
|
|||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<el-card>
|
||||
<template v-slot:header>
|
||||
<el-row>
|
||||
<el-col :span="8" :offset="16">
|
||||
<el-input :placeholder="$t('api_test.definition.request.select_case')" @blur="getTestCases"
|
||||
@keyup.enter.native="getTestCases" class="search-input" size="small" v-model="condition.name"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
v-loading="result.loading"
|
||||
:data="testCases"
|
||||
row-key="id"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
<el-table-column
|
||||
type="selection"/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('commons.name')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
column-key="status"
|
||||
:filters="statusFilters"
|
||||
:label="$t('commons.status')">
|
||||
<template v-slot:default="{row}">
|
||||
<ms-performance-test-status :row="row"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table
|
||||
v-loading="result.loading"
|
||||
:data="testCases"
|
||||
row-key="id"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
<el-table-column
|
||||
type="selection"/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('commons.name')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
column-key="status"
|
||||
:filters="statusFilters"
|
||||
:label="$t('commons.status')">
|
||||
<template v-slot:default="{row}">
|
||||
<ms-performance-test-status :row="row"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
</el-card>
|
||||
<ms-table-pagination :change="getTestCases" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</test-case-relevance-base>
|
||||
|
|
Loading…
Reference in New Issue