Merge branch 'v1.3' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
6d265b55db
|
@ -11,6 +11,7 @@ import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.dto.DashboardTestDTO;
|
import io.metersphere.dto.DashboardTestDTO;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -25,6 +26,8 @@ public class APIReportController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private APIReportService apiReportService;
|
private APIReportService apiReportService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@GetMapping("recent/{count}")
|
@GetMapping("recent/{count}")
|
||||||
public List<APIReportResult> recentTest(@PathVariable int count) {
|
public List<APIReportResult> recentTest(@PathVariable int count) {
|
||||||
|
@ -37,6 +40,7 @@ public class APIReportController {
|
||||||
|
|
||||||
@GetMapping("/list/{testId}")
|
@GetMapping("/list/{testId}")
|
||||||
public List<APIReportResult> listByTestId(@PathVariable String testId) {
|
public List<APIReportResult> listByTestId(@PathVariable String testId) {
|
||||||
|
checkOwnerService.checkApiTestOwner(testId);
|
||||||
return apiReportService.listByTestId(testId);
|
return apiReportService.listByTestId(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.controller.request.QueryScheduleRequest;
|
import io.metersphere.controller.request.QueryScheduleRequest;
|
||||||
import io.metersphere.dto.ScheduleDao;
|
import io.metersphere.dto.ScheduleDao;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -27,6 +28,8 @@ import java.util.List;
|
||||||
public class APITestController {
|
public class APITestController {
|
||||||
@Resource
|
@Resource
|
||||||
private APITestService apiTestService;
|
private APITestService apiTestService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkownerService;
|
||||||
|
|
||||||
@GetMapping("recent/{count}")
|
@GetMapping("recent/{count}")
|
||||||
public List<APITestResult> recentTest(@PathVariable int count) {
|
public List<APITestResult> recentTest(@PathVariable int count) {
|
||||||
|
@ -51,6 +54,7 @@ public class APITestController {
|
||||||
|
|
||||||
@GetMapping("/list/{projectId}")
|
@GetMapping("/list/{projectId}")
|
||||||
public List<ApiTest> list(@PathVariable String projectId) {
|
public List<ApiTest> list(@PathVariable String projectId) {
|
||||||
|
checkownerService.checkProjectOwner(projectId);
|
||||||
return apiTestService.getApiTestByProjectId(projectId);
|
return apiTestService.getApiTestByProjectId(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +75,7 @@ public class APITestController {
|
||||||
|
|
||||||
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
||||||
public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
|
checkownerService.checkApiTestOwner(request.getId());
|
||||||
apiTestService.update(request, file, bodyFiles);
|
apiTestService.update(request, file, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,13 +86,16 @@ public class APITestController {
|
||||||
|
|
||||||
@GetMapping("/get/{testId}")
|
@GetMapping("/get/{testId}")
|
||||||
public APITestResult get(@PathVariable String testId) {
|
public APITestResult get(@PathVariable String testId) {
|
||||||
|
checkownerService.checkApiTestOwner(testId);
|
||||||
return apiTestService.get(testId);
|
return apiTestService.get(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public void delete(@RequestBody DeleteAPITestRequest request) {
|
public void delete(@RequestBody DeleteAPITestRequest request) {
|
||||||
apiTestService.delete(request.getId());
|
String testId = request.getId();
|
||||||
|
checkownerService.checkApiTestOwner(testId);
|
||||||
|
apiTestService.delete(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/run")
|
@PostMapping(value = "/run")
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.api.controller;
|
||||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||||
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -17,9 +18,12 @@ public class ApiTestEnvironmentController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
ApiTestEnvironmentService apiTestEnvironmentService;
|
ApiTestEnvironmentService apiTestEnvironmentService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@GetMapping("/list/{projectId}")
|
@GetMapping("/list/{projectId}")
|
||||||
public List<ApiTestEnvironmentWithBLOBs> list(@PathVariable String projectId) {
|
public List<ApiTestEnvironmentWithBLOBs> list(@PathVariable String projectId) {
|
||||||
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
return apiTestEnvironmentService.list(projectId);
|
return apiTestEnvironmentService.list(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,19 @@ public class KeyValue {
|
||||||
private boolean enable;
|
private boolean enable;
|
||||||
|
|
||||||
public KeyValue() {
|
public KeyValue() {
|
||||||
|
this.enable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyValue(String name, String value) {
|
public KeyValue(String name, String value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.enable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyValue(String name, String value, String description) {
|
public KeyValue(String name, String value, String description) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.enable = true;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,10 @@ public class Swagger2Parser extends ApiImportAbstractParser {
|
||||||
Model model = definitions.get(simpleRef);
|
Model model = definitions.get(simpleRef);
|
||||||
HashSet<String> refSet = new HashSet<>();
|
HashSet<String> refSet = new HashSet<>();
|
||||||
refSet.add(simpleRef);
|
refSet.add(simpleRef);
|
||||||
|
if (model != null ) {
|
||||||
JSONObject bodyParameters = getBodyJSONObjectParameters(model.getProperties(), definitions, refSet);
|
JSONObject bodyParameters = getBodyJSONObjectParameters(model.getProperties(), definitions, refSet);
|
||||||
body.setRaw(bodyParameters.toJSONString());
|
body.setRaw(bodyParameters.toJSONString());
|
||||||
|
}
|
||||||
} else if (schema instanceof ArrayModel) {
|
} else if (schema instanceof ArrayModel) {
|
||||||
ArrayModel arrayModel = (ArrayModel) bodyParameter.getSchema();
|
ArrayModel arrayModel = (ArrayModel) bodyParameter.getSchema();
|
||||||
Property items = arrayModel.getItems();
|
Property items = arrayModel.getItems();
|
||||||
|
|
|
@ -37,5 +37,7 @@ public class TestCase implements Serializable {
|
||||||
|
|
||||||
private String otherTestName;
|
private String otherTestName;
|
||||||
|
|
||||||
|
private String reviewStatus;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
}
|
}
|
|
@ -1183,6 +1183,76 @@ public class TestCaseExample {
|
||||||
addCriterion("other_test_name not between", value1, value2, "otherTestName");
|
addCriterion("other_test_name not between", value1, value2, "otherTestName");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusIsNull() {
|
||||||
|
addCriterion("review_status is null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusIsNotNull() {
|
||||||
|
addCriterion("review_status is not null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusEqualTo(String value) {
|
||||||
|
addCriterion("review_status =", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusNotEqualTo(String value) {
|
||||||
|
addCriterion("review_status <>", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusGreaterThan(String value) {
|
||||||
|
addCriterion("review_status >", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusGreaterThanOrEqualTo(String value) {
|
||||||
|
addCriterion("review_status >=", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusLessThan(String value) {
|
||||||
|
addCriterion("review_status <", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusLessThanOrEqualTo(String value) {
|
||||||
|
addCriterion("review_status <=", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusLike(String value) {
|
||||||
|
addCriterion("review_status like", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusNotLike(String value) {
|
||||||
|
addCriterion("review_status not like", value, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusIn(List<String> values) {
|
||||||
|
addCriterion("review_status in", values, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusNotIn(List<String> values) {
|
||||||
|
addCriterion("review_status not in", values, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusBetween(String value1, String value2) {
|
||||||
|
addCriterion("review_status between", value1, value2, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andReviewStatusNotBetween(String value1, String value2) {
|
||||||
|
addCriterion("review_status not between", value1, value2, "reviewStatus");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Criteria extends GeneratedCriteria {
|
public static class Criteria extends GeneratedCriteria {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<result column="sort" jdbcType="INTEGER" property="sort" />
|
<result column="sort" jdbcType="INTEGER" property="sort" />
|
||||||
<result column="num" jdbcType="INTEGER" property="num" />
|
<result column="num" jdbcType="INTEGER" property="num" />
|
||||||
<result column="other_test_name" jdbcType="VARCHAR" property="otherTestName" />
|
<result column="other_test_name" jdbcType="VARCHAR" property="otherTestName" />
|
||||||
|
<result column="review_status" jdbcType="VARCHAR" property="reviewStatus" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestCaseWithBLOBs">
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestCaseWithBLOBs">
|
||||||
<result column="remark" jdbcType="LONGVARCHAR" property="remark" />
|
<result column="remark" jdbcType="LONGVARCHAR" property="remark" />
|
||||||
|
@ -83,7 +84,7 @@
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, node_id, node_path, project_id, `name`, `type`, maintainer, priority, `method`,
|
id, node_id, node_path, project_id, `name`, `type`, maintainer, priority, `method`,
|
||||||
prerequisite, create_time, update_time, test_id, sort, num, other_test_name
|
prerequisite, create_time, update_time, test_id, sort, num, other_test_name, review_status
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Blob_Column_List">
|
<sql id="Blob_Column_List">
|
||||||
remark, steps
|
remark, steps
|
||||||
|
@ -142,15 +143,15 @@
|
||||||
maintainer, priority, `method`,
|
maintainer, priority, `method`,
|
||||||
prerequisite, create_time, update_time,
|
prerequisite, create_time, update_time,
|
||||||
test_id, sort, num,
|
test_id, sort, num,
|
||||||
other_test_name, remark, steps
|
other_test_name, review_status, remark,
|
||||||
)
|
steps)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{nodeId,jdbcType=VARCHAR}, #{nodePath,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{nodeId,jdbcType=VARCHAR}, #{nodePath,jdbcType=VARCHAR},
|
||||||
#{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
|
#{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
|
||||||
#{maintainer,jdbcType=VARCHAR}, #{priority,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR},
|
#{maintainer,jdbcType=VARCHAR}, #{priority,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR},
|
||||||
#{prerequisite,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
#{prerequisite,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||||
#{testId,jdbcType=VARCHAR}, #{sort,jdbcType=INTEGER}, #{num,jdbcType=INTEGER},
|
#{testId,jdbcType=VARCHAR}, #{sort,jdbcType=INTEGER}, #{num,jdbcType=INTEGER},
|
||||||
#{otherTestName,jdbcType=VARCHAR}, #{remark,jdbcType=LONGVARCHAR}, #{steps,jdbcType=LONGVARCHAR}
|
#{otherTestName,jdbcType=VARCHAR}, #{reviewStatus,jdbcType=VARCHAR}, #{remark,jdbcType=LONGVARCHAR},
|
||||||
)
|
#{steps,jdbcType=LONGVARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseWithBLOBs">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseWithBLOBs">
|
||||||
insert into test_case
|
insert into test_case
|
||||||
|
@ -203,6 +204,9 @@
|
||||||
<if test="otherTestName != null">
|
<if test="otherTestName != null">
|
||||||
other_test_name,
|
other_test_name,
|
||||||
</if>
|
</if>
|
||||||
|
<if test="reviewStatus != null">
|
||||||
|
review_status,
|
||||||
|
</if>
|
||||||
<if test="remark != null">
|
<if test="remark != null">
|
||||||
remark,
|
remark,
|
||||||
</if>
|
</if>
|
||||||
|
@ -259,6 +263,9 @@
|
||||||
<if test="otherTestName != null">
|
<if test="otherTestName != null">
|
||||||
#{otherTestName,jdbcType=VARCHAR},
|
#{otherTestName,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="reviewStatus != null">
|
||||||
|
#{reviewStatus,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="remark != null">
|
<if test="remark != null">
|
||||||
#{remark,jdbcType=LONGVARCHAR},
|
#{remark,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -324,6 +331,9 @@
|
||||||
<if test="record.otherTestName != null">
|
<if test="record.otherTestName != null">
|
||||||
other_test_name = #{record.otherTestName,jdbcType=VARCHAR},
|
other_test_name = #{record.otherTestName,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="record.reviewStatus != null">
|
||||||
|
review_status = #{record.reviewStatus,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="record.remark != null">
|
<if test="record.remark != null">
|
||||||
remark = #{record.remark,jdbcType=LONGVARCHAR},
|
remark = #{record.remark,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -353,6 +363,7 @@
|
||||||
sort = #{record.sort,jdbcType=INTEGER},
|
sort = #{record.sort,jdbcType=INTEGER},
|
||||||
num = #{record.num,jdbcType=INTEGER},
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
other_test_name = #{record.otherTestName,jdbcType=VARCHAR},
|
other_test_name = #{record.otherTestName,jdbcType=VARCHAR},
|
||||||
|
review_status = #{record.reviewStatus,jdbcType=VARCHAR},
|
||||||
remark = #{record.remark,jdbcType=LONGVARCHAR},
|
remark = #{record.remark,jdbcType=LONGVARCHAR},
|
||||||
steps = #{record.steps,jdbcType=LONGVARCHAR}
|
steps = #{record.steps,jdbcType=LONGVARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
|
@ -376,7 +387,8 @@
|
||||||
test_id = #{record.testId,jdbcType=VARCHAR},
|
test_id = #{record.testId,jdbcType=VARCHAR},
|
||||||
sort = #{record.sort,jdbcType=INTEGER},
|
sort = #{record.sort,jdbcType=INTEGER},
|
||||||
num = #{record.num,jdbcType=INTEGER},
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
other_test_name = #{record.otherTestName,jdbcType=VARCHAR}
|
other_test_name = #{record.otherTestName,jdbcType=VARCHAR},
|
||||||
|
review_status = #{record.reviewStatus,jdbcType=VARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
|
@ -429,6 +441,9 @@
|
||||||
<if test="otherTestName != null">
|
<if test="otherTestName != null">
|
||||||
other_test_name = #{otherTestName,jdbcType=VARCHAR},
|
other_test_name = #{otherTestName,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="reviewStatus != null">
|
||||||
|
review_status = #{reviewStatus,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="remark != null">
|
<if test="remark != null">
|
||||||
remark = #{remark,jdbcType=LONGVARCHAR},
|
remark = #{remark,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -455,6 +470,7 @@
|
||||||
sort = #{sort,jdbcType=INTEGER},
|
sort = #{sort,jdbcType=INTEGER},
|
||||||
num = #{num,jdbcType=INTEGER},
|
num = #{num,jdbcType=INTEGER},
|
||||||
other_test_name = #{otherTestName,jdbcType=VARCHAR},
|
other_test_name = #{otherTestName,jdbcType=VARCHAR},
|
||||||
|
review_status = #{reviewStatus,jdbcType=VARCHAR},
|
||||||
remark = #{remark,jdbcType=LONGVARCHAR},
|
remark = #{remark,jdbcType=LONGVARCHAR},
|
||||||
steps = #{steps,jdbcType=LONGVARCHAR}
|
steps = #{steps,jdbcType=LONGVARCHAR}
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
|
@ -475,7 +491,8 @@
|
||||||
test_id = #{testId,jdbcType=VARCHAR},
|
test_id = #{testId,jdbcType=VARCHAR},
|
||||||
sort = #{sort,jdbcType=INTEGER},
|
sort = #{sort,jdbcType=INTEGER},
|
||||||
num = #{num,jdbcType=INTEGER},
|
num = #{num,jdbcType=INTEGER},
|
||||||
other_test_name = #{otherTestName,jdbcType=VARCHAR}
|
other_test_name = #{otherTestName,jdbcType=VARCHAR},
|
||||||
|
review_status = #{reviewStatus,jdbcType=VARCHAR}
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -20,4 +20,12 @@ public interface ExtTestCaseMapper {
|
||||||
|
|
||||||
TestCase getMaxNumByProjectId(@Param("projectId") String projectId);
|
TestCase getMaxNumByProjectId(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查某工作空间下是否有某用例
|
||||||
|
* @param caseId
|
||||||
|
* @param workspaceId
|
||||||
|
* @return TestCase ID
|
||||||
|
*/
|
||||||
|
List<String> checkIsHave(@Param("caseId") String caseId, @Param("workspaceId") String workspaceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
|
|
||||||
|
|
||||||
<select id="getTestCaseNames" resultType="io.metersphere.base.domain.TestCase">
|
<select id="getTestCaseNames" resultType="io.metersphere.base.domain.TestCase">
|
||||||
select test_case.id, test_case.name, test_case.priority, test_case.type
|
select test_case.id, test_case.name, test_case.priority, test_case.type, test_case.review_status
|
||||||
from test_case
|
from test_case
|
||||||
<where>
|
<where>
|
||||||
<if test="request.combine != null">
|
<if test="request.combine != null">
|
||||||
|
@ -130,6 +130,12 @@
|
||||||
#{value}
|
#{value}
|
||||||
</foreach>
|
</foreach>
|
||||||
</when>
|
</when>
|
||||||
|
<when test="key=='status'">
|
||||||
|
and test_case.review_status in
|
||||||
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
#{value}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
<otherwise>
|
<otherwise>
|
||||||
and test_case.type in
|
and test_case.type in
|
||||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
@ -181,6 +187,12 @@
|
||||||
#{value}
|
#{value}
|
||||||
</foreach>
|
</foreach>
|
||||||
</when>
|
</when>
|
||||||
|
<when test="key=='status'">
|
||||||
|
and test_case.review_status in
|
||||||
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
#{value}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
<otherwise>
|
<otherwise>
|
||||||
and test_case.method in
|
and test_case.method in
|
||||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
@ -239,4 +251,11 @@
|
||||||
<select id="getMaxNumByProjectId" resultType="io.metersphere.base.domain.TestCase">
|
<select id="getMaxNumByProjectId" resultType="io.metersphere.base.domain.TestCase">
|
||||||
select * from test_case where test_case.project_id = #{projectId} order by num desc limit 1;
|
select * from test_case where test_case.project_id = #{projectId} order by num desc limit 1;
|
||||||
</select>
|
</select>
|
||||||
|
<select id="checkIsHave" resultType="java.lang.String">
|
||||||
|
select distinct test_case.id
|
||||||
|
from test_case, project
|
||||||
|
where test_case.project_id = project.id
|
||||||
|
and project.workspace_id = #{workspaceId}
|
||||||
|
and test_case.id = #{caseId};
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -15,4 +15,12 @@ public interface ExtTestCaseReviewMapper {
|
||||||
List<TestCaseReviewDTO> listByWorkspaceId(@Param("workspaceId") String workspaceId);
|
List<TestCaseReviewDTO> listByWorkspaceId(@Param("workspaceId") String workspaceId);
|
||||||
|
|
||||||
List<TestReviewDTOWithMetric> listRelate(@Param("request") QueryTestReviewRequest request);
|
List<TestReviewDTOWithMetric> listRelate(@Param("request") QueryTestReviewRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查某工作空间下是否有某测试评审
|
||||||
|
* @param reviewId
|
||||||
|
* @param workspaceId
|
||||||
|
* @return Review ID
|
||||||
|
*/
|
||||||
|
List<String> checkIsHave(@Param("reviewId") String reviewId, @Param("workspaceId") String workspaceId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,4 +58,11 @@
|
||||||
|
|
||||||
order by test_case_review.update_time desc
|
order by test_case_review.update_time desc
|
||||||
</select>
|
</select>
|
||||||
|
<select id="checkIsHave" resultType="java.lang.String">
|
||||||
|
select distinct review_id
|
||||||
|
from project, test_case_review_project
|
||||||
|
where project.id = test_case_review_project.project_id
|
||||||
|
and project.workspace_id = #{workspaceId}
|
||||||
|
and test_case_review_project.review_id = #{reviewId};
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -10,6 +10,6 @@ import java.util.List;
|
||||||
public interface ExtTestReviewCaseMapper {
|
public interface ExtTestReviewCaseMapper {
|
||||||
|
|
||||||
List<TestReviewCaseDTO> list(@Param("request") QueryCaseReviewRequest request);
|
List<TestReviewCaseDTO> list(@Param("request") QueryCaseReviewRequest request);
|
||||||
List<String> getStatusByReviewId(String planId);
|
List<String> getStatusByReviewId(String reviewId);
|
||||||
List<String> findRelateTestReviewId(String userId, String workspaceId);
|
List<String> findRelateTestReviewId(String userId, String workspaceId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,9 +182,9 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getStatusByReviewId" resultType="java.lang.String">
|
<select id="getStatusByReviewId" resultType="java.lang.String">
|
||||||
select status
|
select review_status
|
||||||
from test_case_review_test_case
|
from test_case
|
||||||
where review_id = #{reviewId}
|
where id in (select case_id from test_case_review_test_case where review_id = #{reviewId});
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="findRelateTestReviewId" resultType="java.lang.String">
|
<select id="findRelateTestReviewId" resultType="java.lang.String">
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.controller.request.ProjectRequest;
|
import io.metersphere.controller.request.ProjectRequest;
|
||||||
import io.metersphere.dto.ProjectDTO;
|
import io.metersphere.dto.ProjectDTO;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import io.metersphere.service.ProjectService;
|
import io.metersphere.service.ProjectService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
@ -22,6 +23,8 @@ import java.util.List;
|
||||||
public class ProjectController {
|
public class ProjectController {
|
||||||
@Resource
|
@Resource
|
||||||
private ProjectService projectService;
|
private ProjectService projectService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@GetMapping("/listAll")
|
@GetMapping("/listAll")
|
||||||
public List<ProjectDTO> listAll() {
|
public List<ProjectDTO> listAll() {
|
||||||
|
@ -71,6 +74,7 @@ public class ProjectController {
|
||||||
@GetMapping("/delete/{projectId}")
|
@GetMapping("/delete/{projectId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER,}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER,}, logical = Logical.OR)
|
||||||
public void deleteProject(@PathVariable(value = "projectId") String projectId) {
|
public void deleteProject(@PathVariable(value = "projectId") String projectId) {
|
||||||
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
projectService.deleteProject(projectId);
|
projectService.deleteProject(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ package io.metersphere.controller.handler;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.controller.ResultHolder;
|
import io.metersphere.controller.ResultHolder;
|
||||||
import org.apache.shiro.ShiroException;
|
import org.apache.shiro.ShiroException;
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
@ -21,6 +22,13 @@ public class RestControllerExceptionHandler {
|
||||||
return ResultHolder.error(exception.getMessage());
|
return ResultHolder.error(exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*=========== Shiro 异常拦截==============*/
|
||||||
|
@ExceptionHandler(UnauthorizedException.class)
|
||||||
|
public ResultHolder unauthorizedExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception exception) {
|
||||||
|
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||||
|
return ResultHolder.error(exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ExceptionHandler(MSException.class)
|
@ExceptionHandler(MSException.class)
|
||||||
public ResultHolder msExceptionHandler(HttpServletRequest request, HttpServletResponse response, MSException e) {
|
public ResultHolder msExceptionHandler(HttpServletRequest request, HttpServletResponse response, MSException e) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import io.metersphere.dto.DashboardTestDTO;
|
||||||
import io.metersphere.dto.LoadTestDTO;
|
import io.metersphere.dto.LoadTestDTO;
|
||||||
import io.metersphere.dto.ScheduleDao;
|
import io.metersphere.dto.ScheduleDao;
|
||||||
import io.metersphere.performance.service.PerformanceTestService;
|
import io.metersphere.performance.service.PerformanceTestService;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import io.metersphere.service.FileService;
|
import io.metersphere.service.FileService;
|
||||||
import io.metersphere.track.request.testplan.*;
|
import io.metersphere.track.request.testplan.*;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
|
@ -35,6 +36,8 @@ public class PerformanceTestController {
|
||||||
private PerformanceTestService performanceTestService;
|
private PerformanceTestService performanceTestService;
|
||||||
@Resource
|
@Resource
|
||||||
private FileService fileService;
|
private FileService fileService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@GetMapping("recent/{count}")
|
@GetMapping("recent/{count}")
|
||||||
public List<LoadTestDTO> recentTestPlans(@PathVariable int count) {
|
public List<LoadTestDTO> recentTestPlans(@PathVariable int count) {
|
||||||
|
@ -54,12 +57,14 @@ public class PerformanceTestController {
|
||||||
|
|
||||||
@GetMapping("/list/{projectId}")
|
@GetMapping("/list/{projectId}")
|
||||||
public List<LoadTest> list(@PathVariable String projectId) {
|
public List<LoadTest> list(@PathVariable String projectId) {
|
||||||
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
return performanceTestService.getLoadTestByProjectId(projectId);
|
return performanceTestService.getLoadTestByProjectId(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/state/get/{testId}")
|
@GetMapping("/state/get/{testId}")
|
||||||
public LoadTest listByTestId(@PathVariable String testId) {
|
public LoadTest listByTestId(@PathVariable String testId) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(testId);
|
||||||
return performanceTestService.getLoadTestBytestId(testId);
|
return performanceTestService.getLoadTestBytestId(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,26 +81,31 @@ public class PerformanceTestController {
|
||||||
@RequestPart("request") EditTestPlanRequest request,
|
@RequestPart("request") EditTestPlanRequest request,
|
||||||
@RequestPart(value = "file", required = false) List<MultipartFile> files
|
@RequestPart(value = "file", required = false) List<MultipartFile> files
|
||||||
) {
|
) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(request.getId());
|
||||||
return performanceTestService.edit(request, files);
|
return performanceTestService.edit(request, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get/{testId}")
|
@GetMapping("/get/{testId}")
|
||||||
public LoadTestDTO get(@PathVariable String testId) {
|
public LoadTestDTO get(@PathVariable String testId) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(testId);
|
||||||
return performanceTestService.get(testId);
|
return performanceTestService.get(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-advanced-config/{testId}")
|
@GetMapping("/get-advanced-config/{testId}")
|
||||||
public String getAdvancedConfiguration(@PathVariable String testId) {
|
public String getAdvancedConfiguration(@PathVariable String testId) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(testId);
|
||||||
return performanceTestService.getAdvancedConfiguration(testId);
|
return performanceTestService.getAdvancedConfiguration(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-load-config/{testId}")
|
@GetMapping("/get-load-config/{testId}")
|
||||||
public String getLoadConfiguration(@PathVariable String testId) {
|
public String getLoadConfiguration(@PathVariable String testId) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(testId);
|
||||||
return performanceTestService.getLoadConfiguration(testId);
|
return performanceTestService.getLoadConfiguration(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public void delete(@RequestBody DeleteTestPlanRequest request) {
|
public void delete(@RequestBody DeleteTestPlanRequest request) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(request.getId());
|
||||||
performanceTestService.delete(request);
|
performanceTestService.delete(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +121,7 @@ public class PerformanceTestController {
|
||||||
|
|
||||||
@GetMapping("/file/metadata/{testId}")
|
@GetMapping("/file/metadata/{testId}")
|
||||||
public List<FileMetadata> getFileMetadata(@PathVariable String testId) {
|
public List<FileMetadata> getFileMetadata(@PathVariable String testId) {
|
||||||
|
checkOwnerService.checkPerformanceTestOwner(testId);
|
||||||
return fileService.getFileMetadataByTestId(testId);
|
return fileService.getFileMetadataByTestId(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.APITestResult;
|
||||||
|
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||||
|
import io.metersphere.base.domain.Project;
|
||||||
|
import io.metersphere.base.mapper.ProjectMapper;
|
||||||
|
import io.metersphere.base.mapper.ext.*;
|
||||||
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
|
import io.metersphere.dto.LoadTestDTO;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
|
import io.metersphere.track.dto.TestPlanDTO;
|
||||||
|
import io.metersphere.track.request.testplan.QueryTestPlanRequest;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CheckOwnerService {
|
||||||
|
@Resource
|
||||||
|
private ProjectMapper projectMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtApiTestMapper extApiTestMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtLoadTestMapper extLoadTestMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtTestCaseMapper extTestCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtTestPlanMapper extTestPlanMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtTestCaseReviewMapper extTestCaseReviewMapper;
|
||||||
|
|
||||||
|
public void checkProjectOwner(String projectId) {
|
||||||
|
String workspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||||
|
if (project == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!StringUtils.equals(workspaceId, project.getWorkspaceId())) {
|
||||||
|
throw new UnauthorizedException(Translator.get("check_owner_project"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkApiTestOwner(String testId) {
|
||||||
|
String workspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
QueryAPITestRequest request = new QueryAPITestRequest();
|
||||||
|
request.setWorkspaceId(workspaceId);
|
||||||
|
request.setId(testId);
|
||||||
|
List<APITestResult> apiTestResults = extApiTestMapper.list(request);
|
||||||
|
|
||||||
|
if (CollectionUtils.size(apiTestResults) != 1) {
|
||||||
|
throw new UnauthorizedException(Translator.get("check_owner_test"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkPerformanceTestOwner(String testId) {
|
||||||
|
String workspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
||||||
|
request.setWorkspaceId(workspaceId);
|
||||||
|
request.setId(testId);
|
||||||
|
List<LoadTestDTO> loadTestDTOS = extLoadTestMapper.list(request);
|
||||||
|
|
||||||
|
if (CollectionUtils.size(loadTestDTOS) != 1) {
|
||||||
|
throw new UnauthorizedException(Translator.get("check_owner_test"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkTestCaseOwner(String caseId) {
|
||||||
|
String workspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
List<String> list = extTestCaseMapper.checkIsHave(caseId, workspaceId);
|
||||||
|
if (CollectionUtils.size(list) != 1) {
|
||||||
|
throw new UnauthorizedException(Translator.get("check_owner_case"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkTestPlanOwner(String planId) {
|
||||||
|
String workspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
io.metersphere.track.request.testcase.QueryTestPlanRequest request = new io.metersphere.track.request.testcase.QueryTestPlanRequest();
|
||||||
|
request.setWorkspaceId(workspaceId);
|
||||||
|
request.setId(planId);
|
||||||
|
List<TestPlanDTO> list = extTestPlanMapper.list(request);
|
||||||
|
if (CollectionUtils.size(list) != 1) {
|
||||||
|
throw new UnauthorizedException(Translator.get("check_owner_plan"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkTestReviewOwner(String reviewId) {
|
||||||
|
String workspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
List<String> list = extTestCaseReviewMapper.checkIsHave(reviewId, workspaceId);
|
||||||
|
if (CollectionUtils.size(list) != 1) {
|
||||||
|
throw new UnauthorizedException(Translator.get("check_owner_review"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -487,20 +487,18 @@ public class UserService {
|
||||||
|
|
||||||
/*修改当前用户用户密码*/
|
/*修改当前用户用户密码*/
|
||||||
private User updateCurrentUserPwd(EditPassWordRequest request) {
|
private User updateCurrentUserPwd(EditPassWordRequest request) {
|
||||||
if (SessionUtils.getUser() != null) {
|
String oldPassword = CodingUtil.md5(request.getPassword(), "utf-8");
|
||||||
User user = userMapper.selectByPrimaryKey(SessionUtils.getUser().getId());
|
String newPassword = request.getNewpassword();
|
||||||
String pwd = user.getPassword();
|
UserExample userExample = new UserExample();
|
||||||
String prepwd = CodingUtil.md5(request.getPassword(), "utf-8");
|
userExample.createCriteria().andIdEqualTo(SessionUtils.getUser().getId()).andPasswordEqualTo(oldPassword);
|
||||||
String newped = request.getNewpassword();
|
List<User> users = userMapper.selectByExample(userExample);
|
||||||
if (StringUtils.isNotBlank(prepwd)) {
|
if (!CollectionUtils.isEmpty(users)) {
|
||||||
if (prepwd.trim().equals(pwd.trim())) {
|
User user = users.get(0);
|
||||||
user.setPassword(CodingUtil.md5(newped));
|
user.setPassword(CodingUtil.md5(newPassword));
|
||||||
user.setUpdateTime(System.currentTimeMillis());
|
user.setUpdateTime(System.currentTimeMillis());
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
MSException.throwException(Translator.get("password_modification_failed"));
|
MSException.throwException(Translator.get("password_modification_failed"));
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,8 +510,8 @@ public class UserService {
|
||||||
/*管理员修改用户密码*/
|
/*管理员修改用户密码*/
|
||||||
private User updateUserPwd(EditPassWordRequest request) {
|
private User updateUserPwd(EditPassWordRequest request) {
|
||||||
User user = userMapper.selectByPrimaryKey(request.getId());
|
User user = userMapper.selectByPrimaryKey(request.getId());
|
||||||
String newped = request.getNewpassword();
|
String newPassword = request.getNewpassword();
|
||||||
user.setPassword(CodingUtil.md5(newped));
|
user.setPassword(CodingUtil.md5(newPassword));
|
||||||
user.setUpdateTime(System.currentTimeMillis());
|
user.setUpdateTime(System.currentTimeMillis());
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.excel.domain.ExcelResponse;
|
import io.metersphere.excel.domain.ExcelResponse;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import io.metersphere.track.dto.TestCaseDTO;
|
import io.metersphere.track.dto.TestCaseDTO;
|
||||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||||
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
||||||
|
@ -30,6 +31,8 @@ public class TestCaseController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseService testCaseService;
|
TestCaseService testCaseService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@PostMapping("/list/{goPage}/{pageSize}")
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
public Pager<List<TestCaseDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) {
|
public Pager<List<TestCaseDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) {
|
||||||
|
@ -39,6 +42,7 @@ public class TestCaseController {
|
||||||
|
|
||||||
@GetMapping("/list/{projectId}")
|
@GetMapping("/list/{projectId}")
|
||||||
public List<TestCaseDTO> list(@PathVariable String projectId) {
|
public List<TestCaseDTO> list(@PathVariable String projectId) {
|
||||||
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
QueryTestCaseRequest request = new QueryTestCaseRequest();
|
QueryTestCaseRequest request = new QueryTestCaseRequest();
|
||||||
request.setProjectId(projectId);
|
request.setProjectId(projectId);
|
||||||
return testCaseService.listTestCase(request);
|
return testCaseService.listTestCase(request);
|
||||||
|
@ -47,6 +51,7 @@ public class TestCaseController {
|
||||||
|
|
||||||
@GetMapping("/list/method/{projectId}")
|
@GetMapping("/list/method/{projectId}")
|
||||||
public List<TestCaseDTO> listByMethod(@PathVariable String projectId) {
|
public List<TestCaseDTO> listByMethod(@PathVariable String projectId) {
|
||||||
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
QueryTestCaseRequest request = new QueryTestCaseRequest();
|
QueryTestCaseRequest request = new QueryTestCaseRequest();
|
||||||
request.setProjectId(projectId);
|
request.setProjectId(projectId);
|
||||||
return testCaseService.listTestCaseMthod(request);
|
return testCaseService.listTestCaseMthod(request);
|
||||||
|
@ -78,11 +83,13 @@ public class TestCaseController {
|
||||||
|
|
||||||
@GetMapping("/get/{testCaseId}")
|
@GetMapping("/get/{testCaseId}")
|
||||||
public TestCaseWithBLOBs getTestCase(@PathVariable String testCaseId) {
|
public TestCaseWithBLOBs getTestCase(@PathVariable String testCaseId) {
|
||||||
|
checkOwnerService.checkTestCaseOwner(testCaseId);
|
||||||
return testCaseService.getTestCase(testCaseId);
|
return testCaseService.getTestCase(testCaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/project/{testCaseId}")
|
@GetMapping("/project/{testCaseId}")
|
||||||
public Project getProjectByTestCaseId(@PathVariable String testCaseId) {
|
public Project getProjectByTestCaseId(@PathVariable String testCaseId) {
|
||||||
|
checkOwnerService.checkTestCaseOwner(testCaseId);
|
||||||
return testCaseService.getProjectByTestCaseId(testCaseId);
|
return testCaseService.getProjectByTestCaseId(testCaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +108,15 @@ public class TestCaseController {
|
||||||
@PostMapping("/delete/{testCaseId}")
|
@PostMapping("/delete/{testCaseId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public int deleteTestCase(@PathVariable String testCaseId) {
|
public int deleteTestCase(@PathVariable String testCaseId) {
|
||||||
|
checkOwnerService.checkTestCaseOwner(testCaseId);
|
||||||
return testCaseService.deleteTestCase(testCaseId);
|
return testCaseService.deleteTestCase(testCaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/import/{projectId}/{userId}")
|
@PostMapping("/import/{projectId}/{userId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String projectId,@PathVariable String userId) throws NoSuchFieldException {
|
public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String projectId, @PathVariable String userId) {
|
||||||
return testCaseService.testCaseImport(file, projectId,userId);
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
|
return testCaseService.testCaseImport(file, projectId, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/export/template")
|
@GetMapping("/export/template")
|
||||||
|
@ -115,6 +124,7 @@ public class TestCaseController {
|
||||||
public void testCaseTemplateExport(HttpServletResponse response) {
|
public void testCaseTemplateExport(HttpServletResponse response) {
|
||||||
testCaseService.testCaseTemplateExport(response);
|
testCaseService.testCaseTemplateExport(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/export/xmindTemplate")
|
@GetMapping("/export/xmindTemplate")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public void xmindTemplate(HttpServletResponse response) {
|
public void xmindTemplate(HttpServletResponse response) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.track.controller;
|
||||||
|
|
||||||
import io.metersphere.base.domain.TestCaseNode;
|
import io.metersphere.base.domain.TestCaseNode;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import io.metersphere.track.dto.TestCaseNodeDTO;
|
import io.metersphere.track.dto.TestCaseNodeDTO;
|
||||||
import io.metersphere.track.request.testcase.DragNodeRequest;
|
import io.metersphere.track.request.testcase.DragNodeRequest;
|
||||||
import io.metersphere.track.request.testcase.QueryNodeRequest;
|
import io.metersphere.track.request.testcase.QueryNodeRequest;
|
||||||
|
@ -20,9 +21,12 @@ public class TestCaseNodeController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseNodeService testCaseNodeService;
|
TestCaseNodeService testCaseNodeService;
|
||||||
|
@Resource
|
||||||
|
private CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@GetMapping("/list/{projectId}")
|
@GetMapping("/list/{projectId}")
|
||||||
public List<TestCaseNodeDTO> getNodeByProjectId(@PathVariable String projectId) {
|
public List<TestCaseNodeDTO> getNodeByProjectId(@PathVariable String projectId) {
|
||||||
|
checkOwnerService.checkProjectOwner(projectId);
|
||||||
return testCaseNodeService.getNodeTreeByProjectId(projectId);
|
return testCaseNodeService.getNodeTreeByProjectId(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,11 +43,13 @@ public class TestCaseNodeController {
|
||||||
|
|
||||||
@GetMapping("/list/plan/{planId}")
|
@GetMapping("/list/plan/{planId}")
|
||||||
public List<TestCaseNodeDTO> getNodeByPlanId(@PathVariable String planId) {
|
public List<TestCaseNodeDTO> getNodeByPlanId(@PathVariable String planId) {
|
||||||
|
checkOwnerService.checkTestPlanOwner(planId);
|
||||||
return testCaseNodeService.getNodeByPlanId(planId);
|
return testCaseNodeService.getNodeByPlanId(planId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list/review/{reviewId}")
|
@GetMapping("/list/review/{reviewId}")
|
||||||
public List<TestCaseNodeDTO> getNodeByReviewId(@PathVariable String reviewId) {
|
public List<TestCaseNodeDTO> getNodeByReviewId(@PathVariable String reviewId) {
|
||||||
|
checkOwnerService.checkTestReviewOwner(reviewId);
|
||||||
return testCaseNodeService.getNodeByReviewId(reviewId);
|
return testCaseNodeService.getNodeByReviewId(reviewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import io.metersphere.track.dto.TestCaseReviewDTO;
|
import io.metersphere.track.dto.TestCaseReviewDTO;
|
||||||
import io.metersphere.track.dto.TestReviewDTOWithMetric;
|
import io.metersphere.track.dto.TestReviewDTOWithMetric;
|
||||||
import io.metersphere.track.request.testreview.ReviewRelevanceRequest;
|
import io.metersphere.track.request.testreview.ReviewRelevanceRequest;
|
||||||
|
@ -32,6 +33,8 @@ public class TestCaseReviewController {
|
||||||
TestCaseReviewService testCaseReviewService;
|
TestCaseReviewService testCaseReviewService;
|
||||||
@Resource
|
@Resource
|
||||||
TestReviewProjectService testReviewProjectService;
|
TestReviewProjectService testReviewProjectService;
|
||||||
|
@Resource
|
||||||
|
CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@PostMapping("/list/{goPage}/{pageSize}")
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
public Pager<List<TestCaseReviewDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryCaseReviewRequest request) {
|
public Pager<List<TestCaseReviewDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryCaseReviewRequest request) {
|
||||||
|
@ -71,6 +74,7 @@ public class TestCaseReviewController {
|
||||||
@GetMapping("/delete/{reviewId}")
|
@GetMapping("/delete/{reviewId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public void deleteCaseReview(@PathVariable String reviewId) {
|
public void deleteCaseReview(@PathVariable String reviewId) {
|
||||||
|
checkOwnerService.checkTestReviewOwner(reviewId);
|
||||||
testCaseReviewService.deleteCaseReview(reviewId);
|
testCaseReviewService.deleteCaseReview(reviewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,12 +107,14 @@ public class TestCaseReviewController {
|
||||||
|
|
||||||
@PostMapping("/get/{reviewId}")
|
@PostMapping("/get/{reviewId}")
|
||||||
public TestCaseReview getTestReview(@PathVariable String reviewId) {
|
public TestCaseReview getTestReview(@PathVariable String reviewId) {
|
||||||
|
checkOwnerService.checkTestReviewOwner(reviewId);
|
||||||
return testCaseReviewService.getTestReview(reviewId);
|
return testCaseReviewService.getTestReview(reviewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/edit/status/{reviewId}")
|
@PostMapping("/edit/status/{reviewId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public void editTestPlanStatus(@PathVariable String reviewId) {
|
public void editTestPlanStatus(@PathVariable String reviewId) {
|
||||||
|
checkOwnerService.checkTestReviewOwner(reviewId);
|
||||||
testCaseReviewService.editTestReviewStatus(reviewId);
|
testCaseReviewService.editTestReviewStatus(reviewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
|
import io.metersphere.service.CheckOwnerService;
|
||||||
import io.metersphere.track.dto.TestCaseReportMetricDTO;
|
import io.metersphere.track.dto.TestCaseReportMetricDTO;
|
||||||
import io.metersphere.track.dto.TestPlanDTO;
|
import io.metersphere.track.dto.TestPlanDTO;
|
||||||
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
||||||
|
@ -32,6 +33,8 @@ public class TestPlanController {
|
||||||
TestPlanService testPlanService;
|
TestPlanService testPlanService;
|
||||||
@Resource
|
@Resource
|
||||||
TestPlanProjectService testPlanProjectService;
|
TestPlanProjectService testPlanProjectService;
|
||||||
|
@Resource
|
||||||
|
CheckOwnerService checkOwnerService;
|
||||||
|
|
||||||
@PostMapping("/list/{goPage}/{pageSize}")
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
public Pager<List<TestPlanDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) {
|
public Pager<List<TestPlanDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) {
|
||||||
|
@ -70,6 +73,7 @@ public class TestPlanController {
|
||||||
|
|
||||||
@PostMapping("/get/{testPlanId}")
|
@PostMapping("/get/{testPlanId}")
|
||||||
public TestPlan getTestPlan(@PathVariable String testPlanId) {
|
public TestPlan getTestPlan(@PathVariable String testPlanId) {
|
||||||
|
checkOwnerService.checkTestPlanOwner(testPlanId);
|
||||||
return testPlanService.getTestPlan(testPlanId);
|
return testPlanService.getTestPlan(testPlanId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,12 +92,14 @@ public class TestPlanController {
|
||||||
@PostMapping("/edit/status/{planId}")
|
@PostMapping("/edit/status/{planId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public void editTestPlanStatus(@PathVariable String planId) {
|
public void editTestPlanStatus(@PathVariable String planId) {
|
||||||
|
checkOwnerService.checkTestPlanOwner(planId);
|
||||||
testPlanService.editTestPlanStatus(planId);
|
testPlanService.editTestPlanStatus(planId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete/{testPlanId}")
|
@PostMapping("/delete/{testPlanId}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public int deleteTestPlan(@PathVariable String testPlanId) {
|
public int deleteTestPlan(@PathVariable String testPlanId) {
|
||||||
|
checkOwnerService.checkTestPlanOwner(testPlanId);
|
||||||
return testPlanService.deleteTestPlan(testPlanId);
|
return testPlanService.deleteTestPlan(testPlanId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +115,7 @@ public class TestPlanController {
|
||||||
|
|
||||||
@GetMapping("/project/name/{planId}")
|
@GetMapping("/project/name/{planId}")
|
||||||
public String getProjectNameByPlanId(@PathVariable String planId) {
|
public String getProjectNameByPlanId(@PathVariable String planId) {
|
||||||
|
checkOwnerService.checkTestPlanOwner(planId);
|
||||||
return testPlanService.getProjectNameByPlanId(planId);
|
return testPlanService.getProjectNameByPlanId(planId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import lombok.Setter;
|
||||||
public class TestReviewCaseDTO extends TestCaseWithBLOBs {
|
public class TestReviewCaseDTO extends TestCaseWithBLOBs {
|
||||||
private String reviewer;
|
private String reviewer;
|
||||||
private String reviewerName;
|
private String reviewerName;
|
||||||
private String status;
|
private String reviewStatus;
|
||||||
private String results;
|
private String results;
|
||||||
private String reviewId;
|
private String reviewId;
|
||||||
private String caseId;
|
private String caseId;
|
||||||
|
|
|
@ -9,4 +9,5 @@ public class TestReviewDTOWithMetric extends TestCaseReviewDTO {
|
||||||
private Double testRate;
|
private Double testRate;
|
||||||
private Integer reviewed;
|
private Integer reviewed;
|
||||||
private Integer total;
|
private Integer total;
|
||||||
|
private Integer pass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import io.metersphere.base.mapper.ext.ExtProjectMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestCaseReviewMapper;
|
import io.metersphere.base.mapper.ext.ExtTestCaseReviewMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestReviewCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtTestReviewCaseMapper;
|
||||||
import io.metersphere.commons.constants.TestCaseReviewStatus;
|
import io.metersphere.commons.constants.TestCaseReviewStatus;
|
||||||
import io.metersphere.commons.constants.TestPlanStatus;
|
|
||||||
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
||||||
|
import io.metersphere.commons.constants.TestReviewCaseStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.user.SessionUser;
|
import io.metersphere.commons.user.SessionUser;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
@ -32,7 +32,6 @@ import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -272,15 +271,21 @@ public class TestCaseReviewService {
|
||||||
List<Project> projects = projectMapper.selectByExample(projectExample);
|
List<Project> projects = projectMapper.selectByExample(projectExample);
|
||||||
List<String> projectIds = projects.stream().map(Project::getId).collect(Collectors.toList());
|
List<String> projectIds = projects.stream().map(Project::getId).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(projectIds)) {
|
||||||
TestCaseReviewProjectExample testCaseReviewProjectExample = new TestCaseReviewProjectExample();
|
TestCaseReviewProjectExample testCaseReviewProjectExample = new TestCaseReviewProjectExample();
|
||||||
testCaseReviewProjectExample.createCriteria().andProjectIdIn(projectIds);
|
testCaseReviewProjectExample.createCriteria().andProjectIdIn(projectIds);
|
||||||
List<TestCaseReviewProject> testCaseReviewProjects = testCaseReviewProjectMapper.selectByExample(testCaseReviewProjectExample);
|
List<TestCaseReviewProject> testCaseReviewProjects = testCaseReviewProjectMapper.selectByExample(testCaseReviewProjectExample);
|
||||||
List<String> reviewIds = testCaseReviewProjects.stream().map(TestCaseReviewProject::getReviewId).collect(Collectors.toList());
|
List<String> reviewIds = testCaseReviewProjects.stream().map(TestCaseReviewProject::getReviewId).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(reviewIds)) {
|
||||||
TestCaseReviewExample testCaseReviewExample = new TestCaseReviewExample();
|
TestCaseReviewExample testCaseReviewExample = new TestCaseReviewExample();
|
||||||
testCaseReviewExample.createCriteria().andIdIn(reviewIds);
|
testCaseReviewExample.createCriteria().andIdIn(reviewIds);
|
||||||
return testCaseReviewMapper.selectByExample(testCaseReviewExample);
|
return testCaseReviewMapper.selectByExample(testCaseReviewExample);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
public void testReviewRelevance(ReviewRelevanceRequest request) {
|
public void testReviewRelevance(ReviewRelevanceRequest request) {
|
||||||
String reviewId = request.getReviewId();
|
String reviewId = request.getReviewId();
|
||||||
|
@ -340,13 +345,13 @@ public class TestCaseReviewService {
|
||||||
testCaseReview.setId(reviewId);
|
testCaseReview.setId(reviewId);
|
||||||
|
|
||||||
for (String status : statusList) {
|
for (String status : statusList) {
|
||||||
if (StringUtils.equals(status, TestPlanTestCaseStatus.Prepare.name())) {
|
if (StringUtils.equals(status, TestReviewCaseStatus.Prepare.name())) {
|
||||||
testCaseReview.setStatus(TestPlanStatus.Underway.name());
|
testCaseReview.setStatus(TestCaseReviewStatus.Underway.name());
|
||||||
testCaseReviewMapper.updateByPrimaryKeySelective(testCaseReview);
|
testCaseReviewMapper.updateByPrimaryKeySelective(testCaseReview);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
testCaseReview.setStatus(TestPlanStatus.Completed.name());
|
testCaseReview.setStatus(TestCaseReviewStatus.Completed.name());
|
||||||
SaveTestCaseReviewRequest testCaseReviewRequest = new SaveTestCaseReviewRequest();
|
SaveTestCaseReviewRequest testCaseReviewRequest = new SaveTestCaseReviewRequest();
|
||||||
TestCaseReview _testCaseReview = testCaseReviewMapper.selectByPrimaryKey(reviewId);
|
TestCaseReview _testCaseReview = testCaseReviewMapper.selectByPrimaryKey(reviewId);
|
||||||
List<String> userIds = new ArrayList<>();
|
List<String> userIds = new ArrayList<>();
|
||||||
|
@ -405,16 +410,19 @@ public class TestCaseReviewService {
|
||||||
|
|
||||||
testReview.setReviewed(0);
|
testReview.setReviewed(0);
|
||||||
testReview.setTotal(0);
|
testReview.setTotal(0);
|
||||||
|
testReview.setPass(0);
|
||||||
if (testCases != null) {
|
if (testCases != null) {
|
||||||
testReview.setTotal(testCases.size());
|
testReview.setTotal(testCases.size());
|
||||||
testCases.forEach(testCase -> {
|
testCases.forEach(testCase -> {
|
||||||
if (!StringUtils.equals(testCase.getStatus(), TestPlanTestCaseStatus.Prepare.name())
|
if (!StringUtils.equals(testCase.getReviewStatus(), TestReviewCaseStatus.Prepare.name())) {
|
||||||
&& !StringUtils.equals(testCase.getStatus(), TestPlanTestCaseStatus.Underway.name())) {
|
|
||||||
testReview.setReviewed(testReview.getReviewed() + 1);
|
testReview.setReviewed(testReview.getReviewed() + 1);
|
||||||
}
|
}
|
||||||
|
if (StringUtils.equals(testCase.getReviewStatus(), TestReviewCaseStatus.Pass.name())) {
|
||||||
|
testReview.setPass(testReview.getPass() + 1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
testReview.setTestRate(MathUtils.getPercentWithDecimal(testReview.getTotal() == 0 ? 0 : testReview.getReviewed() * 1.0 / testReview.getTotal()));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return testReviews;
|
return testReviews;
|
||||||
|
|
|
@ -10,6 +10,7 @@ import io.metersphere.base.mapper.*;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.constants.TestCaseConstants;
|
import io.metersphere.commons.constants.TestCaseConstants;
|
||||||
|
import io.metersphere.commons.constants.TestCaseReviewStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.user.SessionUser;
|
import io.metersphere.commons.user.SessionUser;
|
||||||
import io.metersphere.commons.utils.BeanUtils;
|
import io.metersphere.commons.utils.BeanUtils;
|
||||||
|
@ -40,7 +41,9 @@ import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.*;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -88,6 +91,7 @@ public class TestCaseService {
|
||||||
testCase.setCreateTime(System.currentTimeMillis());
|
testCase.setCreateTime(System.currentTimeMillis());
|
||||||
testCase.setUpdateTime(System.currentTimeMillis());
|
testCase.setUpdateTime(System.currentTimeMillis());
|
||||||
testCase.setNum(getNextNum(testCase.getProjectId()));
|
testCase.setNum(getNextNum(testCase.getProjectId()));
|
||||||
|
testCase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
||||||
testCaseMapper.insert(testCase);
|
testCaseMapper.insert(testCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +277,8 @@ public class TestCaseService {
|
||||||
.map(TestCase::getName)
|
.map(TestCase::getName)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
List<ExcelErrData<TestCaseExcelData>> errList = null;
|
List<ExcelErrData<TestCaseExcelData>> errList = null;
|
||||||
|
if (multipartFile == null)
|
||||||
|
MSException.throwException(Translator.get("upload_fail"));
|
||||||
|
|
||||||
if (multipartFile.getOriginalFilename().endsWith(".xmind")) {
|
if (multipartFile.getOriginalFilename().endsWith(".xmind")) {
|
||||||
try {
|
try {
|
||||||
|
@ -284,6 +290,11 @@ public class TestCaseService {
|
||||||
ExcelErrData excelErrData = new ExcelErrData(null, 1, Translator.get("upload_fail") + ":" + processLog);
|
ExcelErrData excelErrData = new ExcelErrData(null, 1, Translator.get("upload_fail") + ":" + processLog);
|
||||||
errList.add(excelErrData);
|
errList.add(excelErrData);
|
||||||
excelResponse.setErrList(errList);
|
excelResponse.setErrList(errList);
|
||||||
|
} else if (xmindParser.getNodePaths().isEmpty() && xmindParser.getTestCase().isEmpty()) {
|
||||||
|
excelResponse.setSuccess(false);
|
||||||
|
ExcelErrData excelErrData = new ExcelErrData(null, 1, Translator.get("upload_fail") + ":" + Translator.get("upload_content_is_null"));
|
||||||
|
errList.add(excelErrData);
|
||||||
|
excelResponse.setErrList(errList);
|
||||||
} else {
|
} else {
|
||||||
if (!xmindParser.getNodePaths().isEmpty()) {
|
if (!xmindParser.getNodePaths().isEmpty()) {
|
||||||
testCaseNodeService.createNodes(xmindParser.getNodePaths(), projectId);
|
testCaseNodeService.createNodes(xmindParser.getNodePaths(), projectId);
|
||||||
|
@ -295,7 +306,8 @@ public class TestCaseService {
|
||||||
excelResponse.setSuccess(true);
|
excelResponse.setSuccess(true);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
MSException.throwException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -339,6 +351,7 @@ public class TestCaseService {
|
||||||
testcase.setNodeId(nodePathMap.get(testcase.getNodePath()));
|
testcase.setNodeId(nodePathMap.get(testcase.getNodePath()));
|
||||||
testcase.setSort(sort.getAndIncrement());
|
testcase.setSort(sort.getAndIncrement());
|
||||||
testcase.setNum(num.decrementAndGet());
|
testcase.setNum(num.decrementAndGet());
|
||||||
|
testcase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
||||||
mapper.insert(testcase);
|
mapper.insert(testcase);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -481,7 +494,7 @@ public class TestCaseService {
|
||||||
if (t.getTestId() != null && t.getTestId().equals("other")) {
|
if (t.getTestId() != null && t.getTestId().equals("other")) {
|
||||||
data.setRemark(t.getOtherTestName());
|
data.setRemark(t.getOtherTestName());
|
||||||
} else {
|
} else {
|
||||||
data.setRemark(t.getApiName());
|
data.setRemark("[" + t.getApiName() + "]" + "\n" + t.getRemark());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (t.getMethod().equals("auto") && t.getType().equals("performance")) {
|
} else if (t.getMethod().equals("auto") && t.getType().equals("performance")) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.track.service;
|
package io.metersphere.track.service;
|
||||||
|
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
|
import io.metersphere.base.mapper.TestCaseMapper;
|
||||||
import io.metersphere.base.mapper.TestCaseReviewMapper;
|
import io.metersphere.base.mapper.TestCaseReviewMapper;
|
||||||
import io.metersphere.base.mapper.TestCaseReviewTestCaseMapper;
|
import io.metersphere.base.mapper.TestCaseReviewTestCaseMapper;
|
||||||
import io.metersphere.base.mapper.TestCaseReviewUsersMapper;
|
import io.metersphere.base.mapper.TestCaseReviewUsersMapper;
|
||||||
|
@ -38,6 +39,8 @@ public class TestReviewTestCaseService {
|
||||||
TestCaseReviewMapper testCaseReviewMapper;
|
TestCaseReviewMapper testCaseReviewMapper;
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseReviewService testCaseReviewService;
|
TestCaseReviewService testCaseReviewService;
|
||||||
|
@Resource
|
||||||
|
TestCaseMapper testCaseMapper;
|
||||||
|
|
||||||
public List<TestReviewCaseDTO> list(QueryCaseReviewRequest request) {
|
public List<TestReviewCaseDTO> list(QueryCaseReviewRequest request) {
|
||||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||||
|
@ -111,9 +114,17 @@ public class TestReviewTestCaseService {
|
||||||
MSException.throwException("此用例评审已到截止时间!");
|
MSException.throwException("此用例评审已到截止时间!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录测试用例评审状态变更
|
||||||
testCaseReviewTestCase.setStatus(testCaseReviewTestCase.getStatus());
|
testCaseReviewTestCase.setStatus(testCaseReviewTestCase.getStatus());
|
||||||
testCaseReviewTestCase.setReviewer(SessionUtils.getUser().getId());
|
testCaseReviewTestCase.setReviewer(SessionUtils.getUser().getId());
|
||||||
testCaseReviewTestCase.setUpdateTime(System.currentTimeMillis());
|
testCaseReviewTestCase.setUpdateTime(System.currentTimeMillis());
|
||||||
testCaseReviewTestCaseMapper.updateByPrimaryKeySelective(testCaseReviewTestCase);
|
testCaseReviewTestCaseMapper.updateByPrimaryKeySelective(testCaseReviewTestCase);
|
||||||
|
|
||||||
|
// 修改用例评审状态
|
||||||
|
String caseId = testCaseReviewTestCase.getCaseId();
|
||||||
|
TestCaseWithBLOBs testCase = new TestCaseWithBLOBs();
|
||||||
|
testCase.setId(caseId);
|
||||||
|
testCase.setReviewStatus(testCaseReviewTestCase.getStatus());
|
||||||
|
testCaseMapper.updateByPrimaryKeySelective(testCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,10 @@ public class XmindCaseParser {
|
||||||
private StringBuffer process; // 过程校验记录
|
private StringBuffer process; // 过程校验记录
|
||||||
// 已存在用例名称
|
// 已存在用例名称
|
||||||
private Set<String> testCaseNames;
|
private Set<String> testCaseNames;
|
||||||
|
|
||||||
// 转换后的案例信息
|
// 转换后的案例信息
|
||||||
private List<TestCaseWithBLOBs> testCases;
|
private List<TestCaseWithBLOBs> testCases;
|
||||||
|
|
||||||
// 案例详情重写了hashCode方法去重用
|
// 案例详情重写了hashCode方法去重用
|
||||||
private List<TestCaseExcelData> compartDatas;
|
private List<TestCaseExcelData> compartDatas;
|
||||||
|
|
||||||
// 记录没有用例的目录
|
// 记录没有用例的目录
|
||||||
private List<String> nodePaths;
|
private List<String> nodePaths;
|
||||||
|
|
||||||
|
@ -54,7 +51,10 @@ public class XmindCaseParser {
|
||||||
nodePaths = new ArrayList<>();
|
nodePaths = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这里清理是为了 加快jvm 回收
|
private static final String TC_REGEX = "(?:tc:|tc:|tc)";
|
||||||
|
private static final String PC_REGEX = "(?:pc:|pc:|pc)";
|
||||||
|
private static final String RC_REGEX = "(?:rc:|rc:|rc)";
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
compartDatas.clear();
|
compartDatas.clear();
|
||||||
testCases.clear();
|
testCases.clear();
|
||||||
|
@ -90,9 +90,9 @@ public class XmindCaseParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归处理案例数据
|
// 递归处理案例数据
|
||||||
private void recursion(StringBuffer processBuffer, Attached parent, int level, List<Attached> attacheds) {
|
private void recursion(Attached parent, int level, List<Attached> attacheds) {
|
||||||
for (Attached item : attacheds) {
|
for (Attached item : attacheds) {
|
||||||
if (isAvailable(item.getTitle(), "(?:tc:|tc:|tc)")) { // 用例
|
if (isAvailable(item.getTitle(), TC_REGEX)) { // 用例
|
||||||
item.setParent(parent);
|
item.setParent(parent);
|
||||||
this.newTestCase(item.getTitle(), parent.getPath(), item.getChildren() != null ? item.getChildren().getAttached() : null);
|
this.newTestCase(item.getTitle(), parent.getPath(), item.getChildren() != null ? item.getChildren().getAttached() : null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,7 +100,7 @@ public class XmindCaseParser {
|
||||||
item.setPath(nodePath);
|
item.setPath(nodePath);
|
||||||
item.setParent(parent);
|
item.setParent(parent);
|
||||||
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
|
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
|
||||||
recursion(processBuffer, item, level + 1, item.getChildren().getAttached());
|
recursion(item, level + 1, item.getChildren().getAttached());
|
||||||
} else {
|
} else {
|
||||||
if (!nodePath.startsWith("/")) {
|
if (!nodePath.startsWith("/")) {
|
||||||
nodePath = "/" + nodePath;
|
nodePath = "/" + nodePath;
|
||||||
|
@ -163,7 +163,7 @@ public class XmindCaseParser {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 用例名称
|
// 用例名称
|
||||||
testCase.setName(this.replace(tcArr[1], "tc:|tc:|tc"));
|
testCase.setName(this.replace(tcArr[1], TC_REGEX));
|
||||||
|
|
||||||
if (!nodePath.startsWith("/")) {
|
if (!nodePath.startsWith("/")) {
|
||||||
nodePath = "/" + nodePath;
|
nodePath = "/" + nodePath;
|
||||||
|
@ -188,10 +188,10 @@ public class XmindCaseParser {
|
||||||
List<Attached> steps = new LinkedList<>();
|
List<Attached> steps = new LinkedList<>();
|
||||||
if (attacheds != null && !attacheds.isEmpty()) {
|
if (attacheds != null && !attacheds.isEmpty()) {
|
||||||
attacheds.forEach(item -> {
|
attacheds.forEach(item -> {
|
||||||
if (isAvailable(item.getTitle(), "(?:pc:|pc:)")) {
|
if (isAvailable(item.getTitle(), PC_REGEX)) {
|
||||||
testCase.setPrerequisite(replace(item.getTitle(), "(?:pc:|pc:)"));
|
testCase.setPrerequisite(replace(item.getTitle(), PC_REGEX));
|
||||||
} else if (isAvailable(item.getTitle(), "(?:rc:|rc:)")) {
|
} else if (isAvailable(item.getTitle(), RC_REGEX)) {
|
||||||
testCase.setRemark(replace(item.getTitle(), "(?:rc:|rc:)"));
|
testCase.setRemark(replace(item.getTitle(), RC_REGEX));
|
||||||
} else {
|
} else {
|
||||||
steps.add(item);
|
steps.add(item);
|
||||||
}
|
}
|
||||||
|
@ -267,28 +267,37 @@ public class XmindCaseParser {
|
||||||
|
|
||||||
// 导入思维导图处理
|
// 导入思维导图处理
|
||||||
public String parse(MultipartFile multipartFile) {
|
public String parse(MultipartFile multipartFile) {
|
||||||
StringBuffer processBuffer = new StringBuffer();
|
|
||||||
try {
|
try {
|
||||||
// 获取思维导图内容
|
// 获取思维导图内容
|
||||||
JsonRootBean root = XmindParser.parseObject(multipartFile);
|
List<JsonRootBean> roots = XmindParser.parseObject(multipartFile);
|
||||||
|
for (JsonRootBean root : roots) {
|
||||||
if (root != null && root.getRootTopic() != null && root.getRootTopic().getChildren() != null) {
|
if (root != null && root.getRootTopic() != null && root.getRootTopic().getChildren() != null) {
|
||||||
// 判断是模块还是用例
|
// 判断是模块还是用例
|
||||||
for (Attached item : root.getRootTopic().getChildren().getAttached()) {
|
for (Attached item : root.getRootTopic().getChildren().getAttached()) {
|
||||||
if (isAvailable(item.getTitle(), "(?:tc:|tc:|tc)")) { // 用例
|
if (isAvailable(item.getTitle(), TC_REGEX)) { // 用例
|
||||||
return replace(item.getTitle(), "(?:tc:|tc:|tc)") + ":" + Translator.get("test_case_create_module_fail");
|
return replace(item.getTitle(), TC_REGEX) + ":" + Translator.get("test_case_create_module_fail");
|
||||||
} else {
|
} else {
|
||||||
item.setPath(item.getTitle());
|
String nodePath = item.getTitle();
|
||||||
|
item.setPath(nodePath);
|
||||||
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
|
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
|
||||||
recursion(processBuffer, item, 1, item.getChildren().getAttached());
|
recursion(item, 1, item.getChildren().getAttached());
|
||||||
|
} else {
|
||||||
|
if (!nodePath.startsWith("/")) {
|
||||||
|
nodePath = "/" + nodePath;
|
||||||
|
}
|
||||||
|
if (nodePath.endsWith("/")) {
|
||||||
|
nodePath = nodePath.substring(0, nodePath.length() - 1);
|
||||||
|
}
|
||||||
|
nodePaths.add(nodePath); // 没有用例的路径
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.validate();
|
}
|
||||||
|
|
||||||
|
this.validate(); //检查目录合规性
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
processBuffer.append(Translator.get("incorrect_format"));
|
return ex.getMessage();
|
||||||
LogUtil.error(ex.getMessage());
|
|
||||||
return "xmind "+Translator.get("incorrect_format");
|
|
||||||
}
|
}
|
||||||
return process.toString();
|
return process.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.json.JSONObject;
|
||||||
import org.json.XML;
|
import org.json.XML;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class XmindLegacy {
|
public class XmindLegacy {
|
||||||
|
@ -18,7 +19,7 @@ public class XmindLegacy {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws DocumentException
|
* @throws DocumentException
|
||||||
*/
|
*/
|
||||||
public static String getContent(String xmlContent, String xmlComments) throws IOException, DocumentException {
|
public static List<String> getContent(String xmlContent, String xmlComments) throws IOException, DocumentException {
|
||||||
// 删除content.xml里面不能识别的字符串
|
// 删除content.xml里面不能识别的字符串
|
||||||
xmlContent = xmlContent.replace("xmlns=\"urn:xmind:xmap:xmlns:content:2.0\"", "");
|
xmlContent = xmlContent.replace("xmlns=\"urn:xmind:xmap:xmlns:content:2.0\"", "");
|
||||||
xmlContent = xmlContent.replace("xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"", "");
|
xmlContent = xmlContent.replace("xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"", "");
|
||||||
|
@ -28,6 +29,8 @@ public class XmindLegacy {
|
||||||
|
|
||||||
// 去除title中svg:width属性
|
// 去除title中svg:width属性
|
||||||
xmlContent = xmlContent.replaceAll("<title svg:width=\"[0-9]*\">", "<title>");
|
xmlContent = xmlContent.replaceAll("<title svg:width=\"[0-9]*\">", "<title>");
|
||||||
|
//去除自由风格主题
|
||||||
|
xmlContent = xmlContent.replaceAll("<topics type=\"detached\">", "");
|
||||||
|
|
||||||
Document document = DocumentHelper.parseText(xmlContent);// 读取XML文件,获得document对象
|
Document document = DocumentHelper.parseText(xmlContent);// 读取XML文件,获得document对象
|
||||||
Element root = document.getRootElement();
|
Element root = document.getRootElement();
|
||||||
|
@ -58,22 +61,27 @@ public class XmindLegacy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第一个topic转换为json中的rootTopic
|
// 第一个topic转换为json中的rootTopic
|
||||||
Node rootTopic = root.selectSingleNode("/xmap-content/sheet/topic");
|
List<Node> rootTopics = root.selectNodes("/xmap-content/sheet/topic");
|
||||||
|
for (Node rootTopic : rootTopics) {
|
||||||
rootTopic.setName("rootTopic");
|
rootTopic.setName("rootTopic");
|
||||||
|
|
||||||
// 将xml中topic节点转换为attached节点
|
// 将xml中topic节点转换为attached节点
|
||||||
List<Node> topicList = rootTopic.selectNodes("//topic");
|
List<Node> topicList = rootTopic.selectNodes("//topic");
|
||||||
|
|
||||||
for (Node node : topicList) {
|
for (Node node : topicList) {
|
||||||
node.setName("attached");
|
node.setName("attached");
|
||||||
}
|
}
|
||||||
// 选取第一个sheet
|
|
||||||
Element sheet = root.elements("sheet").get(0);
|
}
|
||||||
|
|
||||||
|
List<String> sheets = new ArrayList<>();
|
||||||
|
for (Element sheet : root.elements("sheet")) {
|
||||||
String res = sheet.asXML();
|
String res = sheet.asXML();
|
||||||
// 将xml转为json
|
// 将xml转为json
|
||||||
JSONObject xmlJSONObj = XML.toJSONObject(res);
|
JSONObject xmlJSONObj = XML.toJSONObject(res);
|
||||||
JSONObject jsonObject = xmlJSONObj.getJSONObject("sheet");
|
JSONObject jsonObject = xmlJSONObj.getJSONObject("sheet");
|
||||||
|
sheets.add(jsonObject.toString(4));
|
||||||
|
}
|
||||||
// 设置缩进
|
// 设置缩进
|
||||||
return jsonObject.toString(4);
|
return sheets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,61 +34,68 @@ public class XmindParser {
|
||||||
* @throws ArchiveException
|
* @throws ArchiveException
|
||||||
* @throws DocumentException
|
* @throws DocumentException
|
||||||
*/
|
*/
|
||||||
public static String parseJson(MultipartFile multipartFile) throws IOException, ArchiveException, DocumentException {
|
public static List<String> parseJson(MultipartFile multipartFile) throws IOException, ArchiveException, DocumentException {
|
||||||
|
|
||||||
File file = FileUtil.multipartFileToFile(multipartFile);
|
File file = FileUtil.multipartFileToFile(multipartFile);
|
||||||
|
List<String> contents = null;
|
||||||
|
String res = null;
|
||||||
if (file == null || !file.exists())
|
if (file == null || !file.exists())
|
||||||
MSException.throwException(Translator.get("incorrect_format"));
|
MSException.throwException(Translator.get("incorrect_format"));
|
||||||
|
try {
|
||||||
String res = ZipUtils.extract(file);
|
res = ZipUtils.extract(file);
|
||||||
String content = null;
|
|
||||||
if (isXmindZen(res, file)) {
|
if (isXmindZen(res, file)) {
|
||||||
content = getXmindZenContent(file, res);
|
contents = (getXmindZenContent(file, res));
|
||||||
} else {
|
} else {
|
||||||
content = getXmindLegacyContent(file, res);
|
contents = getXmindLegacyContent(file, res);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
MSException.throwException(e.getMessage());
|
||||||
|
} finally {
|
||||||
// 删除生成的文件夹
|
// 删除生成的文件夹
|
||||||
|
if (res != null) {
|
||||||
File dir = new File(res);
|
File dir = new File(res);
|
||||||
FileUtil.deleteDir(dir);
|
FileUtil.deleteDir(dir);
|
||||||
JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
|
}
|
||||||
// 删除零时文件
|
// 删除零时文件
|
||||||
if (file != null)
|
if (file != null)
|
||||||
file.delete();
|
file.delete();
|
||||||
String json = (JSON.toJSONString(jsonRootBean, false));
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(content) || content.split("(?:tc:|tc:|TC:|TC:|tc|TC)").length == 1) {
|
|
||||||
MSException.throwException(Translator.get("import_xmind_not_found"));
|
|
||||||
}
|
}
|
||||||
if (!StringUtils.isEmpty(content) && content.split("(?:tc:|tc:|TC:|TC:|tc|TC)").length > 500) {
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<JsonRootBean> parseObject(MultipartFile multipartFile) throws DocumentException, ArchiveException, IOException {
|
||||||
|
List<String> contents = parseJson(multipartFile);
|
||||||
|
int caseCount = 0;
|
||||||
|
List<JsonRootBean> jsonRootBeans = new ArrayList<>();
|
||||||
|
if (contents != null) {
|
||||||
|
for (String content : contents) {
|
||||||
|
caseCount += content.split("(?:tc:|tc:|TC:|TC:|tc|TC)").length;
|
||||||
|
JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
|
||||||
|
jsonRootBeans.add(jsonRootBean);
|
||||||
|
}
|
||||||
|
if (caseCount > 500) {
|
||||||
MSException.throwException(Translator.get("import_xmind_count_error"));
|
MSException.throwException(Translator.get("import_xmind_count_error"));
|
||||||
}
|
}
|
||||||
return json;
|
|
||||||
}
|
}
|
||||||
|
return jsonRootBeans;
|
||||||
|
|
||||||
public static JsonRootBean parseObject(MultipartFile multipartFile) throws DocumentException, ArchiveException, IOException {
|
|
||||||
String content = parseJson(multipartFile);
|
|
||||||
JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
|
|
||||||
return jsonRootBean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getXmindZenContent(File file, String extractFileDir)
|
public static List<String> getXmindZenContent(File file, String extractFileDir)
|
||||||
throws IOException, ArchiveException {
|
throws IOException, ArchiveException {
|
||||||
List<String> keys = new ArrayList<>();
|
List<String> keys = new ArrayList<>();
|
||||||
keys.add(xmindZenJson);
|
keys.add(xmindZenJson);
|
||||||
Map<String, String> map = ZipUtils.getContents(keys, file, extractFileDir);
|
Map<String, String> map = ZipUtils.getContents(keys, file, extractFileDir);
|
||||||
String content = map.get(xmindZenJson);
|
String content = map.get(xmindZenJson);
|
||||||
content = XmindZen.getContent(content);
|
return XmindZen.getContent(content);
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getXmindLegacyContent(File file, String extractFileDir)
|
public static List<String> getXmindLegacyContent(File file, String extractFileDir)
|
||||||
throws IOException, ArchiveException, DocumentException {
|
throws IOException, ArchiveException, DocumentException {
|
||||||
List<String> keys = new ArrayList<>();
|
List<String> keys = new ArrayList<>();
|
||||||
keys.add(xmindLegacyContent);
|
keys.add(xmindLegacyContent);
|
||||||
|
@ -97,7 +104,7 @@ public class XmindParser {
|
||||||
|
|
||||||
String contentXml = map.get(xmindLegacyContent);
|
String contentXml = map.get(xmindLegacyContent);
|
||||||
String commentsXml = map.get(xmindLegacyComments);
|
String commentsXml = map.get(xmindLegacyComments);
|
||||||
String xmlContent = XmindLegacy.getContent(contentXml, commentsXml);
|
List<String> xmlContent = XmindLegacy.getContent(contentXml, commentsXml);
|
||||||
|
|
||||||
return xmlContent;
|
return xmlContent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import com.alibaba.fastjson.JSONObject;
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class XmindZen {
|
public class XmindZen {
|
||||||
|
|
||||||
|
@ -14,13 +16,18 @@ public class XmindZen {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws DocumentException
|
* @throws DocumentException
|
||||||
*/
|
*/
|
||||||
public static String getContent(String jsonContent) {
|
public static List<String> getContent(String jsonContent) {
|
||||||
JSONObject jsonObject = JSONArray.parseArray(jsonContent).getJSONObject(0);
|
JSONArray jsonArray = JSONArray.parseArray(jsonContent);//.getJSONObject(0);
|
||||||
|
List<String> contents = new ArrayList<>();
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
|
||||||
JSONObject rootTopic = jsonObject.getJSONObject("rootTopic");
|
JSONObject rootTopic = jsonObject.getJSONObject("rootTopic");
|
||||||
transferNotes(rootTopic);
|
transferNotes(rootTopic);
|
||||||
JSONObject children = rootTopic.getJSONObject("children");
|
JSONObject children = rootTopic.getJSONObject("children");
|
||||||
recursionChildren(children);
|
recursionChildren(children);
|
||||||
return jsonObject.toString();
|
contents.add(jsonObject.toString());
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c2dacf960cdb1ed35664bdd3432120b1203b73d8
|
Subproject commit cf6b06526324326a563d933e07118fac014a63b4
|
|
@ -0,0 +1,3 @@
|
||||||
|
alter table test_case add review_status varchar(25) null;
|
||||||
|
|
||||||
|
update test_case set review_status = 'Prepare' where review_status is null;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE test_case
|
||||||
|
MODIFY maintainer varchar(50) NOT NULL COMMENT 'Test case maintainer';
|
|
@ -158,3 +158,10 @@ license_valid_license_error=Authorization authentication failed
|
||||||
timing_task_result_notification=Timing task result notification
|
timing_task_result_notification=Timing task result notification
|
||||||
test_review_task_notice=Test review task notice
|
test_review_task_notice=Test review task notice
|
||||||
test_track.length_less_than=The title is too long, the length must be less than
|
test_track.length_less_than=The title is too long, the length must be less than
|
||||||
|
# check owner
|
||||||
|
check_owner_project=The current user does not have permission to operate this project
|
||||||
|
check_owner_test=The current user does not have permission to operate this test
|
||||||
|
check_owner_case=The current user does not have permission to operate this use case
|
||||||
|
check_owner_plan=The current user does not have permission to operate this plan
|
||||||
|
check_owner_review=The current user does not have permission to operate this review
|
||||||
|
upload_content_is_null=Imported content is empty
|
|
@ -158,4 +158,10 @@ import_xmind_not_found=未找到测试用例
|
||||||
timing_task_result_notification=定时任务结果通知
|
timing_task_result_notification=定时任务结果通知
|
||||||
test_review_task_notice=测试评审任务通知
|
test_review_task_notice=测试评审任务通知
|
||||||
test_track.length_less_than=标题过长,字数必须小于
|
test_track.length_less_than=标题过长,字数必须小于
|
||||||
|
# check owner
|
||||||
|
check_owner_project=当前用户没有操作此项目的权限
|
||||||
|
check_owner_test=当前用户没有操作此测试的权限
|
||||||
|
check_owner_case=当前用户没有操作此用例的权限
|
||||||
|
check_owner_plan=当前用户没有操作此计划的权限
|
||||||
|
check_owner_review=当前用户没有操作此评审的权限
|
||||||
|
upload_content_is_null=导入内容为空
|
|
@ -159,3 +159,10 @@ import_xmind_not_found=未找到测试用例
|
||||||
timing_task_result_notification=定時任務結果通知
|
timing_task_result_notification=定時任務結果通知
|
||||||
test_review_task_notice=測試評審任務通知
|
test_review_task_notice=測試評審任務通知
|
||||||
test_track.length_less_than=標題過長,字數必須小於
|
test_track.length_less_than=標題過長,字數必須小於
|
||||||
|
# check owner
|
||||||
|
check_owner_project=當前用戶沒有操作此項目的權限
|
||||||
|
check_owner_test=當前用戶沒有操作此測試的權限
|
||||||
|
check_owner_case=當前用戶沒有操作此用例的權限
|
||||||
|
check_owner_plan=當前用戶沒有操作此計劃的權限
|
||||||
|
check_owner_review=當前用戶沒有操作此評審的權限
|
||||||
|
upload_content_is_null=導入內容為空
|
|
@ -32,7 +32,8 @@
|
||||||
"js-base64": "^3.4.4",
|
"js-base64": "^3.4.4",
|
||||||
"json-bigint": "^1.0.0",
|
"json-bigint": "^1.0.0",
|
||||||
"html2canvas": "^1.0.0-rc.7",
|
"html2canvas": "^1.0.0-rc.7",
|
||||||
"jspdf": "^2.1.1"
|
"jspdf": "^2.1.1",
|
||||||
|
"yan-progress": "^1.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^4.1.0",
|
"@vue/cli-plugin-babel": "^4.1.0",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="menu-bar">
|
<div id="menu-bar" v-if="isRouterAlive">
|
||||||
<el-row type="flex">
|
<el-row type="flex">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
{{ $t("i18n.home") }}
|
{{ $t("i18n.home") }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|
||||||
<el-submenu v-permission="['test_manager','test_user','test_viewer']" index="3">
|
<el-submenu :class="{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
<ms-recent-list ref="projectRecent" :options="projectRecent"/>
|
<ms-recent-list ref="projectRecent" :options="projectRecent"/>
|
||||||
<el-divider class="menu-divider"/>
|
<el-divider class="menu-divider"/>
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
<ms-recent-list ref="testRecent" :options="testRecent"/>
|
<ms-recent-list ref="testRecent" :options="testRecent"/>
|
||||||
<el-divider class="menu-divider"/>
|
<el-divider class="menu-divider"/>
|
||||||
<ms-show-all :index="'/api/test/list/all'"/>
|
<ms-show-all :index="'/api/test/list/all'"/>
|
||||||
|
<el-menu-item :index="apiTestProjectPath" class="blank_item"></el-menu-item>
|
||||||
<ms-create-button v-permission="['test_manager','test_user']" :index="'/api/test/create'"
|
<ms-create-button v-permission="['test_manager','test_user']" :index="'/api/test/create'"
|
||||||
:title="$t('load_test.create')"/>
|
:title="$t('load_test.create')"/>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
@ -84,7 +85,15 @@ export default {
|
||||||
index: function (item) {
|
index: function (item) {
|
||||||
return '/api/report/view/' + item.id;
|
return '/api/report/view/' + item.id;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
isProjectActivation: true,
|
||||||
|
isRouterAlive: true,
|
||||||
|
apiTestProjectPath: '',
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$route'(to) {
|
||||||
|
this.init();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -98,7 +107,25 @@ export default {
|
||||||
this.$refs.testRecent.recent();
|
this.$refs.testRecent.recent();
|
||||||
this.$refs.reportRecent.recent();
|
this.$refs.reportRecent.recent();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
reload() {
|
||||||
|
this.isRouterAlive = false;
|
||||||
|
this.$nextTick(function () {
|
||||||
|
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();
|
||||||
|
@ -108,12 +135,20 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#menu-bar {
|
#menu-bar {
|
||||||
border-bottom: 1px solid #E6E6E6;
|
border-bottom: 1px solid #E6E6E6;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-divider {
|
.menu-divider {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blank_item {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deactivation >>> .el-submenu__title {
|
||||||
|
border-bottom: white !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<span class="title">{{$t('api_report.title')}}</span>
|
<span class="title">{{$t('api_report.title')}}</span>
|
||||||
</template>
|
</template>
|
||||||
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link">
|
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link" height="300px">
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column width="250" :label="$t('commons.create_time')">
|
<el-table-column width="250" :label="$t('commons.create_time')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<span class="title">{{$t('commons.test')}}</span>
|
<span class="title">{{$t('commons.test')}}</span>
|
||||||
</template>
|
</template>
|
||||||
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link">
|
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link" height="300px">
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column prop="projectName" :label="$t('load_test.project_name')" width="150" show-overflow-tooltip/>
|
<el-table-column prop="projectName" :label="$t('load_test.project_name')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column width="250" :label="$t('commons.create_time')">
|
<el-table-column width="250" :label="$t('commons.create_time')">
|
||||||
|
|
|
@ -69,7 +69,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
console.log(this.response.headers);
|
|
||||||
if (!this.response.headers) {
|
if (!this.response.headers) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,18 +70,18 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsApiScenarioConfig from "./components/ApiScenarioConfig";
|
import MsApiScenarioConfig from "./components/ApiScenarioConfig";
|
||||||
import {Scenario, Test} from "./model/ScenarioModel"
|
import {Scenario, Test} from "./model/ScenarioModel"
|
||||||
import MsApiReportStatus from "../report/ApiReportStatus";
|
import MsApiReportStatus from "../report/ApiReportStatus";
|
||||||
import MsApiReportDialog from "./ApiReportDialog";
|
import MsApiReportDialog from "./ApiReportDialog";
|
||||||
import {checkoutTestManagerOrTestUser, downloadFile, getUUID} from "@/common/js/utils";
|
import {checkoutTestManagerOrTestUser, downloadFile, getUUID} from "@/common/js/utils";
|
||||||
import MsScheduleConfig from "../../common/components/MsScheduleConfig";
|
import MsScheduleConfig from "../../common/components/MsScheduleConfig";
|
||||||
import ApiImport from "./components/import/ApiImport";
|
import ApiImport from "./components/import/ApiImport";
|
||||||
import {ApiEvent, LIST_CHANGE} from "@/business/components/common/head/ListEvent";
|
import {ApiEvent, LIST_CHANGE} from "@/business/components/common/head/ListEvent";
|
||||||
import MsContainer from "@/business/components/common/components/MsContainer";
|
import MsContainer from "@/business/components/common/components/MsContainer";
|
||||||
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
|
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiTestConfig",
|
name: "MsApiTestConfig",
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
@ -392,26 +392,26 @@ export default {
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
document.removeEventListener('keydown', this.handleEvent);
|
document.removeEventListener('keydown', this.handleEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.test-container {
|
.test-container {
|
||||||
height: calc(100vh - 155px);
|
height: calc(100vh - 155px);
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-name {
|
.test-name {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-project {
|
.test-project {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-container .more {
|
.test-container .more {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.items.length === 0) {
|
if (this.items.length === 0 || this.items[this.items.length - 1].name) {
|
||||||
this.items.push(new KeyValue({enable: true}));
|
this.items.push(new KeyValue({enable: true}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,8 @@ export default {
|
||||||
clone(row) {
|
clone(row) {
|
||||||
let scenarios = [];
|
let scenarios = [];
|
||||||
row.selected.forEach(options => {
|
row.selected.forEach(options => {
|
||||||
|
// 去掉ID,创建新的ID
|
||||||
|
options.id = undefined;
|
||||||
scenarios.push(new Scenario(options));
|
scenarios.push(new Scenario(options));
|
||||||
})
|
})
|
||||||
this.$emit('select', scenarios);
|
this.$emit('select', scenarios);
|
||||||
|
|
|
@ -168,7 +168,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.parameters.length === 0) {
|
if (this.parameters.length === 0 || this.parameters[this.parameters.length - 1].name) {
|
||||||
this.parameters.push(new KeyValue( {type: 'text', enable: true, uuid: this.uuid(), contentType: 'text/plain'}));
|
this.parameters.push(new KeyValue( {type: 'text', enable: true, uuid: this.uuid(), contentType: 'text/plain'}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="useEnvironment || selectedPlatformValue == 'Swagger2'" :label="$t('api_test.environment.environment_config')" prop="environmentId">
|
<el-form-item v-if="useEnvironment || selectedPlatformValue == 'Swagger2'" :label="$t('api_test.environment.environment_config')" prop="environmentId">
|
||||||
<el-select v-if="showEnvironmentSelect" size="small" v-model="formData.environmentId" class="environment-select" clearable>
|
<el-select v-if="showEnvironmentSelect" size="small" v-model="formData.environmentId" class="environment-select" clearable>
|
||||||
<el-option v-for="(environment, index) in environments" :key="index" :label="environment.name + ': ' + environment.protocol + '://' + environment.socket" :value="environment.id"/>
|
<el-option v-for="(environment, index) in environments" :key="index" :label="environment.name" :value="environment.id"/>
|
||||||
<el-button class="environment-button" size="mini" type="primary" @click="openEnvironmentConfig">{{$t('api_test.environment.environment_config')}}</el-button>
|
<el-button class="environment-button" size="mini" type="primary" @click="openEnvironmentConfig">{{$t('api_test.environment.environment_config')}}</el-button>
|
||||||
<template v-slot:empty>
|
<template v-slot:empty>
|
||||||
<div class="empty-environment">
|
<div class="empty-environment">
|
||||||
|
@ -203,6 +203,15 @@
|
||||||
if (this.formData.projectId) {
|
if (this.formData.projectId) {
|
||||||
this.$get('/api/environment/list/' + this.formData.projectId, response => {
|
this.$get('/api/environment/list/' + this.formData.projectId, response => {
|
||||||
this.environments = response.data;
|
this.environments = response.data;
|
||||||
|
let hasEnvironmentId = false;
|
||||||
|
this.environments.forEach(env => {
|
||||||
|
if (env.id === this.formData.environmentId) {
|
||||||
|
hasEnvironmentId = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!hasEnvironmentId) {
|
||||||
|
this.formData.environmentId = '';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.environments = [];
|
this.environments = [];
|
||||||
|
|
|
@ -1043,11 +1043,8 @@ class JMXGenerator {
|
||||||
this.addScenarioHeaders(threadGroup, scenario);
|
this.addScenarioHeaders(threadGroup, scenario);
|
||||||
|
|
||||||
this.addScenarioCookieManager(threadGroup, scenario);
|
this.addScenarioCookieManager(threadGroup, scenario);
|
||||||
// 放在计划或线程组中,不建议放具体某个请求中
|
|
||||||
this.addDNSCacheManager(threadGroup, scenario);
|
|
||||||
|
|
||||||
this.addJDBCDataSources(threadGroup, scenario);
|
this.addJDBCDataSources(threadGroup, scenario);
|
||||||
|
|
||||||
scenario.requests.forEach(request => {
|
scenario.requests.forEach(request => {
|
||||||
if (request.enable) {
|
if (request.enable) {
|
||||||
if (!request.isValid()) return;
|
if (!request.isValid()) return;
|
||||||
|
@ -1065,6 +1062,8 @@ class JMXGenerator {
|
||||||
sampler = new JDBCSampler(request.name || "", request);
|
sampler = new JDBCSampler(request.name || "", request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.addDNSCacheManager(sampler, scenario.environment, request.useEnvironment);
|
||||||
|
|
||||||
this.addRequestExtractor(sampler, request);
|
this.addRequestExtractor(sampler, request);
|
||||||
|
|
||||||
this.addRequestAssertion(sampler, request);
|
this.addRequestAssertion(sampler, request);
|
||||||
|
@ -1126,28 +1125,26 @@ class JMXGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addDNSCacheManager(threadGroup, scenario) {
|
addDNSCacheManager(httpSamplerProxy, environment, useEnv) {
|
||||||
if (scenario.requests.length < 1) {
|
if (environment && useEnv === true) {
|
||||||
return
|
let commonConfig = environment.config.commonConfig;
|
||||||
}
|
|
||||||
let request = scenario.requests[0];
|
|
||||||
if (request.environment) {
|
|
||||||
let commonConfig = request.environment.config.commonConfig;
|
|
||||||
let hosts = commonConfig.hosts;
|
let hosts = commonConfig.hosts;
|
||||||
if (commonConfig.enableHost && hosts.length > 0) {
|
if (commonConfig.enableHost && hosts.length > 0) {
|
||||||
let name = request.name + " DNSCacheManager";
|
let name = " DNSCacheManager";
|
||||||
// 强化判断,如果未匹配到合适的host则不开启DNSCache
|
// 强化判断,如果未匹配到合适的host则不开启DNSCache
|
||||||
let domain = request.environment.config.httpConfig.domain;
|
let domain = environment.config.httpConfig.domain;
|
||||||
let validHosts = [];
|
let validHosts = [];
|
||||||
hosts.forEach(item => {
|
hosts.forEach(item => {
|
||||||
|
if (item.domain != undefined && domain != undefined) {
|
||||||
let d = item.domain.trim().replace("http://", "").replace("https://", "");
|
let d = item.domain.trim().replace("http://", "").replace("https://", "");
|
||||||
if (item && d === domain.trim()) {
|
if (d === domain.trim()) {
|
||||||
item.domain = d; // 域名去掉协议
|
item.domain = d; // 域名去掉协议
|
||||||
validHosts.push(item);
|
validHosts.push(item);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (validHosts.length > 0) {
|
if (validHosts.length > 0) {
|
||||||
threadGroup.put(new DNSCacheManager(name, validHosts));
|
httpSamplerProxy.put(new DNSCacheManager(name, validHosts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1222,21 +1219,22 @@ class JMXGenerator {
|
||||||
if (request.controller.isValid() && request.controller.enable) {
|
if (request.controller.isValid() && request.controller.enable) {
|
||||||
if (request.controller instanceof IfController) {
|
if (request.controller instanceof IfController) {
|
||||||
let name = request.controller.label();
|
let name = request.controller.label();
|
||||||
let variable = request.controller.variable;
|
let variable = "\"" + request.controller.variable + "\"";
|
||||||
let operator = request.controller.operator;
|
let operator = request.controller.operator;
|
||||||
let value = request.controller.value;
|
let value = "\"" + request.controller.value + "\"";
|
||||||
|
|
||||||
if (operator === "=~" || operator === "!~") {
|
if (operator === "=~" || operator === "!~") {
|
||||||
value = "\".*" + value + ".*\"";
|
value = "\".*" + request.controller.value + ".*\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operator === "is empty") {
|
if (operator === "is empty") {
|
||||||
variable = "empty(\"" + variable + "\")";
|
variable = "empty(" + variable + ")";
|
||||||
operator = "";
|
operator = "";
|
||||||
value = "";
|
value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operator === "is not empty") {
|
if (operator === "is not empty") {
|
||||||
variable = "!empty(\"" + variable + "\")";
|
variable = "!empty(" + variable + ")";
|
||||||
operator = "";
|
operator = "";
|
||||||
value = "";
|
value = "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,13 @@ router.beforeEach((to, from, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//重复点击导航路由报错
|
||||||
|
const routerPush = VueRouter.prototype.push;
|
||||||
|
VueRouter.prototype.push = function push(location) {
|
||||||
|
return routerPush.call(this, location).catch(error => error)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 登入后跳转至原路径
|
// 登入后跳转至原路径
|
||||||
function redirectLoginPath(originPath) {
|
function redirectLoginPath(originPath) {
|
||||||
let redirectUrl = sessionStorage.getItem('redirectUrl');
|
let redirectUrl = sessionStorage.getItem('redirectUrl');
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<span class="title">{{$t('api_report.title')}}</span>
|
<span class="title">{{$t('api_report.title')}}</span>
|
||||||
</template>
|
</template>
|
||||||
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link">
|
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link" height="300px">
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column width="250" :label="$t('commons.create_time')">
|
<el-table-column width="250" :label="$t('commons.create_time')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<span class="title">{{$t('commons.test')}}</span>
|
<span class="title">{{$t('commons.test')}}</span>
|
||||||
</template>
|
</template>
|
||||||
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link">
|
<el-table border :data="tableData" class="adjust-table table-content" @row-click="link" height="300px">
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
<el-table-column prop="name" :label="$t('commons.name')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column prop="projectName" :label="$t('load_test.project_name')" width="150" show-overflow-tooltip/>
|
<el-table-column prop="projectName" :label="$t('load_test.project_name')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column width="250" :label="$t('commons.create_time')">
|
<el-table-column width="250" :label="$t('commons.create_time')">
|
||||||
|
|
|
@ -39,8 +39,7 @@
|
||||||
:disabled="!row.edit || readOnly"
|
:disabled="!row.edit || readOnly"
|
||||||
size="mini"
|
size="mini"
|
||||||
v-model="row.enable"
|
v-model="row.enable"
|
||||||
active-color="#13ce66"
|
inactive-color="#DCDFE6">
|
||||||
inactive-color="#ff4949">
|
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
|
@ -37,8 +37,7 @@
|
||||||
<el-table-column prop="status" :label="$t('commons.status')">
|
<el-table-column prop="status" :label="$t('commons.status')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-switch v-model="scope.row.status"
|
<el-switch v-model="scope.row.status"
|
||||||
active-color="#13ce66"
|
inactive-color="#DCDFE6"
|
||||||
inactive-color="#ff4949"
|
|
||||||
active-value="ACTIVE"
|
active-value="ACTIVE"
|
||||||
inactive-value="DISABLED"
|
inactive-value="DISABLED"
|
||||||
@change="changeSwitch(scope.row)"
|
@change="changeSwitch(scope.row)"
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
<el-table-column prop="status" :label="$t('test_resource_pool.enable_disable')">
|
<el-table-column prop="status" :label="$t('test_resource_pool.enable_disable')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-switch v-model="scope.row.status"
|
<el-switch v-model="scope.row.status"
|
||||||
active-color="#13ce66"
|
inactive-color="#DCDFE6"
|
||||||
inactive-color="#ff4949"
|
|
||||||
active-value="VALID"
|
active-value="VALID"
|
||||||
inactive-value="INVALID"
|
inactive-value="INVALID"
|
||||||
@change="changeSwitch(scope.row)"
|
@change="changeSwitch(scope.row)"
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
<el-table-column prop="status" :label="$t('commons.status')" width="120">
|
<el-table-column prop="status" :label="$t('commons.status')" width="120">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-switch v-model="scope.row.status"
|
<el-switch v-model="scope.row.status"
|
||||||
active-color="#13ce66"
|
inactive-color="#DCDFE6"
|
||||||
inactive-color="#ff4949"
|
|
||||||
active-value="1"
|
active-value="1"
|
||||||
inactive-value="0"
|
inactive-value="0"
|
||||||
@change="changeSwitch(scope.row)"
|
@change="changeSwitch(scope.row)"
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
@filter-change="filter"
|
@filter-change="filter"
|
||||||
@select-all="handleSelectAll"
|
@select-all="handleSelectAll"
|
||||||
@select="handleSelectionChange"
|
@select="handleSelectionChange"
|
||||||
@row-click="showDetail"
|
|
||||||
row-key="id"
|
row-key="id"
|
||||||
class="test-content adjust-table">
|
class="test-content adjust-table">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
@ -54,7 +53,13 @@
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
:label="$t('commons.name')"
|
:label="$t('commons.name')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<div @mouseover="showDetail(scope.row)">
|
||||||
|
<p>{{ scope.row.name }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="priority"
|
prop="priority"
|
||||||
|
@ -86,6 +91,18 @@
|
||||||
<method-table-item :value="scope.row.method"/>
|
<method-table-item :value="scope.row.method"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
:filters="statusFilters"
|
||||||
|
column-key="status"
|
||||||
|
:label="$t('test_track.case.status')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span class="el-dropdown-link">
|
||||||
|
<status-table-item :value="scope.row.reviewStatus"/>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="nodePath"
|
prop="nodePath"
|
||||||
:label="$t('test_track.case.module')"
|
:label="$t('test_track.case.module')"
|
||||||
|
@ -146,6 +163,7 @@
|
||||||
import BatchEdit from "./BatchEdit";
|
import BatchEdit from "./BatchEdit";
|
||||||
import {WORKSPACE_ID} from "../../../../../common/js/constants";
|
import {WORKSPACE_ID} from "../../../../../common/js/constants";
|
||||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestCaseList",
|
name: "TestCaseList",
|
||||||
|
@ -163,7 +181,8 @@
|
||||||
NodeBreadcrumb,
|
NodeBreadcrumb,
|
||||||
MsTableHeader,
|
MsTableHeader,
|
||||||
ShowMoreBtn,
|
ShowMoreBtn,
|
||||||
BatchEdit
|
BatchEdit,
|
||||||
|
StatusTableItem
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -192,6 +211,11 @@
|
||||||
{text: this.$t('commons.performance'), value: 'performance'},
|
{text: this.$t('commons.performance'), value: 'performance'},
|
||||||
{text: this.$t('commons.api'), value: 'api'}
|
{text: this.$t('commons.api'), value: 'api'}
|
||||||
],
|
],
|
||||||
|
statusFilters: [
|
||||||
|
{text: this.$t('test_track.plan.plan_status_prepare'), value: 'Prepare'},
|
||||||
|
{text: this.$t('test_track.plan_view.pass'), value: 'Pass'},
|
||||||
|
{text: '未通过', value: 'UnPass'},
|
||||||
|
],
|
||||||
showMore: false,
|
showMore: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
border
|
border
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
@row-click="intoPlan"
|
@row-click="intoPlan"
|
||||||
v-loading="result.loading">
|
v-loading="result.loading" height="300px">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
fixed
|
fixed
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
border
|
border
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
@row-click="intoPlan"
|
@row-click="intoPlan"
|
||||||
v-loading="result.loading">
|
v-loading="result.loading" height="300px">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
fixed
|
fixed
|
||||||
|
@ -36,29 +36,19 @@
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="status"
|
prop="status"
|
||||||
:label="$t('test_track.plan.plan_status')"
|
:label="$t('test_track.plan.plan_status')">
|
||||||
show-overflow-tooltip>
|
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<plan-status-table-item :value="scope.row.status"/>
|
<plan-status-table-item :value="scope.row.status"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="projectName"
|
:label="$t('test_track.review.result_distribution')">
|
||||||
:label="$t('test_track.review.done')"
|
|
||||||
show-overflow-tooltip>
|
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
{{scope.row.reviewed}}/{{scope.row.total}}
|
<el-tooltip :content="getResultTip(scope.row.total,scope.row.reviewed,scope.row.pass)"
|
||||||
</template>
|
placement="top" :enterable="false" class="item" effect="dark">
|
||||||
</el-table-column>
|
<yan-progress :total="scope.row.total" :done="scope.row.reviewed" :modify="scope.row.pass" :tip="tip"/>
|
||||||
|
</el-tooltip>
|
||||||
<el-table-column
|
|
||||||
prop="projectName"
|
|
||||||
:label="$t('test_track.home.review_progress')"
|
|
||||||
min-width="100"
|
|
||||||
show-overflow-tooltip>
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-progress :percentage="scope.row.testRate"></el-progress>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
@ -87,7 +77,12 @@ export default {
|
||||||
return {
|
return {
|
||||||
result: {},
|
result: {},
|
||||||
tableData: [],
|
tableData: [],
|
||||||
showMyCreator: false
|
showMyCreator: false,
|
||||||
|
tip: [
|
||||||
|
{text: "X", fillStyle: '#D3D3D3'},
|
||||||
|
{text: "X", fillStyle: '#ee4545'},
|
||||||
|
{text: "X", fillStyle: '#4dcf4d'}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -115,11 +110,14 @@ export default {
|
||||||
},
|
},
|
||||||
searchMyCreator() {
|
searchMyCreator() {
|
||||||
this.showMyCreator = !this.showMyCreator;
|
this.showMyCreator = !this.showMyCreator;
|
||||||
if (this.showMyCreator){
|
if (this.showMyCreator) {
|
||||||
this.initTableData("creator");
|
this.initTableData("creator");
|
||||||
} else {
|
} else {
|
||||||
this.initTableData("reviewer");
|
this.initTableData("reviewer");
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
getResultTip(total, reviewed, pass) {
|
||||||
|
return '通过: ' + pass + '; ' + '未通过: ' + (reviewed - pass) + '; ' + '未评审: ' + (total - reviewed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
class="adjust-table"
|
class="adjust-table"
|
||||||
@row-click="editTestCase"
|
@row-click="editTestCase"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
v-loading="result.loading">
|
v-loading="result.loading" height="300px">
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
|
|
|
@ -62,6 +62,15 @@
|
||||||
<type-table-item :value="scope.row.type"/>
|
<type-table-item :value="scope.row.type"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:filters="statusFilters"
|
||||||
|
column-key="status"
|
||||||
|
:label="$t('test_track.case.status')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<status-table-item :value="scope.row.reviewStatus"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div style="text-align: center">共 {{testReviews.length}} 条</div>
|
<div style="text-align: center">共 {{testReviews.length}} 条</div>
|
||||||
</el-main>
|
</el-main>
|
||||||
|
@ -91,6 +100,7 @@ import MsTableHeader from "../../../../common/components/MsTableHeader";
|
||||||
import SwitchProject from "../../../case/components/SwitchProject";
|
import SwitchProject from "../../../case/components/SwitchProject";
|
||||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||||
import {_filter} from "../../../../../../common/js/utils";
|
import {_filter} from "../../../../../../common/js/utils";
|
||||||
|
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestReviewRelevance",
|
name: "TestReviewRelevance",
|
||||||
|
@ -102,7 +112,8 @@ export default {
|
||||||
MsTableSearchBar,
|
MsTableSearchBar,
|
||||||
MsTableAdvSearchBar,
|
MsTableAdvSearchBar,
|
||||||
MsTableHeader,
|
MsTableHeader,
|
||||||
SwitchProject
|
SwitchProject,
|
||||||
|
StatusTableItem
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -130,7 +141,12 @@ export default {
|
||||||
{text: this.$t('commons.functional'), value: 'functional'},
|
{text: this.$t('commons.functional'), value: 'functional'},
|
||||||
{text: this.$t('commons.performance'), value: 'performance'},
|
{text: this.$t('commons.performance'), value: 'performance'},
|
||||||
{text: this.$t('commons.api'), value: 'api'}
|
{text: this.$t('commons.api'), value: 'api'}
|
||||||
]
|
],
|
||||||
|
statusFilters: [
|
||||||
|
{text: this.$t('test_track.case.status_prepare'), value: 'Prepare'},
|
||||||
|
{text: this.$t('test_track.case.status_pass'), value: 'Pass'},
|
||||||
|
{text: this.$t('test_track.case.status_un_pass'), value: 'UnPass'},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -283,6 +283,7 @@ export default {
|
||||||
saveCase(status) {
|
saveCase(status) {
|
||||||
let param = {};
|
let param = {};
|
||||||
param.id = this.testCase.id;
|
param.id = this.testCase.id;
|
||||||
|
param.caseId = this.testCase.caseId;
|
||||||
param.reviewId = this.testCase.reviewId;
|
param.reviewId = this.testCase.reviewId;
|
||||||
param.status = status;
|
param.status = status;
|
||||||
this.$post('/test/review/case/edit', param, () => {
|
this.$post('/test/review/case/edit', param, () => {
|
||||||
|
|
|
@ -104,13 +104,12 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="status"
|
|
||||||
:filters="statusFilters"
|
:filters="statusFilters"
|
||||||
column-key="status"
|
column-key="status"
|
||||||
:label="$t('test_track.review_view.execute_result')">
|
:label="$t('test_track.review_view.execute_result')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span class="el-dropdown-link">
|
<span class="el-dropdown-link">
|
||||||
<status-table-item :value="scope.row.status"/>
|
<status-table-item :value="scope.row.reviewStatus"/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -207,9 +206,9 @@ export default {
|
||||||
{text: this.$t('commons.api'), value: 'api'}
|
{text: this.$t('commons.api'), value: 'api'}
|
||||||
],
|
],
|
||||||
statusFilters: [
|
statusFilters: [
|
||||||
{text: this.$t('test_track.plan.plan_status_prepare'), value: 'Prepare'},
|
{text: this.$t('test_track.case.status_prepare'), value: 'Prepare'},
|
||||||
{text: this.$t('test_track.plan_view.pass'), value: 'Pass'},
|
{text: this.$t('test_track.case.status_pass'), value: 'Pass'},
|
||||||
{text: '未通过', value: 'UnPass'},
|
{text: this.$t('test_track.case.status_un_pass'), value: 'UnPass'},
|
||||||
],
|
],
|
||||||
showMore: false,
|
showMore: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit cc38137a69a0f20fadece9c0f9f50a9468c4ace9
|
Subproject commit 06d935cd1d22ab36f09763745c2aff8ad3fb08c1
|
|
@ -7,6 +7,7 @@ import ajax from "../common/js/ajax";
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import message from "../common/js/message";
|
import message from "../common/js/message";
|
||||||
import router from "./components/common/router/router";
|
import router from "./components/common/router/router";
|
||||||
|
import YanProgress from 'yan-progress';
|
||||||
import './permission' // permission control
|
import './permission' // permission control
|
||||||
import i18n from "../i18n/i18n";
|
import i18n from "../i18n/i18n";
|
||||||
import store from "./store";
|
import store from "./store";
|
||||||
|
@ -28,6 +29,7 @@ Vue.use(chart);
|
||||||
Vue.use(CalendarHeatmap);
|
Vue.use(CalendarHeatmap);
|
||||||
Vue.use(message);
|
Vue.use(message);
|
||||||
Vue.use(CKEditor);
|
Vue.use(CKEditor);
|
||||||
|
Vue.use(YanProgress)
|
||||||
|
|
||||||
// v-permission
|
// v-permission
|
||||||
Vue.directive('permission', permission);
|
Vue.directive('permission', permission);
|
||||||
|
|
|
@ -27,14 +27,14 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*解决高度塌陷和边距重叠*/
|
/*解决高度塌陷和边距重叠*/
|
||||||
.clearfix:before,.clearfix:after{
|
.clearfix:before, .clearfix:after {
|
||||||
content: "";
|
content: "";
|
||||||
display: table;
|
display: table;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*解决富文本框中link显示问题*/
|
/*解决富文本框中link显示问题*/
|
||||||
.ck-rounded-corners .ck.ck-balloon-panel,.ck.ck-balloon-panel.ck-rounded-corners {
|
.ck-rounded-corners .ck.ck-balloon-panel, .ck.ck-balloon-panel.ck-rounded-corners {
|
||||||
z-index: 10055 !important;
|
z-index: 10055 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ body {
|
||||||
|
|
||||||
/* <-- 表格拖拽表头调整宽度,在 t-bable 上添加 border 属性,并添加 adjust-table 类名*/
|
/* <-- 表格拖拽表头调整宽度,在 t-bable 上添加 border 属性,并添加 adjust-table 类名*/
|
||||||
.adjust-table td {
|
.adjust-table td {
|
||||||
border-right-color: white;
|
border-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adjust-table th {
|
.adjust-table th {
|
||||||
|
@ -74,12 +74,18 @@ body {
|
||||||
width: 3px;
|
width: 3px;
|
||||||
background-color: #EBEEF5;
|
background-color: #EBEEF5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adjust-table tr:hover td {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 表格拖拽表头调整宽度 --> */
|
/* 表格拖拽表头调整宽度 --> */
|
||||||
|
|
||||||
/* <-- 表格 input 编辑效果*/
|
/* <-- 表格 input 编辑效果*/
|
||||||
.table-edit-input .el-textarea__inner {
|
.table-edit-input .el-textarea__inner {
|
||||||
border-style: hidden;
|
border-style: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-edit-input.is-disabled .el-textarea__inner {
|
.table-edit-input.is-disabled .el-textarea__inner {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
color: #606266;
|
color: #606266;
|
||||||
|
@ -93,6 +99,7 @@ body {
|
||||||
.table-edit-input .el-textarea__inner:focus {
|
.table-edit-input .el-textarea__inner:focus {
|
||||||
border: 1px solid #409EFF;
|
border: 1px solid #409EFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 表格 input 编辑效果 --> */
|
/* 表格 input 编辑效果 --> */
|
||||||
|
|
||||||
.ms-border {
|
.ms-border {
|
||||||
|
|
|
@ -53,6 +53,10 @@ export default {
|
||||||
login();
|
login();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (error.response && error.response.status === 403) {
|
||||||
|
window.location.href = "/";
|
||||||
|
return;
|
||||||
|
}
|
||||||
result.loading = false;
|
result.loading = false;
|
||||||
window.console.error(error.response || error.message);
|
window.console.error(error.response || error.message);
|
||||||
if (error.response && error.response.data) {
|
if (error.response && error.response.data) {
|
||||||
|
|
|
@ -695,6 +695,10 @@ export default {
|
||||||
batch_delete_case: 'Batch delete',
|
batch_delete_case: 'Batch delete',
|
||||||
batch_unlink: 'Batch Unlink',
|
batch_unlink: 'Batch Unlink',
|
||||||
project_name: "Project",
|
project_name: "Project",
|
||||||
|
status: 'Status',
|
||||||
|
status_prepare: 'Prepare',
|
||||||
|
status_pass: 'Pass',
|
||||||
|
status_un_pass: 'UnPass',
|
||||||
import: {
|
import: {
|
||||||
import: "Import test case",
|
import: "Import test case",
|
||||||
case_import: "Import test case",
|
case_import: "Import test case",
|
||||||
|
@ -740,6 +744,10 @@ export default {
|
||||||
plan_status_prepare: "Not started",
|
plan_status_prepare: "Not started",
|
||||||
plan_status_running: "Starting",
|
plan_status_running: "Starting",
|
||||||
plan_status_completed: "Completed",
|
plan_status_completed: "Completed",
|
||||||
|
planned_start_time: "Scheduled Start Time",
|
||||||
|
planned_end_time: "Scheduled End Time",
|
||||||
|
actual_start_time: "Actual Start Time",
|
||||||
|
actual_end_time: "Actual End Time",
|
||||||
plan_delete_confirm: "All use cases under this plan will be deleted,confirm delete test plan: ",
|
plan_delete_confirm: "All use cases under this plan will be deleted,confirm delete test plan: ",
|
||||||
plan_delete: "Delete test plan",
|
plan_delete: "Delete test plan",
|
||||||
},
|
},
|
||||||
|
@ -765,7 +773,8 @@ export default {
|
||||||
my_create: "My Create",
|
my_create: "My Create",
|
||||||
reviewed_by_me: "Review By Me",
|
reviewed_by_me: "Review By Me",
|
||||||
creator: "Creator",
|
creator: "Creator",
|
||||||
done: "Commented use cases"
|
done: "Commented use cases",
|
||||||
|
result_distribution: "Result Distribution"
|
||||||
},
|
},
|
||||||
comment: {
|
comment: {
|
||||||
no_comment: "No Comment",
|
no_comment: "No Comment",
|
||||||
|
|
|
@ -697,6 +697,10 @@ export default {
|
||||||
batch_delete_case: '批量删除用例',
|
batch_delete_case: '批量删除用例',
|
||||||
batch_unlink: '批量取消关联',
|
batch_unlink: '批量取消关联',
|
||||||
project_name: '所属项目',
|
project_name: '所属项目',
|
||||||
|
status: '状态',
|
||||||
|
status_prepare: '未开始',
|
||||||
|
status_pass: '通过',
|
||||||
|
status_un_pass: '未通过',
|
||||||
import: {
|
import: {
|
||||||
import: "导入用例",
|
import: "导入用例",
|
||||||
case_import: "导入测试用例",
|
case_import: "导入测试用例",
|
||||||
|
@ -771,7 +775,8 @@ export default {
|
||||||
my_create: "我创建的评审",
|
my_create: "我创建的评审",
|
||||||
reviewed_by_me: "待我评审",
|
reviewed_by_me: "待我评审",
|
||||||
creator: "创建人",
|
creator: "创建人",
|
||||||
done: "已评用例"
|
done: "已评用例",
|
||||||
|
result_distribution: "结果分布"
|
||||||
},
|
},
|
||||||
comment: {
|
comment: {
|
||||||
no_comment: "暂无评论",
|
no_comment: "暂无评论",
|
||||||
|
@ -785,7 +790,7 @@ export default {
|
||||||
all_case: "全部用例",
|
all_case: "全部用例",
|
||||||
start_review: "开始评审",
|
start_review: "开始评审",
|
||||||
relevance_case: "关联用例",
|
relevance_case: "关联用例",
|
||||||
execute_result: "执行结果",
|
execute_result: "评审结果",
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
search: "搜索模块",
|
search: "搜索模块",
|
||||||
|
|
|
@ -469,9 +469,9 @@ export default {
|
||||||
input_url: "請輸入請求URL",
|
input_url: "請輸入請求URL",
|
||||||
input_path: "請輸入請求路徑",
|
input_path: "請輸入請求路徑",
|
||||||
name: "請求名稱",
|
name: "請求名稱",
|
||||||
|
content_type: "請求類型",
|
||||||
method: "請求方法",
|
method: "請求方法",
|
||||||
url: "請求URL",
|
url: "請求URL",
|
||||||
content_type: "請求類型",
|
|
||||||
path: "請求路徑",
|
path: "請求路徑",
|
||||||
address: "請求地址",
|
address: "請求地址",
|
||||||
refer_to_environment: "引用環境",
|
refer_to_environment: "引用環境",
|
||||||
|
@ -697,6 +697,10 @@ export default {
|
||||||
batch_delete_case: '批量刪除用例',
|
batch_delete_case: '批量刪除用例',
|
||||||
batch_unlink: '批量取消關聯',
|
batch_unlink: '批量取消關聯',
|
||||||
project_name: '所屬項目',
|
project_name: '所屬項目',
|
||||||
|
status: '狀態',
|
||||||
|
status_prepare: '未開始',
|
||||||
|
status_pass: '通過',
|
||||||
|
status_un_pass: '未通過',
|
||||||
import: {
|
import: {
|
||||||
import: "導入用例",
|
import: "導入用例",
|
||||||
case_import: "導入測試用例",
|
case_import: "導入測試用例",
|
||||||
|
@ -742,6 +746,10 @@ export default {
|
||||||
plan_status_prepare: "未開始",
|
plan_status_prepare: "未開始",
|
||||||
plan_status_running: "進行中",
|
plan_status_running: "進行中",
|
||||||
plan_status_completed: "已完成",
|
plan_status_completed: "已完成",
|
||||||
|
planned_start_time: "計劃開始",
|
||||||
|
planned_end_time: "計劃結束",
|
||||||
|
actual_start_time: "實際開始",
|
||||||
|
actual_end_time: "實際結束",
|
||||||
plan_delete_confirm: "將刪除該測試計劃下所有用例,確認刪除測試計劃: ",
|
plan_delete_confirm: "將刪除該測試計劃下所有用例,確認刪除測試計劃: ",
|
||||||
plan_delete: "刪除計劃",
|
plan_delete: "刪除計劃",
|
||||||
},
|
},
|
||||||
|
@ -767,7 +775,8 @@ export default {
|
||||||
my_create: "我創建的評審",
|
my_create: "我創建的評審",
|
||||||
reviewed_by_me: "待我評審",
|
reviewed_by_me: "待我評審",
|
||||||
creator: "創建人",
|
creator: "創建人",
|
||||||
done: "已評用例"
|
done: "已評用例",
|
||||||
|
result_distribution: "結果分佈"
|
||||||
},
|
},
|
||||||
comment: {
|
comment: {
|
||||||
no_comment: "暫無評論",
|
no_comment: "暫無評論",
|
||||||
|
@ -781,7 +790,7 @@ export default {
|
||||||
all_case: "全部用例",
|
all_case: "全部用例",
|
||||||
start_review: "開始評審",
|
start_review: "開始評審",
|
||||||
relevance_case: "關聯用例",
|
relevance_case: "關聯用例",
|
||||||
execute_result: "執行結果",
|
execute_result: "評審結果",
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
search: "搜索模塊",
|
search: "搜索模塊",
|
||||||
|
|
Loading…
Reference in New Issue