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

This commit is contained in:
BugKing 2021-03-22 16:54:45 +08:00
commit 05dc583719
27 changed files with 783 additions and 633 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

@ -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

@ -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

@ -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

@ -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

@ -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) {

@ -1 +1 @@
Subproject commit 2fb883803fa9909162ce9f6fab8a15b63af66923 Subproject commit e20541d8c864216ebdaade01226b795efeb10c48

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

@ -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

@ -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) {
if(variables){
this.variables = variables; this.variables = variables;
}
if(headers){
this.headers = 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

@ -45,7 +45,7 @@
<span style="cursor:pointer" v-if="isReadOnly"> {{ scope.row.num }} </span> <span style="cursor:pointer" v-if="isReadOnly"> {{ scope.row.num }} </span>
<el-tooltip v-else content="编辑"> <el-tooltip v-else content="编辑">
<a style="cursor:pointer" @click="editApi(scope.row)"> {{ scope.row.num }} </a> <a style="cursor:pointer" @click="editApi(scope.row)"> {{ scope.row.num }} </a>
</el-tooltip > </el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -116,7 +116,7 @@
min-width="120px" min-width="120px"
:key="index"> :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" :show-tooltip="true" :content="itemName" style="margin-left: 5px"/>
</template> </template>
</el-table-column> </el-table-column>
@ -211,42 +211,42 @@
<script> <script>
import MsTableHeader from '../../../../common/components/MsTableHeader'; import MsTableHeader from '../../../../common/components/MsTableHeader';
import MsTableOperator from "../../../../common/components/MsTableOperator"; import MsTableOperator from "../../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton"; import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
import MsTableButton from "../../../../common/components/MsTableButton"; import MsTableButton from "../../../../common/components/MsTableButton";
import MsTablePagination from "../../../../common/pagination/TablePagination"; import MsTablePagination from "../../../../common/pagination/TablePagination";
import MsTag from "../../../../common/components/MsTag"; import MsTag from "../../../../common/components/MsTag";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsBottomContainer from "../BottomContainer"; import MsBottomContainer from "../BottomContainer";
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn"; import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
import MsBatchEdit from "../basis/BatchEdit"; import MsBatchEdit from "../basis/BatchEdit";
import {API_METHOD_COLOUR, API_STATUS, DUBBO_METHOD, REQ_METHOD, SQL_METHOD, TCP_METHOD} from "../../model/JsonData"; import {API_METHOD_COLOUR, API_STATUS, DUBBO_METHOD, REQ_METHOD, SQL_METHOD, TCP_METHOD} from "../../model/JsonData";
import {checkoutTestManagerOrTestUser, downloadFile, getUUID} from "@/common/js/utils"; import {checkoutTestManagerOrTestUser, downloadFile, getUUID} from "@/common/js/utils";
import {PROJECT_NAME} from '@/common/js/constants'; import {PROJECT_NAME} from '@/common/js/constants';
import {getCurrentProjectID, getCurrentUser} from "@/common/js/utils"; import {getCurrentProjectID, getCurrentUser} from "@/common/js/utils";
import {API_LIST, TEST_CASE_LIST, WORKSPACE_ID} from '@/common/js/constants'; import {API_LIST, TEST_CASE_LIST, WORKSPACE_ID} from '@/common/js/constants';
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover"; import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus"; import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar"; import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components"; import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components";
import MsTipButton from "@/business/components/common/components/MsTipButton"; import MsTipButton from "@/business/components/common/components/MsTipButton";
import CaseBatchMove from "@/business/components/api/definition/components/basis/BatchMove"; import CaseBatchMove from "@/business/components/api/definition/components/basis/BatchMove";
import { import {
_handleSelect, _handleSelect,
_handleSelectAll, buildBatchParam, getLabel, _handleSelectAll, buildBatchParam, getLabel,
getSelectDataCounts, initCondition, getSelectDataCounts, initCondition,
setUnSelectIds, toggleAllSelection setUnSelectIds, toggleAllSelection
} from "@/common/js/tableUtils"; } from "@/common/js/tableUtils";
import {_filter, _sort} from "@/common/js/tableUtils"; import {_filter, _sort} from "@/common/js/tableUtils";
import {Api_List} from "@/business/components/common/model/JsonData"; import {Api_List} from "@/business/components/common/model/JsonData";
import HeaderCustom from "@/business/components/common/head/HeaderCustom"; import HeaderCustom from "@/business/components/common/head/HeaderCustom";
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate"; import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
import {Body} from "@/business/components/api/definition/model/ApiTestModel"; import {Body} from "@/business/components/api/definition/model/ApiTestModel";
export default { export default {
name: "ApiList", name: "ApiList",
components: { components: {
HeaderLabelOperate, HeaderLabelOperate,
@ -334,7 +334,7 @@ export default {
currentProtocol: String, currentProtocol: String,
selectNodeIds: Array, selectNodeIds: Array,
isSelectThisWeek: String, isSelectThisWeek: String,
activeDom:String, activeDom: String,
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false,
@ -626,7 +626,7 @@ export default {
let ids = arr.map(row => row.id); let ids = arr.map(row => row.id);
param.ids = ids; param.ids = ids;
param.projectId = getCurrentProjectID(); param.projectId = getCurrentProjectID();
param.moduleId=param.nodeId; param.moduleId = param.nodeId;
param.condition = this.condition; param.condition = this.condition;
param.selectAllDate = this.isSelectAllDate; param.selectAllDate = this.isSelectAllDate;
param.unSelectIds = this.unSelection; param.unSelectIds = this.unSelection;
@ -709,7 +709,7 @@ export default {
} }
this.result = this.$post("/api/definition/export/" + type, param, response => { this.result = this.$post("/api/definition/export/" + type, param, response => {
let obj = response.data; let obj = response.data;
if(type == 'MS') { if (type == 'MS') {
obj.protocol = this.currentProtocol; obj.protocol = this.currentProtocol;
this.buildApiPath(obj.data); this.buildApiPath(obj.data);
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj)); downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
@ -752,7 +752,7 @@ export default {
this.$refs.searchBar.open(); this.$refs.searchBar.open();
} }
}, },
} }
</script> </script>
<style scoped> <style scoped>

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,5 +1,9 @@
<template> <template>
<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-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>
@ -20,6 +24,10 @@
effect: { effect: {
type: String, type: String,
default: 'dark', default: 'dark',
},
showTooltip: {
type: Boolean,
default: false,
} }
} }
} }

View File

@ -3,11 +3,11 @@
: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
@ -23,7 +23,7 @@
</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"
@ -37,8 +37,8 @@
<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,9 +3,11 @@
: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
style="padding-right: 10px;" style="margin-bottom: 10px;"
accept=".jmx,.jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx" accept=".jmx,.jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx"
action="" action=""
:limit="fileNumLimit" :limit="fileNumLimit"
@ -18,7 +20,8 @@
<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"
@ -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

@ -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 => {