Merge branch 'master' of github.com:metersphere/metersphere

This commit is contained in:
chenjianxing 2021-03-22 18:16:40 +08:00
commit 3f04d930d6
49 changed files with 1158 additions and 963 deletions

View File

@ -32,6 +32,7 @@ import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.commons.constants.LoopConstants; import io.metersphere.commons.constants.LoopConstants;
import io.metersphere.commons.constants.MsTestElementConstants; import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils; import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
@ -48,6 +49,7 @@ import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree; import org.apache.jorphan.collections.ListedHashTree;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -211,6 +213,9 @@ public abstract class MsTestElement {
csvDataSet.setName(StringUtils.isEmpty(item.getName()) ? "CSVDataSet" : item.getName()); csvDataSet.setName(StringUtils.isEmpty(item.getName()) ? "CSVDataSet" : item.getName());
csvDataSet.setProperty("fileEncoding", StringUtils.isEmpty(item.getEncoding()) ? "UTF-8" : item.getEncoding()); csvDataSet.setProperty("fileEncoding", StringUtils.isEmpty(item.getEncoding()) ? "UTF-8" : item.getEncoding());
if (CollectionUtils.isNotEmpty(item.getFiles())) { if (CollectionUtils.isNotEmpty(item.getFiles())) {
if (new File(BODY_FILE_DIR + "/" + item.getFiles().get(0).getId() + "_" + item.getFiles().get(0).getName()).exists()) {
MSException.throwException(StringUtils.isEmpty(item.getName()) ? "CSVDataSet" : item.getName() + "[ CSV文件不存在 ]");
}
csvDataSet.setProperty("filename", BODY_FILE_DIR + "/" + item.getFiles().get(0).getId() + "_" + item.getFiles().get(0).getName()); csvDataSet.setProperty("filename", BODY_FILE_DIR + "/" + item.getFiles().get(0).getId() + "_" + item.getFiles().get(0).getName());
} }
csvDataSet.setIgnoreFirstLine(false); csvDataSet.setIgnoreFirstLine(false);

View File

@ -67,7 +67,8 @@ public class MsAssertions extends MsTestElement {
private ResponseAssertion responseAssertion(MsAssertionRegex assertionRegex) { private ResponseAssertion responseAssertion(MsAssertionRegex assertionRegex) {
ResponseAssertion assertion = new ResponseAssertion(); ResponseAssertion assertion = new ResponseAssertion();
assertion.setEnabled(this.isEnable()); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : assertionRegex.getDescription()); assertion.setName(assertionRegex.getDescription());
assertion.setName(StringUtils.isNotEmpty(assertionRegex.getDescription()) ? assertionRegex.getDescription() : this.getName());
assertion.setProperty(TestElement.TEST_CLASS, ResponseAssertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, ResponseAssertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AssertionGui"));
assertion.setAssumeSuccess(assertionRegex.isAssumeSuccess()); assertion.setAssumeSuccess(assertionRegex.isAssumeSuccess());
@ -92,7 +93,8 @@ public class MsAssertions extends MsTestElement {
private JSONPathAssertion jsonPathAssertion(MsAssertionJsonPath assertionJsonPath) { private JSONPathAssertion jsonPathAssertion(MsAssertionJsonPath assertionJsonPath) {
JSONPathAssertion assertion = new JSONPathAssertion(); JSONPathAssertion assertion = new JSONPathAssertion();
assertion.setEnabled(this.isEnable()); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "JSONPathAssertion"); assertion.setName(StringUtils.isNotEmpty(assertionJsonPath.getDescription()) ? assertionJsonPath.getDescription() : this.getName());
/* assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "JSONPathAssertion");*/
assertion.setProperty(TestElement.TEST_CLASS, JSONPathAssertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, JSONPathAssertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPathAssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPathAssertionGui"));
assertion.setJsonPath(assertionJsonPath.getExpression()); assertion.setJsonPath(assertionJsonPath.getExpression());
@ -112,7 +114,8 @@ public class MsAssertions extends MsTestElement {
private XPath2Assertion xPath2Assertion(MsAssertionXPath2 assertionXPath2) { private XPath2Assertion xPath2Assertion(MsAssertionXPath2 assertionXPath2) {
XPath2Assertion assertion = new XPath2Assertion(); XPath2Assertion assertion = new XPath2Assertion();
assertion.setEnabled(this.isEnable()); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "XPath2Assertion"); assertion.setName(StringUtils.isNotEmpty(assertionXPath2.getExpression()) ? assertionXPath2.getExpression() : this.getName());
/*assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "XPath2Assertion");*/
assertion.setProperty(TestElement.TEST_CLASS, XPath2Assertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, XPath2Assertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2AssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2AssertionGui"));
assertion.setXPathString(assertionXPath2.getExpression()); assertion.setXPathString(assertionXPath2.getExpression());
@ -123,7 +126,8 @@ public class MsAssertions extends MsTestElement {
private DurationAssertion durationAssertion(MsAssertionDuration assertionDuration) { private DurationAssertion durationAssertion(MsAssertionDuration assertionDuration) {
DurationAssertion assertion = new DurationAssertion(); DurationAssertion assertion = new DurationAssertion();
assertion.setEnabled(this.isEnable()); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "Response In Time: " + assertionDuration.getValue()); assertion.setName("Response In Time: " + assertionDuration.getValue());
/* assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "Response In Time: " + assertionDuration.getValue());*/
assertion.setProperty(TestElement.TEST_CLASS, DurationAssertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, DurationAssertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DurationAssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DurationAssertionGui"));
assertion.setAllowedDuration(assertionDuration.getValue()); assertion.setAllowedDuration(assertionDuration.getValue());
@ -133,7 +137,8 @@ public class MsAssertions extends MsTestElement {
private JSR223Assertion jsr223Assertion(MsAssertionJSR223 assertionJSR223) { private JSR223Assertion jsr223Assertion(MsAssertionJSR223 assertionJSR223) {
JSR223Assertion assertion = new JSR223Assertion(); JSR223Assertion assertion = new JSR223Assertion();
assertion.setEnabled(this.isEnable()); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "JSR223Assertion"); assertion.setName(StringUtils.isNotEmpty(assertionJSR223.getDesc()) ? assertionJSR223.getDesc() : this.getName());
/*assertion.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "JSR223Assertion");*/
assertion.setProperty(TestElement.TEST_CLASS, JSR223Assertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, JSR223Assertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
assertion.setProperty("cacheKey", "true"); assertion.setProperty("cacheKey", "true");

View File

@ -70,7 +70,8 @@ public class MsExtract extends MsTestElement {
RegexExtractor extractor = new RegexExtractor(); RegexExtractor extractor = new RegexExtractor();
extractor.setEnabled(this.isEnable()); extractor.setEnabled(this.isEnable());
extractor.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : " RegexExtractor"); extractor.setName(StringUtils.isNotEmpty(extractRegex.getVariable()) ? extractRegex.getVariable() : this.getName());
/*extractor.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : " RegexExtractor");*/
extractor.setProperty(TestElement.TEST_CLASS, RegexExtractor.class.getName()); extractor.setProperty(TestElement.TEST_CLASS, RegexExtractor.class.getName());
extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("RegexExtractorGui")); extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("RegexExtractorGui"));
extractor.setRefName(extractRegex.getVariable()); extractor.setRefName(extractRegex.getVariable());
@ -88,7 +89,8 @@ public class MsExtract extends MsTestElement {
private XPath2Extractor xPath2Extractor(MsExtractXPath extractXPath, StringJoiner extract) { private XPath2Extractor xPath2Extractor(MsExtractXPath extractXPath, StringJoiner extract) {
XPath2Extractor extractor = new XPath2Extractor(); XPath2Extractor extractor = new XPath2Extractor();
extractor.setEnabled(this.isEnable()); extractor.setEnabled(this.isEnable());
extractor.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : " XPath2Extractor"); extractor.setName(StringUtils.isNotEmpty(extractXPath.getVariable()) ? extractXPath.getVariable() : this.getName());
/*extractor.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : " XPath2Extractor");*/
extractor.setProperty(TestElement.TEST_CLASS, XPath2Extractor.class.getName()); extractor.setProperty(TestElement.TEST_CLASS, XPath2Extractor.class.getName());
extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2ExtractorGui")); extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2ExtractorGui"));
extractor.setRefName(extractXPath.getVariable()); extractor.setRefName(extractXPath.getVariable());
@ -103,7 +105,8 @@ public class MsExtract extends MsTestElement {
private JSONPostProcessor jsonPostProcessor(MsExtractJSONPath extractJSONPath, StringJoiner extract) { private JSONPostProcessor jsonPostProcessor(MsExtractJSONPath extractJSONPath, StringJoiner extract) {
JSONPostProcessor extractor = new JSONPostProcessor(); JSONPostProcessor extractor = new JSONPostProcessor();
extractor.setEnabled(this.isEnable()); extractor.setEnabled(this.isEnable());
extractor.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : " JSONExtractor"); extractor.setName(StringUtils.isNotEmpty(extractJSONPath.getVariable()) ? extractJSONPath.getVariable() : this.getName());
/*extractor.setName(StringUtils.isNotEmpty(this.getName()) ? this.getName() : " JSONExtractor");*/
extractor.setProperty(TestElement.TEST_CLASS, JSONPostProcessor.class.getName()); extractor.setProperty(TestElement.TEST_CLASS, JSONPostProcessor.class.getName());
extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPostProcessorGui")); extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPostProcessorGui"));
extractor.setRefNames(extractJSONPath.getVariable()); extractor.setRefNames(extractJSONPath.getVariable());

View File

@ -3,11 +3,14 @@ package io.metersphere.api.dto.definition.request.unknown;
import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.annotation.JSONType;
import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.CSVDataSet;
import org.apache.jmeter.save.SaveService; import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan; import org.apache.jmeter.testelement.TestPlan;
@ -15,6 +18,7 @@ import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
@ -53,6 +57,13 @@ public class MsJmeterElement extends MsTestElement {
if (!config.isOperating() && scriptWrapper instanceof ThreadGroup && !((ThreadGroup) scriptWrapper).isEnabled()) { if (!config.isOperating() && scriptWrapper instanceof ThreadGroup && !((ThreadGroup) scriptWrapper).isEnabled()) {
LogUtil.info(((ThreadGroup) scriptWrapper).getName() + "是被禁用线程组不加入执行"); LogUtil.info(((ThreadGroup) scriptWrapper).getName() + "是被禁用线程组不加入执行");
} else { } else {
// CSV数据检查文件路径是否还存在
if (scriptWrapper instanceof CSVDataSet) {
String path = ((CSVDataSet) scriptWrapper).getPropertyAsString("filename");
if (!new File(path).exists()) {
MSException.throwException(StringUtils.isEmpty(((CSVDataSet) scriptWrapper).getName()) ? "CSVDataSet" : ((CSVDataSet) scriptWrapper).getName() + "[ CSV文件不存在 ]");
}
}
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) { for (MsTestElement el : hashTree) {
el.toHashTree(elementTree, el.getHashTree(), config); el.toHashTree(elementTree, el.getHashTree(), config);
@ -62,6 +73,7 @@ public class MsJmeterElement extends MsTestElement {
} }
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
MSException.throwException(ex.getMessage());
} }
} }

View File

@ -535,8 +535,12 @@ public class ApiAutomationService {
} }
// 生成报告和HashTree // 生成报告和HashTree
HashTree hashTree = generateHashTree(item, reportId, planEnvMap); HashTree hashTree = null;
try {
hashTree = generateHashTree(item, reportId, planEnvMap);
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
//存储报告 //存储报告
batchMapper.insert(report); batchMapper.insert(report);
@ -602,7 +606,12 @@ public class ApiAutomationService {
} }
ParameterConfig config = new ParameterConfig(); ParameterConfig config = new ParameterConfig();
config.setConfig(envConfig); config.setConfig(envConfig);
HashTree hashTree = request.getTestElement().generateHashTree(config); HashTree hashTree = null;
try {
hashTree = request.getTestElement().generateHashTree(config);
} catch (Exception e) {
MSException.throwException(e.getMessage());
}
// 调用执行方法 // 调用执行方法
APIScenarioReportResult reportResult = createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(), APIScenarioReportResult reportResult = createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
SessionUtils.getUserId()); SessionUtils.getUserId());

View File

@ -1,18 +1,19 @@
package io.metersphere.base.domain; package io.metersphere.base.domain;
import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import lombok.Data;
@Data @Data
public class TestCaseTest implements Serializable { public class TestCaseTest implements Serializable {
private String id;
private String testCaseId; private String testCaseId;
private String testId; private String testId;
private String testType; private String testType;
private Long createTime;
private Long updateTime;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -104,76 +104,6 @@ public class TestCaseTestExample {
criteria.add(new Criterion(condition, value1, value2)); criteria.add(new Criterion(condition, value1, value2));
} }
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andTestCaseIdIsNull() { public Criteria andTestCaseIdIsNull() {
addCriterion("test_case_id is null"); addCriterion("test_case_id is null");
return (Criteria) this; return (Criteria) this;
@ -383,6 +313,126 @@ public class TestCaseTestExample {
addCriterion("test_type not between", value1, value2, "testType"); addCriterion("test_type not between", value1, value2, "testType");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andCreateTimeIsNull() {
addCriterion("create_time is null");
return (Criteria) this;
}
public Criteria andCreateTimeIsNotNull() {
addCriterion("create_time is not null");
return (Criteria) this;
}
public Criteria andCreateTimeEqualTo(Long value) {
addCriterion("create_time =", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotEqualTo(Long value) {
addCriterion("create_time <>", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThan(Long value) {
addCriterion("create_time >", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("create_time >=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThan(Long value) {
addCriterion("create_time <", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThanOrEqualTo(Long value) {
addCriterion("create_time <=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeIn(List<Long> values) {
addCriterion("create_time in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotIn(List<Long> values) {
addCriterion("create_time not in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeBetween(Long value1, Long value2) {
addCriterion("create_time between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotBetween(Long value1, Long value2) {
addCriterion("create_time not between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andUpdateTimeIsNull() {
addCriterion("update_time is null");
return (Criteria) this;
}
public Criteria andUpdateTimeIsNotNull() {
addCriterion("update_time is not null");
return (Criteria) this;
}
public Criteria andUpdateTimeEqualTo(Long value) {
addCriterion("update_time =", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotEqualTo(Long value) {
addCriterion("update_time <>", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeGreaterThan(Long value) {
addCriterion("update_time >", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("update_time >=", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeLessThan(Long value) {
addCriterion("update_time <", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeLessThanOrEqualTo(Long value) {
addCriterion("update_time <=", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeIn(List<Long> values) {
addCriterion("update_time in", values, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotIn(List<Long> values) {
addCriterion("update_time not in", values, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeBetween(Long value1, Long value2) {
addCriterion("update_time between", value1, value2, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotBetween(Long value1, Long value2) {
addCriterion("update_time not between", value1, value2, "updateTime");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -2,30 +2,21 @@ package io.metersphere.base.mapper;
import io.metersphere.base.domain.TestCaseTest; import io.metersphere.base.domain.TestCaseTest;
import io.metersphere.base.domain.TestCaseTestExample; import io.metersphere.base.domain.TestCaseTestExample;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface TestCaseTestMapper { public interface TestCaseTestMapper {
long countByExample(TestCaseTestExample example); long countByExample(TestCaseTestExample example);
int deleteByExample(TestCaseTestExample example); int deleteByExample(TestCaseTestExample example);
int deleteByPrimaryKey(String id);
int insert(TestCaseTest record); int insert(TestCaseTest record);
int insertSelective(TestCaseTest record); int insertSelective(TestCaseTest record);
List<TestCaseTest> selectByExample(TestCaseTestExample example); List<TestCaseTest> selectByExample(TestCaseTestExample example);
TestCaseTest selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") TestCaseTest record, @Param("example") TestCaseTestExample example); int updateByExampleSelective(@Param("record") TestCaseTest record, @Param("example") TestCaseTestExample example);
int updateByExample(@Param("record") TestCaseTest record, @Param("example") TestCaseTestExample example); int updateByExample(@Param("record") TestCaseTest record, @Param("example") TestCaseTestExample example);
int updateByPrimaryKeySelective(TestCaseTest record);
int updateByPrimaryKey(TestCaseTest record);
} }

View File

@ -1,201 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.base.mapper.TestCaseTestMapper"> <mapper namespace="io.metersphere.base.mapper.TestCaseTestMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestCaseTest"> <resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestCaseTest">
<id column="id" jdbcType="VARCHAR" property="id"/> <result column="test_case_id" jdbcType="VARCHAR" property="testCaseId" />
<result column="test_case_id" jdbcType="VARCHAR" property="testCaseId"/> <result column="test_id" jdbcType="VARCHAR" property="testId" />
<result column="test_id" jdbcType="VARCHAR" property="testId"/> <result column="test_type" jdbcType="VARCHAR" property="testType" />
<result column="test_type" jdbcType="VARCHAR" property="testType"/> <result column="create_time" jdbcType="BIGINT" property="createTime" />
</resultMap> <result column="update_time" jdbcType="BIGINT" property="updateTime" />
<sql id="Example_Where_Clause"> </resultMap>
<where> <sql id="Example_Where_Clause">
<foreach collection="oredCriteria" item="criteria" separator="or"> <where>
<if test="criteria.valid"> <foreach collection="oredCriteria" item="criteria" separator="or">
<trim prefix="(" prefixOverrides="and" suffix=")"> <if test="criteria.valid">
<foreach collection="criteria.criteria" item="criterion"> <trim prefix="(" prefixOverrides="and" suffix=")">
<choose> <foreach collection="criteria.criteria" item="criterion">
<when test="criterion.noValue"> <choose>
and ${criterion.condition} <when test="criterion.noValue">
</when> and ${criterion.condition}
<when test="criterion.singleValue"> </when>
and ${criterion.condition} #{criterion.value} <when test="criterion.singleValue">
</when> and ${criterion.condition} #{criterion.value}
<when test="criterion.betweenValue"> </when>
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} <when test="criterion.betweenValue">
</when> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
<when test="criterion.listValue"> </when>
and ${criterion.condition} <when test="criterion.listValue">
<foreach close=")" collection="criterion.value" item="listItem" open="(" and ${criterion.condition}
separator=","> <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem} #{listItem}
</foreach> </foreach>
</when> </when>
</choose> </choose>
</foreach>
</trim>
</if>
</foreach> </foreach>
</where> </trim>
</sql> </if>
<sql id="Update_By_Example_Where_Clause"> </foreach>
<where> </where>
<foreach collection="example.oredCriteria" item="criteria" separator="or"> </sql>
<if test="criteria.valid"> <sql id="Update_By_Example_Where_Clause">
<trim prefix="(" prefixOverrides="and" suffix=")"> <where>
<foreach collection="criteria.criteria" item="criterion"> <foreach collection="example.oredCriteria" item="criteria" separator="or">
<choose> <if test="criteria.valid">
<when test="criterion.noValue"> <trim prefix="(" prefixOverrides="and" suffix=")">
and ${criterion.condition} <foreach collection="criteria.criteria" item="criterion">
</when> <choose>
<when test="criterion.singleValue"> <when test="criterion.noValue">
and ${criterion.condition} #{criterion.value} and ${criterion.condition}
</when> </when>
<when test="criterion.betweenValue"> <when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} and ${criterion.condition} #{criterion.value}
</when> </when>
<when test="criterion.listValue"> <when test="criterion.betweenValue">
and ${criterion.condition} and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
<foreach close=")" collection="criterion.value" item="listItem" open="(" </when>
separator=","> <when test="criterion.listValue">
#{listItem} and ${criterion.condition}
</foreach> <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
</when> #{listItem}
</choose> </foreach>
</foreach> </when>
</trim> </choose>
</if>
</foreach> </foreach>
</where> </trim>
</sql>
<sql id="Base_Column_List">
id, test_case_id, test_id, test_type
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.TestCaseTestExample"
resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if> </if>
<include refid="Base_Column_List"/> </foreach>
from test_case_test </where>
<if test="_parameter != null"> </sql>
<include refid="Example_Where_Clause"/> <sql id="Base_Column_List">
</if> test_case_id, test_id, test_type, create_time, update_time
<if test="orderByClause != null"> </sql>
order by ${orderByClause} <select id="selectByExample" parameterType="io.metersphere.base.domain.TestCaseTestExample" resultMap="BaseResultMap">
</if> select
</select> <if test="distinct">
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap"> distinct
select </if>
<include refid="Base_Column_List"/> <include refid="Base_Column_List" />
from test_case_test from test_case_test
where id = #{id,jdbcType=VARCHAR} <if test="_parameter != null">
</select> <include refid="Example_Where_Clause" />
<delete id="deleteByPrimaryKey" parameterType="java.lang.String"> </if>
delete <if test="orderByClause != null">
from test_case_test order by ${orderByClause}
where id = #{id,jdbcType=VARCHAR} </if>
</delete> </select>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.TestCaseTestExample"> <delete id="deleteByExample" parameterType="io.metersphere.base.domain.TestCaseTestExample">
delete from test_case_test delete from test_case_test
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Example_Where_Clause"/> <include refid="Example_Where_Clause" />
</if> </if>
</delete> </delete>
<insert id="insert" parameterType="io.metersphere.base.domain.TestCaseTest"> <insert id="insert" parameterType="io.metersphere.base.domain.TestCaseTest">
insert into test_case_test (id, test_case_id, test_id, insert into test_case_test (test_case_id, test_id, test_type,
test_type) create_time, update_time)
values (#{id,jdbcType=VARCHAR}, #{testCaseId,jdbcType=VARCHAR}, #{testId,jdbcType=VARCHAR}, values (#{testCaseId,jdbcType=VARCHAR}, #{testId,jdbcType=VARCHAR}, #{testType,jdbcType=VARCHAR},
#{testType,jdbcType=VARCHAR}) #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT})
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseTest"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseTest">
insert into test_case_test insert into test_case_test
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null"> <if test="testCaseId != null">
id, test_case_id,
</if> </if>
<if test="testCaseId != null"> <if test="testId != null">
test_case_id, test_id,
</if> </if>
<if test="testId != null"> <if test="testType != null">
test_id, test_type,
</if> </if>
<if test="testType != null"> <if test="createTime != null">
test_type, create_time,
</if> </if>
</trim> <if test="updateTime != null">
<trim prefix="values (" suffix=")" suffixOverrides=","> update_time,
<if test="id != null"> </if>
#{id,jdbcType=VARCHAR}, </trim>
</if> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="testCaseId != null"> <if test="testCaseId != null">
#{testCaseId,jdbcType=VARCHAR}, #{testCaseId,jdbcType=VARCHAR},
</if> </if>
<if test="testId != null"> <if test="testId != null">
#{testId,jdbcType=VARCHAR}, #{testId,jdbcType=VARCHAR},
</if> </if>
<if test="testType != null"> <if test="testType != null">
#{testType,jdbcType=VARCHAR}, #{testType,jdbcType=VARCHAR},
</if> </if>
</trim> <if test="createTime != null">
</insert> #{createTime,jdbcType=BIGINT},
<select id="countByExample" parameterType="io.metersphere.base.domain.TestCaseTestExample" </if>
resultType="java.lang.Long"> <if test="updateTime != null">
select count(*) from test_case_test #{updateTime,jdbcType=BIGINT},
<if test="_parameter != null"> </if>
<include refid="Example_Where_Clause"/> </trim>
</if> </insert>
</select> <select id="countByExample" parameterType="io.metersphere.base.domain.TestCaseTestExample" resultType="java.lang.Long">
<update id="updateByExampleSelective" parameterType="map"> select count(*) from test_case_test
update test_case_test <if test="_parameter != null">
<set> <include refid="Example_Where_Clause" />
<if test="record.id != null"> </if>
id = #{record.id,jdbcType=VARCHAR}, </select>
</if> <update id="updateByExampleSelective" parameterType="map">
<if test="record.testCaseId != null"> update test_case_test
test_case_id = #{record.testCaseId,jdbcType=VARCHAR}, <set>
</if> <if test="record.testCaseId != null">
<if test="record.testId != null">
test_id = #{record.testId,jdbcType=VARCHAR},
</if>
<if test="record.testType != null">
test_type = #{record.testType,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause"/>
</if>
</update>
<update id="updateByExample" parameterType="map">
update test_case_test
set id = #{record.id,jdbcType=VARCHAR},
test_case_id = #{record.testCaseId,jdbcType=VARCHAR}, test_case_id = #{record.testCaseId,jdbcType=VARCHAR},
</if>
<if test="record.testId != null">
test_id = #{record.testId,jdbcType=VARCHAR}, test_id = #{record.testId,jdbcType=VARCHAR},
test_type = #{record.testType,jdbcType=VARCHAR} </if>
<if test="_parameter != null"> <if test="record.testType != null">
<include refid="Update_By_Example_Where_Clause"/> test_type = #{record.testType,jdbcType=VARCHAR},
</if> </if>
</update> <if test="record.createTime != null">
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestCaseTest"> create_time = #{record.createTime,jdbcType=BIGINT},
update test_case_test </if>
<set> <if test="record.updateTime != null">
<if test="testCaseId != null"> update_time = #{record.updateTime,jdbcType=BIGINT},
test_case_id = #{testCaseId,jdbcType=VARCHAR}, </if>
</if> </set>
<if test="testId != null"> <if test="_parameter != null">
test_id = #{testId,jdbcType=VARCHAR}, <include refid="Update_By_Example_Where_Clause" />
</if> </if>
<if test="testType != null"> </update>
test_type = #{testType,jdbcType=VARCHAR}, <update id="updateByExample" parameterType="map">
</if> update test_case_test
</set> set test_case_id = #{record.testCaseId,jdbcType=VARCHAR},
where id = #{id,jdbcType=VARCHAR} test_id = #{record.testId,jdbcType=VARCHAR},
</update> test_type = #{record.testType,jdbcType=VARCHAR},
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestCaseTest"> create_time = #{record.createTime,jdbcType=BIGINT},
update test_case_test update_time = #{record.updateTime,jdbcType=BIGINT}
set test_case_id = #{testCaseId,jdbcType=VARCHAR}, <if test="_parameter != null">
test_id = #{testId,jdbcType=VARCHAR}, <include refid="Update_By_Example_Where_Clause" />
test_type = #{testType,jdbcType=VARCHAR} </if>
where id = #{id,jdbcType=VARCHAR} </update>
</update>
</mapper> </mapper>

View File

@ -3,6 +3,7 @@ package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.FileMetadata; import io.metersphere.base.domain.FileMetadata;
import io.metersphere.base.domain.LoadTest; import io.metersphere.base.domain.LoadTest;
import io.metersphere.dto.LoadTestDTO; import io.metersphere.dto.LoadTestDTO;
import io.metersphere.performance.request.QueryProjectFileRequest;
import io.metersphere.performance.request.QueryTestPlanRequest; import io.metersphere.performance.request.QueryTestPlanRequest;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -18,6 +19,7 @@ public interface ExtLoadTestMapper {
LoadTest getNextNum(@Param("projectId") String projectId); LoadTest getNextNum(@Param("projectId") String projectId);
List<FileMetadata> getProjectFiles(@Param("projectId") String projectId, @Param("loadTypes") List<String> loadType); List<FileMetadata> getProjectFiles(@Param("projectId") String projectId, @Param("loadTypes") List<String> loadType,
@Param("request") QueryProjectFileRequest request);
} }

View File

@ -145,5 +145,8 @@
#{id} #{id}
</foreach> </foreach>
AND project_id = #{projectId,jdbcType=VARCHAR} AND project_id = #{projectId,jdbcType=VARCHAR}
<if test="request.name!=null">
AND file_metadata.name LIKE CONCAT('%', #{request.name}, '%')
</if>
</select> </select>
</mapper> </mapper>

View File

@ -65,7 +65,7 @@ public interface ExtTestCaseMapper {
long countRelevanceCreatedThisWeek(@Param("projectId") String projectId,@Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp); long countRelevanceCreatedThisWeek(@Param("projectId") String projectId,@Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp);
List<TrackCountResult> countCoverage(@Param("projectId") String projectId); int countCoverage(@Param("projectId") String projectId);
List<TrackCountResult> countFuncMaintainer(@Param("projectId") String projectId); List<TrackCountResult> countFuncMaintainer(@Param("projectId") String projectId);

View File

@ -343,17 +343,19 @@
</select> </select>
<select id="countRelevance" resultType="io.metersphere.track.response.TrackCountResult"> <select id="countRelevance" resultType="io.metersphere.track.response.TrackCountResult">
SELECT type AS groupField, count(id) AS countNumber FROM test_case WHERE test_case.project_id = #{projectId} GROUP BY test_case.type SELECT test_case_test.test_type AS groupField, count(test_case_test.test_case_id) AS countNumber
FROM test_case join test_case_test on test_case.id = test_case_test.test_case_id
WHERE test_case.project_id = #{projectId} GROUP BY test_case_test.test_type
</select> </select>
<select id="countRelevanceCreatedThisWeek" resultType="java.lang.Long"> <select id="countRelevanceCreatedThisWeek" resultType="java.lang.Long">
SELECT count(id) AS countNumber FROM test_case WHERE test_case.project_id = #{projectId} SELECT count(distinct test_case_test.test_case_id) AS countNumber FROM test_case join test_case_test on test_case.id = test_case_test.test_case_id
AND create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp} WHERE test_case.project_id = #{projectId}
AND test_case_test.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
</select> </select>
<select id="countCoverage" resultType="io.metersphere.track.response.TrackCountResult"> <select id="countCoverage" resultType="int">
SELECT count(test_case.id) AS countNumber, select count(test_case.id) from test_case where test_case.project_id = #{projectId}
if(test_case.test_id is null,"uncoverage","coverage") AS groupField and test_case.id in (select distinct test_case_test.test_case_id from test_case_test)
FROM test_case WHERE test_case.project_id=#{projectId} and test_case.type != 'functional' GROUP BY groupField
</select> </select>
<select id="countFuncMaintainer" resultType="io.metersphere.track.response.TrackCountResult"> <select id="countFuncMaintainer" resultType="io.metersphere.track.response.TrackCountResult">
select count(tc.id) as countNumber, user.name as groupField from test_case tc right join user on tc.maintainer = user.id select count(tc.id) as countNumber, user.name as groupField from test_case tc right join user on tc.maintainer = user.id
@ -362,7 +364,7 @@
</select> </select>
<select id="countRelevanceMaintainer" resultType="io.metersphere.track.response.TrackCountResult"> <select id="countRelevanceMaintainer" resultType="io.metersphere.track.response.TrackCountResult">
select count(tc.id) as countNumber, user.name as groupField from test_case tc right join user on tc.maintainer = user.id select count(tc.id) as countNumber, user.name as groupField from test_case tc right join user on tc.maintainer = user.id
where tc.project_id = #{projectId} and tc.test_id is not null where tc.project_id = #{projectId} and tc.id in (select distinct test_case_test.test_case_id from test_case_test)
group by tc.maintainer group by tc.maintainer
</select> </select>
<select id="getTestPlanBug" resultType="int"> <select id="getTestPlanBug" resultType="int">

View File

@ -1,6 +1,7 @@
package io.metersphere.base.mapper.ext; package io.metersphere.base.mapper.ext;
import io.metersphere.track.dto.TestCaseReportStatusResultDTO; import io.metersphere.track.dto.TestCaseReportStatusResultDTO;
import io.metersphere.track.dto.TestCaseTestDTO;
import io.metersphere.track.dto.TestPlanCaseDTO; import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest; import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -47,4 +48,6 @@ public interface ExtTestPlanTestCaseMapper {
List<String> getExecResultByPlanId(String planId); List<String> getExecResultByPlanId(String planId);
List<TestPlanCaseDTO> listForMinder(@Param("planId") String planId); List<TestPlanCaseDTO> listForMinder(@Param("planId") String planId);
List<TestCaseTestDTO> listTestCaseTest(@Param("caseId") String caseId);
} }

View File

@ -421,6 +421,9 @@
pc.plan_id = #{planId} pc.plan_id = #{planId}
</where> </where>
</select> </select>
<select id="listTestCaseTest" resultType="io.metersphere.track.dto.TestCaseTestDTO">
select * from test_case_test where test_case_id = #{caseId};
</select>
<update id="updateTestCaseStates" parameterType="java.lang.String"> <update id="updateTestCaseStates" parameterType="java.lang.String">
update test_plan_test_case update test_plan_test_case

View File

@ -120,12 +120,13 @@ public class PerformanceTestController {
return performanceTestService.exportJmx(fileIds); return performanceTestService.exportJmx(fileIds);
} }
@GetMapping("/project/{loadType}/{projectId}/{goPage}/{pageSize}") @PostMapping("/project/{loadType}/{projectId}/{goPage}/{pageSize}")
public Pager<List<FileMetadata>> getProjectFiles(@PathVariable String projectId, @PathVariable String loadType, public Pager<List<FileMetadata>> getProjectFiles(@PathVariable String projectId, @PathVariable String loadType,
@PathVariable int goPage, @PathVariable int pageSize) { @PathVariable int goPage, @PathVariable int pageSize,
@RequestBody QueryProjectFileRequest request) {
checkPermissionService.checkProjectOwner(projectId); checkPermissionService.checkProjectOwner(projectId);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, performanceTestService.getProjectFiles(projectId, loadType)); return PageUtils.setPageInfo(page, performanceTestService.getProjectFiles(projectId, loadType, request));
} }
@PostMapping("/delete") @PostMapping("/delete")

View File

@ -19,8 +19,8 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
public abstract class AbstractEngine implements Engine { public abstract class AbstractEngine implements Engine {
protected String JMETER_IMAGE; protected String JMETER_IMAGE;
@ -106,17 +106,20 @@ public abstract class AbstractEngine implements Engine {
String loadConfiguration = t.getLoadConfiguration(); String loadConfiguration = t.getLoadConfiguration();
JSONArray jsonArray = JSON.parseArray(loadConfiguration); JSONArray jsonArray = JSON.parseArray(loadConfiguration);
for (int i = 0; i < jsonArray.size(); i++) { for (int i = 0; i < jsonArray.size(); i++) {
if (jsonArray.get(i) instanceof Map) {
JSONObject o = jsonArray.getJSONObject(i);
if (StringUtils.equals(o.getString("key"), "TargetLevel")) {
s = o.getInteger("value");
break;
}
}
if (jsonArray.get(i) instanceof List) { if (jsonArray.get(i) instanceof List) {
JSONArray o = jsonArray.getJSONArray(i); JSONArray o = jsonArray.getJSONArray(i);
for (int j = 0; j < o.size(); j++) { List<JSONObject> enabledConfig = o.stream()
JSONObject b = o.getJSONObject(j); .filter(b -> {
JSONObject c = JSON.parseObject(b.toString());
if (StringUtils.equals(c.getString("deleted"), "true")) {
return false;
}
return !StringUtils.equals(c.getString("enabled"), "false");
})
.map(b -> JSON.parseObject(b.toString()))
.collect(Collectors.toList());
for (JSONObject b : enabledConfig) {
if (StringUtils.equals(b.getString("key"), "TargetLevel")) { if (StringUtils.equals(b.getString("key"), "TargetLevel")) {
s += b.getInteger("value"); s += b.getInteger("value");
break; break;

View File

@ -4,5 +4,5 @@ import lombok.Data;
@Data @Data
public class QueryProjectFileRequest { public class QueryProjectFileRequest {
private String filename; private String name;
} }

View File

@ -561,19 +561,23 @@ public class PerformanceTestService {
} }
} }
public List<FileMetadata> getProjectFiles(String projectId, String loadType) { public List<FileMetadata> getProjectFiles(String projectId, String loadType, QueryProjectFileRequest request) {
List<String> loadTypes = new ArrayList<>(); List<String> loadTypes = new ArrayList<>();
loadTypes.add(StringUtils.upperCase(loadType)); loadTypes.add(StringUtils.upperCase(loadType));
if (StringUtils.equalsIgnoreCase(loadType, "resource")) { if (StringUtils.equalsIgnoreCase(loadType, "resource")) {
loadTypes.add(FileType.CSV.name()); List<String> fileTypes = Arrays.stream(FileType.values())
loadTypes.add(FileType.JAR.name()); .filter(fileType -> !fileType.equals(FileType.JMX))
.map(FileType::name)
.collect(Collectors.toList());
loadTypes.addAll(fileTypes);
} }
if (StringUtils.equalsIgnoreCase(loadType, "all")) { if (StringUtils.equalsIgnoreCase(loadType, "all")) {
loadTypes.add(FileType.CSV.name()); List<String> fileTypes = Arrays.stream(FileType.values())
loadTypes.add(FileType.JAR.name()); .map(FileType::name)
loadTypes.add(FileType.JMX.name()); .collect(Collectors.toList());
loadTypes.addAll(fileTypes);
} }
return extLoadTestMapper.getProjectFiles(projectId, loadTypes); return extLoadTestMapper.getProjectFiles(projectId, loadTypes, request);
} }
public List<LoadTestExportJmx> exportJmx(List<String> fileIds) { public List<LoadTestExportJmx> exportJmx(List<String> fileIds) {

View File

@ -202,8 +202,8 @@ public class FileService {
FileMetadataExample example = new FileMetadataExample(); FileMetadataExample example = new FileMetadataExample();
FileMetadataExample.Criteria criteria = example.createCriteria(); FileMetadataExample.Criteria criteria = example.createCriteria();
criteria.andProjectIdEqualTo(projectId); criteria.andProjectIdEqualTo(projectId);
if (!StringUtils.isEmpty(request.getFilename())) { if (!StringUtils.isEmpty(request.getName())) {
criteria.andNameEqualTo(request.getFilename()); criteria.andNameEqualTo(request.getName());
} }
return fileMetadataMapper.selectByExample(example); return fileMetadataMapper.selectByExample(example);
} }

View File

@ -173,7 +173,7 @@ public class ProjectService {
if (files != null) { if (files != null) {
for (MultipartFile file : files) { for (MultipartFile file : files) {
QueryProjectFileRequest request = new QueryProjectFileRequest(); QueryProjectFileRequest request = new QueryProjectFileRequest();
request.setFilename(file.getOriginalFilename()); request.setName(file.getOriginalFilename());
if (CollectionUtils.isEmpty(fileService.getProjectFiles(projectId, request))) { if (CollectionUtils.isEmpty(fileService.getProjectFiles(projectId, request))) {
fileService.saveFile(file, projectId); fileService.saveFile(file, projectId);
} else { } else {

View File

@ -1,11 +1,13 @@
package io.metersphere.track.controller; package io.metersphere.track.controller;
import io.metersphere.base.domain.TestCase;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.performance.base.ChartsData; import io.metersphere.performance.base.ChartsData;
import io.metersphere.track.response.BugStatustics; import io.metersphere.track.response.BugStatustics;
import io.metersphere.track.response.TrackCountResult; import io.metersphere.track.response.TrackCountResult;
import io.metersphere.track.response.TrackStatisticsDTO; import io.metersphere.track.response.TrackStatisticsDTO;
import io.metersphere.track.service.TestCaseService;
import io.metersphere.track.service.TrackService; import io.metersphere.track.service.TrackService;
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;
@ -25,6 +27,8 @@ public class TrackController {
@Resource @Resource
private TrackService trackService; private TrackService trackService;
@Resource
private TestCaseService testCaseService;
@GetMapping("/count/{projectId}") @GetMapping("/count/{projectId}")
public TrackStatisticsDTO getTrackCount(@PathVariable String projectId) { public TrackStatisticsDTO getTrackCount(@PathVariable String projectId) {
@ -63,10 +67,11 @@ public class TrackController {
long size = trackService.countRelevanceCreatedThisWeek(projectId); long size = trackService.countRelevanceCreatedThisWeek(projectId);
statistics.setThisWeekAddedCount(size); statistics.setThisWeekAddedCount(size);
List<TrackCountResult> coverageResults = trackService.countCoverage(projectId); List<TestCase> list = testCaseService.getTestCaseByProjectId(projectId);
statistics.countCoverage(coverageResults); long total = list.size();
int coverage = trackService.countCoverage(projectId);
long total = statistics.getUncoverageCount() + statistics.getCoverageCount(); statistics.setCoverageCount(coverage);
statistics.setUncoverageCount(total - coverage);
if (total != 0) { if (total != 0) {
float coverageRageNumber = (float) statistics.getCoverageCount() * 100 / total; float coverageRageNumber = (float) statistics.getCoverageCount() * 100 / total;

View File

@ -0,0 +1,11 @@
package io.metersphere.track.dto;
import io.metersphere.base.domain.TestCaseTest;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestCaseTestDTO extends TestCaseTest {
private String testName;
}

View File

@ -3,6 +3,8 @@ package io.metersphere.track.dto;
import io.metersphere.base.domain.TestCaseWithBLOBs; import io.metersphere.base.domain.TestCaseWithBLOBs;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.util.List;
@Getter @Getter
@Setter @Setter
@ -18,4 +20,6 @@ public class TestPlanCaseDTO extends TestCaseWithBLOBs {
private String reportId; private String reportId;
private String model; private String model;
private String projectName; private String projectName;
private List<TestCaseTestDTO> list;
} }

View File

@ -664,8 +664,9 @@ public class TestCaseService {
selecteds.forEach(id -> { selecteds.forEach(id -> {
test.setTestType(id.get(0)); test.setTestType(id.get(0));
test.setTestId(id.get(1)); test.setTestId(id.get(1));
test.setId(UUID.randomUUID().toString());
test.setTestCaseId(request.getId()); test.setTestCaseId(request.getId());
test.setCreateTime(System.currentTimeMillis());
test.setUpdateTime(System.currentTimeMillis());
testCaseTestMapper.insert(test); testCaseTestMapper.insert(test);
}); });
} }
@ -707,7 +708,8 @@ public class TestCaseService {
selecteds.forEach(id -> { selecteds.forEach(id -> {
test.setTestType(id.get(0)); test.setTestType(id.get(0));
test.setTestId(id.get(1)); test.setTestId(id.get(1));
test.setId(UUID.randomUUID().toString()); test.setCreateTime(System.currentTimeMillis());
test.setUpdateTime(System.currentTimeMillis());
test.setTestCaseId(request.getId()); test.setTestCaseId(request.getId());
testCaseTestMapper.insert(test); testCaseTestMapper.insert(test);
}); });
@ -779,4 +781,10 @@ public class TestCaseService {
} }
}); });
} }
public List<TestCase> getTestCaseByProjectId(String projectId) {
TestCaseExample example = new TestCaseExample();
example.createCriteria().andProjectIdEqualTo(projectId);
return testCaseMapper.selectByExample(example);
}
} }

View File

@ -1,11 +1,8 @@
package io.metersphere.track.service; package io.metersphere.track.service;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.TestPlan; import io.metersphere.base.domain.*;
import io.metersphere.base.domain.TestPlanTestCaseExample; import io.metersphere.base.mapper.*;
import io.metersphere.base.domain.TestPlanTestCaseWithBLOBs;
import io.metersphere.base.domain.User;
import io.metersphere.base.mapper.TestPlanTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.commons.constants.TestPlanTestCaseStatus; import io.metersphere.commons.constants.TestPlanTestCaseStatus;
import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.user.SessionUser;
@ -14,6 +11,7 @@ import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.member.QueryMemberRequest; import io.metersphere.controller.request.member.QueryMemberRequest;
import io.metersphere.service.UserService; import io.metersphere.service.UserService;
import io.metersphere.track.dto.TestCaseTestDTO;
import io.metersphere.track.dto.TestPlanCaseDTO; import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.request.testcase.TestPlanCaseBatchRequest; import io.metersphere.track.request.testcase.TestPlanCaseBatchRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest; import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
@ -42,6 +40,14 @@ public class TestPlanTestCaseService {
@Resource @Resource
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper; ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
@Resource
private TestCaseTestMapper testCaseTestMapper;
@Resource
private LoadTestMapper loadTestMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private ApiScenarioMapper apiScenarioMapper;
public List<TestPlanCaseDTO> list(QueryTestPlanCaseRequest request) { public List<TestPlanCaseDTO> list(QueryTestPlanCaseRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
@ -134,7 +140,40 @@ public class TestPlanTestCaseService {
} }
public TestPlanCaseDTO get(String testplanTestCaseId) { public TestPlanCaseDTO get(String testplanTestCaseId) {
return extTestPlanTestCaseMapper.get(testplanTestCaseId); TestPlanCaseDTO testPlanCaseDTO = extTestPlanTestCaseMapper.get(testplanTestCaseId);
List<TestCaseTestDTO> testCaseTestDTOS = extTestPlanTestCaseMapper.listTestCaseTest(testPlanCaseDTO.getCaseId());
testCaseTestDTOS.forEach(dto -> {
setTestName(dto);
});
testPlanCaseDTO.setList(testCaseTestDTOS);
return testPlanCaseDTO;
}
private void setTestName(TestCaseTestDTO dto) {
String type = dto.getTestType();
String id = dto.getTestId();
switch (type) {
case "performance":
LoadTest loadTest = loadTestMapper.selectByPrimaryKey(id);
if (loadTest != null) {
dto.setTestName(loadTest.getName());
}
break;
case "testcase":
ApiTestCaseWithBLOBs apiTestCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(id);
if (apiTestCaseWithBLOBs != null) {
dto.setTestName(apiTestCaseWithBLOBs.getName());
}
break;
case "automation":
ApiScenarioWithBLOBs apiScenarioWithBLOBs = apiScenarioMapper.selectByPrimaryKey(id);
if (apiScenarioWithBLOBs != null) {
dto.setTestName(apiScenarioWithBLOBs.getName());
}
break;
default:
break;
}
} }
public void deleteTestCaseBath(TestPlanCaseBatchRequest request) { public void deleteTestCaseBath(TestPlanCaseBatchRequest request) {

View File

@ -80,7 +80,7 @@ public class TrackService {
} }
} }
public List<TrackCountResult> countCoverage(String projectId) { public int countCoverage(String projectId) {
return extTestCaseMapper.countCoverage(projectId); return extTestCaseMapper.countCoverage(projectId);
} }

@ -1 +1 @@
Subproject commit 2fb883803fa9909162ce9f6fab8a15b63af66923 Subproject commit 493663be7c000ceef5913783788def1f43b15b2f

View File

@ -185,6 +185,8 @@ create table test_case_test
test_case_id varchar(70) null, test_case_id varchar(70) null,
test_id varchar(70) null, test_id varchar(70) null,
test_type varchar(70) null, test_type varchar(70) null,
create_time bigint(13) null,
update_time bigint(13) null,
constraint test_case_test_pk constraint test_case_test_pk
primary key (id) primary key (id)
) ENGINE = InnoDB ) ENGINE = InnoDB

View File

@ -69,7 +69,7 @@
<el-table-column v-if="item.id == 'tags'" prop="tags" min-width="120px" <el-table-column v-if="item.id == 'tags'" prop="tags" min-width="120px"
:label="$t('api_test.automation.tag')" :key="index"> :label="$t('api_test.automation.tag')" :key="index">
<template v-slot:default="scope"> <template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 5px"/> <ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" :show-tooltip="true" tooltip style="margin-left: 5px"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="item.id == 'userId'" prop="userId" min-width="120px" <el-table-column v-if="item.id == 'userId'" prop="userId" min-width="120px"
@ -758,7 +758,6 @@
z-index: auto !important; z-index: auto !important;
} }
/deep/ .el-table__fixed-right { /deep/ .el-table__fixed-right {
height: 100% !important; height: 100% !important;
} }

View File

@ -8,7 +8,8 @@
<env-select :project-ids="projectIds" :env-map="envMap" @close="visible = false" <env-select :project-ids="projectIds" :env-map="envMap" @close="visible = false"
ref="envSelect" @setProjectEnvMap="setProjectEnvMap" :project-list="projectList"/> ref="envSelect" @setProjectEnvMap="setProjectEnvMap" :project-list="projectList"/>
<el-button type="primary" slot="reference" size="mini" style="margin-top: 2px;"> <el-button type="primary" slot="reference" size="mini" style="margin-top: 2px;">
环境配置<i class="el-icon-caret-bottom el-icon--right"></i> {{ $t('api_test.definition.request.run_env') }}
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button> </el-button>
</el-popover> </el-popover>
</template> </template>

View File

@ -28,10 +28,10 @@
<div class="header-right" @click.stop> <div class="header-right" @click.stop>
<slot name="message"></slot> <slot name="message"></slot>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn"> <el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn">
<el-switch v-model="data.enable" class="enable-switch" size="mini"/> <el-switch v-model="data.enable" class="enable-switch" size="mini" :disabled="data.disabled"/>
</el-tooltip> </el-tooltip>
<slot name="button"></slot> <slot name="button"></slot>
<step-extend-btns style="display: contents" :data="data" @copy="copyRow" @remove="remove" @openScenario="openScenario" v-if="showBtn"/> <step-extend-btns style="display: contents" :data="data" @copy="copyRow" @remove="remove" @openScenario="openScenario" v-if="showBtn && !data.disabled"/>
</div> </div>
</div> </div>

View File

@ -99,7 +99,7 @@
protocol: "", protocol: "",
platforms: [ platforms: [
{ {
name: 'Metersphere', name: 'MeterSphere',
value: 'Metersphere', value: 'Metersphere',
tip: this.$t('api_test.api_import.ms_tip'), tip: this.$t('api_test.api_import.ms_tip'),
exportTip: this.$t('api_test.api_import.ms_export_tip'), exportTip: this.$t('api_test.api_import.ms_export_tip'),
@ -113,14 +113,14 @@
suffixes: new Set(['json']) suffixes: new Set(['json'])
}, },
{ {
name: 'Jmeter', name: 'JMeter',
value: 'Jmeter', value: 'Jmeter',
tip: this.$t('api_test.api_import.jmeter_tip'), tip: this.$t('api_test.api_import.jmeter_tip'),
exportTip: this.$t('api_test.api_import.jmeter_export_tip'), exportTip: this.$t('api_test.api_import.jmeter_export_tip'),
suffixes: new Set(['jmx']) suffixes: new Set(['jmx'])
}, },
{ {
name: 'Har', name: 'HAR',
value: 'Har', value: 'Har',
tip: this.$t('api_test.api_import.har_tip'), tip: this.$t('api_test.api_import.har_tip'),
exportTip: this.$t('api_test.api_import.har_export_tip'), exportTip: this.$t('api_test.api_import.har_export_tip'),

View File

@ -219,8 +219,12 @@
return this.selection.includes(row.id) return this.selection.includes(row.id)
}, },
open: function (variables, headers, disabled) { open: function (variables, headers, disabled) {
this.variables = variables; if(variables){
this.headers = headers; this.variables = variables;
}
if(headers){
this.headers = headers;
}
this.visible = true; this.visible = true;
this.editData = {type: "CONSTANT"}; this.editData = {type: "CONSTANT"};
this.addParameters(this.editData); this.addParameters(this.editData);

View File

@ -128,7 +128,7 @@ export default {
protocol: "", protocol: "",
platforms: [ platforms: [
{ {
name: 'Metersphere', name: 'MeterSphere',
value: 'Metersphere', value: 'Metersphere',
tip: this.$t('api_test.api_import.ms_tip'), tip: this.$t('api_test.api_import.ms_tip'),
exportTip: this.$t('api_test.api_import.ms_export_tip'), exportTip: this.$t('api_test.api_import.ms_export_tip'),
@ -149,7 +149,7 @@ export default {
suffixes: new Set(['json']) suffixes: new Set(['json'])
}, },
{ {
name: 'Har', name: 'HAR',
value: 'Har', value: 'Har',
tip: this.$t('api_test.api_import.har_tip'), tip: this.$t('api_test.api_import.har_tip'),
exportTip: this.$t('api_test.api_import.har_export_tip'), exportTip: this.$t('api_test.api_import.har_export_tip'),

View File

@ -44,12 +44,12 @@ export default {
component: () => import('@/business/components/api/report/ApiReportView'), component: () => import('@/business/components/api/report/ApiReportView'),
}, },
{ {
path: "definition", path: "definition/:redirectID?/:dataType?/:dataSelectRange?",
name: "ApiDefinition", name: "ApiDefinition",
component: () => import('@/business/components/api/definition/ApiDefinition'), component: () => import('@/business/components/api/definition/ApiDefinition'),
}, },
{ {
path: "automation", path: "automation/:redirectID?/:dataType?/:dataSelectRange?",
name: "ApiAutomation", name: "ApiAutomation",
component: () => import('@/business/components/api/automation/ApiAutomation'), component: () => import('@/business/components/api/automation/ApiAutomation'),
}, },

View File

@ -1,28 +1,36 @@
<template> <template>
<el-tag :type="type" :effect="effect" :color="color" size="mini">{{content}}</el-tag> <el-tooltip placement="top" v-if="showTooltip">
<div slot="content">{{content}}</div>
<el-tag :type="type" :effect="effect" :color="color" size="mini">{{content}}</el-tag>
</el-tooltip>
<el-tag :type="type" :effect="effect" :color="color" size="mini" v-else>{{content}}</el-tag>
</template> </template>
<script> <script>
export default { export default {
name: "MsTag", name: "MsTag",
props: { props: {
type: { type: {
type: String, type: String,
default: 'primary', default: 'primary',
}, },
color: { color: {
type: String, type: String,
default: '', default: '',
}, },
content: { content: {
type: String type: String
}, },
effect: { effect: {
type: String, type: String,
default: 'dark', default: 'dark',
} },
showTooltip: {
type: Boolean,
default: false,
} }
} }
}
</script> </script>
<style scoped> <style scoped>

View File

@ -3,42 +3,42 @@
:destroy-on-close="true" :destroy-on-close="true"
:title="$t('load_test.exist_jmx')" width="70%" :title="$t('load_test.exist_jmx')" width="70%"
:visible.sync="loadFileVisible"> :visible.sync="loadFileVisible">
<el-row> <ms-table-header :is-tester-permission="true" title="" :condition.sync="condition" @search="getProjectFiles" :show-create="false">
<template v-slot:button>
<el-upload <el-upload
v-if="loadType === 'jmx'" v-if="loadType === 'jmx'"
style="padding-right: 10px;" style="margin-bottom: 10px"
accept=".jmx" accept=".jmx"
action="" action=""
multiple multiple
:limit="fileNumLimit" :limit="fileNumLimit"
:show-file-list="false" :show-file-list="false"
:before-upload="beforeUploadFile" :before-upload="beforeUploadFile"
:http-request="handleUpload" :http-request="handleUpload"
:on-exceed="handleExceed" :on-exceed="handleExceed"
:disabled="isReadOnly" :disabled="isReadOnly"
:file-list="fileList"> :file-list="fileList">
<ms-table-button :is-tester-permission="true" icon="el-icon-upload2" <ms-table-button :is-tester-permission="true" icon="el-icon-upload2"
:content="$t('load_test.upload_jmx')"/> :content="$t('load_test.upload_jmx')"/>
</el-upload> </el-upload>
<el-upload <el-upload
v-else v-else
style="padding-right: 10px;" style="margin-bottom: 10px"
accept=".jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx" accept=".jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx"
action="" action=""
:limit="fileNumLimit" :limit="fileNumLimit"
multiple multiple
:show-file-list="false" :show-file-list="false"
:before-upload="beforeUploadFile" :before-upload="beforeUploadFile"
:http-request="handleUpload" :http-request="handleUpload"
:on-exceed="handleExceed" :on-exceed="handleExceed"
:disabled="isReadOnly" :disabled="isReadOnly"
:file-list="fileList"> :file-list="fileList">
<ms-table-button :is-tester-permission="true" icon="el-icon-upload2" <ms-table-button :is-tester-permission="true" icon="el-icon-upload2"
:content="$t('load_test.upload_file')"/> :content="$t('load_test.upload_file')"/>
</el-upload> </el-upload>
</el-row> </template>
</ms-table-header>
<el-table v-loading="projectLoadingResult.loading" <el-table v-loading="projectLoadingResult.loading"
class="basic-config" class="basic-config"
:data="existFiles" :data="existFiles"
@ -78,10 +78,11 @@ import {getCurrentProjectID} from "@/common/js/utils";
import {findThreadGroup} from "@/business/components/performance/test/model/ThreadGroup"; import {findThreadGroup} from "@/business/components/performance/test/model/ThreadGroup";
import MsTableButton from "@/business/components/common/components/MsTableButton"; import MsTableButton from "@/business/components/common/components/MsTableButton";
import axios from "axios"; import axios from "axios";
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
export default { export default {
name: "ExistFiles", name: "ExistFiles",
components: {MsTableButton, MsTablePagination, MsDialogFooter}, components: {MsTableHeader, MsTableButton, MsTablePagination, MsDialogFooter},
props: { props: {
fileList: Array, fileList: Array,
tableData: Array, tableData: Array,
@ -100,6 +101,7 @@ export default {
existFiles: [], existFiles: [],
selectIds: new Set, selectIds: new Set,
fileNumLimit: 10, fileNumLimit: 10,
condition: {}
} }
}, },
methods: { methods: {
@ -133,7 +135,7 @@ export default {
} }
}, },
getProjectFiles() { getProjectFiles() {
this.projectLoadingResult = this.$get('/performance/project/' + this.loadType + '/' + getCurrentProjectID() + "/" + this.currentPage + "/" + this.pageSize, res => { this.projectLoadingResult = this.$post('/performance/project/' + this.loadType + '/' + getCurrentProjectID() + "/" + this.currentPage + "/" + this.pageSize, this.condition, res => {
let data = res.data; let data = res.data;
this.total = data.itemCount; this.total = data.itemCount;
this.existFiles = data.listObject; this.existFiles = data.listObject;

View File

@ -329,10 +329,10 @@ export default {
} }
return true; return true;
}, },
beforeUploadJmx(file){ beforeUploadJmx(file) {
this.$refs.existFiles.beforeUploadFile(file); this.$refs.existFiles.beforeUploadFile(file);
}, },
handleUpload(file){ handleUpload(file) {
this.$refs.existFiles.handleUpload(file); this.$refs.existFiles.handleUpload(file);
}, },
}, },
@ -341,7 +341,7 @@ export default {
<style scoped> <style scoped>
.basic-config { .basic-config {
width: 100% width: 100%;
} }
.last-modified { .last-modified {

View File

@ -3,22 +3,25 @@
:destroy-on-close="true" :destroy-on-close="true"
:title="$t('load_test.exist_jmx')" width="70%" :title="$t('load_test.exist_jmx')" width="70%"
:visible.sync="loadFileVisible"> :visible.sync="loadFileVisible">
<el-row>
<el-upload <ms-table-header :is-tester-permission="true" title="" :condition.sync="condition" @search="getProjectFiles" :show-create="false">
style="padding-right: 10px;" <template v-slot:button>
accept=".jmx,.jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx" <el-upload
action="" style="margin-bottom: 10px;"
:limit="fileNumLimit" accept=".jmx,.jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx"
multiple action=""
:show-file-list="false" :limit="fileNumLimit"
:before-upload="beforeUploadFile" multiple
:http-request="handleUpload" :show-file-list="false"
:on-exceed="handleExceed" :before-upload="beforeUploadFile"
:file-list="fileList"> :http-request="handleUpload"
<ms-table-button :is-tester-permission="true" icon="el-icon-upload2" :on-exceed="handleExceed"
:content="$t('load_test.upload_file')"/> :file-list="fileList">
</el-upload> <ms-table-button :is-tester-permission="true" icon="el-icon-upload2"
</el-row> :content="$t('load_test.upload_file')"/>
</el-upload>
</template>
</ms-table-header>
<el-table v-loading="projectLoadingResult.loading" <el-table v-loading="projectLoadingResult.loading"
class="basic-config" class="basic-config"
@ -64,10 +67,12 @@ import MsDialogFooter from "@/business/components/common/components/MsDialogFoot
import {getCurrentProjectID} from "@/common/js/utils"; import {getCurrentProjectID} from "@/common/js/utils";
import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton"; import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton";
import {Message} from "element-ui"; import {Message} from "element-ui";
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import MsTableSearchBar from "@/business/components/common/components/MsTableSearchBar";
export default { export default {
name: "MsResourceFiles", name: "MsResourceFiles",
components: {MsTableOperatorButton, MsDialogFooter, MsTableButton, MsTablePagination}, components: {MsTableSearchBar, MsTableHeader, MsTableOperatorButton, MsDialogFooter, MsTableButton, MsTablePagination},
data() { data() {
return { return {
loadFileVisible: false, loadFileVisible: false,
@ -79,6 +84,7 @@ export default {
fileList: [], fileList: [],
uploadList: [], uploadList: [],
fileNumLimit: 10, fileNumLimit: 10,
condition: {}
} }
}, },
methods: { methods: {
@ -91,7 +97,7 @@ export default {
this.selectIds.clear(); this.selectIds.clear();
}, },
getProjectFiles() { getProjectFiles() {
this.projectLoadingResult = this.$get('/performance/project/all/' + getCurrentProjectID() + "/" + this.currentPage + "/" + this.pageSize, res => { this.projectLoadingResult = this.$post('/performance/project/all/' + getCurrentProjectID() + "/" + this.currentPage + "/" + this.pageSize, this.condition, res => {
let data = res.data; let data = res.data;
this.total = data.itemCount; this.total = data.itemCount;
this.existFiles = data.listObject; this.existFiles = data.listObject;

View File

@ -19,8 +19,8 @@
<el-tab-pane name="default" :label="$t('api_test.definition.case_title')"> <el-tab-pane name="default" :label="$t('api_test.definition.case_title')">
<ms-tab-button <ms-tab-button
:active-dom.sync="activeDom" :active-dom.sync="activeDom"
:left-tip="$t('api_test.definition.case_title')" :left-tip="$t('test_track.case.list')"
:left-content="'CASE'" :left-content="$t('test_track.case.list')"
:right-tip="$t('test_track.case.minder')" :right-tip="$t('test_track.case.minder')"
:right-content="$t('test_track.case.minder')" :right-content="$t('test_track.case.minder')"
:middle-button-enable="false"> :middle-button-enable="false">

View File

@ -85,6 +85,15 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row>
<el-col :offset="1">
<span class="cast_label">关联测试</span>
<span v-for="(item,index) in testCase.list" :key="index">
<el-button @click="openTest(item)" type="text" style="margin-left: 7px;">{{ item.testName }}</el-button>
</span>
</el-col>
</el-row>
<el-row> <el-row>
<el-col :offset="1"> <el-col :offset="1">
<span class="cast_label">{{ $t('test_track.case.prerequisite') }}</span> <span class="cast_label">{{ $t('test_track.case.prerequisite') }}</span>
@ -351,7 +360,7 @@ import ApiTestDetail from "../test/ApiTestDetail";
import ApiTestResult from "../test/ApiTestResult"; import ApiTestResult from "../test/ApiTestResult";
import PerformanceTestDetail from "../test/PerformanceTestDetail"; import PerformanceTestDetail from "../test/PerformanceTestDetail";
import PerformanceTestResult from "../test/PerformanceTestResult"; import PerformanceTestResult from "../test/PerformanceTestResult";
import {listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {getUUID, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment"; import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import CaseComment from "@/business/components/track/case/components/CaseComment"; import CaseComment from "@/business/components/track/case/components/CaseComment";
import MsPreviousNextButton from "../../../../../common/components/MsPreviousNextButton"; import MsPreviousNextButton from "../../../../../common/components/MsPreviousNextButton";
@ -559,6 +568,29 @@ export default {
} }
}); });
}, },
openTest(item) {
const type = item.testType;
const id = item.testId;
switch (type) {
case "performance": {
let performanceData = this.$router.resolve({
path: '/performance/test/edit/' + id,
})
window.open(performanceData.href, '_blank');
break;
}
case "testcase": {
let caseData = this.$router.resolve({name:'ApiDefinition',params:{redirectID:getUUID(),dataType:"apiTestCase",dataSelectRange:'single:'+id}});
window.open(caseData.href, '_blank');
break;
}
case "automation": {
let automationData = this.$router.resolve({name:'ApiAutomation',params:{redirectID:getUUID(),dataType:"scenario",dataSelectRange:'edit:'+id}});
window.open(automationData.href, '_blank');
break;
}
}
},
getRelatedTest() { getRelatedTest() {
if (this.testCase.method === 'auto' && this.testCase.testId && this.testCase.testId !== 'other') { if (this.testCase.method === 'auto' && this.testCase.testId && this.testCase.testId !== 'other') {
this.$get('/' + this.testCase.type + '/get/' + this.testCase.testId, response => { this.$get('/' + this.testCase.type + '/get/' + this.testCase.testId, response => {

View File

@ -11,8 +11,8 @@
<template v-slot:main> <template v-slot:main>
<ms-tab-button <ms-tab-button
:active-dom.sync="activeDom" :active-dom.sync="activeDom"
:left-tip="$t('api_test.definition.case_title')" :left-tip="$t('test_track.case.list')"
:left-content="'CASE'" :left-content="$t('test_track.case.list')"
:right-tip="$t('test_track.case.minder')" :right-tip="$t('test_track.case.minder')"
:right-content="$t('test_track.case.minder')" :right-content="$t('test_track.case.minder')"
:middle-button-enable="false"> :middle-button-enable="false">

View File

@ -12,8 +12,8 @@
<template v-slot:main> <template v-slot:main>
<ms-tab-button <ms-tab-button
:active-dom.sync="activeDom" :active-dom.sync="activeDom"
:left-tip="$t('api_test.definition.case_title')" :left-tip="$t('test_track.case.list')"
:left-content="'CASE'" :left-content="$t('test_track.case.list')"
:right-tip="$t('test_track.case.minder')" :right-tip="$t('test_track.case.minder')"
:right-content="$t('test_track.case.minder')" :right-content="$t('test_track.case.minder')"
:middle-button-enable="false"> :middle-button-enable="false">

@ -1 +1 @@
Subproject commit 3dbd5a3d7ec96a10e11d817cdec25832986af1d2 Subproject commit f63ebb68ebad78de42fd711f17e2671e34577a86

View File

@ -327,7 +327,7 @@ export default {
use_tip_tapd: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"', use_tip_tapd: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"',
use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)', use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)',
use_tip_zentao: 'The account password is a Zentao account with corresponding permissions, and the account needs to have super model calling interface permissions', use_tip_zentao: 'The account password is a Zentao account with corresponding permissions, and the account needs to have super model calling interface permissions',
use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key in the Metersphere project', use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key in the MeterSphere project',
link_the_project_now: 'Link the project now', link_the_project_now: 'Link the project now',
cancel_edit: 'Cancel edit', cancel_edit: 'Cancel edit',
cancel_integration: 'Cancel integration', cancel_integration: 'Cancel integration',
@ -437,7 +437,7 @@ export default {
downloadJtl: 'Download JTL', downloadJtl: 'Download JTL',
test_execute_again: 'Test Execute Again', test_execute_again: 'Test Execute Again',
export: 'Export', export: 'Export',
export_to_ms_format: 'Export to Metersphere format', export_to_ms_format: 'Export to MeterSphere format',
export_to_swagger3_format: 'Export to Swagger3.0 format', export_to_swagger3_format: 'Export to Swagger3.0 format',
compare: 'Compare', compare: 'Compare',
generation_error: 'Report generation error, unable to view, please check log details!', generation_error: 'Report generation error, unable to view, please check log details!',
@ -809,7 +809,7 @@ export default {
url_description: "etc: https://fit2cloud.com", url_description: "etc: https://fit2cloud.com",
path_description: "etc/login", path_description: "etc/login",
parameters: "Query parameters", parameters: "Query parameters",
jmeter_func: "Jmeter Functions", jmeter_func: "JMeter Functions",
parameters_filter_example: "Example", parameters_filter_example: "Example",
parameters_filter_tips: "Only support MockJs function result preview", parameters_filter_tips: "Only support MockJs function result preview",
parameters_advance: "Advanced parameter settings", parameters_advance: "Advanced parameter settings",
@ -1126,6 +1126,7 @@ export default {
cancel_relevance_success: "Unlinked successfully", cancel_relevance_success: "Unlinked successfully",
switch_project: "Switch project", switch_project: "Switch project",
case: { case: {
list: "List",
minder: "Minder", minder: "Minder",
check_select: "Please check the case", check_select: "Please check the case",
export_all_cases: 'Are you sure you want to export all use cases?', export_all_cases: 'Are you sure you want to export all use cases?',

View File

@ -325,7 +325,7 @@ export default {
use_tip_tapd: 'Tapd Basic Auth 账号信息在"公司管理-安全与集成-开放平台"中查询', use_tip_tapd: 'Tapd Basic Auth 账号信息在"公司管理-安全与集成-开放平台"中查询',
use_tip_jira: 'Jira software server 认证信息为 账号密码Jira software cloud 认证信息为 账号+令牌(账户设置-安全-创建API令牌)', use_tip_jira: 'Jira software server 认证信息为 账号密码Jira software cloud 认证信息为 账号+令牌(账户设置-安全-创建API令牌)',
use_tip_zentao: '账号密码为具有相应权限的Zentao账号账号需要具有 超级model调用接口权限', use_tip_zentao: '账号密码为具有相应权限的Zentao账号账号需要具有 超级model调用接口权限',
use_tip_two: '保存 Basic Auth 账号信息后,需要在 Metersphere 项目中手动关联 ID/key', use_tip_two: '保存 Basic Auth 账号信息后,需要在 MeterSphere 项目中手动关联 ID/key',
link_the_project_now: '马上关联项目', link_the_project_now: '马上关联项目',
cancel_edit: '取消编辑', cancel_edit: '取消编辑',
cancel_integration: '取消集成', cancel_integration: '取消集成',
@ -435,7 +435,7 @@ export default {
test_execute_again: '再次执行', test_execute_again: '再次执行',
downloadJtl: '下载JTL', downloadJtl: '下载JTL',
export: '导出', export: '导出',
export_to_ms_format: '导出 Metersphere 格式', export_to_ms_format: '导出 MeterSphere 格式',
export_to_swagger3_format: '导出 Swagger3.0 格式', export_to_swagger3_format: '导出 Swagger3.0 格式',
compare: '比较', compare: '比较',
generation_error: '报告生成错误, 无法查看, 请检查日志详情!', generation_error: '报告生成错误, 无法查看, 请检查日志详情!',
@ -810,7 +810,7 @@ export default {
path_description: "例如:/login", path_description: "例如:/login",
url_invalid: "URL无效", url_invalid: "URL无效",
parameters: "Query参数", parameters: "Query参数",
jmeter_func: "Jmeter 方法", jmeter_func: "JMeter 方法",
parameters_filter_example: "示例", parameters_filter_example: "示例",
parameters_filter_tips: "只支持 MockJs 函数结果预览", parameters_filter_tips: "只支持 MockJs 函数结果预览",
parameters_advance: "return", parameters_advance: "return",
@ -946,16 +946,16 @@ export default {
file_size_limit: "文件大小不超过 20 M", file_size_limit: "文件大小不超过 20 M",
tip: "说明", tip: "说明",
export_tip: "导出方法", export_tip: "导出方法",
ms_tip: "支持 Metersphere json 格式", ms_tip: "支持 MeterSphere json 格式",
ms_export_tip: "通过 Metersphere 接口测试页面或者浏览器插件导出 json 格式文件", ms_export_tip: "通过 MeterSphere 接口测试页面或者浏览器插件导出 json 格式文件",
har_export_tip: "通过 浏览器的开发者工具 导出 Har 格式文件", har_export_tip: "通过 浏览器的开发者工具 导出 Har 格式文件",
postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件", postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件",
swagger_tip: "支持 Swagger 2.0 与 3.0 版本的 json 文件", swagger_tip: "支持 Swagger 2.0 与 3.0 版本的 json 文件",
har_tip: "只支持 Har 文件", har_tip: "只支持 Har 文件",
post_export_tip: "通过 Postman 导出测试集合", post_export_tip: "通过 Postman 导出测试集合",
swagger_export_tip: "通过 Swagger 页面导出", swagger_export_tip: "通过 Swagger 页面导出",
jmeter_export_tip: "通过 Jmeter 生成JMX文件", jmeter_export_tip: "通过 JMeter 生成JMX文件",
jmeter_tip: "支持 Jmeter 5.2版本的JMX 文件", jmeter_tip: "支持 JMeter 5.2版本的JMX 文件",
suffixFormatErr: "文件格式不符合要求", suffixFormatErr: "文件格式不符合要求",
swagger_url_import: "使用URL导入", swagger_url_import: "使用URL导入",
timing_synchronization: "定时同步", timing_synchronization: "定时同步",
@ -1130,6 +1130,7 @@ export default {
cancel_relevance_success: "取消关联成功", cancel_relevance_success: "取消关联成功",
switch_project: "切换项目", switch_project: "切换项目",
case: { case: {
list: "列表",
minder: "脑图", minder: "脑图",
check_select: "请勾选用例", check_select: "请勾选用例",
export_all_cases: '确定要导出全部用例吗?', export_all_cases: '确定要导出全部用例吗?',

View File

@ -325,7 +325,7 @@ export default {
use_tip_tapd: 'Tapd Basic Auth 賬號信息在"公司管理-安全與集成-開放平臺"中查詢', use_tip_tapd: 'Tapd Basic Auth 賬號信息在"公司管理-安全與集成-開放平臺"中查詢',
use_tip_jira: 'Jira software server 認證信息為 賬號密碼Jira software cloud 認證信息為 賬號+令牌(賬戶設置-安全-創建API令牌)', use_tip_jira: 'Jira software server 認證信息為 賬號密碼Jira software cloud 認證信息為 賬號+令牌(賬戶設置-安全-創建API令牌)',
use_tip_zentao: '賬號密碼為具有相應權限的Zentao賬號賬號需要具有 超級model調用接口權限', use_tip_zentao: '賬號密碼為具有相應權限的Zentao賬號賬號需要具有 超級model調用接口權限',
use_tip_two: '保存 Basic Auth 賬號信息後,需要在 Metersphere 項目中手動關聯 ID/key', use_tip_two: '保存 Basic Auth 賬號信息後,需要在 MeterSphere 項目中手動關聯 ID/key',
link_the_project_now: '馬上關聯項目', link_the_project_now: '馬上關聯項目',
cancel_edit: '取消編輯', cancel_edit: '取消編輯',
cancel_integration: '取消集成', cancel_integration: '取消集成',
@ -435,7 +435,7 @@ export default {
test_execute_again: '再次執行', test_execute_again: '再次執行',
downloadJtl: '下載JTL', downloadJtl: '下載JTL',
export: '導出', export: '導出',
export_to_ms_format: '導出 Metersphere 格式', export_to_ms_format: '導出 MeterSphere 格式',
export_to_swagger3_format: '導出 Swagger3.0 格式', export_to_swagger3_format: '導出 Swagger3.0 格式',
compare: '比較', compare: '比較',
generation_error: '報告生成錯誤, 無法查看, 請檢查日誌詳情!', generation_error: '報告生成錯誤, 無法查看, 請檢查日誌詳情!',
@ -809,7 +809,7 @@ export default {
path_description: "例如:/login", path_description: "例如:/login",
url_invalid: "URL無效", url_invalid: "URL無效",
parameters: "Query參數", parameters: "Query參數",
jmeter_func: "Jmeter 方法", jmeter_func: "JMeter 方法",
parameters_filter_example: "示例", parameters_filter_example: "示例",
parameters_filter_tips: "只支持 MockJs 函數結果預覽", parameters_filter_tips: "只支持 MockJs 函數結果預覽",
parameters_advance: "高級參數設置", parameters_advance: "高級參數設置",
@ -945,16 +945,16 @@ export default {
file_size_limit: "文件大小不超過 20 M", file_size_limit: "文件大小不超過 20 M",
tip: "說明", tip: "說明",
export_tip: "導出方法", export_tip: "導出方法",
ms_tip: "支持 Metersphere json 格式", ms_tip: "支持 MeterSphere json 格式",
ms_export_tip: "通過 Metersphere 接口測試頁面或者瀏覽器插件導出 json 格式文件", ms_export_tip: "通過 MeterSphere 接口測試頁面或者瀏覽器插件導出 json 格式文件",
har_export_tip: "通过 瀏覽器到開發者工具 导出 Har 格式文件", har_export_tip: "通过 瀏覽器到開發者工具 导出 Har 格式文件",
postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件", postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件",
swagger_tip: "支持 Swagger 2.0 與 3.0 版本的 json 文件", swagger_tip: "支持 Swagger 2.0 與 3.0 版本的 json 文件",
har_tip: "只支持 Har 文件", har_tip: "只支持 Har 文件",
post_export_tip: "通過 Postman 導出測試集合", post_export_tip: "通過 Postman 導出測試集合",
swagger_export_tip: "通過 Swagger 頁面導出", swagger_export_tip: "通過 Swagger 頁面導出",
jmeter_export_tip: "通過 Jmeter 生成JMX文件", jmeter_export_tip: "通過 JMeter 生成JMX文件",
jmeter_tip: "支持 Jmeter 5.2版本的JMX 文件", jmeter_tip: "支持 JMeter 5.2版本的JMX 文件",
suffixFormatErr: "文件格式不符合要求", suffixFormatErr: "文件格式不符合要求",
swagger_url_import: "使用URL導入", swagger_url_import: "使用URL導入",
timing_synchronization: "定時同步", timing_synchronization: "定時同步",
@ -1128,6 +1128,7 @@ export default {
cancel_relevance_success: "取消關聯成功", cancel_relevance_success: "取消關聯成功",
switch_project: "切換項目", switch_project: "切換項目",
case: { case: {
list: "列表",
minder: "腦圖", minder: "腦圖",
check_select: "請勾選用例", check_select: "請勾選用例",
export_all_cases: '確定要導出全部用例嗎?', export_all_cases: '確定要導出全部用例嗎?',