Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
8342b10f0a
|
@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
|
||||||
import io.metersphere.api.jmeter.TestResult;
|
import io.metersphere.api.jmeter.TestResult;
|
||||||
import io.metersphere.base.domain.ApiDefinitionExecResult;
|
import io.metersphere.base.domain.ApiDefinitionExecResult;
|
||||||
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
|
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -18,14 +17,9 @@ import java.util.UUID;
|
||||||
public class ApiDefinitionExecResultService {
|
public class ApiDefinitionExecResultService {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
|
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
|
||||||
@Resource
|
|
||||||
private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
|
|
||||||
|
|
||||||
|
|
||||||
public void saveApiResult(TestResult result) {
|
public void saveApiResult(TestResult result) {
|
||||||
result.getScenarios().get(0).getRequestResults().forEach(item -> {
|
result.getScenarios().get(0).getRequestResults().forEach(item -> {
|
||||||
// 清理原始资源,每个执行 保留一条结果
|
|
||||||
extApiDefinitionExecResultMapper.deleteByResourceId(item.getName());
|
|
||||||
ApiDefinitionExecResult saveResult = new ApiDefinitionExecResult();
|
ApiDefinitionExecResult saveResult = new ApiDefinitionExecResult();
|
||||||
saveResult.setId(UUID.randomUUID().toString());
|
saveResult.setId(UUID.randomUUID().toString());
|
||||||
saveResult.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
saveResult.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
||||||
|
|
|
@ -326,7 +326,7 @@ public class ApiDefinitionService {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public APIReportResult getDbResult(String testId) {
|
public APIReportResult getDbResult(String testId) {
|
||||||
ApiDefinitionExecResult result = extApiDefinitionExecResultMapper.selectByResourceId(testId);
|
ApiDefinitionExecResult result = extApiDefinitionExecResultMapper.selectMaxResultByResourceId(testId);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ public interface ExtApiDefinitionExecResultMapper {
|
||||||
|
|
||||||
void deleteByResourceId(String id);
|
void deleteByResourceId(String id);
|
||||||
|
|
||||||
ApiDefinitionExecResult selectByResourceId(String resourceId);
|
ApiDefinitionExecResult selectMaxResultByResourceId(String resourceId);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,8 +5,8 @@
|
||||||
delete from api_definition_exec_result where resource_id = #{id,jdbcType=VARCHAR}
|
delete from api_definition_exec_result where resource_id = #{id,jdbcType=VARCHAR}
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<select id="selectByResourceId" parameterType="java.lang.String" resultType="io.metersphere.base.domain.ApiDefinitionExecResult">
|
<select id="selectMaxResultByResourceId" parameterType="java.lang.String" resultType="io.metersphere.base.domain.ApiDefinitionExecResult">
|
||||||
select * from api_definition_exec_result
|
select * from api_definition_exec_result
|
||||||
where resource_id = #{resourceId,jdbcType=VARCHAR}
|
where resource_id = #{resourceId,jdbcType=VARCHAR} ORDER BY update_time DESC LIMIT 1
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -94,12 +94,24 @@
|
||||||
when 'error' then '未通过'
|
when 'error' then '未通过'
|
||||||
ELSE '未执行' end as status ,
|
ELSE '未执行' end as status ,
|
||||||
CONCAT(FORMAT(SUM(IF(t2.`status` = 'success', 1, 0))/ COUNT(t1.id)*100, 2), '%') passRate
|
CONCAT(FORMAT(SUM(IF(t2.`status` = 'success', 1, 0))/ COUNT(t1.id)*100, 2), '%') passRate
|
||||||
from api_test_case t1 left join api_definition_exec_result t2 on t1.id = t2.resource_id
|
from api_test_case t1 left join (
|
||||||
|
select
|
||||||
|
a.status, a.id, a.resource_id
|
||||||
|
from
|
||||||
|
api_definition_exec_result a
|
||||||
|
left join (
|
||||||
|
select
|
||||||
|
max(start_time) start_time , id, resource_id
|
||||||
|
from
|
||||||
|
api_definition_exec_result
|
||||||
|
group by
|
||||||
|
resource_id ) as b on a.id = b.id
|
||||||
|
where
|
||||||
|
a.start_time = b.start_time)as t2 on t1.id = t2.resource_id
|
||||||
group by t1.api_definition_id having t1.api_definition_id in
|
group by t1.api_definition_id having t1.api_definition_id in
|
||||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||||
#{v}
|
#{v}
|
||||||
</foreach>
|
</foreach>
|
||||||
order by t2.end_time desc;
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<sql id="combine">
|
<sql id="combine">
|
||||||
|
|
|
@ -146,15 +146,45 @@
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="list" resultType="io.metersphere.api.dto.definition.ApiTestCaseResult">
|
<select id="list" resultType="io.metersphere.api.dto.definition.ApiTestCaseResult">
|
||||||
select atc.id, atc.project_id,
|
select
|
||||||
atc.name,atc.priority,atc.api_definition_id,T1.name as createUser ,T2.name as updateUser,
|
atc.id,
|
||||||
atc.description,atc.request,atc.response,atc.create_user_id,
|
atc.project_id,
|
||||||
atc.create_time,atc.update_user_id, atc.update_time,ader.status execResult
|
atc.name,
|
||||||
from api_test_case atc left join user T1 on atc.create_user_id = T1.id left join user T2 on
|
atc.priority,
|
||||||
atc.update_user_id = T2.id left join api_definition_exec_result ader on atc.id = ader.resource_id
|
atc.api_definition_id,
|
||||||
|
u1.name as createUser ,
|
||||||
|
u2.name as updateUser,
|
||||||
|
atc.description,
|
||||||
|
atc.request,
|
||||||
|
atc.response,
|
||||||
|
atc.create_user_id,
|
||||||
|
atc.create_time,
|
||||||
|
atc.update_user_id,
|
||||||
|
atc.update_time,
|
||||||
|
ader.status execResult
|
||||||
|
from
|
||||||
|
api_test_case atc
|
||||||
|
left join user u1 on
|
||||||
|
atc.create_user_id = u1.id
|
||||||
|
left join user u2 on
|
||||||
|
atc.update_user_id = u2.id
|
||||||
|
left join (
|
||||||
|
select
|
||||||
|
a.status, a.id, a.resource_id
|
||||||
|
from
|
||||||
|
api_definition_exec_result a
|
||||||
|
left join (
|
||||||
|
select
|
||||||
|
max(start_time) start_time , id, resource_id
|
||||||
|
from
|
||||||
|
api_definition_exec_result
|
||||||
|
group by
|
||||||
|
resource_id ) as b on a.id = b.id
|
||||||
|
where
|
||||||
|
a.start_time = b.start_time) as ader
|
||||||
|
on atc.id = ader.resource_id
|
||||||
<where>
|
<where>
|
||||||
<if test="request.name != null and request.name!=''">
|
<if test="request.name != null and request.name!=''">
|
||||||
|
|
||||||
and atc.name like CONCAT('%', #{request.name},'%')
|
and atc.name like CONCAT('%', #{request.name},'%')
|
||||||
</if>
|
</if>
|
||||||
<if test="request.id != null and request.id!=''">
|
<if test="request.id != null and request.id!=''">
|
||||||
|
|
|
@ -84,9 +84,4 @@ public class ProjectController {
|
||||||
projectService.updateProject(Project);
|
projectService.updateProject(Project);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/search")
|
|
||||||
public List<ProjectDTO> searchProject(@RequestBody ProjectRequest projectRequest) {
|
|
||||||
projectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
|
||||||
return projectService.getProjectList(projectRequest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,16 +67,6 @@ export default {
|
||||||
components: {SearchList, MsCreateTest, MsCreateButton, MsShowAll, MsRecentList, ProjectChange},
|
components: {SearchList, MsCreateTest, MsCreateButton, MsShowAll, MsRecentList, ProjectChange},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
projectRecent: {
|
|
||||||
title: this.$t('project.recent'),
|
|
||||||
url: "/project/recent/5",
|
|
||||||
index: function (item) {
|
|
||||||
return '/api/test/list/' + item.id;
|
|
||||||
},
|
|
||||||
router: function (item) {
|
|
||||||
return {name: 'ApiTestList', params: {projectId: item.id, projectName: item.name}}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
testRecent: {
|
testRecent: {
|
||||||
title: this.$t('load_test.recent'),
|
title: this.$t('load_test.recent'),
|
||||||
url: "/api/recent/5",
|
url: "/api/recent/5",
|
||||||
|
@ -101,19 +91,10 @@ export default {
|
||||||
currentProject: ''
|
currentProject: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// watch: {
|
|
||||||
// '$route'(to) {
|
|
||||||
// this.init();
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
methods: {
|
methods: {
|
||||||
registerEvents() {
|
registerEvents() {
|
||||||
ApiEvent.$on(LIST_CHANGE, () => {
|
ApiEvent.$on(LIST_CHANGE, () => {
|
||||||
// // todo 这里偶尔会有 refs 为空的情况
|
// // todo 这里偶尔会有 refs 为空的情况
|
||||||
// if (!this.$refs.projectRecent) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// this.$refs.projectRecent.recent();
|
|
||||||
this.$refs.testRecent.recent();
|
this.$refs.testRecent.recent();
|
||||||
this.$refs.reportRecent.recent();
|
this.$refs.reportRecent.recent();
|
||||||
});
|
});
|
||||||
|
@ -124,17 +105,6 @@ export default {
|
||||||
this.isRouterAlive = true;
|
this.isRouterAlive = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// init() {
|
|
||||||
// let path = this.$route.path;
|
|
||||||
// if (path.indexOf("/api/test/list") >= 0 && !!this.$route.params.projectId) {
|
|
||||||
// this.apiTestProjectPath = path;
|
|
||||||
// //不激活项目菜单栏
|
|
||||||
// this.isProjectActivation = false;
|
|
||||||
// this.reload();
|
|
||||||
// } else {
|
|
||||||
// this.isProjectActivation = true;
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.registerEvents();
|
this.registerEvents();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" default-active="1">
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" default-active="1" router>
|
||||||
<!-- 不激活项目路由-->
|
<!-- 不激活项目路由-->
|
||||||
<el-menu-item index="1" v-show="false">Placeholder</el-menu-item>
|
<el-menu-item index="1" v-show="false">Placeholder</el-menu-item>
|
||||||
<el-submenu v-permission="['test_manager','test_user','test_viewer']" index="2" popper-class="submenu">
|
<el-submenu v-permission="['test_manager','test_user','test_viewer']" index="2" popper-class="submenu">
|
||||||
|
@ -14,21 +14,23 @@
|
||||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<ms-show-all :index="'/setting/project/all'"/>
|
<el-menu-item :index="'/setting/project/all'">
|
||||||
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
|
<span style="padding-left: 7px;">{{ $t('commons.show_all') }}</span>
|
||||||
|
</el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SearchList from "@/business/components/common/head/SearchList";
|
import SearchList from "@/business/components/common/head/SearchList";
|
||||||
import MsShowAll from "@/business/components/common/head/ShowAll";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ProjectSwitch",
|
name: "ProjectSwitch",
|
||||||
props: {
|
props: {
|
||||||
projectName: String
|
projectName: String
|
||||||
},
|
},
|
||||||
components: {SearchList, MsShowAll},
|
components: {SearchList},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentProject: this.projectName
|
currentProject: this.projectName
|
||||||
|
|
|
@ -76,13 +76,6 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
search() {
|
|
||||||
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
|
||||||
this.result = this.$post("/project/search", {name: this.searchString},response => {
|
|
||||||
this.items = response.data;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
query(queryString) {
|
query(queryString) {
|
||||||
this.items = queryString ? this.searchArray.filter(this.createFilter(queryString)) : this.searchArray;
|
this.items = queryString ? this.searchArray.filter(this.createFilter(queryString)) : this.searchArray;
|
||||||
},
|
},
|
||||||
|
|
|
@ -59,16 +59,6 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
projectRecent: {
|
|
||||||
title: this.$t('project.recent'),
|
|
||||||
url: "/project/recent/5",
|
|
||||||
index(item) {
|
|
||||||
return '/performance/test/' + item.id;
|
|
||||||
},
|
|
||||||
router(item) {
|
|
||||||
return {name: 'perPlan', params: {projectId: item.id, projectName: item.name}}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
testRecent: {
|
testRecent: {
|
||||||
title: this.$t('load_test.recent'),
|
title: this.$t('load_test.recent'),
|
||||||
url: "/performance/recent/5",
|
url: "/performance/recent/5",
|
||||||
|
@ -95,10 +85,6 @@ export default {
|
||||||
registerEvents() {
|
registerEvents() {
|
||||||
PerformanceEvent.$on(LIST_CHANGE, () => {
|
PerformanceEvent.$on(LIST_CHANGE, () => {
|
||||||
// // todo 这里偶尔会有 refs 为空的情况
|
// // todo 这里偶尔会有 refs 为空的情况
|
||||||
// if (!this.$refs.projectRecent) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// this.$refs.projectRecent.recent();
|
|
||||||
this.$refs.testRecent.recent();
|
this.$refs.testRecent.recent();
|
||||||
this.$refs.reportRecent.recent();
|
this.$refs.reportRecent.recent();
|
||||||
});
|
});
|
||||||
|
|
|
@ -69,16 +69,6 @@ export default {
|
||||||
testCaseProjectPath: '',
|
testCaseProjectPath: '',
|
||||||
isProjectActivation: true,
|
isProjectActivation: true,
|
||||||
currentProject: '',
|
currentProject: '',
|
||||||
projectRecent: {
|
|
||||||
title: this.$t('project.recent'),
|
|
||||||
url: "/project/recent/5",
|
|
||||||
index: function (item) {
|
|
||||||
return '/track/case/' + item.id;
|
|
||||||
},
|
|
||||||
router: function (item) {
|
|
||||||
return {name: 'testCase', params: {projectId: item.id, projectName: item.name}}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
caseRecent: {
|
caseRecent: {
|
||||||
title: this.$t('test_track.recent_case'),
|
title: this.$t('test_track.recent_case'),
|
||||||
url: "/test/case/recent/5",
|
url: "/test/case/recent/5",
|
||||||
|
@ -126,14 +116,6 @@ export default {
|
||||||
},
|
},
|
||||||
init() {
|
init() {
|
||||||
let path = this.$route.path;
|
let path = this.$route.path;
|
||||||
// if (path.indexOf("/track/case") >= 0 && !!this.$route.params.projectId) {
|
|
||||||
// this.testCaseProjectPath = path;
|
|
||||||
// //不激活项目菜单栏
|
|
||||||
// this.isProjectActivation = false;
|
|
||||||
// this.reload();
|
|
||||||
// } else {
|
|
||||||
// this.isProjectActivation = true;
|
|
||||||
// }
|
|
||||||
if (path.indexOf("/track/plan/view") >= 0) {
|
if (path.indexOf("/track/plan/view") >= 0) {
|
||||||
this.testPlanViewPath = path;
|
this.testPlanViewPath = path;
|
||||||
this.reload();
|
this.reload();
|
||||||
|
@ -150,10 +132,6 @@ export default {
|
||||||
registerEvents() {
|
registerEvents() {
|
||||||
TrackEvent.$on(LIST_CHANGE, () => {
|
TrackEvent.$on(LIST_CHANGE, () => {
|
||||||
// // todo 这里偶尔会有 refs 为空的情况
|
// // todo 这里偶尔会有 refs 为空的情况
|
||||||
// if (!this.$refs.projectRecent) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// this.$refs.projectRecent.recent();
|
|
||||||
this.$refs.planRecent.recent();
|
this.$refs.planRecent.recent();
|
||||||
this.$refs.caseRecent.recent();
|
this.$refs.caseRecent.recent();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue