This commit is contained in:
chenjianxing 2020-09-08 17:26:22 +08:00
commit fdde95218d
24 changed files with 567 additions and 240 deletions

View File

@ -104,9 +104,6 @@ public class APITestService {
} }
private void createBodyFiles(ApiTest test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) { private void createBodyFiles(ApiTest test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
if (bodyFiles == null || bodyFiles.isEmpty()) {
}
String dir = BODY_FILE_DIR + "/" + test.getId(); String dir = BODY_FILE_DIR + "/" + test.getId();
File testDir = new File(dir); File testDir = new File(dir);
if (!testDir.exists()) { if (!testDir.exists()) {
@ -115,24 +112,12 @@ public class APITestService {
for (int i = 0; i < bodyUploadIds.size(); i++) { for (int i = 0; i < bodyUploadIds.size(); i++) {
MultipartFile item = bodyFiles.get(i); MultipartFile item = bodyFiles.get(i);
File file = new File(testDir + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename()); File file = new File(testDir + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename());
InputStream in = null; try (InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(file)) {
OutputStream out = null;
try {
file.createNewFile(); file.createNewFile();
in = item.getInputStream();
out = new FileOutputStream(file);
FileUtil.copyStream(in, out); FileUtil.copyStream(in, out);
} catch (IOException e) { } catch (IOException e) {
LogUtil.error(e); LogUtil.error(e);
MSException.throwException(Translator.get("upload_fail")); MSException.throwException(Translator.get("upload_fail"));
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
LogUtil.error(e);
MSException.throwException(Translator.get("upload_fail"));
}
} }
} }
} }

View File

@ -97,9 +97,7 @@
<select id="list" resultMap="BaseResultMap" <select id="list" resultMap="BaseResultMap"
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest"> parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
select test_plan.*, project.name as project_name select test_plan.* from test_plan
from test_plan
left join project on test_plan.project_id = project.id
<where> <where>
<if test="request.combine != null"> <if test="request.combine != null">
<include refid="combine"> <include refid="combine">
@ -111,10 +109,7 @@
and test_plan.name like CONCAT('%', #{request.name},'%') and test_plan.name like CONCAT('%', #{request.name},'%')
</if> </if>
<if test="request.workspaceId != null"> <if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId} AND test_plan.workspace_id = #{request.workspaceId}
</if>
<if test="request.projectId != null">
AND project.id = #{request.projectId}
</if> </if>
<if test="request.id != null"> <if test="request.id != null">
AND test_plan.id = #{request.id} AND test_plan.id = #{request.id}
@ -150,9 +145,7 @@
</select> </select>
<select id="listRelate" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric"> <select id="listRelate" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric">
select test_plan.*, project.name as project_name select test_plan.* from test_plan
from test_plan
left join project on test_plan.project_id = project.id
where test_plan.workspace_id = #{request.workspaceId} where test_plan.workspace_id = #{request.workspaceId}
and (test_plan.principal = #{request.principal} and (test_plan.principal = #{request.principal}
<if test="request.planIds != null and request.planIds.size() > 0"> <if test="request.planIds != null and request.planIds.size() > 0">

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import io.metersphere.commons.constants.ParamConstants; import io.metersphere.commons.constants.ParamConstants;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.EncryptUtils; import io.metersphere.commons.utils.EncryptUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.controller.request.LoginRequest; import io.metersphere.controller.request.LoginRequest;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
@ -47,6 +48,7 @@ public class LdapService {
// 执行登录认证 // 执行登录认证
authenticate(String.valueOf(dirContextOperations.getDn()), credentials); authenticate(String.valueOf(dirContextOperations.getDn()), credentials);
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("authentication_failed")); MSException.throwException(Translator.get("authentication_failed"));
} }
@ -93,8 +95,10 @@ public class LdapService {
return result.get(0); return result.get(0);
} }
} catch (NameNotFoundException | InvalidNameException e) { } catch (NameNotFoundException | InvalidNameException e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("login_fail_ou_error")); MSException.throwException(Translator.get("login_fail_ou_error"));
} catch (InvalidSearchFilterException e) { } catch (InvalidSearchFilterException e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("login_fail_filter_error")); MSException.throwException(Translator.get("login_fail_filter_error"));
} }
} }
@ -161,8 +165,10 @@ public class LdapService {
try { try {
authenticate(dn, credentials, ldapTemplate); authenticate(dn, credentials, ldapTemplate);
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("ldap_connect_fail_user")); MSException.throwException(Translator.get("ldap_connect_fail_user"));
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("ldap_connect_fail")); MSException.throwException(Translator.get("ldap_connect_fail"));
} }

View File

@ -16,13 +16,14 @@ import io.metersphere.controller.request.ProjectRequest;
import io.metersphere.dto.ProjectDTO; import io.metersphere.dto.ProjectDTO;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.DeleteTestPlanRequest; import io.metersphere.track.request.testplan.DeleteTestPlanRequest;
import io.metersphere.track.service.TestCaseService; import io.metersphere.track.service.TestCaseService;
import io.metersphere.track.service.TestPlanProjectService;
import io.metersphere.track.service.TestPlanService; import io.metersphere.track.service.TestPlanService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
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 javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
@ -54,6 +55,8 @@ public class ProjectService {
private TestCaseService testCaseService; private TestCaseService testCaseService;
@Resource @Resource
private APITestService apiTestService; private APITestService apiTestService;
@Resource
private TestPlanProjectService testPlanProjectService;
public Project addProject(Project project) { public Project addProject(Project project) {
if (StringUtils.isBlank(project.getName())) { if (StringUtils.isBlank(project.getName())) {
@ -96,21 +99,22 @@ public class ProjectService {
performanceTestService.delete(deleteTestPlanRequest); performanceTestService.delete(deleteTestPlanRequest);
}); });
// TODO 删除项目下 测试跟踪 相关 // 删除项目下 测试跟踪 相关
deleteTrackResourceByProjectId(projectId); deleteTrackResourceByProjectId(projectId);
// TODO 删除项目下 接口测试 相关 // 删除项目下 接口测试 相关
deleteAPIResourceByProjectId(projectId); deleteAPIResourceByProjectId(projectId);
// delete project // delete project
projectMapper.deleteByPrimaryKey(projectId); projectMapper.deleteByPrimaryKey(projectId);
} }
private void deleteTrackResourceByProjectId(String projectId) { private void deleteTrackResourceByProjectId(String projectId) {
QueryTestPlanRequest request = new QueryTestPlanRequest(); List<String> testPlanIds = testPlanProjectService.getPlanIdByProjectId(projectId);
request.setProjectId(projectId); if (!CollectionUtils.isEmpty(testPlanIds)) {
testPlanService.listTestPlan(request).forEach(testPlan -> { testPlanIds.forEach(testPlanId -> {
testPlanService.deleteTestPlan(testPlan.getId()); testPlanService.deleteTestPlan(testPlanId);
}); });
}
testCaseService.deleteTestCaseByProjectId(projectId); testCaseService.deleteTestCaseByProjectId(projectId);
} }

View File

@ -4,6 +4,7 @@ import io.metersphere.base.domain.TestCaseNode;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
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.service.TestCaseNodeService; import io.metersphere.track.service.TestCaseNodeService;
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;
@ -26,9 +27,9 @@ public class TestCaseNodeController {
} }
/*模块列表列表*/ /*模块列表列表*/
@GetMapping("/list/all/plan/{planId}") @PostMapping("/list/all/plan")
public List<TestCaseNodeDTO> getAllNodeByPlanId(@PathVariable String planId) { public List<TestCaseNodeDTO> getAllNodeByPlanId(@RequestBody QueryNodeRequest request) {
return testCaseNodeService.getAllNodeByPlanId(planId); return testCaseNodeService.getAllNodeByPlanId(request);
} }
@GetMapping("/list/plan/{planId}") @GetMapping("/list/plan/{planId}")

View File

@ -2,6 +2,7 @@ package io.metersphere.track.controller;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.Project;
import io.metersphere.base.domain.TestPlan; import io.metersphere.base.domain.TestPlan;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.PageUtils;
@ -12,6 +13,8 @@ import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.dto.TestPlanDTOWithMetric; import io.metersphere.track.dto.TestPlanDTOWithMetric;
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest; import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.AddTestPlanRequest;
import io.metersphere.track.service.TestPlanProjectService;
import io.metersphere.track.service.TestPlanService; import io.metersphere.track.service.TestPlanService;
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;
@ -26,6 +29,8 @@ public class TestPlanController {
@Resource @Resource
TestPlanService testPlanService; TestPlanService testPlanService;
@Resource
TestPlanProjectService testPlanProjectService;
@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) {
@ -37,7 +42,7 @@ public class TestPlanController {
/*jenkins测试计划*/ /*jenkins测试计划*/
@GetMapping("/list/all/{projectId}/{workspaceId}") @GetMapping("/list/all/{projectId}/{workspaceId}")
public List<TestPlanDTO> listByprojectId(@PathVariable String projectId, @PathVariable String workspaceId) { public List<TestPlanDTO> listByProjectId(@PathVariable String projectId, @PathVariable String workspaceId) {
QueryTestPlanRequest request = new QueryTestPlanRequest(); QueryTestPlanRequest request = new QueryTestPlanRequest();
request.setWorkspaceId(workspaceId); request.setWorkspaceId(workspaceId);
request.setProjectId(projectId); request.setProjectId(projectId);
@ -69,7 +74,7 @@ public class TestPlanController {
@PostMapping("/add") @PostMapping("/add")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void addTestPlan(@RequestBody TestPlan testPlan) { public void addTestPlan(@RequestBody AddTestPlanRequest testPlan) {
testPlanService.addTestPlan(testPlan); testPlanService.addTestPlan(testPlan);
} }
@ -100,4 +105,14 @@ public class TestPlanController {
public TestCaseReportMetricDTO getMetric(@PathVariable String planId) { public TestCaseReportMetricDTO getMetric(@PathVariable String planId) {
return testPlanService.getMetric(planId); return testPlanService.getMetric(planId);
} }
@GetMapping("/project/name/{planId}")
public String getProjectNameByPlanId(@PathVariable String planId) {
return testPlanService.getProjectNameByPlanId(planId);
}
@GetMapping("/project/{planId}")
public List<Project> getProjectByPlanId(@PathVariable String planId) {
return testPlanProjectService.getProjectByPlanId(planId);
}
} }

View File

@ -1,7 +1,5 @@
package io.metersphere.track.domain; package io.metersphere.track.domain;
import com.alibaba.fastjson.JSON;
import io.metersphere.base.domain.Issues;
import io.metersphere.base.domain.TestCaseNode; import io.metersphere.base.domain.TestCaseNode;
import io.metersphere.base.domain.TestCaseNodeExample; import io.metersphere.base.domain.TestCaseNodeExample;
import io.metersphere.base.mapper.TestCaseNodeMapper; import io.metersphere.base.mapper.TestCaseNodeMapper;
@ -11,6 +9,7 @@ import io.metersphere.commons.utils.MathUtils;
import io.metersphere.track.dto.*; import io.metersphere.track.dto.*;
import io.metersphere.track.service.IssuesService; import io.metersphere.track.service.IssuesService;
import io.metersphere.track.service.TestCaseNodeService; import io.metersphere.track.service.TestCaseNodeService;
import io.metersphere.track.service.TestPlanProjectService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.*; import java.util.*;
@ -30,8 +29,9 @@ public class ReportResultComponent extends ReportComponent {
public void init() { public void init() {
TestCaseNodeService testCaseNodeService = (TestCaseNodeService) CommonBeanFactory.getBean("testCaseNodeService"); TestCaseNodeService testCaseNodeService = (TestCaseNodeService) CommonBeanFactory.getBean("testCaseNodeService");
TestCaseNodeMapper testCaseNodeMapper = (TestCaseNodeMapper) CommonBeanFactory.getBean("testCaseNodeMapper"); TestCaseNodeMapper testCaseNodeMapper = (TestCaseNodeMapper) CommonBeanFactory.getBean("testCaseNodeMapper");
TestPlanProjectService testPlanProjectService = (TestPlanProjectService) CommonBeanFactory.getBean("testPlanProjectService");
TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample(); TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample();
testCaseNodeExample.createCriteria().andProjectIdEqualTo(testPlan.getProjectId()); testCaseNodeExample.createCriteria().andProjectIdIn(testPlanProjectService.getProjectIdsByPlanId(testPlan.getId()));
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample); List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample);
nodeTrees = testCaseNodeService.getNodeTrees(nodes); nodeTrees = testCaseNodeService.getNodeTrees(nodes);
nodeTrees.forEach(item -> { nodeTrees.forEach(item -> {

View File

@ -0,0 +1,13 @@
package io.metersphere.track.request.testcase;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class QueryNodeRequest {
private String testPlanId;
private String projectId;
}

View File

@ -0,0 +1,13 @@
package io.metersphere.track.request.testplan;
import io.metersphere.base.domain.TestPlan;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class AddTestPlanRequest extends TestPlan {
private List<String> projectIds;
}

View File

@ -2,10 +2,7 @@ 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.*;
import io.metersphere.base.mapper.TestCaseNodeMapper;
import io.metersphere.base.mapper.TestPlanMapper;
import io.metersphere.base.mapper.TestPlanTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
import io.metersphere.commons.constants.TestCaseConstants; import io.metersphere.commons.constants.TestCaseConstants;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
@ -15,6 +12,7 @@ import io.metersphere.i18n.Translator;
import io.metersphere.track.dto.TestCaseDTO; import io.metersphere.track.dto.TestCaseDTO;
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.QueryTestCaseRequest; import io.metersphere.track.request.testcase.QueryTestCaseRequest;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
@ -43,6 +41,10 @@ public class TestCaseNodeService {
ExtTestCaseMapper extTestCaseMapper; ExtTestCaseMapper extTestCaseMapper;
@Resource @Resource
SqlSessionFactory sqlSessionFactory; SqlSessionFactory sqlSessionFactory;
@Resource
TestPlanProjectService testPlanProjectService;
@Resource
ProjectMapper projectMapper;
public String addNode(TestCaseNode node) { public String addNode(TestCaseNode node) {
validateNode(node); validateNode(node);
@ -182,8 +184,22 @@ public class TestCaseNodeService {
*/ */
public List<TestCaseNodeDTO> getNodeByPlanId(String planId) { public List<TestCaseNodeDTO> getNodeByPlanId(String planId) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId); List<TestCaseNodeDTO> list = new ArrayList<>();
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(planId);
projectIds.forEach(id -> {
String name = projectMapper.selectByPrimaryKey(id).getName();
List<TestCaseNodeDTO> nodeList = getNodeDTO(id, planId);
TestCaseNodeDTO testCaseNodeDTO = new TestCaseNodeDTO();
testCaseNodeDTO.setName(name);
testCaseNodeDTO.setLabel(name);
testCaseNodeDTO.setChildren(nodeList);
list.add(testCaseNodeDTO);
});
return list;
}
private List<TestCaseNodeDTO> getNodeDTO(String projectId, String planId) {
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample(); TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(planId); testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(planId);
List<TestPlanTestCase> testPlanTestCases = testPlanTestCaseMapper.selectByExample(testPlanTestCaseExample); List<TestPlanTestCase> testPlanTestCases = testPlanTestCaseMapper.selectByExample(testPlanTestCaseExample);
@ -193,7 +209,7 @@ public class TestCaseNodeService {
} }
TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample(); TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample();
testCaseNodeExample.createCriteria().andProjectIdEqualTo(testPlan.getProjectId()); testCaseNodeExample.createCriteria().andProjectIdEqualTo(projectId);
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample); List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample);
List<String> caseIds = testPlanTestCases.stream() List<String> caseIds = testPlanTestCases.stream()
@ -254,12 +270,15 @@ public class TestCaseNodeService {
return false; return false;
} }
public List<TestCaseNodeDTO> getAllNodeByPlanId(String planId) { public List<TestCaseNodeDTO> getAllNodeByPlanId(QueryNodeRequest request) {
String planId = request.getTestPlanId();
String projectId = request.getProjectId();
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
if (testPlan == null) { if (testPlan == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
return getNodeTreeByProjectId(testPlan.getProjectId());
return getNodeTreeByProjectId(projectId);
} }
public Map<String, String> createNodeByTestCases(List<TestCaseWithBLOBs> testCases, String projectId) { public Map<String, String> createNodeByTestCases(List<TestCaseWithBLOBs> testCases, String projectId) {

View File

@ -182,9 +182,7 @@ public class TestCaseService {
public List<TestCase> getTestCaseNames(QueryTestCaseRequest request) { public List<TestCase> getTestCaseNames(QueryTestCaseRequest request) {
if (StringUtils.isNotBlank(request.getPlanId())) { if (StringUtils.isNotBlank(request.getPlanId())) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId()); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
if (testPlan != null) { // request 传入要查询的 projectId 切换的项目ID
request.setProjectId(testPlan.getProjectId());
}
} }
List<TestCase> testCaseNames = extTestCaseMapper.getTestCaseNames(request); List<TestCase> testCaseNames = extTestCaseMapper.getTestCaseNames(request);

View File

@ -0,0 +1,70 @@
package io.metersphere.track.service;
import io.metersphere.base.domain.Project;
import io.metersphere.base.domain.ProjectExample;
import io.metersphere.base.domain.TestPlanProject;
import io.metersphere.base.domain.TestPlanProjectExample;
import io.metersphere.base.mapper.ProjectMapper;
import io.metersphere.base.mapper.TestPlanProjectMapper;
import org.python.antlr.ast.Str;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanProjectService {
@Resource
TestPlanProjectMapper testPlanProjectMapper;
@Resource
ProjectMapper projectMapper;
public List<String> getProjectIdsByPlanId(String planId) {
TestPlanProjectExample example = new TestPlanProjectExample();
example.createCriteria().andTestPlanIdEqualTo(planId);
List<String> projectIds = testPlanProjectMapper.selectByExample(example)
.stream()
.map(TestPlanProject::getProjectId)
.collect(Collectors.toList());
if (projectIds.isEmpty()) {
return null;
}
return projectIds;
}
public List<Project> getProjectByPlanId(String planId) {
List<String> projectIds = getProjectIdsByPlanId(planId);
ProjectExample projectExample = new ProjectExample();
projectExample.createCriteria().andIdIn(projectIds);
List<Project> projects = projectMapper.selectByExample(projectExample);
return Optional.ofNullable(projects).orElse(new ArrayList<>());
}
public void deleteTestPlanProjectByPlanId(String planId) {
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
testPlanProjectExample.createCriteria().andTestPlanIdEqualTo(planId);
testPlanProjectMapper.deleteByExample(testPlanProjectExample);
}
public List<String> getPlanIdByProjectId(String projectId) {
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
testPlanProjectExample.createCriteria().andProjectIdEqualTo(projectId);
List<TestPlanProject> testPlanProjects = testPlanProjectMapper.selectByExample(testPlanProjectExample);
if (CollectionUtils.isEmpty(testPlanProjects)) {
return null;
}
return testPlanProjects
.stream()
.map(TestPlanProject::getTestPlanId)
.collect(Collectors.toList());
}
}

View File

@ -4,10 +4,7 @@ package io.metersphere.track.service;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.TestCaseMapper; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.TestCaseReportMapper;
import io.metersphere.base.mapper.TestPlanMapper;
import io.metersphere.base.mapper.TestPlanTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtProjectMapper; import io.metersphere.base.mapper.ext.ExtProjectMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
@ -28,6 +25,7 @@ import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.dto.TestPlanDTOWithMetric; import io.metersphere.track.dto.TestPlanDTOWithMetric;
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest; import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.AddTestPlanRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest; import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
@ -72,12 +70,29 @@ public class TestPlanService {
@Resource @Resource
TestCaseReportMapper testCaseReportMapper; TestCaseReportMapper testCaseReportMapper;
public void addTestPlan(TestPlan testPlan) { @Resource
TestPlanProjectMapper testPlanProjectMapper;
@Resource
TestPlanProjectService testPlanProjectService;
@Resource
ProjectMapper projectMapper;
public void addTestPlan(AddTestPlanRequest testPlan) {
if (getTestPlanByName(testPlan.getName()).size() > 0) { if (getTestPlanByName(testPlan.getName()).size() > 0) {
MSException.throwException(Translator.get("plan_name_already_exists")); MSException.throwException(Translator.get("plan_name_already_exists"));
} }
;
testPlan.setId(UUID.randomUUID().toString()); String testPlanId = UUID.randomUUID().toString();
List<String> projectIds = testPlan.getProjectIds();
projectIds.forEach(id -> {
TestPlanProject testPlanProject = new TestPlanProject();
testPlanProject.setProjectId(id);
testPlanProject.setTestPlanId(testPlanId);
testPlanProjectMapper.insertSelective(testPlanProject);
});
testPlan.setId(testPlanId);
testPlan.setStatus(TestPlanStatus.Prepare.name()); testPlan.setStatus(TestPlanStatus.Prepare.name());
testPlan.setCreateTime(System.currentTimeMillis()); testPlan.setCreateTime(System.currentTimeMillis());
testPlan.setUpdateTime(System.currentTimeMillis()); testPlan.setUpdateTime(System.currentTimeMillis());
@ -116,6 +131,7 @@ public class TestPlanService {
public int deleteTestPlan(String planId) { public int deleteTestPlan(String planId) {
deleteTestCaseByPlanId(planId); deleteTestCaseByPlanId(planId);
testPlanProjectService.deleteTestPlanProjectByPlanId(planId);
return testPlanMapper.deleteByPrimaryKey(planId); return testPlanMapper.deleteByPrimaryKey(planId);
} }
@ -316,4 +332,23 @@ public class TestPlanService {
testPlan.setStatus(TestPlanStatus.Completed.name()); testPlan.setStatus(TestPlanStatus.Completed.name());
testPlanMapper.updateByPrimaryKeySelective(testPlan); testPlanMapper.updateByPrimaryKeySelective(testPlan);
} }
public String getProjectNameByPlanId(String testPlanId) {
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(testPlanId);
ProjectExample projectExample = new ProjectExample();
projectExample.createCriteria().andIdIn(projectIds);
List<Project> projects = projectMapper.selectByExample(projectExample);
StringBuilder stringBuilder = new StringBuilder();
String projectName = "";
if (projects.size() > 0) {
for (Project project : projects) {
stringBuilder.append(project.getName()).append("");
}
projectName = stringBuilder.toString().substring(0, stringBuilder.length() - 1);
}
return projectName;
}
} }

View File

@ -123,6 +123,9 @@
validateDomain(domain) { validateDomain(domain) {
let url = {}; let url = {};
try { try {
if (!domain.startsWith("http") || !domain.startsWith("https")) {
domain += "http://";
}
url = new URL(domain); url = new URL(domain);
} catch (e) { } catch (e) {
this.$warning(this.$t('load_test.input_domain')); this.$warning(this.$t('load_test.input_domain'));

View File

@ -2,7 +2,7 @@
<el-container> <el-container>
<el-aside class="scenario-aside"> <el-aside class="scenario-aside">
<div class="scenario-list"> <div class="scenario-list">
<ms-api-collapse v-model="activeName" @change="handleChange" accordion> <ms-api-collapse v-model="activeName" @change="handleChange">
<draggable :list="scenarios" group="Scenario" class="scenario-draggable" ghost-class="scenario-ghost"> <draggable :list="scenarios" group="Scenario" class="scenario-draggable" ghost-class="scenario-ghost">
<ms-api-collapse-item v-for="(scenario, index) in scenarios" :key="index" <ms-api-collapse-item v-for="(scenario, index) in scenarios" :key="index"
:title="scenario.name" :name="index" :class="{'disable-scenario': !scenario.enable}"> :title="scenario.name" :name="index" :class="{'disable-scenario': !scenario.enable}">

View File

@ -1,33 +1,36 @@
<template> <template>
<div class="request-container"> <div class="request-container">
<draggable :list="this.scenario.requests" group="Request" class="request-draggable" ghost-class="request-ghost"> <draggable :list="this.scenario.requests" group="Request" class="request-draggable" ghost-class="request-ghost"
:disabled="isReference">
<div class="request-item" v-for="(request, index) in this.scenario.requests" :key="index" @click="select(request)" <div class="request-item" v-for="(request, index) in this.scenario.requests" :key="index" @click="select(request)"
:class="{'selected': isSelected(request), 'disable-request': !request.enable || !scenario.enable}"> :class="{'selected': isSelected(request), 'disable-request': !request.enable || !scenario.enable}">
<el-row type="flex" align="middle"> <el-row type="flex" align="middle">
<div class="request-type"> <div class="request-type">
{{request.showType()}} {{ request.showType() }}
</div> </div>
<div class="request-method"> <div class="request-method">
{{request.showMethod()}} {{ request.showMethod() }}
</div> </div>
<div class="request-name"> <div class="request-name">
{{request.name}} {{ request.name }}
</div> </div>
<div class="request-btn"> <div class="request-btn">
<el-dropdown trigger="click" @command="handleCommand"> <el-dropdown trigger="click" @command="handleCommand">
<span class="el-dropdown-link el-icon-more"/> <span class="el-dropdown-link el-icon-more"/>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'copy', index: index}"> <el-dropdown-item :disabled="isReadOnly" :command="{type: 'copy', index: index}">
{{$t('api_test.request.copy')}} {{ $t('api_test.request.copy') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'delete', index: index}"> <el-dropdown-item :disabled="isReadOnly" :command="{type: 'delete', index: index}">
{{$t('api_test.request.delete')}} {{ $t('api_test.request.delete') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="request.enable" :disabled="isReadOnly" :command="{type: 'disable', index: index}"> <el-dropdown-item v-if="request.enable" :disabled="isReadOnly"
{{$t('api_test.scenario.disable')}} :command="{type: 'disable', index: index}">
{{ $t('api_test.scenario.disable') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="!request.enable" :disabled="isReadOnly" :command="{type: 'enable', index: index}"> <el-dropdown-item v-if="!request.enable" :disabled="isReadOnly"
{{$t('api_test.scenario.enable')}} :command="{type: 'enable', index: index}">
{{ $t('api_test.scenario.enable') }}
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
@ -48,173 +51,176 @@
</template> </template>
<script> <script>
import {RequestFactory} from "../../model/ScenarioModel"; import {RequestFactory} from "../../model/ScenarioModel";
import draggable from 'vuedraggable'; import draggable from 'vuedraggable';
export default { export default {
name: "MsApiRequestConfig", name: "MsApiRequestConfig",
components: {draggable}, components: {draggable},
props: { props: {
scenario: Object, scenario: Object,
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
}
},
data() {
return {
selected: 0,
visible: false,
types: RequestFactory.TYPES,
type: ""
}
},
computed: {
isSelected() {
return function (request) {
return this.selected === request;
}
}
},
methods: {
createRequest: function (type) {
let request = new RequestFactory({type: type});
if (this.scenario.environmentId) {
request.useEnvironment = true;
}
this.scenario.requests.push(request);
this.type = "";
this.visible = false;
},
copyRequest: function (index) {
let request = this.scenario.requests[index];
this.scenario.requests.push(new RequestFactory(request));
},
disableRequest: function (index) {
this.scenario.requests[index].enable = false;
},
enableRequest: function (index) {
this.scenario.requests[index].enable = true;
},
deleteRequest: function (index) {
this.scenario.requests.splice(index, 1);
if (this.scenario.requests.length === 0) {
this.createRequest();
}
},
handleCommand: function (command) {
switch (command.type) {
case "copy":
this.copyRequest(command.index);
break;
case "delete":
this.deleteRequest(command.index);
break;
case "disable":
this.disableRequest(command.index);
break;
case "enable":
this.enableRequest(command.index);
break;
}
},
select: function (request) {
request.environment = this.scenario.environment;
if (!request.useEnvironment) {
request.useEnvironment = false;
}
request.dubboConfig = this.scenario.dubboConfig;
this.selected = request;
this.$emit("select", request, this.scenario);
}
},
created() {
this.select(this.scenario.requests[0]);
} }
},
data() {
return {
selected: 0,
visible: false,
types: RequestFactory.TYPES,
type: ""
}
},
computed: {
isSelected() {
return function (request) {
return this.selected === request;
}
},
isReference() {
return this.scenario.isReference();
}
},
methods: {
createRequest: function (type) {
let request = new RequestFactory({type: type});
if (this.scenario.environmentId) {
request.useEnvironment = true;
}
this.scenario.requests.push(request);
this.type = "";
this.visible = false;
},
copyRequest: function (index) {
let request = this.scenario.requests[index];
this.scenario.requests.push(new RequestFactory(request));
},
disableRequest: function (index) {
this.scenario.requests[index].enable = false;
},
enableRequest: function (index) {
this.scenario.requests[index].enable = true;
},
deleteRequest: function (index) {
this.scenario.requests.splice(index, 1);
if (this.scenario.requests.length === 0) {
this.createRequest();
}
},
handleCommand: function (command) {
switch (command.type) {
case "copy":
this.copyRequest(command.index);
break;
case "delete":
this.deleteRequest(command.index);
break;
case "disable":
this.disableRequest(command.index);
break;
case "enable":
this.enableRequest(command.index);
break;
}
},
select: function (request) {
request.environment = this.scenario.environment;
if (!request.useEnvironment) {
request.useEnvironment = false;
}
request.dubboConfig = this.scenario.dubboConfig;
this.selected = request;
this.$emit("select", request, this.scenario);
}
},
created() {
this.select(this.scenario.requests[0]);
} }
}
</script> </script>
<style scoped> <style scoped>
.request-item { .request-item {
border-left: 5px solid #1E90FF; border-left: 5px solid #1E90FF;
max-height: 40px; max-height: 40px;
border-top: 1px solid #EBEEF5; border-top: 1px solid #EBEEF5;
cursor: pointer; cursor: pointer;
} }
.request-item:first-child { .request-item:first-child {
border-top: 0; border-top: 0;
} }
.request-item:hover, .request-item.selected:hover { .request-item:hover, .request-item.selected:hover {
background-color: #ECF5FF; background-color: #ECF5FF;
} }
.request-item.selected { .request-item.selected {
background-color: #F5F5F5; background-color: #F5F5F5;
} }
.request-type { .request-type {
background-color: #409eff; background-color: #409eff;
color: #fff; color: #fff;
margin-left: 5px; margin-left: 5px;
padding: 4px 8px; padding: 4px 8px;
border-radius: 20px; border-radius: 20px;
white-space: nowrap; white-space: nowrap;
font-size: 12px; font-size: 12px;
display: inline-block; display: inline-block;
line-height: 1; line-height: 1;
text-align: center; text-align: center;
} }
.request-method { .request-method {
padding: 0 5px; padding: 0 5px;
color: #1E90FF; color: #1E90FF;
} }
.request-name { .request-name {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: 14px; font-size: 14px;
width: 100%; width: 100%;
} }
.request-btn { .request-btn {
float: right; float: right;
text-align: center; text-align: center;
height: 40px; height: 40px;
} }
.request-btn .el-icon-more { .request-btn .el-icon-more {
padding: 13px; padding: 13px;
} }
.request-create { .request-create {
width: 100%; width: 100%;
} }
.request-ghost { .request-ghost {
opacity: 0.5; opacity: 0.5;
background-color: #909399; background-color: #909399;
} }
.request-item.disable-request { .request-item.disable-request {
border-left-color: #909399; border-left-color: #909399;
} }
.disable-request .request-type { .disable-request .request-type {
background-color: #909399; background-color: #909399;
} }
.disable-request .request-method { .disable-request .request-method {
color: #909399; color: #909399;
} }
</style> </style>

View File

@ -504,8 +504,8 @@ export class DNSCacheManager extends DefaultTestElement {
let collectionPropHosts = this.collectionProp('DNSCacheManager.hosts'); let collectionPropHosts = this.collectionProp('DNSCacheManager.hosts');
hosts.forEach(host => { hosts.forEach(host => {
let elementProp = collectionPropHosts.elementProp('', 'StaticHost'); let elementProp = collectionPropHosts.elementProp(host.domain, 'StaticHost');
if (host && host.domain.trim() === domain.trim()) { if (host && host.domain.trim().indexOf(domain.trim()) != -1) {
elementProp.stringProp('StaticHost.Name', host.domain); elementProp.stringProp('StaticHost.Name', host.domain);
elementProp.stringProp('StaticHost.Address', host.ip); elementProp.stringProp('StaticHost.Address', host.ip);
} }

View File

@ -405,7 +405,7 @@ export class DubboRequest extends Request {
this.debugReport = undefined; this.debugReport = undefined;
this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor); this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor);
this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor); this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor);
this.enable = options.enable == undefined ? true : options.enable; this.enable = options.enable === undefined ? true : options.enable;
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor); this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor); this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
@ -956,8 +956,8 @@ class JMXGenerator {
let name = request.name + " DNSCacheManager"; let name = request.name + " DNSCacheManager";
let hosts = JSON.parse(request.environment.hosts); let hosts = JSON.parse(request.environment.hosts);
if (hosts.length > 0) { if (hosts.length > 0) {
let domain = request.environment.protocol + "://" + request.environment.domain; //let domain = request.environment.protocol + "://" + request.environment.domain;
threadGroup.put(new DNSCacheManager(name, domain, hosts)); threadGroup.put(new DNSCacheManager(name, request.environment.domain, hosts));
} }
} }
} }
@ -1038,7 +1038,7 @@ class JMXGenerator {
this.addRequestBodyFile(httpSamplerProxy, request, testId); this.addRequestBodyFile(httpSamplerProxy, request, testId);
} else { } else {
httpSamplerProxy.boolProp('HTTPSampler.postBodyRaw', true); httpSamplerProxy.boolProp('HTTPSampler.postBodyRaw', true);
body.push({name: '', value: request.body.raw, encode: false}); body.push({name: '', value: request.body.raw, encode: false, enable: true});
} }
httpSamplerProxy.add(new HTTPSamplerArguments(body)); httpSamplerProxy.add(new HTTPSamplerArguments(body));

View File

@ -0,0 +1,86 @@
<template>
<el-dialog v-loading="result.loading"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
>
<el-table
:data="tableData"
highlight-current-row
@current-change="handleCurrentChange"
style="width: 100%">
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
<template v-slot:default="scope">
{{ scope.row.description }}
</template>
</el-table-column>
<el-table-column
sortable
prop="createTime"
:label="$t('commons.create_time')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
sortable
prop="updateTime"
:label="$t('commons.update_time')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
</el-table>
<template v-slot:footer>
<div class="dialog-footer">
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="submit()"/>
</div>
</template>
</el-dialog>
</template>
<script>
import MsDialogFooter from "../../../common/components/MsDialogFooter";
export default {
name: "SwitchProject",
components: {MsDialogFooter},
data() {
return {
tableData: [],
result: {},
dialogVisible: false,
projectId: ''
}
},
methods: {
open(planId) {
this.dialogVisible = true;
this.initData(planId);
},
initData(planId) {
this.result = this.$get("/test/plan/project/" + planId,res => {
this.tableData = res.data;
})
},
handleCurrentChange(currentRow) {
// initData
if (currentRow) {
this.projectId = currentRow.id;
}
},
submit() {
this.$emit('getProjectNode', this.projectId);
this.dialogVisible = false;
}
}
}
</script>
<style scoped>
</style>

View File

@ -230,10 +230,14 @@ export default {
this.$emit("refresh"); this.$emit("refresh");
}, },
nodeExpand(data) { nodeExpand(data) {
this.expandedNode.push(data.id); if (data.id) {
this.expandedNode.push(data.id);
}
}, },
nodeCollapse(data) { nodeCollapse(data) {
this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1); if (data.id) {
this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1);
}
} }
} }
}; };

View File

@ -90,6 +90,12 @@
initTableData() { initTableData() {
this.result = this.$post('/test/plan/list/all/relate', this.condition, response => { this.result = this.$post('/test/plan/list/all/relate', this.condition, response => {
this.tableData = response.data; this.tableData = response.data;
for (let i = 0; i < this.tableData.length; i++) {
let path = "/test/plan/project/name/" + this.tableData[i].id;
this.$get(path, res => {
this.$set(this.tableData[i], "projectName", res.data);
})
}
}); });
}, },
intoPlan(row, event, column) { intoPlan(row, event, column) {

View File

@ -22,11 +22,14 @@
</el-col> </el-col>
<el-col :span="11" :offset="2"> <el-col :span="11" :offset="2">
<el-form-item :label="$t('test_track.plan.plan_project')" :label-width="formLabelWidth" prop="projectId"> <el-form-item :label="$t('test_track.plan.plan_project')" :label-width="formLabelWidth" prop="projectIds">
<el-select <el-select
:disabled="(form.status == null) ? false : true" :disabled="(form.status == null) ? false : true"
v-model="form.projectId" v-model="form.projectIds"
:placeholder="$t('test_track.plan.input_plan_project')" :placeholder="$t('test_track.plan.input_plan_project')"
multiple
style="width: 100%"
collapse-tags
filterable> filterable>
<el-option <el-option
v-for="item in projects" v-for="item in projects"
@ -68,7 +71,7 @@
</el-row> </el-row>
<el-row type="flex" justify="left" style="margin-top: 10px;"> <el-row type="flex" justify="left" style="margin-top: 10px;">
<el-col :span="19" :offset="1"> <el-col :span="23" :offset="1">
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description"> <el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
<el-input v-model="form.description" <el-input v-model="form.description"
type="textarea" type="textarea"
@ -124,7 +127,7 @@ export default {
dialogFormVisible: false, dialogFormVisible: false,
form: { form: {
name: '', name: '',
projectId: '', projectIds: [],
principal: '', principal: '',
stage: '', stage: '',
description: '' description: ''
@ -134,7 +137,7 @@ export default {
{required: true, message: this.$t('test_track.plan.input_plan_name'), trigger: 'blur'}, {required: true, message: this.$t('test_track.plan.input_plan_name'), trigger: 'blur'},
{max: 30, message: this.$t('test_track.length_less_than') + '30', trigger: 'blur'} {max: 30, message: this.$t('test_track.length_less_than') + '30', trigger: 'blur'}
], ],
projectId: [{required: true, message: this.$t('test_track.plan.input_plan_project'), trigger: 'change'}], projectIds: [{required: true, message: this.$t('test_track.plan.input_plan_project'), trigger: 'change'}],
principal: [{required: true, message: this.$t('test_track.plan.input_plan_principal'), trigger: 'change'}], principal: [{required: true, message: this.$t('test_track.plan.input_plan_principal'), trigger: 'change'}],
stage: [{required: true, message: this.$t('test_track.plan.input_plan_stage'), trigger: 'change'}], stage: [{required: true, message: this.$t('test_track.plan.input_plan_stage'), trigger: 'change'}],
description: [{max: 200, message: this.$t('test_track.length_less_than') + '200', trigger: 'blur'}] description: [{max: 200, message: this.$t('test_track.length_less_than') + '200', trigger: 'blur'}]
@ -213,7 +216,7 @@ export default {
this.$refs['planFrom'].validate((valid) => { this.$refs['planFrom'].validate((valid) => {
this.$refs['planFrom'].resetFields(); this.$refs['planFrom'].resetFields();
this.form.name = ''; this.form.name = '';
this.form.projectId = ''; this.form.projectIds = [];
this.form.principal = ''; this.form.principal = '';
this.form.stage = ''; this.form.stage = '';
this.form.description = ''; this.form.description = '';

View File

@ -191,6 +191,16 @@ export default {
let data = response.data; let data = response.data;
this.total = data.itemCount; this.total = data.itemCount;
this.tableData = data.listObject; this.tableData = data.listObject;
for (let i = 0; i < this.tableData.length; i++) {
let path = "/test/plan/project/" + this.tableData[i].id;
this.$get(path, res => {
let arr = res.data;
let projectName = arr.map(data => data.name).join("、");
let projectIds = arr.map(data => data.id);
this.$set(this.tableData[i], "projectName", projectName);
this.$set(this.tableData[i], "projectIds", projectIds);
})
}
}); });
}, },
buildPagePath(path) { buildPagePath(path) {

View File

@ -6,10 +6,12 @@
:visible.sync="dialogFormVisible" :visible.sync="dialogFormVisible"
@close="close" @close="close"
width="60%" v-loading="result.loading" width="60%" v-loading="result.loading"
:close-on-click-modal="false"
top="50px"> top="50px">
<el-container class="main-content"> <el-container class="main-content">
<el-aside class="tree-aside" width="250px"> <el-aside class="tree-aside" width="250px">
<el-link type="primary" class="project-link" @click="switchProject">{{projectName ? projectName : '切换项目' }}</el-link>
<node-tree class="node-tree" <node-tree class="node-tree"
@nodeSelectEvent="nodeChange" @nodeSelectEvent="nodeChange"
@refresh="refresh" @refresh="refresh"
@ -71,6 +73,8 @@
</template> </template>
</el-dialog> </el-dialog>
<switch-project ref="switchProject" @getProjectNode="getProjectNode"/>
</div> </div>
</template> </template>
@ -86,6 +90,7 @@
import MsTableAdvSearchBar from "../../../../common/components/search/MsTableAdvSearchBar"; import MsTableAdvSearchBar from "../../../../common/components/search/MsTableAdvSearchBar";
import MsTableHeader from "../../../../common/components/MsTableHeader"; import MsTableHeader from "../../../../common/components/MsTableHeader";
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components"; import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
import SwitchProject from "../../../case/components/SwitchProject";
export default { export default {
name: "TestCaseRelevance", name: "TestCaseRelevance",
@ -96,7 +101,8 @@
TypeTableItem, TypeTableItem,
MsTableSearchBar, MsTableSearchBar,
MsTableAdvSearchBar, MsTableAdvSearchBar,
MsTableHeader MsTableHeader,
SwitchProject
}, },
data() { data() {
return { return {
@ -108,6 +114,9 @@
treeNodes: [], treeNodes: [],
selectNodeIds: [], selectNodeIds: [],
selectNodeNames: [], selectNodeNames: [],
projectId: '',
projectName: '',
projects: [],
condition: { condition: {
components: TEST_CASE_CONFIGS components: TEST_CASE_CONFIGS
}, },
@ -135,6 +144,9 @@
}, },
selectNodeIds() { selectNodeIds() {
this.getCaseNames(); this.getCaseNames();
},
projectId() {
this.getProjectNode();
} }
}, },
updated() { updated() {
@ -157,7 +169,6 @@
}); });
}, },
getCaseNames() { getCaseNames() {
let param = {};
if (this.planId) { if (this.planId) {
// param.planId = this.planId; // param.planId = this.planId;
this.condition.planId = this.planId; this.condition.planId = this.planId;
@ -168,12 +179,17 @@
} else { } else {
this.condition.nodeIds = []; this.condition.nodeIds = [];
} }
this.result = this.$post('/test/case/name', this.condition, response => {
this.testCases = response.data; if (this.projectId) {
this.testCases.forEach(item => { this.condition.projectId = this.projectId;
item.checked = false; this.result = this.$post('/test/case/name', this.condition, response => {
this.testCases = response.data;
this.testCases.forEach(item => {
item.checked = false;
});
}); });
}); }
}, },
handleSelectAll(selection) { handleSelectAll(selection) {
if (selection.length > 0) { if (selection.length > 0) {
@ -203,13 +219,18 @@
initData() { initData() {
this.getCaseNames(); this.getCaseNames();
this.getAllNodeTreeByPlanId(); this.getAllNodeTreeByPlanId();
this.getProject();
}, },
refresh() { refresh() {
this.close(); this.close();
}, },
getAllNodeTreeByPlanId() { getAllNodeTreeByPlanId() {
if (this.planId) { if (this.planId) {
this.result = this.$get("/case/node/list/all/plan/" + this.planId, response => { let param = {
testPlanId: this.planId,
projectId: this.projectId
};
this.result = this.$post("/case/node/list/all/plan", param , response => {
this.treeNodes = response.data; this.treeNodes = response.data;
}); });
} }
@ -233,6 +254,36 @@
}) })
}) })
}, },
getProject() {
if (this.planId) {
this.$get("/test/plan/project/" + this.planId,res => {
let data = res.data;
if (data) {
this.projects = data;
this.projectId = data[0].id;
this.projectName = data[0].name;
}
})
}
},
switchProject() {
this.$refs.switchProject.open(this.planId);
},
getProjectNode(projectId) {
const index = this.projects.findIndex(project => project.id === projectId);
if (index !== -1) {
this.projectName = this.projects[index].name;
}
if (projectId) {
this.projectId = projectId;
}
this.result = this.$post("/case/node/list/all/plan",
{testPlanId: this.planId, projectId: this.projectId} , response => {
this.treeNodes = response.data;
});
this.selectNodeIds = [];
}
} }
} }
</script> </script>
@ -281,4 +332,10 @@
/*border: 1px solid #EBEEF5;*/ /*border: 1px solid #EBEEF5;*/
} }
.project-link {
float: right;
margin-right: 12px;
margin-bottom: 10px;
}
</style> </style>