This commit is contained in:
chenjianxing 2020-12-01 10:38:44 +08:00
commit 65c0bf3f32
16 changed files with 200 additions and 133 deletions

View File

@ -8,21 +8,29 @@ import java.io.Serializable;
public class ApiScenario implements Serializable { public class ApiScenario implements Serializable {
private String id; private String id;
private String apiScenarioId; private String projectId;
private String name; private String name;
private String scenarioId;
private String level;
private String status;
private String principal;
private String stepTotal;
private String followPeople;
private String description; private String description;
private String scenarioDefinition;
private String userId;
private Long createTime; private Long createTime;
private Long updateTime; private Long updateTime;
private String status;
private String userId;
private String triggerMode;
private static final long serialVersionUID = 1L;
} }

View File

@ -8,27 +8,21 @@ import java.io.Serializable;
public class ApiScenarioReport implements Serializable { public class ApiScenarioReport implements Serializable {
private String id; private String id;
private String projectId; private String apiScenarioId;
private String name; private String name;
private String scenarioId;
private String level;
private String status;
private String principal;
private String followPeople;
private String description; private String description;
private String scenarioDefinition;
private String userId;
private Long createTime; private Long createTime;
private Long updateTime; private Long updateTime;
private String status;
private String userId;
private String triggerMode;
private static final long serialVersionUID = 1L;
} }

View File

@ -39,4 +39,12 @@ public interface ExtTestPlanTestCaseMapper {
List<TestPlanCaseDTO> listTestCaseByProjectIds(@Param("ids") List<String> ids); List<TestPlanCaseDTO> listTestCaseByProjectIds(@Param("ids") List<String> ids);
TestPlanCaseDTO get(String testPlanTestCaseId); TestPlanCaseDTO get(String testPlanTestCaseId);
/**
* 获取测试计划下的 TestPlanTestCaseID TestCaseName
* @param request planId 不能为空
* @return List<TestPlanCaseDTO>
*/
List<TestPlanCaseDTO> getTestPlanTestCaseList(@Param("request") QueryTestPlanCaseRequest request);
} }

View File

@ -121,7 +121,9 @@
</select> </select>
<select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO"> <select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
select test_case.remark, test_plan_test_case.id as id, test_plan_test_case.*,test_case.*,test_case_node.name as model, project.name as projectName select test_plan_test_case.id as id, test_case.id as caseId, test_case.name, test_case.priority, test_case.type,
test_case.node_path, test_case.method, test_case.num, test_plan_test_case.executor, test_plan_test_case.status,
test_plan_test_case.update_time, test_case_node.name as model, project.name as projectName, test_plan_test_case.plan_id as planId
from test_plan_test_case from test_plan_test_case
inner join test_case on test_plan_test_case.case_id = test_case.id inner join test_case on test_plan_test_case.case_id = test_case.id
left join test_case_node on test_case_node.id=test_case.node_id left join test_case_node on test_case_node.id=test_case.node_id
@ -134,7 +136,8 @@
</include> </include>
</if> </if>
<if test="request.name != null"> <if test="request.name != null">
and (test_case.name like CONCAT('%', #{request.name},'%') or test_case.num like CONCAT('%', #{request.name},'%')) and (test_case.name like CONCAT('%', #{request.name},'%') or test_case.num like
CONCAT('%',#{request.name},'%'))
</if> </if>
<if test="request.id != null"> <if test="request.id != null">
and test_case.id = #{request.id} and test_case.id = #{request.id}
@ -210,6 +213,14 @@
</foreach> </foreach>
</if> </if>
</select> </select>
<select id="getTestPlanTestCaseList" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
select test_plan_test_case.id as id, test_case.name
from test_plan_test_case
inner join test_case on test_plan_test_case.case_id = test_case.id
where test_plan_test_case.plan_id = #{request.planId}
</select>
<select id="listTestCaseByProjectIds" resultType="io.metersphere.track.dto.TestPlanCaseDTO"> <select id="listTestCaseByProjectIds" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
select distinct * from test_plan_test_case, test_case select distinct * from test_plan_test_case, test_case
where test_plan_test_case.case_id = test_case.id where test_plan_test_case.case_id = test_case.id

View File

@ -491,9 +491,9 @@ public class JmeterDocumentParser implements DocumentParser {
setupElement.setAttribute("testclass", "SetupThreadGroup"); setupElement.setAttribute("testclass", "SetupThreadGroup");
setupElement.setAttribute("testname", "setUp Thread Group"); setupElement.setAttribute("testname", "setUp Thread Group");
setupElement.setAttribute("enabled", "true"); setupElement.setAttribute("enabled", "true");
setupElement.appendChild(createStringProp(document, "MsThreadGroup.on_sample_error", "stoptestnow")); setupElement.appendChild(createStringProp(document, "ThreadGroup.on_sample_error", "stoptestnow"));
Element elementProp = document.createElement("elementProp"); Element elementProp = document.createElement("elementProp");
elementProp.setAttribute("name", "MsThreadGroup.main_controller"); elementProp.setAttribute("name", "ThreadGroup.main_controller");
elementProp.setAttribute("elementType", "LoopController"); elementProp.setAttribute("elementType", "LoopController");
elementProp.setAttribute("guiclass", "LoopControlPanel"); elementProp.setAttribute("guiclass", "LoopControlPanel");
elementProp.setAttribute("testclass", "LoopController"); elementProp.setAttribute("testclass", "LoopController");
@ -502,12 +502,12 @@ public class JmeterDocumentParser implements DocumentParser {
elementProp.appendChild(createBoolProp(document, "LoopController.continue_forever", false)); elementProp.appendChild(createBoolProp(document, "LoopController.continue_forever", false));
elementProp.appendChild(createIntProp(document, "LoopController.loops", 1)); elementProp.appendChild(createIntProp(document, "LoopController.loops", 1));
setupElement.appendChild(elementProp); setupElement.appendChild(elementProp);
setupElement.appendChild(createStringProp(document, "MsThreadGroup.num_threads", "1")); setupElement.appendChild(createStringProp(document, "ThreadGroup.num_threads", "1"));
setupElement.appendChild(createStringProp(document, "MsThreadGroup.ramp_time", "1")); setupElement.appendChild(createStringProp(document, "ThreadGroup.ramp_time", "1"));
setupElement.appendChild(createStringProp(document, "MsThreadGroup.duration", "")); setupElement.appendChild(createStringProp(document, "ThreadGroup.duration", ""));
setupElement.appendChild(createStringProp(document, "MsThreadGroup.delay", "")); setupElement.appendChild(createStringProp(document, "ThreadGroup.delay", ""));
setupElement.appendChild(createBoolProp(document, "MsThreadGroup.scheduler", false)); setupElement.appendChild(createBoolProp(document, "ThreadGroup.scheduler", false));
setupElement.appendChild(createBoolProp(document, "MsThreadGroup.same_user_on_next_iteration", true)); setupElement.appendChild(createBoolProp(document, "ThreadGroup.same_user_on_next_iteration", true));
hashTree.appendChild(setupElement); hashTree.appendChild(setupElement);
Element setupHashTree = document.createElement(HASH_TREE_ELEMENT); Element setupHashTree = document.createElement(HASH_TREE_ELEMENT);
@ -568,17 +568,17 @@ public class JmeterDocumentParser implements DocumentParser {
} }
/* /*
<PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown Thread Group" enabled="true"> <PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown Thread Group" enabled="true">
<stringProp name="MsThreadGroup.on_sample_error">continue</stringProp> <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="MsThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp> <boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp> <stringProp name="LoopController.loops">1</stringProp>
</elementProp> </elementProp>
<stringProp name="MsThreadGroup.num_threads">1</stringProp> <stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="MsThreadGroup.ramp_time">1</stringProp> <stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="MsThreadGroup.scheduler">false</boolProp> <boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="MsThreadGroup.duration"></stringProp> <stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="MsThreadGroup.delay"></stringProp> <stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="MsThreadGroup.same_user_on_next_iteration">true</boolProp> <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</PostThreadGroup> </PostThreadGroup>
*/ */
Element tearDownElement = document.createElement("PostThreadGroup"); Element tearDownElement = document.createElement("PostThreadGroup");
@ -586,15 +586,15 @@ public class JmeterDocumentParser implements DocumentParser {
tearDownElement.setAttribute("testclass", "PostThreadGroup"); tearDownElement.setAttribute("testclass", "PostThreadGroup");
tearDownElement.setAttribute("testname", "tearDown Thread Group"); tearDownElement.setAttribute("testname", "tearDown Thread Group");
tearDownElement.setAttribute("enabled", "true"); tearDownElement.setAttribute("enabled", "true");
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.on_sample_error", "continue")); tearDownElement.appendChild(createStringProp(document, "ThreadGroup.on_sample_error", "continue"));
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.num_threads", "1")); tearDownElement.appendChild(createStringProp(document, "ThreadGroup.num_threads", "1"));
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.ramp_time", "1")); tearDownElement.appendChild(createStringProp(document, "ThreadGroup.ramp_time", "1"));
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.duration", "")); tearDownElement.appendChild(createStringProp(document, "ThreadGroup.duration", ""));
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.delay", "")); tearDownElement.appendChild(createStringProp(document, "ThreadGroup.delay", ""));
tearDownElement.appendChild(createBoolProp(document, "MsThreadGroup.scheduler", false)); tearDownElement.appendChild(createBoolProp(document, "ThreadGroup.scheduler", false));
tearDownElement.appendChild(createBoolProp(document, "MsThreadGroup.same_user_on_next_iteration", true)); tearDownElement.appendChild(createBoolProp(document, "ThreadGroup.same_user_on_next_iteration", true));
Element elementProp = document.createElement("elementProp"); Element elementProp = document.createElement("elementProp");
elementProp.setAttribute("name", "MsThreadGroup.main_controller"); elementProp.setAttribute("name", "ThreadGroup.main_controller");
elementProp.setAttribute("elementType", "LoopController"); elementProp.setAttribute("elementType", "LoopController");
elementProp.setAttribute("guiclass", "LoopControlPanel"); elementProp.setAttribute("guiclass", "LoopControlPanel");
elementProp.setAttribute("testclass", "LoopController"); elementProp.setAttribute("testclass", "LoopController");
@ -760,8 +760,8 @@ public class JmeterDocumentParser implements DocumentParser {
threadGroup.setAttribute("guiclass", CONCURRENCY_THREAD_GROUP + "Gui"); threadGroup.setAttribute("guiclass", CONCURRENCY_THREAD_GROUP + "Gui");
threadGroup.setAttribute("testclass", CONCURRENCY_THREAD_GROUP); threadGroup.setAttribute("testclass", CONCURRENCY_THREAD_GROUP);
/* /*
<elementProp name="MsThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/> <elementProp name="ThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/>
<stringProp name="MsThreadGroup.on_sample_error">continue</stringProp> <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<stringProp name="TargetLevel">2</stringProp> <stringProp name="TargetLevel">2</stringProp>
<stringProp name="RampUp">12</stringProp> <stringProp name="RampUp">12</stringProp>
<stringProp name="Steps">2</stringProp> <stringProp name="Steps">2</stringProp>
@ -773,11 +773,11 @@ public class JmeterDocumentParser implements DocumentParser {
removeChildren(threadGroup); removeChildren(threadGroup);
// elementProp // elementProp
Element elementProp = document.createElement("elementProp"); Element elementProp = document.createElement("elementProp");
elementProp.setAttribute("name", "MsThreadGroup.main_controller"); elementProp.setAttribute("name", "ThreadGroup.main_controller");
elementProp.setAttribute("elementType", "com.blazemeter.jmeter.control.VirtualUserController"); elementProp.setAttribute("elementType", "com.blazemeter.jmeter.control.VirtualUserController");
threadGroup.appendChild(elementProp); threadGroup.appendChild(elementProp);
threadGroup.appendChild(createStringProp(document, "MsThreadGroup.on_sample_error", "continue")); threadGroup.appendChild(createStringProp(document, "ThreadGroup.on_sample_error", "continue"));
threadGroup.appendChild(createStringProp(document, "TargetLevel", "2")); threadGroup.appendChild(createStringProp(document, "TargetLevel", "2"));
threadGroup.appendChild(createStringProp(document, "RampUp", "12")); threadGroup.appendChild(createStringProp(document, "RampUp", "12"));
threadGroup.appendChild(createStringProp(document, "Steps", "2")); threadGroup.appendChild(createStringProp(document, "Steps", "2"));
@ -785,8 +785,6 @@ public class JmeterDocumentParser implements DocumentParser {
threadGroup.appendChild(createStringProp(document, "LogFilename", "")); threadGroup.appendChild(createStringProp(document, "LogFilename", ""));
// bzm - Concurrency Thread Group "Thread Iterations Limit:" 设置为空 // bzm - Concurrency Thread Group "Thread Iterations Limit:" 设置为空
// threadGroup.appendChild(createStringProp(document, "Iterations", "1")); // threadGroup.appendChild(createStringProp(document, "Iterations", "1"));
// threadGroup.appendChild(createStringProp(document, "Unit", "M"));
// 单位改成秒
threadGroup.appendChild(createStringProp(document, "Unit", "S")); threadGroup.appendChild(createStringProp(document, "Unit", "S"));
} }
@ -880,24 +878,6 @@ public class JmeterDocumentParser implements DocumentParser {
} }
private void processVariableThroughputTimer(Element variableThroughputTimer) { private void processVariableThroughputTimer(Element variableThroughputTimer) {
Object durations = context.getProperty("duration");
Integer duration;
if (durations instanceof List) {
Object o = ((List<?>) durations).get(0);
duration = (Integer) o;
((List<?>) durations).remove(0);
} else {
duration = (Integer) durations;
}
Object rpsLimits = context.getProperty("rpsLimit");
String rpsLimit;
if (rpsLimits instanceof List) {
Object o = ((List<?>) rpsLimits).get(0);
((List<?>) rpsLimits).remove(0);
rpsLimit = o.toString();
} else {
rpsLimit = rpsLimits.toString();
}
if (variableThroughputTimer.getChildNodes().getLength() > 0) { if (variableThroughputTimer.getChildNodes().getLength() > 0) {
final NodeList childNodes = variableThroughputTimer.getChildNodes(); final NodeList childNodes = variableThroughputTimer.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) { for (int i = 0; i < childNodes.getLength(); i++) {
@ -923,9 +903,27 @@ public class JmeterDocumentParser implements DocumentParser {
stringPropCount++; stringPropCount++;
} else { } else {
stringPropCount = 0; stringPropCount = 0;
Object durations = context.getProperty("duration");// 传入的是分钟数, 需要转化成秒数
Integer duration;
if (durations instanceof List) {
Object o = ((List<?>) durations).get(0);
duration = (Integer) o;
((List<?>) durations).remove(0);
} else {
duration = (Integer) durations;
}
prop.getFirstChild().setNodeValue(String.valueOf(duration)); prop.getFirstChild().setNodeValue(String.valueOf(duration));
continue; continue;
} }
Object rpsLimits = context.getProperty("rpsLimit");
String rpsLimit;
if (rpsLimits instanceof List) {
Object o = ((List<?>) rpsLimits).get(0);
((List<?>) rpsLimits).remove(0);
rpsLimit = o.toString();
} else {
rpsLimit = rpsLimits.toString();
}
prop.getFirstChild().setNodeValue(rpsLimit); prop.getFirstChild().setNodeValue(rpsLimit);
} }
} }

View File

@ -83,6 +83,11 @@ public class TestPlanTestCaseController {
return testPlanTestCaseService.list(request); return testPlanTestCaseService.list(request);
} }
@PostMapping("/list/ids")
public List<TestPlanCaseDTO> getTestPlanCaseIds(@RequestBody QueryTestPlanCaseRequest request) {
return testPlanTestCaseService.list(request);
}
@PostMapping("/edit") @PostMapping("/edit")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void editTestCase(@RequestBody TestPlanTestCaseWithBLOBs testPlanTestCase) { public void editTestCase(@RequestBody TestPlanTestCaseWithBLOBs testPlanTestCase) {

View File

@ -372,7 +372,7 @@ public class TestCaseNodeService {
public Map<String, String> createNodes(List<String> nodePaths, String projectId) { public Map<String, String> createNodes(List<String> nodePaths, String projectId) {
List<TestCaseNodeDTO> nodeTrees = getNodeTreeByProjectId(projectId); List<TestCaseNodeDTO> nodeTrees = getNodeTreeByProjectId(projectId);
Map<String, String> pathMap = new HashMap<>(); Map<String, String> pathMap = new HashMap<>();
for(String item : nodePaths){ for (String item : nodePaths) {
if (item == null) { if (item == null) {
throw new ExcelException(Translator.get("test_case_module_not_null")); throw new ExcelException(Translator.get("test_case_module_not_null"));
} }
@ -590,6 +590,7 @@ public class TestCaseNodeService {
/** /**
* 测试用例同级模块排序 * 测试用例同级模块排序
*
* @param ids 被拖拽模块相邻的前一个模块 id * @param ids 被拖拽模块相邻的前一个模块 id
* 被拖拽的模块 id * 被拖拽的模块 id
* 被拖拽模块相邻的后一个模块 id * 被拖拽模块相邻的后一个模块 id
@ -635,10 +636,11 @@ public class TestCaseNodeService {
/** /**
* 按照指定排序方式获取同级模块的列表 * 按照指定排序方式获取同级模块的列表
*
* @param projectId 所属项目 id * @param projectId 所属项目 id
* @param level node level * @param level node level
* @param parentId node parent id * @param parentId node parent id
* @param order pos 排序方式 * @param order pos 排序方式
* @return 按照指定排序方式排序的同级模块列表 * @return 按照指定排序方式排序的同级模块列表
*/ */
private List<TestCaseNode> getPos(String projectId, int level, String parentId, String order) { private List<TestCaseNode> getPos(String projectId, int level, String parentId, String order) {
@ -654,9 +656,10 @@ public class TestCaseNodeService {
/** /**
* 刷新同级模块的 pos * 刷新同级模块的 pos
*
* @param projectId project id * @param projectId project id
* @param level node level * @param level node level
* @param parentId node parent id * @param parentId node parent id
*/ */
private void refreshPos(String projectId, int level, String parentId) { private void refreshPos(String projectId, int level, String parentId) {
List<TestCaseNode> nodes = getPos(projectId, level, parentId, "pos asc"); List<TestCaseNode> nodes = getPos(projectId, level, parentId, "pos asc");
@ -675,14 +678,15 @@ public class TestCaseNodeService {
/** /**
* 获得同级模块下一个 pos * 获得同级模块下一个 pos
*
* @param projectId project id * @param projectId project id
* @param level node level * @param level node level
* @param parentId node parent id * @param parentId node parent id
* @return 同级模块下一个 pos * @return 同级模块下一个 pos
*/ */
private double getNextLevelPos(String projectId, int level, String parentId) { private double getNextLevelPos(String projectId, int level, String parentId) {
List<TestCaseNode> list = getPos(projectId, level, parentId, "pos desc"); List<TestCaseNode> list = getPos(projectId, level, parentId, "pos desc");
if (!CollectionUtils.isEmpty(list)) { if (!CollectionUtils.isEmpty(list) && list.get(0) != null && list.get(0).getPos() != null) {
return list.get(0).getPos() + 65536; return list.get(0).getPos() + 65536;
} else { } else {
return 65536; return 65536;

View File

@ -35,7 +35,7 @@
</el-form-item> </el-form-item>
<!-- 请求地址 --> <!-- 请求地址 -->
<el-form-item prop="url"> <el-form-item prop="path">
<el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="api.request.path" class="ms-htt-width" <el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="api.request.path" class="ms-htt-width"
size="small" :disabled="false"/> size="small" :disabled="false"/>
</el-form-item> </el-form-item>
@ -120,7 +120,7 @@
environments: [], environments: [],
rules: { rules: {
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}], method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
url: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}], path: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}],
environmentId: [{required: true, message: this.$t('api_test.definition.request.run_env'), trigger: 'change'}], environmentId: [{required: true, message: this.$t('api_test.definition.request.run_env'), trigger: 'change'}],
}, },
runData: [], runData: [],

View File

@ -27,7 +27,6 @@
<el-form-item :label="$t('load_test.thread_num')"> <el-form-item :label="$t('load_test.thread_num')">
<el-input-number <el-input-number
:disabled="isReadOnly" :disabled="isReadOnly"
:placeholder="$t('load_test.input_thread_num')"
v-model="threadGroup.threadNumber" v-model="threadGroup.threadNumber"
@change="calculateChart(threadGroup)" @change="calculateChart(threadGroup)"
:min="resourcePoolResourceLength" :min="resourcePoolResourceLength"
@ -37,7 +36,6 @@
<el-form-item :label="$t('load_test.duration')"> <el-form-item :label="$t('load_test.duration')">
<el-input-number <el-input-number
:disabled="isReadOnly" :disabled="isReadOnly"
:placeholder="$t('load_test.duration')"
v-model="threadGroup.duration" v-model="threadGroup.duration"
:min="1" :min="1"
@change="calculateChart(threadGroup)" @change="calculateChart(threadGroup)"
@ -49,7 +47,6 @@
&nbsp; &nbsp;
<el-input-number <el-input-number
:disabled="isReadOnly || !threadGroup.rpsLimitEnable" :disabled="isReadOnly || !threadGroup.rpsLimitEnable"
:placeholder="$t('load_test.input_rps_limit')"
v-model="threadGroup.rpsLimit" v-model="threadGroup.rpsLimit"
@change="calculateChart(threadGroup)" @change="calculateChart(threadGroup)"
:min="1" :min="1"
@ -59,7 +56,6 @@
<el-form-item :label="$t('load_test.ramp_up_time_within')"> <el-form-item :label="$t('load_test.ramp_up_time_within')">
<el-input-number <el-input-number
:disabled="isReadOnly" :disabled="isReadOnly"
placeholder=""
:min="1" :min="1"
:max="threadGroup.duration" :max="threadGroup.duration"
v-model="threadGroup.rampUpTime" v-model="threadGroup.rampUpTime"
@ -69,7 +65,6 @@
<el-form-item :label="$t('load_test.ramp_up_time_minutes')"> <el-form-item :label="$t('load_test.ramp_up_time_minutes')">
<el-input-number <el-input-number
:disabled="isReadOnly" :disabled="isReadOnly"
placeholder=""
:min="1" :min="1"
:max="Math.min(threadGroup.threadNumber, threadGroup.rampUpTime)" :max="Math.min(threadGroup.threadNumber, threadGroup.rampUpTime)"
v-model="threadGroup.step" v-model="threadGroup.step"
@ -465,7 +460,13 @@ export default {
for (let i = 0; i < this.threadGroups.length; i++) { for (let i = 0; i < this.threadGroups.length; i++) {
if (!this.threadGroups[i].threadNumber || !this.threadGroups[i].duration if (!this.threadGroups[i].threadNumber || !this.threadGroups[i].duration
|| !this.threadGroups[i].rampUpTime || !this.threadGroups[i].step || !this.threadGroups[i].rpsLimit) { || !this.threadGroups[i].rampUpTime || !this.threadGroups[i].step) {
this.$warning(this.$t('load_test.pressure_config_params_is_empty'));
this.$emit('changeActive', '1');
return false;
}
if (this.threadGroups[i].rpsLimitEnable && !this.threadGroups[i].rpsLimit) {
this.$warning(this.$t('load_test.pressure_config_params_is_empty')); this.$warning(this.$t('load_test.pressure_config_params_is_empty'));
this.$emit('changeActive', '1'); this.$emit('changeActive', '1');
return false; return false;

View File

@ -10,7 +10,7 @@
<img class="platform" src="../../../../assets/jira.png" alt="Jira"/> <img class="platform" src="../../../../assets/jira.png" alt="Jira"/>
</el-radio> </el-radio>
<el-radio label="Zentao"> <el-radio label="Zentao">
<img class="platform" src="../../../../assets/zentao.jpg" alt="Zentao"/> <img class="zentao_platform" src="../../../../assets/zentao.jpg" alt="Zentao"/>
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
@ -66,7 +66,12 @@ export default {
} }
.platform { .platform {
height: 90px; height: 80px;
vertical-align: middle
}
.zentao_platform {
height: 100px;
vertical-align: middle vertical-align: middle
} }
</style> </style>

View File

@ -34,7 +34,6 @@ export default {
}, },
...requireContext.keys().map(key => requireContext(key).system), ...requireContext.keys().map(key => requireContext(key).system),
...requireContext.keys().map(key => requireContext(key).license), ...requireContext.keys().map(key => requireContext(key).license),
...requireContext.keys().map(key => requireContext(key).display),
{ {
path: 'organizationpmnmember', path: 'organizationpmnmember',
component: () => import('@/business/components/settings/organization/OrganizationMember'), component: () => import('@/business/components/settings/organization/OrganizationMember'),

View File

@ -11,6 +11,9 @@
<el-tab-pane :label="$t('system_parameter_setting.ldap_setting')" name="ldap"> <el-tab-pane :label="$t('system_parameter_setting.ldap_setting')" name="ldap">
<ldap-setting/> <ldap-setting/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane v-if="hasLicense()" :label="$t('display.title')" name="display">
<ms-display/>
</el-tab-pane>
</el-tabs> </el-tabs>
</el-card> </el-card>
</template> </template>
@ -19,10 +22,13 @@
import EmailSetting from "./EmailSetting"; import EmailSetting from "./EmailSetting";
import LdapSetting from "./LdapSetting"; import LdapSetting from "./LdapSetting";
import BaseSetting from "./BaseSetting"; import BaseSetting from "./BaseSetting";
import MsDisplay from "@/business/components/xpack/display/Display";
import {hasLicense} from '@/common/js/utils';
export default { export default {
name: "SystemParameterSetting", name: "SystemParameterSetting",
components: { components: {
MsDisplay,
BaseSetting, BaseSetting,
EmailSetting, LdapSetting EmailSetting, LdapSetting
}, },
@ -30,6 +36,9 @@ export default {
return { return {
activeName: 'base' activeName: 'base'
} }
},
methods: {
hasLicense,
} }
} }
</script> </script>

View File

@ -473,26 +473,30 @@ export default {
}, },
getTestCase(index) { getTestCase(index) {
let testCase = this.testCases[index]; let testCase = this.testCases[index];
let item = {}; // id TestPlanTestCase id
Object.assign(item, testCase); this.result = this.$get('/test/plan/case/get/' + testCase.id, response => {
item.results = JSON.parse(item.results); let item = {};
item.steps = JSON.parse(item.steps); Object.assign(item, response.data);
if (item.issues) { item.results = JSON.parse(item.results);
item.issues = JSON.parse(item.issues); item.steps = JSON.parse(item.steps);
} else { if (item.issues) {
item.issues = {}; item.issues = JSON.parse(item.issues);
item.issues.hasIssues = false; } else {
} item.issues = {};
item.steptResults = [];
for (let i = 0; i < item.steps.length; i++) {
if (item.results[i]) {
item.steps[i].actualResult = item.results[i].actualResult;
item.steps[i].executeResult = item.results[i].executeResult;
} }
item.steptResults.push(item.steps[i]); item.steptResults = [];
} for (let i = 0; i < item.steps.length; i++) {
this.testCase = item; if (item.results[i]) {
this.initTest(); item.steps[i].actualResult = item.results[i].actualResult;
item.steps[i].executeResult = item.results[i].executeResult;
}
item.steptResults.push(item.steps[i]);
}
this.testCase = item;
this.getRelatedTest();
this.initTest();
})
this.getIssues(testCase.caseId); this.getIssues(testCase.caseId);
this.stepResultChange(); this.stepResultChange();
this.getFileMetaData(testCase); this.getFileMetaData(testCase);
@ -521,12 +525,13 @@ export default {
}, },
initTest() { initTest() {
this.$nextTick(() => { this.$nextTick(() => {
if (this.testCase.method === 'auto') { if (this.testCase.testId && this.testCase.testId !== 'other') {
if (this.$refs.apiTestDetail && this.testCase.type === 'api') { if (this.testCase.method === 'auto') {
if (this.$refs.apiTestDetail && this.testCase.type === 'api') {
this.$refs.apiTestDetail.init(); this.$refs.apiTestDetail.init();
} else if (this.testCase.type === 'performance') { } else if (this.testCase.type === 'performance') {
this.$refs.performanceTestDetail.init(); this.$refs.performanceTestDetail.init();
}
} }
} }
}); });
@ -546,13 +551,12 @@ export default {
this.$post('/test/plan/case/edit', {id: this.testCase.id, reportId: reportId}); this.$post('/test/plan/case/edit', {id: this.testCase.id, reportId: reportId});
}, },
initData(testCase) { initData(testCase) {
this.result = this.$post('/test/plan/case/list/all', this.searchParam, response => { this.result = this.$post('/test/plan/case/list/ids', this.searchParam, response => {
this.testCases = response.data; this.testCases = response.data;
for (let i = 0; i < this.testCases.length; i++) { for (let i = 0; i < this.testCases.length; i++) {
if (this.testCases[i].id === testCase.id) { if (this.testCases[i].id === testCase.id) {
this.index = i; this.index = i;
this.getTestCase(i); this.getTestCase(i);
this.getRelatedTest();
} }
} }
}); });

View File

@ -11,7 +11,7 @@ import YanProgress from 'yan-progress';
import './permission' // permission control import './permission' // permission control
import i18n from "../i18n/i18n"; import i18n from "../i18n/i18n";
import store from "./store"; import store from "./store";
import {permission, roles} from './permission' import {permission, roles, xpack} from './permission'
import chart from "../common/js/chart"; import chart from "../common/js/chart";
import CalendarHeatmap from "../common/js/calendar-heatmap"; import CalendarHeatmap from "../common/js/calendar-heatmap";
import '../common/css/menu-header.css'; import '../common/css/menu-header.css';
@ -37,6 +37,8 @@ Vue.directive('permission', permission);
// v-roles // v-roles
Vue.directive('roles', roles); Vue.directive('roles', roles);
Vue.directive('xpack', xpack);
new Vue({ new Vue({
el: '#app', el: '#app',
router, router,

View File

@ -1,6 +1,6 @@
import router from './components/common/router/router' import router from './components/common/router/router'
import {TokenKey} from '@/common/js/constants'; import {TokenKey} from '@/common/js/constants';
import {hasRolePermissions, hasRoles} from "@/common/js/utils"; import {hasLicense, hasRolePermissions, hasRoles} from "@/common/js/utils";
import NProgress from 'nprogress' // progress bar import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style import 'nprogress/nprogress.css' // progress bar style
const whiteList = ['/login']; // no redirect whitelist const whiteList = ['/login']; // no redirect whitelist
@ -19,6 +19,20 @@ export const roles = {
} }
}; };
export const xpack = {
inserted(el, binding) {
checkLicense(el, binding);
}
};
function checkLicense(el, binding, type) {
let v = hasLicense()
if (v) {
el.parentNode && el.parentNode.removeChild(el)
}
}
function checkRolePermission(el, binding, type) { function checkRolePermission(el, binding, type) {
const {value} = binding; const {value} = binding;
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {

View File

@ -1,12 +1,12 @@
import { import {
LicenseKey,
REFRESH_SESSION_USER_URL, REFRESH_SESSION_USER_URL,
ROLE_ORG_ADMIN,
ROLE_ADMIN, ROLE_ADMIN,
ROLE_ORG_ADMIN,
ROLE_TEST_MANAGER, ROLE_TEST_MANAGER,
ROLE_TEST_USER, ROLE_TEST_USER,
ROLE_TEST_VIEWER, ROLE_TEST_VIEWER,
TokenKey, TokenKey
LicenseKey
} from "./constants"; } from "./constants";
import axios from "axios"; import axios from "axios";
import {jsPDF} from "jspdf"; import {jsPDF} from "jspdf";
@ -45,6 +45,11 @@ export function hasRolePermission(role) {
return false return false
} }
export function hasLicense() {
let v = localStorage.getItem(LicenseKey);
return v === 'valid';
}
//是否含有对应组织或工作空间的角色 //是否含有对应组织或工作空间的角色
export function hasRolePermissions(...roles) { export function hasRolePermissions(...roles) {
for (let role of roles) { for (let role of roles) {
@ -238,7 +243,7 @@ export function exportPdf(name, canvasList) {
// html页面生成的canvas在pdf中图片的宽高 // html页面生成的canvas在pdf中图片的宽高
let imgWidth = a4Width; let imgWidth = a4Width;
let imgHeight = a4Width/contentWidth * contentHeight; let imgHeight = a4Width / contentWidth * contentHeight;
let pageData = canvas.toDataURL('image/jpeg', 1.0); let pageData = canvas.toDataURL('image/jpeg', 1.0);
@ -251,7 +256,7 @@ export function exportPdf(name, canvasList) {
if (leftHeight > blankHeight) { if (leftHeight > blankHeight) {
//页面偏移 //页面偏移
let position = 0; let position = 0;
while(leftHeight > 0) { while (leftHeight > 0) {
// 本次添加占用的高度 // 本次添加占用的高度
let occupation = a4Height - currentHeight; let occupation = a4Height - currentHeight;
pdf.addImage(pageData, 'JPEG', 0, position + currentHeight, imgWidth, imgHeight); pdf.addImage(pageData, 'JPEG', 0, position + currentHeight, imgWidth, imgHeight);
@ -259,7 +264,7 @@ export function exportPdf(name, canvasList) {
leftHeight -= occupation; leftHeight -= occupation;
position -= occupation; position -= occupation;
//避免添加空白页 //避免添加空白页
if(leftHeight > 0) { if (leftHeight > 0) {
pdf.addPage(); pdf.addPage();
currentHeight = 0; currentHeight = 0;
} }
@ -277,15 +282,15 @@ export function exportPdf(name, canvasList) {
export function windowPrint(id, zoom) { export function windowPrint(id, zoom) {
//根据div标签ID拿到div中的局部内容 //根据div标签ID拿到div中的局部内容
let bdhtml=window.document.body.innerHTML; let bdhtml = window.document.body.innerHTML;
let el = document.getElementById(id); let el = document.getElementById(id);
var jubuData = el.innerHTML; var jubuData = el.innerHTML;
document.getElementsByTagName('body')[0].style.zoom=zoom; document.getElementsByTagName('body')[0].style.zoom = zoom;
//把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容 //把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容
window.document.body.innerHTML= jubuData; window.document.body.innerHTML = jubuData;
//调用打印功能 //调用打印功能
window.print(); window.print();
window.document.body.innerHTML=bdhtml;//重新给页面内容赋值; window.document.body.innerHTML = bdhtml;//重新给页面内容赋值;
return false; return false;
} }