Merge branch 'master' of https://github.com/metersphere/metersphere
Conflicts: frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue frontend/src/business/components/api/definition/components/list/ApiList.vue
This commit is contained in:
commit
6e6ca3c0b9
|
@ -48,7 +48,7 @@ curl -sSL https://github.com/metersphere/metersphere/releases/latest/download/qu
|
|||
文档和演示视频:
|
||||
|
||||
- [完整文档](https://metersphere.io/docs/)
|
||||
- [演示视频](http://video.fit2cloud.com/%E3%80%90%E6%BC%94%E7%A4%BA%E8%A7%86%E9%A2%91%E3%80%91202006%20MeterSphere%20v1.0%20%E5%8A%9F%E8%83%BD%E6%BC%94%E7%A4%BA.mp4)
|
||||
- [演示视频](https://www.bilibili.com/video/BV1yp4y1p72C/)
|
||||
|
||||
## MeterSphere 企业版
|
||||
|
||||
|
|
|
@ -2,9 +2,13 @@ package io.metersphere.api.controller;
|
|||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.JmxInfoDTO;
|
||||
import io.metersphere.api.dto.automation.*;
|
||||
import io.metersphere.api.dto.definition.ApiBatchRequest;
|
||||
import io.metersphere.api.dto.definition.ApiExportResult;
|
||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.base.domain.ApiScenario;
|
||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||
|
@ -103,7 +107,7 @@ public class ApiAutomationController {
|
|||
|
||||
@PostMapping("/batch/edit")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public void bathEdit(@RequestBody SaveApiScenarioRequest request) {
|
||||
public void bathEdit(@RequestBody ApiScenarioBatchRequest request) {
|
||||
apiAutomationService.bathEdit(request);
|
||||
}
|
||||
|
||||
|
@ -146,5 +150,18 @@ public class ApiAutomationController {
|
|||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileOperationRequest.getName() + "\"")
|
||||
.body(bytes);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/import", consumes = {"multipart/form-data"})
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public ApiDefinitionImport testCaseImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ApiTestImportRequest request) {
|
||||
return apiAutomationService.scenarioImport(file, request);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/export")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public ApiScenrioExportResult export(@RequestBody ApiScenarioBatchRequest request) {
|
||||
return apiAutomationService.export(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ import io.metersphere.api.dto.APIReportResult;
|
|||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.automation.ApiScenarioRequest;
|
||||
import io.metersphere.api.dto.automation.ReferenceDTO;
|
||||
import io.metersphere.api.dto.datacount.request.ScheduleInfoRequest;
|
||||
import io.metersphere.api.dto.datacount.response.TaskInfoResult;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest;
|
||||
|
@ -92,7 +90,7 @@ public class ApiDefinitionController {
|
|||
}
|
||||
|
||||
@PostMapping("/deleteBatchByParams")
|
||||
public void deleteBatchByParams(@RequestBody ApiDefinitionBatchProcessingRequest request) {
|
||||
public void deleteBatchByParams(@RequestBody ApiBatchRequest request) {
|
||||
apiDefinitionService.deleteByParams(request);
|
||||
}
|
||||
|
||||
|
@ -104,7 +102,7 @@ public class ApiDefinitionController {
|
|||
|
||||
@PostMapping("/removeToGcByParams")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
||||
public void removeToGcByParams(@RequestBody ApiDefinitionBatchProcessingRequest request) {
|
||||
public void removeToGcByParams(@RequestBody ApiBatchRequest request) {
|
||||
apiDefinitionService.removeToGcByParams(request);
|
||||
}
|
||||
|
||||
|
@ -149,6 +147,13 @@ public class ApiDefinitionController {
|
|||
public ApiDefinitionImport testCaseImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ApiTestImportRequest request) {
|
||||
return apiDefinitionService.apiTestImport(file, request);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/export")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public ApiExportResult export(@RequestBody ApiBatchRequest request) {
|
||||
return apiDefinitionService.export(request);
|
||||
}
|
||||
|
||||
//定时任务创建
|
||||
@PostMapping(value = "/schedule/create")
|
||||
public void createSchedule(@RequestBody Schedule request) {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package io.metersphere.api.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiDocumentInfoDTO;
|
||||
import io.metersphere.api.dto.ApiDocumentRequest;
|
||||
import io.metersphere.api.dto.ApiDocumentSimpleInfoDTO;
|
||||
import io.metersphere.api.service.ApiDefinitionService;
|
||||
import io.metersphere.api.service.ApiDocumentService;
|
||||
import io.metersphere.base.domain.ApiDefinition;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.python.antlr.ast.Str;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/2/5 6:25 下午
|
||||
* @Description
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/document")
|
||||
public class ApiDocumentController {
|
||||
@Resource
|
||||
ApiDocumentService apiDocumentService;
|
||||
@Resource
|
||||
ApiDefinitionService apiDefinitionService;
|
||||
|
||||
@PostMapping("/selectApiSimpleInfo")
|
||||
public List<ApiDocumentSimpleInfoDTO> list(@RequestBody ApiDocumentRequest request) {
|
||||
List<ApiDocumentSimpleInfoDTO> returnList = apiDocumentService.findApiDocumentSimpleInfoByRequest(request);
|
||||
return returnList;
|
||||
}
|
||||
|
||||
@GetMapping("/selectApiInfoById/{id}")
|
||||
public ApiDocumentInfoDTO selectApiInfoById(@PathVariable String id) {
|
||||
ApiDefinitionWithBLOBs apiModel = apiDefinitionService.getBLOBs(id);
|
||||
ApiDocumentInfoDTO returnDTO = apiDocumentService.conversionModelToDTO(apiModel);
|
||||
return returnDTO;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/2/8 4:37 下午
|
||||
* @Description
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiDocumentInfoDTO {
|
||||
private String id;
|
||||
private String method;
|
||||
private String uri;
|
||||
private String name;
|
||||
private String status;
|
||||
|
||||
private String requestHead;
|
||||
private String urlParams;
|
||||
private String requestBodyParamType;
|
||||
private String requestBodyFormData;
|
||||
private String requestBodyStrutureData;
|
||||
|
||||
private String responseHead;
|
||||
private String responseBody;
|
||||
private String responseBodyParamType;
|
||||
private String responseBodyFormData;
|
||||
private String responseBodyStrutureData;
|
||||
|
||||
private String responseCode;
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/2/7 10:32 上午
|
||||
* @Description
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiDocumentRequest {
|
||||
private String projectId;
|
||||
private List<String> moduleIds;
|
||||
private String shareId;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 接口定义的简易信息
|
||||
* @author song.tianyang
|
||||
* @Date 2021/2/7 10:15 上午
|
||||
* @Description
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiDocumentSimpleInfoDTO {
|
||||
private String id;
|
||||
private String name;
|
||||
}
|
|
@ -13,8 +13,6 @@ public class ApiTestImportRequest {
|
|||
private String projectId;
|
||||
private String platform;
|
||||
private Boolean useEnvironment;
|
||||
// 来自场景的导入不需要存储
|
||||
private boolean saved = true;
|
||||
private String swaggerUrl;
|
||||
//导入策略
|
||||
private String modeId;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
|
||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiScenarioBatchRequest extends ApiScenarioWithBLOBs {
|
||||
private List<String> ids;
|
||||
private String projectId;
|
||||
private String environmentId;
|
||||
|
||||
private ApiScenarioRequest condition;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -9,21 +10,14 @@ import java.util.Map;
|
|||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiScenarioRequest {
|
||||
public class ApiScenarioRequest extends BaseQueryRequest {
|
||||
private String id;
|
||||
private String excludeId;
|
||||
private String projectId;
|
||||
private String moduleId;
|
||||
private List<String> moduleIds;
|
||||
private String name;
|
||||
private String workspaceId;
|
||||
private String userId;
|
||||
private String planId;
|
||||
private boolean recent = false;
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
private Map<String, Object> combine;
|
||||
private List<String> ids;
|
||||
private boolean isSelectThisWeedData;
|
||||
private long createTime = 0;
|
||||
private String executeStatus;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiScenrioExportResult {
|
||||
private String projectId;
|
||||
private String version;
|
||||
private List<ApiScenarioWithBLOBs> data;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -8,14 +9,10 @@ import java.util.Map;
|
|||
|
||||
@Setter
|
||||
@Getter
|
||||
public class RunScenarioRequest {
|
||||
|
||||
private String id;
|
||||
public class RunScenarioRequest extends ApiScenarioWithBLOBs {
|
||||
|
||||
private String reportId;
|
||||
|
||||
private String projectId;
|
||||
|
||||
private String environmentId;
|
||||
|
||||
private String triggerMode;
|
||||
|
@ -29,28 +26,12 @@ public class RunScenarioRequest {
|
|||
|
||||
private List<String> planCaseIds;
|
||||
|
||||
private String reportUserID;
|
||||
private List<String> ids;
|
||||
|
||||
private List<String> scenarioIds;
|
||||
private String reportUserID;
|
||||
|
||||
private Map<String,String> scenarioTestPlanIdMap;
|
||||
|
||||
/**
|
||||
* isSelectAllDate:选择的数据是否是全部数据(全部数据是不受分页影响的数据)
|
||||
* filters: 数据状态
|
||||
* name:如果是全部数据,那么表格如果历经查询,查询参数是什么
|
||||
* moduleIds: 哪些模块的数据
|
||||
* unSelectIds:是否在页面上有未勾选的数据,有的话他们的ID是哪些。
|
||||
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要。为了让程序能明确批量的范围。
|
||||
*/
|
||||
private boolean isSelectAllDate;
|
||||
|
||||
private Map<String, List<String>> filters;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<String> moduleIds;
|
||||
|
||||
private List<String> unSelectIds;
|
||||
private ApiScenarioRequest condition;
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
@ -14,25 +13,8 @@ public class ApiBatchRequest extends ApiDefinitionWithBLOBs {
|
|||
private List<String> ids;
|
||||
private List<OrderRequest> orders;
|
||||
private String projectId;
|
||||
|
||||
/**
|
||||
* isSelectAllDate:选择的数据是否是全部数据(全部数据是不受分页影响的数据)
|
||||
* filters: 数据状态
|
||||
* name:如果是全部数据,那么表格如果历经查询,查询参数是什么
|
||||
* moduleIds: 哪些模块的数据
|
||||
* unSelectIds:是否在页面上有未勾选的数据,有的话他们的ID是哪些。
|
||||
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要。为了让程序能明确批量的范围。
|
||||
*/
|
||||
private boolean isSelectAllDate;
|
||||
|
||||
private Map<String, List<String>> filters;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<String> moduleIds;
|
||||
|
||||
private List<String> unSelectIds;
|
||||
|
||||
private String moduleId;
|
||||
private String protocol;
|
||||
|
||||
private ApiDefinitionRequest condition;
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 接口定义模块-批量处理请求类
|
||||
* @author song.tianyang
|
||||
* @Date 2020/12/29 4:13 下午
|
||||
* @Description
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiDefinitionBatchProcessingRequest {
|
||||
/**
|
||||
* isSelectAllDate:选择的数据是否是全部数据(全部数据是不受分页影响的数据)
|
||||
* filters: 数据状态
|
||||
* name:如果是全部数据,那么表格如果历经查询,查询参数是什么
|
||||
* moduleIds: 哪些模块的数据
|
||||
* unSelectIds:是否在页面上有未勾选的数据,有的话他们的ID是哪些。
|
||||
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要。为了让程序能明确批量的范围。
|
||||
*/
|
||||
private boolean isSelectAllDate;
|
||||
|
||||
private Map<String, List<String>> filters;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<String> moduleIds;
|
||||
|
||||
private List<String> unSelectIds;
|
||||
|
||||
private String projectId;
|
||||
|
||||
private List<String> dataIds;
|
||||
|
||||
private String protocol;
|
||||
|
||||
}
|
|
@ -1,31 +1,21 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiDefinitionRequest {
|
||||
public class ApiDefinitionRequest extends BaseQueryRequest {
|
||||
|
||||
private String id;
|
||||
private String excludeId;
|
||||
private String projectId;
|
||||
private String moduleId;
|
||||
private List<String> moduleIds;
|
||||
private String protocol;
|
||||
private String name;
|
||||
private String workspaceId;
|
||||
private String userId;
|
||||
private String planId;
|
||||
private boolean recent = false;
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
private Map<String, Object> combine;
|
||||
private List<String> ids;
|
||||
private boolean isSelectThisWeedData = false;
|
||||
private long createTime = 0;
|
||||
private String status;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiExportResult {
|
||||
private String projectName;
|
||||
private String protocol;
|
||||
private List<ApiDefinitionWithBLOBs> data;
|
||||
private List<ApiTestCaseWithBLOBs> cases;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package io.metersphere.api.dto.definition.parse;
|
||||
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.request.MsScenario;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -9,5 +11,11 @@ import java.util.List;
|
|||
public class ApiDefinitionImport {
|
||||
private String projectName;
|
||||
private String protocol;
|
||||
private List<ApiDefinitionResult> data;
|
||||
private List<ApiDefinitionWithBLOBs> data;
|
||||
|
||||
//导入场景
|
||||
private MsScenario scenarioDefinition;
|
||||
|
||||
// 新版本带用例导出
|
||||
private List<ApiTestCaseWithBLOBs> cases;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ public class MsScenario extends MsTestElement {
|
|||
@JSONField(ordinal = 24)
|
||||
private boolean enableCookieShare;
|
||||
|
||||
@JSONField(ordinal = 26)
|
||||
private List<KeyValue> headers;
|
||||
|
||||
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
|
||||
|
||||
@Override
|
||||
|
@ -87,7 +90,7 @@ public class MsScenario extends MsTestElement {
|
|||
}
|
||||
// 场景变量和环境变量
|
||||
tree.add(arguments(config));
|
||||
//this.addCsvDataSet(tree, variables);
|
||||
this.addCsvDataSet(tree, variables);
|
||||
this.addCounter(tree, variables);
|
||||
this.addRandom(tree, variables);
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
|
@ -131,6 +134,12 @@ public class MsScenario extends MsTestElement {
|
|||
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
|
||||
);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(this.headers)) {
|
||||
this.headers.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
|
||||
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
|
||||
);
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,13 +79,13 @@ public class MsIfController extends MsTestElement {
|
|||
}
|
||||
|
||||
if (StringUtils.equals(operator, "is empty")) {
|
||||
variable = "!empty(" + variable + ")";
|
||||
variable = variable + "==" + "\"\\" + this.variable + "\"" + "|| empty(" + variable + ")";
|
||||
operator = "";
|
||||
value = "";
|
||||
}
|
||||
|
||||
if (StringUtils.equals(operator, "is not empty")) {
|
||||
variable = "empty(" + variable + ")";
|
||||
variable = variable + "!=" + "\"\\" + this.variable + "\"" + "&& !empty(" + variable + ")";
|
||||
operator = "";
|
||||
value = "";
|
||||
}
|
||||
|
|
|
@ -123,13 +123,13 @@ public class MsLoopController extends MsTestElement {
|
|||
}
|
||||
|
||||
if (StringUtils.equals(operator, "is empty")) {
|
||||
variable = "!empty(" + variable + ")";
|
||||
variable = variable + "==" + "\"\\" + this.whileController.getVariable() + "\"" + "|| empty(" + variable + ")";
|
||||
operator = "";
|
||||
value = "";
|
||||
}
|
||||
|
||||
if (StringUtils.equals(operator, "is not empty")) {
|
||||
variable = "empty(" + variable + ")";
|
||||
variable = variable + "!=" + "\"\\" + this.whileController.getVariable() + "\"" + "&& !empty(" + variable + ")";
|
||||
operator = "";
|
||||
value = "";
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.api.parse;
|
||||
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.ApiModuleDTO;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
|
@ -9,6 +8,7 @@ import io.metersphere.api.dto.scenario.KeyValue;
|
|||
import io.metersphere.api.dto.scenario.Scenario;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.api.service.ApiModuleService;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
|
@ -75,7 +75,7 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected ApiModule buildModule(ApiModule parentModule, String name, boolean isSaved) {
|
||||
protected ApiModule buildModule(ApiModule parentModule, String name) {
|
||||
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
|
||||
ApiModule module;
|
||||
if (parentModule != null) {
|
||||
|
@ -84,9 +84,7 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
|
|||
} else {
|
||||
module = apiModuleService.getNewModule(name, this.projectId, 1);
|
||||
}
|
||||
if (isSaved) {
|
||||
createModule(module);
|
||||
}
|
||||
createModule(module);
|
||||
return module;
|
||||
}
|
||||
|
||||
|
@ -151,8 +149,8 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
|
|||
}
|
||||
}
|
||||
|
||||
protected ApiDefinitionResult buildApiDefinition(String id, String name, String path, String method, ApiTestImportRequest importRequest) {
|
||||
ApiDefinitionResult apiDefinition = new ApiDefinitionResult();
|
||||
protected ApiDefinitionWithBLOBs buildApiDefinition(String id, String name, String path, String method, ApiTestImportRequest importRequest) {
|
||||
ApiDefinitionWithBLOBs apiDefinition = new ApiDefinitionWithBLOBs();
|
||||
apiDefinition.setName(name);
|
||||
apiDefinition.setPath(formatPath(path));
|
||||
apiDefinition.setProtocol(RequestType.HTTP);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package io.metersphere.api.parse;
|
||||
|
||||
import io.metersphere.commons.constants.ApiImportPlatform;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class ApiScenarioImportParserFactory {
|
||||
public static ApiImportParser getApiImportParser(String platform) {
|
||||
if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) {
|
||||
return new MsParser();
|
||||
} else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) {
|
||||
return new ScenarioPostmanParser();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -6,13 +6,16 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.alibaba.fastjson.parser.Feature;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.ApiExportResult;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.api.service.ApiModuleService;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||
import io.metersphere.commons.constants.ApiImportPlatform;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
|
@ -41,34 +44,36 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
}
|
||||
|
||||
private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
|
||||
|
||||
ApiDefinitionImport apiDefinitionImport = JSON.parseObject(testStr, ApiDefinitionImport.class);
|
||||
List<ApiDefinitionResult> data = apiDefinitionImport.getData();
|
||||
data.forEach(apiDefinition -> {
|
||||
String id = UUID.randomUUID().toString();
|
||||
if (StringUtils.isBlank(apiDefinition.getModulePath())) {
|
||||
apiDefinition.setModuleId(null);
|
||||
}
|
||||
parseModule(apiDefinition, importRequest);
|
||||
apiDefinition.setId(id);
|
||||
apiDefinition.setProjectId(this.projectId);
|
||||
String request = apiDefinition.getRequest();
|
||||
JSONObject requestObj = JSONObject.parseObject(request);
|
||||
requestObj.put("id", id);
|
||||
apiDefinition.setRequest(JSONObject.toJSONString(requestObj));
|
||||
apiDefinitionImport.getData().forEach(apiDefinition -> {
|
||||
parseApiDefinition(apiDefinition, importRequest);
|
||||
});
|
||||
return apiDefinitionImport;
|
||||
}
|
||||
|
||||
private void parseApiDefinition(ApiDefinitionWithBLOBs apiDefinition, ApiTestImportRequest importRequest) {
|
||||
String id = UUID.randomUUID().toString();
|
||||
if (StringUtils.isBlank(apiDefinition.getModulePath())) {
|
||||
apiDefinition.setModuleId(null);
|
||||
}
|
||||
parseModule(apiDefinition, importRequest);
|
||||
apiDefinition.setId(id);
|
||||
apiDefinition.setProjectId(this.projectId);
|
||||
String request = apiDefinition.getRequest();
|
||||
JSONObject requestObj = JSONObject.parseObject(request);
|
||||
requestObj.put("id", id);
|
||||
apiDefinition.setRequest(JSONObject.toJSONString(requestObj));
|
||||
}
|
||||
|
||||
private ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) {
|
||||
List<ApiDefinitionResult> results = new ArrayList<>();
|
||||
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
|
||||
ApiDefinitionImport apiImport = new ApiDefinitionImport();
|
||||
apiImport.setProtocol(RequestType.HTTP);
|
||||
apiImport.setData(results);
|
||||
testObject.keySet().forEach(tag -> {
|
||||
|
||||
ApiModule parentModule = getSelectModule(importRequest.getModuleId());
|
||||
ApiModule module = buildModule(parentModule, tag, importRequest.isSaved());
|
||||
ApiModule module = buildModule(parentModule, tag);
|
||||
|
||||
JSONObject requests = testObject.getJSONObject(tag);
|
||||
requests.keySet().forEach(requestName -> {
|
||||
|
@ -78,7 +83,7 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
String method = requestObject.getString("method");
|
||||
|
||||
MsHTTPSamplerProxy request = buildRequest(requestName, path, method);
|
||||
ApiDefinitionResult apiDefinition = buildApiDefinition(request.getId(), requestName, path, method,importRequest);
|
||||
ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), requestName, path, method,importRequest);
|
||||
apiDefinition.setModuleId(module.getId());
|
||||
apiDefinition.setProjectId(this.projectId);
|
||||
parseBody(requestObject, request.getBody());
|
||||
|
@ -91,7 +96,7 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
return apiImport;
|
||||
}
|
||||
|
||||
private void parsePath(MsHTTPSamplerProxy request, ApiDefinitionResult apiDefinition) {
|
||||
private void parsePath(MsHTTPSamplerProxy request, ApiDefinitionWithBLOBs apiDefinition) {
|
||||
if (StringUtils.isNotBlank(request.getPath())) {
|
||||
String[] split = request.getPath().split("\\?");
|
||||
String path = split[0];
|
||||
|
@ -160,7 +165,7 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
}
|
||||
|
||||
|
||||
private void parseModule(ApiDefinitionResult apiDefinition, ApiTestImportRequest importRequest) {
|
||||
private void parseModule(ApiDefinitionWithBLOBs apiDefinition, ApiTestImportRequest importRequest) {
|
||||
String modulePath = apiDefinition.getModulePath();
|
||||
if (StringUtils.isBlank(modulePath)) {
|
||||
return;
|
||||
|
@ -176,7 +181,7 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
Iterator<String> iterator = modules.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
String item = iterator.next();
|
||||
parent = buildModule(parent, item, importRequest.isSaved());
|
||||
parent = buildModule(parent, item);
|
||||
if (!iterator.hasNext()) {
|
||||
apiDefinition.setModuleId(parent.getId());
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package io.metersphere.api.parse;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
||||
|
@ -11,6 +10,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
|||
import io.metersphere.api.dto.parse.postman.*;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.commons.constants.MsRequestBodyType;
|
||||
import io.metersphere.commons.constants.PostmanRequestBodyMode;
|
||||
|
@ -32,20 +32,23 @@ public class PostmanParser extends ApiImportAbstractParser {
|
|||
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
|
||||
List<PostmanKeyValue> variables = postmanCollection.getVariable();
|
||||
ApiDefinitionImport apiImport = new ApiDefinitionImport();
|
||||
List<ApiDefinitionResult> results = new ArrayList<>();
|
||||
parseItem(postmanCollection.getItem(), variables, results, buildModule(getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName(), request.isSaved()), request.isSaved());
|
||||
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
|
||||
parseItem(postmanCollection.getItem(), variables, results, buildModule(getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName()), true);
|
||||
apiImport.setData(results);
|
||||
return apiImport;
|
||||
}
|
||||
|
||||
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionResult> results, ApiModule parentModule, boolean isSaved) {
|
||||
protected void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionWithBLOBs> results, ApiModule parentModule, Boolean isCreateModule) {
|
||||
for (PostmanItem item : items) {
|
||||
List<PostmanItem> childItems = item.getItem();
|
||||
if (childItems != null) {
|
||||
ApiModule module = buildModule(parentModule, item.getName() , isSaved);
|
||||
parseItem(childItems, variables, results, module, isSaved);
|
||||
ApiModule module = null;
|
||||
if (isCreateModule) {
|
||||
module = buildModule(parentModule, item.getName());
|
||||
}
|
||||
parseItem(childItems, variables, results, module, isCreateModule);
|
||||
} else {
|
||||
ApiDefinitionResult request = parsePostman(item);
|
||||
ApiDefinitionWithBLOBs request = parsePostman(item);
|
||||
if (request != null) {
|
||||
results.add(request);
|
||||
}
|
||||
|
@ -56,7 +59,7 @@ public class PostmanParser extends ApiImportAbstractParser {
|
|||
}
|
||||
}
|
||||
|
||||
private ApiDefinitionResult parsePostman(PostmanItem requestItem) {
|
||||
private ApiDefinitionWithBLOBs parsePostman(PostmanItem requestItem) {
|
||||
PostmanRequest requestDesc = requestItem.getRequest();
|
||||
if (requestDesc == null) {
|
||||
return null;
|
||||
|
@ -64,7 +67,7 @@ public class PostmanParser extends ApiImportAbstractParser {
|
|||
requestDesc.getAuth(); // todo 认证方式等待优化
|
||||
PostmanUrl url = requestDesc.getUrl();
|
||||
MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url.getRaw(), requestDesc.getMethod());
|
||||
ApiDefinitionResult apiDefinition =
|
||||
ApiDefinitionWithBLOBs apiDefinition =
|
||||
buildApiDefinition(request.getId(), requestItem.getName(), url.getRaw(), requestDesc.getMethod(),new ApiTestImportRequest());
|
||||
if (StringUtils.isNotBlank(request.getPath())) {
|
||||
String path = request.getPath().split("\\?")[0];
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package io.metersphere.api.parse;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.MsScenario;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.parse.postman.PostmanCollection;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class ScenarioPostmanParser extends PostmanParser {
|
||||
|
||||
@Override
|
||||
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
|
||||
this.projectId = request.getProjectId();
|
||||
ApiDefinitionImport apiImport = new ApiDefinitionImport();
|
||||
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
|
||||
PostmanCollection postmanCollection = JSON.parseObject(getApiTestStr(source), PostmanCollection.class);
|
||||
parseItem(postmanCollection.getItem(), postmanCollection.getVariable(), results, null, false);
|
||||
|
||||
MsScenario msScenario = new MsScenario();
|
||||
LinkedList<MsTestElement> msHTTPSamplerProxies = new LinkedList<>();
|
||||
results.forEach(res -> {
|
||||
msHTTPSamplerProxies.add(JSONObject.parseObject(res.getRequest(), MsHTTPSamplerProxy.class));
|
||||
});
|
||||
msScenario.setHashTree(msHTTPSamplerProxies);
|
||||
msScenario.setType("scenario");
|
||||
msScenario.setName(postmanCollection.getInfo().getName());
|
||||
apiImport.setScenarioDefinition(msScenario);
|
||||
return apiImport;
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.definition.response.HttpResponse;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.commons.constants.SwaggerParameterType;
|
||||
import io.swagger.models.*;
|
||||
|
@ -49,13 +49,13 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
|||
return definitionImport;
|
||||
}
|
||||
|
||||
private List<ApiDefinitionResult> parseRequests(Swagger swagger, ApiTestImportRequest importRequest) {
|
||||
private List<ApiDefinitionWithBLOBs> parseRequests(Swagger swagger, ApiTestImportRequest importRequest) {
|
||||
Map<String, Path> paths = swagger.getPaths();
|
||||
Set<String> pathNames = paths.keySet();
|
||||
|
||||
this.definitions = swagger.getDefinitions();
|
||||
|
||||
List<ApiDefinitionResult> results = new ArrayList<>();
|
||||
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
|
||||
|
||||
ApiModule parentNode = getSelectModule(importRequest.getModuleId());
|
||||
|
||||
|
@ -66,12 +66,12 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
|||
for (HttpMethod method : httpMethods) {
|
||||
Operation operation = operationMap.get(method);
|
||||
MsHTTPSamplerProxy request = buildRequest(operation, pathName, method.name());
|
||||
ApiDefinitionResult apiDefinition = buildApiDefinition(request.getId(), operation, pathName, method.name(),importRequest);
|
||||
ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), operation, pathName, method.name(),importRequest);
|
||||
parseParameters(operation, request);
|
||||
addBodyHeader(request);
|
||||
apiDefinition.setRequest(JSON.toJSONString(request));
|
||||
apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation, operation.getResponses())));
|
||||
buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved());
|
||||
buildModule(parentNode, apiDefinition, operation.getTags());
|
||||
results.add(apiDefinition);
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
|||
return results;
|
||||
}
|
||||
|
||||
private ApiDefinitionResult buildApiDefinition(String id, Operation operation, String path, String method,ApiTestImportRequest importRequest) {
|
||||
private ApiDefinitionWithBLOBs buildApiDefinition(String id, Operation operation, String path, String method,ApiTestImportRequest importRequest) {
|
||||
String name = "";
|
||||
if (StringUtils.isNotBlank(operation.getSummary())) {
|
||||
name = operation.getSummary();
|
||||
|
|
|
@ -4,13 +4,13 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.definition.response.HttpResponse;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
|
@ -69,14 +69,14 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
return definitionImport;
|
||||
}
|
||||
|
||||
private List<ApiDefinitionResult> parseRequests(OpenAPI openAPI, ApiTestImportRequest importRequest) {
|
||||
private List<ApiDefinitionWithBLOBs> parseRequests(OpenAPI openAPI, ApiTestImportRequest importRequest) {
|
||||
Paths paths = openAPI.getPaths();
|
||||
|
||||
Set<String> pathNames = paths.keySet();
|
||||
|
||||
this.components = openAPI.getComponents();
|
||||
|
||||
List<ApiDefinitionResult> results = new ArrayList<>();
|
||||
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
|
||||
|
||||
ApiModule parentNode = getSelectModule(importRequest.getModuleId());
|
||||
|
||||
|
@ -97,13 +97,13 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
Operation operation = operationsMap.get(method);
|
||||
if (operation != null) {
|
||||
MsHTTPSamplerProxy request = buildRequest(operation, pathName, method);
|
||||
ApiDefinitionResult apiDefinition = buildApiDefinition(request.getId(), operation, pathName, method,importRequest);
|
||||
ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), operation, pathName, method,importRequest);
|
||||
parseParameters(operation, request);
|
||||
parseRequestBody(operation.getRequestBody(), request.getBody());
|
||||
addBodyHeader(request);
|
||||
apiDefinition.setRequest(JSON.toJSONString(request));
|
||||
apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses())));
|
||||
buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved());
|
||||
buildModule(parentNode, apiDefinition, operation.getTags());
|
||||
results.add(apiDefinition);
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
return results;
|
||||
}
|
||||
|
||||
private ApiDefinitionResult buildApiDefinition(String id, Operation operation, String path, String method,ApiTestImportRequest importRequest) {
|
||||
private ApiDefinitionWithBLOBs buildApiDefinition(String id, Operation operation, String path, String method,ApiTestImportRequest importRequest) {
|
||||
String name = "";
|
||||
if (StringUtils.isNotBlank(operation.getSummary())) {
|
||||
name = operation.getSummary();
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package io.metersphere.api.parse;
|
||||
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class SwaggerAbstractParser extends ApiImportAbstractParser {
|
||||
|
||||
protected void buildModule(ApiModule parentModule, ApiDefinitionResult apiDefinition, List<String> tags, boolean isSaved) {
|
||||
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) {
|
||||
if (tags != null) {
|
||||
tags.forEach(tag -> {
|
||||
ApiModule module = buildModule(parentModule, tag, isSaved);
|
||||
ApiModule module = buildModule(parentModule, tag);
|
||||
apiDefinition.setModuleId(module.getId());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package io.metersphere.api.parse.old;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.configurations.MsHeaderManager;
|
||||
|
@ -16,6 +15,7 @@ import io.metersphere.api.dto.scenario.Scenario;
|
|||
import io.metersphere.api.dto.scenario.request.HttpRequest;
|
||||
import io.metersphere.api.dto.scenario.request.Request;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.commons.constants.MsRequestBodyType;
|
||||
import io.metersphere.commons.constants.PostmanRequestBodyMode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -54,20 +54,20 @@ public class PostmanParser extends ApiImportAbstractParser {
|
|||
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
|
||||
List<PostmanKeyValue> variables = postmanCollection.getVariable();
|
||||
ApiDefinitionImport apiImport = new ApiDefinitionImport();
|
||||
List<ApiDefinitionResult> requests = new ArrayList<>();
|
||||
List<ApiDefinitionWithBLOBs> requests = new ArrayList<>();
|
||||
|
||||
parseItem(postmanCollection.getItem(), variables, requests);
|
||||
apiImport.setData(requests);
|
||||
return apiImport;
|
||||
}
|
||||
|
||||
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionResult> scenarios) {
|
||||
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionWithBLOBs> scenarios) {
|
||||
for (PostmanItem item : items) {
|
||||
List<PostmanItem> childItems = item.getItem();
|
||||
if (childItems != null) {
|
||||
parseItem(childItems, variables, scenarios);
|
||||
} else {
|
||||
ApiDefinitionResult request = parsePostman(item);
|
||||
ApiDefinitionWithBLOBs request = parsePostman(item);
|
||||
if (request != null) {
|
||||
scenarios.add(request);
|
||||
}
|
||||
|
@ -75,13 +75,13 @@ public class PostmanParser extends ApiImportAbstractParser {
|
|||
}
|
||||
}
|
||||
|
||||
private ApiDefinitionResult parsePostman(PostmanItem requestItem) {
|
||||
private ApiDefinitionWithBLOBs parsePostman(PostmanItem requestItem) {
|
||||
PostmanRequest requestDesc = requestItem.getRequest();
|
||||
if (requestDesc == null) {
|
||||
return null;
|
||||
}
|
||||
PostmanUrl url = requestDesc.getUrl();
|
||||
ApiDefinitionResult request = new ApiDefinitionResult();
|
||||
ApiDefinitionWithBLOBs request = new ApiDefinitionWithBLOBs();
|
||||
request.setName(requestItem.getName());
|
||||
request.setPath(url.getRaw());
|
||||
request.setMethod(requestDesc.getMethod());
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.configurations.MsHeaderManager;
|
||||
|
@ -16,6 +15,7 @@ import io.metersphere.api.dto.scenario.Scenario;
|
|||
import io.metersphere.api.dto.scenario.request.HttpRequest;
|
||||
import io.metersphere.api.dto.scenario.request.Request;
|
||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.commons.constants.MsRequestBodyType;
|
||||
import io.metersphere.commons.constants.SwaggerParameterType;
|
||||
import io.swagger.models.*;
|
||||
|
@ -54,13 +54,13 @@ public class Swagger2Parser extends ApiImportAbstractParser {
|
|||
return definitionImport;
|
||||
}
|
||||
|
||||
private List<ApiDefinitionResult> parseSwagger(ApiImport apiImport) {
|
||||
List<ApiDefinitionResult> results = new LinkedList<>();
|
||||
private List<ApiDefinitionWithBLOBs> parseSwagger(ApiImport apiImport) {
|
||||
List<ApiDefinitionWithBLOBs> results = new LinkedList<>();
|
||||
apiImport.getScenarios().forEach(item -> {
|
||||
item.getRequests().forEach(childItem -> {
|
||||
if (childItem instanceof HttpRequest) {
|
||||
HttpRequest res = (HttpRequest) childItem;
|
||||
ApiDefinitionResult request = new ApiDefinitionResult();
|
||||
ApiDefinitionWithBLOBs request = new ApiDefinitionWithBLOBs();
|
||||
request.setName(res.getName());
|
||||
request.setPath(res.getPath());
|
||||
request.setMethod(res.getMethod());
|
||||
|
|
|
@ -5,15 +5,20 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.DeleteAPIReportRequest;
|
||||
import io.metersphere.api.dto.JmxInfoDTO;
|
||||
import io.metersphere.api.dto.automation.*;
|
||||
import io.metersphere.api.dto.datacount.ApiDataCountResult;
|
||||
import io.metersphere.api.dto.definition.ApiExportResult;
|
||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.*;
|
||||
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
|
||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.parse.ApiImportParser;
|
||||
import io.metersphere.api.parse.ApiScenarioImportParserFactory;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiScenarioMapper;
|
||||
import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
||||
|
@ -62,8 +67,6 @@ public class ApiAutomationService {
|
|||
@Resource
|
||||
private ApiScenarioMapper apiScenarioMapper;
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
@Resource
|
||||
private ExtApiScenarioMapper extApiScenarioMapper;
|
||||
@Resource
|
||||
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
|
||||
|
@ -103,13 +106,13 @@ public class ApiAutomationService {
|
|||
if (setDefultOrders) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
}
|
||||
if(StringUtils.isNotEmpty(request.getExecuteStatus())){
|
||||
Map<String,List<String>> statusFilter = new HashMap<>();
|
||||
if (StringUtils.isNotEmpty(request.getExecuteStatus())) {
|
||||
Map<String, List<String>> statusFilter = new HashMap<>();
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("Prepare");
|
||||
list.add("Underway");
|
||||
list.add("Completed");
|
||||
statusFilter.put("status",list);
|
||||
statusFilter.put("status", list);
|
||||
request.setFilters(statusFilter);
|
||||
}
|
||||
if (checkThisWeekData) {
|
||||
|
@ -145,36 +148,15 @@ public class ApiAutomationService {
|
|||
request.setId(UUID.randomUUID().toString());
|
||||
checkNameExist(request);
|
||||
|
||||
final ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
|
||||
scenario.setId(request.getId());
|
||||
scenario.setName(request.getName());
|
||||
scenario.setProjectId(request.getProjectId());
|
||||
scenario.setTags(request.getTags());
|
||||
scenario.setApiScenarioModuleId(request.getApiScenarioModuleId());
|
||||
scenario.setModulePath(request.getModulePath());
|
||||
scenario.setLevel(request.getLevel());
|
||||
scenario.setFollowPeople(request.getFollowPeople());
|
||||
scenario.setPrincipal(request.getPrincipal());
|
||||
scenario.setStepTotal(request.getStepTotal());
|
||||
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request);
|
||||
|
||||
scenario.setCreateTime(System.currentTimeMillis());
|
||||
scenario.setUpdateTime(System.currentTimeMillis());
|
||||
scenario.setNum(getNextNum(request.getProjectId()));
|
||||
if (StringUtils.isNotEmpty(request.getStatus())) {
|
||||
scenario.setStatus(request.getStatus());
|
||||
} else {
|
||||
scenario.setStatus(ScenarioStatus.Underway.name());
|
||||
}
|
||||
if (request.getUserId() == null) {
|
||||
scenario.setUserId(SessionUtils.getUserId());
|
||||
} else {
|
||||
scenario.setUserId(request.getUserId());
|
||||
}
|
||||
scenario.setDescription(request.getDescription());
|
||||
|
||||
apiScenarioMapper.insert(scenario);
|
||||
|
||||
List<String> bodyUploadIds = request.getBodyUploadIds();
|
||||
apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
return scenario;
|
||||
}
|
||||
|
||||
|
@ -190,9 +172,14 @@ public class ApiAutomationService {
|
|||
public void update(SaveApiScenarioRequest request, List<MultipartFile> bodyFiles) {
|
||||
checkNameExist(request);
|
||||
List<String> bodyUploadIds = request.getBodyUploadIds();
|
||||
apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
|
||||
final ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
|
||||
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request);
|
||||
apiScenarioMapper.updateByPrimaryKeySelective(scenario);
|
||||
}
|
||||
|
||||
public ApiScenarioWithBLOBs buildSaveScenario(SaveApiScenarioRequest request) {
|
||||
ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
|
||||
scenario.setId(request.getId());
|
||||
scenario.setName(request.getName());
|
||||
scenario.setProjectId(request.getProjectId());
|
||||
|
@ -203,16 +190,19 @@ public class ApiAutomationService {
|
|||
scenario.setFollowPeople(request.getFollowPeople());
|
||||
scenario.setPrincipal(request.getPrincipal());
|
||||
scenario.setStepTotal(request.getStepTotal());
|
||||
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||
scenario.setUpdateTime(System.currentTimeMillis());
|
||||
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||
if (StringUtils.isNotEmpty(request.getStatus())) {
|
||||
scenario.setStatus(request.getStatus());
|
||||
} else {
|
||||
scenario.setStatus(ScenarioStatus.Underway.name());
|
||||
}
|
||||
scenario.setUserId(request.getUserId());
|
||||
scenario.setDescription(request.getDescription());
|
||||
apiScenarioMapper.updateByPrimaryKeySelective(scenario);
|
||||
if (request.getUserId() == null) {
|
||||
scenario.setUserId(SessionUtils.getUserId());
|
||||
} else {
|
||||
scenario.setUserId(request.getUserId());
|
||||
}
|
||||
return scenario;
|
||||
}
|
||||
|
||||
public void delete(String id) {
|
||||
|
@ -454,11 +444,11 @@ public class ApiAutomationService {
|
|||
* @return
|
||||
*/
|
||||
public String run(RunScenarioRequest request) {
|
||||
List<String> ids = request.getScenarioIds();
|
||||
if (request.isSelectAllDate()) {
|
||||
ids = this.getAllScenarioIdsByFontedSelect(
|
||||
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
|
||||
}
|
||||
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query));
|
||||
|
||||
List<String> ids = request.getIds();
|
||||
//检查是否有正在执行中的情景
|
||||
this.checkScenarioIsRunnng(ids);
|
||||
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(ids);
|
||||
|
@ -480,8 +470,8 @@ public class ApiAutomationService {
|
|||
public void checkScenarioIsRunnng(List<String> ids) {
|
||||
List<ApiScenarioReport> lastReportStatusByIds = apiReportService.selectLastReportByIds(ids);
|
||||
for (ApiScenarioReport report : lastReportStatusByIds) {
|
||||
if(StringUtils.equals(report.getStatus(),APITestStatus.Running.name())){
|
||||
MSException.throwException(report.getName()+" Is Running!");
|
||||
if (StringUtils.equals(report.getStatus(), APITestStatus.Running.name())) {
|
||||
MSException.throwException(report.getName() + " Is Running!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -518,7 +508,7 @@ public class ApiAutomationService {
|
|||
*/
|
||||
public String debugRun(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
EnvironmentConfig envConfig = null;
|
||||
if (request.getEnvironmentId() != null) {
|
||||
ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId());
|
||||
|
@ -667,11 +657,7 @@ public class ApiAutomationService {
|
|||
|
||||
public JmxInfoDTO genPerformanceTestJmx(RunScenarioRequest request) throws Exception {
|
||||
List<ApiScenarioWithBLOBs> apiScenarios = null;
|
||||
List<String> ids = request.getScenarioIds();
|
||||
if (request.isSelectAllDate()) {
|
||||
ids = this.getAllScenarioIdsByFontedSelect(
|
||||
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
|
||||
}
|
||||
List<String> ids = request.getIds();
|
||||
apiScenarios = extApiScenarioMapper.selectIds(ids);
|
||||
String testName = "";
|
||||
if (!apiScenarios.isEmpty()) {
|
||||
|
@ -699,20 +685,17 @@ public class ApiAutomationService {
|
|||
return dto;
|
||||
}
|
||||
|
||||
public void bathEdit(SaveApiScenarioRequest request) {
|
||||
if (CollectionUtils.isEmpty(request.getScenarioIds())) {
|
||||
return;
|
||||
}
|
||||
if (request.isSelectAllDate()) {
|
||||
request.setScenarioIds(this.getAllScenarioIdsByFontedSelect(
|
||||
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds()));
|
||||
}
|
||||
public void bathEdit(ApiScenarioBatchRequest request) {
|
||||
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query));
|
||||
|
||||
if (StringUtils.isNotBlank(request.getEnvironmentId())) {
|
||||
bathEditEnv(request);
|
||||
return;
|
||||
}
|
||||
ApiScenarioExample apiScenarioExample = new ApiScenarioExample();
|
||||
apiScenarioExample.createCriteria().andIdIn(request.getScenarioIds());
|
||||
apiScenarioExample.createCriteria().andIdIn(request.getIds());
|
||||
ApiScenarioWithBLOBs apiScenarioWithBLOBs = new ApiScenarioWithBLOBs();
|
||||
BeanUtils.copyBean(apiScenarioWithBLOBs, request);
|
||||
apiScenarioWithBLOBs.setUpdateTime(System.currentTimeMillis());
|
||||
|
@ -721,9 +704,9 @@ public class ApiAutomationService {
|
|||
apiScenarioExample);
|
||||
}
|
||||
|
||||
public void bathEditEnv(SaveApiScenarioRequest request) {
|
||||
public void bathEditEnv(ApiScenarioBatchRequest request) {
|
||||
if (StringUtils.isNotBlank(request.getEnvironmentId())) {
|
||||
List<ApiScenarioWithBLOBs> apiScenarios = selectByIdsWithBLOBs(request.getScenarioIds());
|
||||
List<ApiScenarioWithBLOBs> apiScenarios = selectByIdsWithBLOBs(request.getIds());
|
||||
apiScenarios.forEach(item -> {
|
||||
JSONObject object = JSONObject.parseObject(item.getScenarioDefinition());
|
||||
object.put("environmentId", request.getEnvironmentId());
|
||||
|
@ -734,4 +717,40 @@ public class ApiAutomationService {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ApiDefinitionImport scenarioImport(MultipartFile file, ApiTestImportRequest request) {
|
||||
ApiImportParser apiImportParser = ApiScenarioImportParserFactory.getApiImportParser(request.getPlatform());
|
||||
ApiDefinitionImport apiImport = null;
|
||||
try {
|
||||
apiImport = apiImportParser.parse(file == null ? null : file.getInputStream(), request);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(Translator.get("parse_data_error"));
|
||||
}
|
||||
SaveApiScenarioRequest saveReq = new SaveApiScenarioRequest();
|
||||
saveReq.setScenarioDefinition(apiImport.getScenarioDefinition());
|
||||
saveReq.setName(saveReq.getScenarioDefinition().getName());
|
||||
saveReq.setProjectId(request.getProjectId());
|
||||
saveReq.setApiScenarioModuleId(request.getModuleId());
|
||||
if (StringUtils.isNotBlank(request.getUserId())) {
|
||||
saveReq.setPrincipal(request.getUserId());
|
||||
} else {
|
||||
saveReq.setPrincipal(SessionUtils.getUserId());
|
||||
}
|
||||
create(saveReq, new ArrayList<>());
|
||||
return apiImport;
|
||||
}
|
||||
|
||||
public ApiScenrioExportResult export(ApiScenarioBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query));
|
||||
ApiScenarioExample example = new ApiScenarioExample();
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
List<ApiScenarioWithBLOBs> apiScenarioWithBLOBs = apiScenarioMapper.selectByExampleWithBLOBs(example);
|
||||
ApiScenrioExportResult result = new ApiScenrioExportResult();
|
||||
result.setData(apiScenarioWithBLOBs);
|
||||
result.setProjectId(request.getProjectId());
|
||||
result.setVersion(System.getenv("MS_VERSION"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ public class ApiDefinitionService {
|
|||
public void create(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
createTest(request);
|
||||
createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
}
|
||||
|
||||
public void update(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
|
@ -141,27 +141,7 @@ public class ApiDefinitionService {
|
|||
List<String> bodyUploadIds = request.getBodyUploadIds();
|
||||
request.setBodyUploadIds(null);
|
||||
updateTest(request);
|
||||
createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
}
|
||||
|
||||
public void createBodyFiles(List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
||||
if (CollectionUtils.isNotEmpty(bodyUploadIds) && CollectionUtils.isNotEmpty(bodyFiles)) {
|
||||
File testDir = new File(BODY_FILE_DIR);
|
||||
if (!testDir.exists()) {
|
||||
testDir.mkdirs();
|
||||
}
|
||||
for (int i = 0; i < bodyUploadIds.size(); i++) {
|
||||
MultipartFile item = bodyFiles.get(i);
|
||||
File file = new File(BODY_FILE_DIR + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename());
|
||||
try (InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(file)) {
|
||||
file.createNewFile();
|
||||
FileUtil.copyStream(in, out);
|
||||
} catch (IOException e) {
|
||||
LogUtil.error(e);
|
||||
MSException.throwException(Translator.get("upload_fail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
}
|
||||
|
||||
public void delete(String apiId) {
|
||||
|
@ -298,24 +278,23 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private ApiDefinition importCreate(ApiDefinitionResult request, ApiDefinitionMapper batchMapper, ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest) {
|
||||
private ApiDefinition importCreate(ApiDefinitionWithBLOBs apiDefinition, ApiDefinitionMapper batchMapper,
|
||||
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases) {
|
||||
SaveApiDefinitionRequest saveReq = new SaveApiDefinitionRequest();
|
||||
BeanUtils.copyBean(saveReq, request);
|
||||
final ApiDefinitionWithBLOBs apiDefinition = new ApiDefinitionWithBLOBs();
|
||||
BeanUtils.copyBean(apiDefinition, request);
|
||||
BeanUtils.copyBean(saveReq, apiDefinition);
|
||||
apiDefinition.setCreateTime(System.currentTimeMillis());
|
||||
apiDefinition.setUpdateTime(System.currentTimeMillis());
|
||||
apiDefinition.setStatus(APITestStatus.Underway.name());
|
||||
if (request.getUserId() == null) {
|
||||
if (apiDefinition.getUserId() == null) {
|
||||
apiDefinition.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
||||
} else {
|
||||
apiDefinition.setUserId(request.getUserId());
|
||||
apiDefinition.setUserId(apiDefinition.getUserId());
|
||||
}
|
||||
apiDefinition.setDescription(request.getDescription());
|
||||
apiDefinition.setDescription(apiDefinition.getDescription());
|
||||
|
||||
List<ApiDefinition> sameRequest = getSameRequest(saveReq);
|
||||
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
|
||||
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest);
|
||||
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases);
|
||||
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
|
||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||
//postman 可能含有前置脚本,接口定义去掉脚本
|
||||
|
@ -325,25 +304,34 @@ public class ApiDefinitionService {
|
|||
importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, true);
|
||||
}
|
||||
} else {
|
||||
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest);
|
||||
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases);
|
||||
}
|
||||
return apiDefinition;
|
||||
}
|
||||
|
||||
private void _importCreate(List<ApiDefinition> sameRequest, ApiDefinitionMapper batchMapper, ApiDefinitionWithBLOBs apiDefinition,
|
||||
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest) {
|
||||
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases) {
|
||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||
String request = setImportHashTree(apiDefinition);
|
||||
batchMapper.insert(apiDefinition);
|
||||
apiDefinition.setRequest(request);
|
||||
importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, true);
|
||||
} else {
|
||||
String originId = apiDefinition.getId();
|
||||
//如果存在则修改
|
||||
apiDefinition.setId(sameRequest.get(0).getId());
|
||||
String request = setImportHashTree(apiDefinition);
|
||||
apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
|
||||
apiDefinition.setRequest(request);
|
||||
importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, false);
|
||||
// 如果是带用例导出,重新设置接口id
|
||||
if (CollectionUtils.isNotEmpty(cases)) {
|
||||
cases.forEach(item -> {
|
||||
if (StringUtils.equals(item.getApiDefinitionId(), originId)) {
|
||||
item.setApiDefinitionId(apiDefinition.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,10 +344,30 @@ public class ApiDefinitionService {
|
|||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入是插件或者postman时创建用例
|
||||
* postman考虑是否有前置脚本
|
||||
*/
|
||||
private void importMsCase(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestCaseMapper apiTestCaseMapper) {
|
||||
List<ApiTestCaseWithBLOBs> cases = apiImport.getCases();
|
||||
if (CollectionUtils.isNotEmpty(cases)) {
|
||||
int batchCount = 0;
|
||||
cases.forEach(item -> {
|
||||
item.setId(UUID.randomUUID().toString());
|
||||
item.setCreateTime(System.currentTimeMillis());
|
||||
item.setUpdateTime(System.currentTimeMillis());
|
||||
item.setCreateUserId(SessionUtils.getUserId());
|
||||
item.setUpdateUserId(SessionUtils.getUserId());
|
||||
item.setProjectId(SessionUtils.getCurrentProjectId());
|
||||
item.setNum(getNextNum(item.getApiDefinitionId()));
|
||||
apiTestCaseMapper.insert(item);
|
||||
});
|
||||
if (batchCount % 300 == 0) {
|
||||
sqlSession.flushStatements();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入是插件或者postman时创建用例
|
||||
* postman考虑是否有前置脚本
|
||||
*/
|
||||
private void importApiCase(ApiDefinitionWithBLOBs apiDefinition, ApiTestCaseMapper apiTestCaseMapper,
|
||||
ApiTestImportRequest apiTestImportRequest, Boolean isInsert) {
|
||||
try {
|
||||
|
@ -372,6 +380,7 @@ public class ApiDefinitionService {
|
|||
apiTestCase.setUpdateTime(System.currentTimeMillis());
|
||||
apiTestCase.setCreateUserId(SessionUtils.getUserId());
|
||||
apiTestCase.setUpdateUserId(SessionUtils.getUserId());
|
||||
apiTestCase.setNum(getNextNum(apiTestCase.getApiDefinitionId()));
|
||||
apiTestCase.setPriority("P0");
|
||||
if (!isInsert) {
|
||||
apiTestCase.setName(apiTestCase.getName() + "_" + apiTestCase.getId().substring(0, 5));
|
||||
|
@ -404,7 +413,7 @@ public class ApiDefinitionService {
|
|||
*/
|
||||
public String run(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
|
||||
HashTree hashTree = request.getTestElement().generateHashTree();
|
||||
String runMode = ApiRunMode.DEFINITION.name();
|
||||
|
@ -489,28 +498,27 @@ public class ApiDefinitionService {
|
|||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(Translator.get("parse_data_error"));
|
||||
}
|
||||
if (request.isSaved()) {
|
||||
importApi(request, apiImport);
|
||||
}
|
||||
importApi(request, apiImport);
|
||||
return apiImport;
|
||||
}
|
||||
|
||||
private void importApi(ApiTestImportRequest request, ApiDefinitionImport apiImport) {
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
List<ApiDefinitionWithBLOBs> data = apiImport.getData();
|
||||
ApiDefinitionMapper batchMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
|
||||
ApiTestCaseMapper apiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
|
||||
List<ApiDefinitionResult> data = apiImport.getData();
|
||||
int num = 0;
|
||||
if (!CollectionUtils.isEmpty(data) && data.get(0) != null && data.get(0).getProjectId() != null) {
|
||||
num = getNextNum(data.get(0).getProjectId());
|
||||
}
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
ApiDefinitionResult item = data.get(i);
|
||||
ApiDefinitionWithBLOBs item = data.get(i);
|
||||
if (item.getName().length() > 255) {
|
||||
item.setName(item.getName().substring(0, 255));
|
||||
}
|
||||
item.setNum(num++);
|
||||
importCreate(item, batchMapper, apiTestCaseMapper, request);
|
||||
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases());
|
||||
importMsCase(apiImport, sqlSession, apiTestCaseMapper);
|
||||
if (i % 300 == 0) {
|
||||
sqlSession.flushStatements();
|
||||
}
|
||||
|
@ -518,6 +526,7 @@ public class ApiDefinitionService {
|
|||
sqlSession.flushStatements();
|
||||
}
|
||||
|
||||
|
||||
public ReferenceDTO getReference(ApiScenarioRequest request) {
|
||||
ReferenceDTO dto = new ReferenceDTO();
|
||||
dto.setScenarioList(extApiScenarioMapper.selectReference(request));
|
||||
|
@ -539,20 +548,12 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
public void editApiByParam(ApiBatchRequest request) {
|
||||
List<String> ids = request.getIds();
|
||||
if (request.isSelectAllDate()) {
|
||||
ids = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds(),request.getProtocol());
|
||||
}
|
||||
//name在这里只是查询参数
|
||||
request.setName(null);
|
||||
|
||||
ApiDefinitionExample definitionExample = new ApiDefinitionExample();
|
||||
definitionExample.createCriteria().andIdIn(ids);
|
||||
|
||||
ApiDefinitionWithBLOBs definitionWithBLOBs = new ApiDefinitionWithBLOBs();
|
||||
BeanUtils.copyBean(definitionWithBLOBs, request);
|
||||
definitionWithBLOBs.setUpdateTime(System.currentTimeMillis());
|
||||
apiDefinitionMapper.updateByExampleSelective(definitionWithBLOBs, definitionExample);
|
||||
apiDefinitionMapper.updateByExampleSelective(definitionWithBLOBs, getBatchExample(request));
|
||||
}
|
||||
|
||||
public void testPlanRelevance(ApiCaseRelevanceRequest request) {
|
||||
|
@ -602,14 +603,16 @@ public class ApiDefinitionService {
|
|||
return apiDefinitionMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public void deleteByParams(ApiDefinitionBatchProcessingRequest request) {
|
||||
List<String> apiIds = request.getDataIds();
|
||||
if (request.isSelectAllDate()) {
|
||||
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds(),request.getProtocol());
|
||||
}
|
||||
public void deleteByParams(ApiBatchRequest request) {
|
||||
apiDefinitionMapper.deleteByExample(getBatchExample(request));
|
||||
}
|
||||
|
||||
public ApiDefinitionExample getBatchExample(ApiBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extApiDefinitionMapper.selectIds(query));
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(apiIds);
|
||||
apiDefinitionMapper.deleteByExample(example);
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
return example;
|
||||
}
|
||||
|
||||
private List<String> getAllApiIdsByFontedSelect(Map<String, List<String>> filters, String name, List<String> moduleIds, String projectId, List<String> unSelectIds,String protocol) {
|
||||
|
@ -629,12 +632,10 @@ public class ApiDefinitionService {
|
|||
return ids;
|
||||
}
|
||||
|
||||
public void removeToGcByParams(ApiDefinitionBatchProcessingRequest request) {
|
||||
List<String> apiIds = request.getDataIds();
|
||||
if (request.isSelectAllDate()) {
|
||||
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds(),request.getProtocol());
|
||||
}
|
||||
extApiDefinitionMapper.removeToGc(apiIds);
|
||||
public void removeToGcByParams(ApiBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extApiDefinitionMapper.selectIds(query));
|
||||
extApiDefinitionMapper.removeToGc(request.getIds());
|
||||
}
|
||||
|
||||
public List<ApiDefinitionResult> listRelevance(ApiDefinitionRequest request) {
|
||||
|
@ -732,4 +733,17 @@ public class ApiDefinitionService {
|
|||
private void addOrUpdateSwaggerImportCronJob(Schedule request) {
|
||||
scheduleService.addOrUpdateCronJob(request, SwaggerUrlImportJob.getJobKey(request.getResourceId()), SwaggerUrlImportJob.getTriggerKey(request.getResourceId()), SwaggerUrlImportJob.class);
|
||||
}
|
||||
|
||||
public ApiExportResult export(ApiBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extApiDefinitionMapper.selectIds(query));
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
ApiExportResult apiExportResult = new ApiExportResult();
|
||||
apiExportResult.setData(apiDefinitionMapper.selectByExampleWithBLOBs(example));
|
||||
apiExportResult.setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds()));
|
||||
apiExportResult.setProjectName(request.getProjectId());
|
||||
apiExportResult.setProtocol(request.getProtocol());
|
||||
return apiExportResult;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.ApiDocumentInfoDTO;
|
||||
import io.metersphere.api.dto.ApiDocumentRequest;
|
||||
import io.metersphere.api.dto.ApiDocumentSimpleInfoDTO;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.mapper.ext.ExtApiDocumentMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/2/7 10:37 上午
|
||||
* @Description
|
||||
*/
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiDocumentService {
|
||||
|
||||
@Resource
|
||||
ExtApiDocumentMapper extApiDocumentMapper;
|
||||
|
||||
public List<ApiDocumentSimpleInfoDTO> findApiDocumentSimpleInfoByRequest(ApiDocumentRequest request) {
|
||||
return extApiDocumentMapper.findApiDocumentSimpleInfoByRequest(request);
|
||||
}
|
||||
|
||||
public ApiDocumentInfoDTO conversionModelToDTO(ApiDefinitionWithBLOBs apiModel) {
|
||||
ApiDocumentInfoDTO apiInfoDTO = new ApiDocumentInfoDTO();
|
||||
if (apiModel != null) {
|
||||
apiInfoDTO.setId(apiModel.getId());
|
||||
apiInfoDTO.setName(apiModel.getName());
|
||||
apiInfoDTO.setMethod(apiModel.getMethod());
|
||||
apiInfoDTO.setUri(apiModel.getPath());
|
||||
apiInfoDTO.setStatus(apiModel.getStatus());
|
||||
|
||||
JSONObject requestJsonObj = JSONObject.parseObject(apiModel.getRequest());
|
||||
|
||||
//head赋值
|
||||
if (requestJsonObj.containsKey("headers")) {
|
||||
JSONArray requestHeadDataArr = new JSONArray();
|
||||
//head赋值
|
||||
JSONArray headArr = requestJsonObj.getJSONArray("headers");
|
||||
for (int index = 0; index < headArr.size(); index++) {
|
||||
JSONObject headObj = headArr.getJSONObject(index);
|
||||
if (headObj.containsKey("name") && headObj.containsKey("value")) {
|
||||
requestHeadDataArr.add(headObj);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setRequestHead(requestHeadDataArr.toJSONString());
|
||||
}
|
||||
|
||||
//url参数赋值
|
||||
JSONArray urlParamArr = new JSONArray();
|
||||
if (requestJsonObj.containsKey("arguments")) {
|
||||
//urlParam -- query赋值
|
||||
JSONArray headArr = requestJsonObj.getJSONArray("arguments");
|
||||
for (int index = 0; index < headArr.size(); index++) {
|
||||
JSONObject headObj = headArr.getJSONObject(index);
|
||||
if (headObj.containsKey("name") && headObj.containsKey("value")) {
|
||||
urlParamArr.add(headObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requestJsonObj.containsKey("rest")) {
|
||||
//urlParam -- rest赋值
|
||||
JSONArray headArr = requestJsonObj.getJSONArray("rest");
|
||||
for (int index = 0; index < headArr.size(); index++) {
|
||||
JSONObject headObj = headArr.getJSONObject(index);
|
||||
if (headObj.containsKey("name") && headObj.containsKey("value")) {
|
||||
urlParamArr.add(headObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setUrlParams(urlParamArr.toJSONString());
|
||||
|
||||
//请求体参数类型
|
||||
if (requestJsonObj.containsKey("body")) {
|
||||
JSONObject bodyObj = requestJsonObj.getJSONObject("body");
|
||||
if (bodyObj.containsKey("type")) {
|
||||
String type = bodyObj.getString("type");
|
||||
apiInfoDTO.setRequestBodyParamType(type);
|
||||
if (StringUtils.equalsAny(type, "JSON", "XML", "Raw")) {
|
||||
if (bodyObj.containsKey("raw")) {
|
||||
String raw = bodyObj.getString("raw");
|
||||
apiInfoDTO.setRequestBodyStrutureData(raw);
|
||||
}
|
||||
} else if (StringUtils.equalsAny(type, "Form Data", "WWW_FORM")) {
|
||||
if (bodyObj.containsKey("kvs")) {
|
||||
JSONArray bodyParamArr = new JSONArray();
|
||||
JSONArray kvsArr = bodyObj.getJSONArray("kvs");
|
||||
for (int i = 0; i < kvsArr.size(); i++) {
|
||||
JSONObject kv = kvsArr.getJSONObject(i);
|
||||
if (kv.containsKey("name")) {
|
||||
bodyParamArr.add(kv);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setRequestBodyFormData(bodyParamArr.toJSONString());
|
||||
}
|
||||
} else if (StringUtils.equals(type, "BINARY")) {
|
||||
if (bodyObj.containsKey("binary")) {
|
||||
List<Map<String, String>> bodyParamList = new ArrayList<>();
|
||||
JSONArray kvsArr = bodyObj.getJSONArray("kvs");
|
||||
for (int i = 0; i < kvsArr.size(); i++) {
|
||||
JSONObject kv = kvsArr.getJSONObject(i);
|
||||
if (kv.containsKey("description") && kv.containsKey("files")) {
|
||||
Map<String, String> bodyMap = new HashMap<>();
|
||||
|
||||
String name = kv.getString("description");
|
||||
JSONArray fileArr = kv.getJSONArray("files");
|
||||
String value = "";
|
||||
for (int j = 0; j < fileArr.size(); j++) {
|
||||
JSONObject fileObj = fileArr.getJSONObject(j);
|
||||
if (fileObj.containsKey("name")) {
|
||||
value += fileObj.getString("name") + " ;";
|
||||
}
|
||||
}
|
||||
|
||||
bodyMap.put("name", name);
|
||||
bodyMap.put("value", value);
|
||||
|
||||
bodyParamList.add(bodyMap);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setRequestBodyFormData(JSONArray.toJSONString(bodyParamList));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject responseJsonObj = JSONObject.parseObject(apiModel.getResponse());
|
||||
//赋值响应头
|
||||
if (responseJsonObj.containsKey("headers")) {
|
||||
JSONArray responseHeadDataArr = new JSONArray();
|
||||
JSONArray headArr = responseJsonObj.getJSONArray("headers");
|
||||
for (int index = 0; index < headArr.size(); index++) {
|
||||
JSONObject headObj = headArr.getJSONObject(index);
|
||||
if (headObj.containsKey("name") && headObj.containsKey("value")) {
|
||||
responseHeadDataArr.add(headObj);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setResponseHead(responseHeadDataArr.toJSONString());
|
||||
}
|
||||
|
||||
// 赋值响应体
|
||||
if (responseJsonObj.containsKey("body")) {
|
||||
JSONObject bodyObj = responseJsonObj.getJSONObject("body");
|
||||
if (bodyObj.containsKey("type")) {
|
||||
String type = bodyObj.getString("type");
|
||||
apiInfoDTO.setResponseBodyParamType(type);
|
||||
if (StringUtils.equalsAny(type, "JSON", "XML", "Raw")) {
|
||||
if (bodyObj.containsKey("raw")) {
|
||||
String raw = bodyObj.getString("raw");
|
||||
apiInfoDTO.setResponseBodyStrutureData(raw);
|
||||
}
|
||||
} else if (StringUtils.equalsAny(type, "Form Data", "WWW_FORM")) {
|
||||
if (bodyObj.containsKey("kvs")) {
|
||||
JSONArray bodyParamArr = new JSONArray();
|
||||
JSONArray kvsArr = bodyObj.getJSONArray("kvs");
|
||||
for (int i = 0; i < kvsArr.size(); i++) {
|
||||
JSONObject kv = kvsArr.getJSONObject(i);
|
||||
if (kv.containsKey("name")) {
|
||||
bodyParamArr.add(kv);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setResponseBodyFormData(bodyParamArr.toJSONString());
|
||||
}
|
||||
} else if (StringUtils.equals(type, "BINARY")) {
|
||||
if (bodyObj.containsKey("binary")) {
|
||||
List<Map<String, String>> bodyParamList = new ArrayList<>();
|
||||
JSONArray kvsArr = bodyObj.getJSONArray("kvs");
|
||||
for (int i = 0; i < kvsArr.size(); i++) {
|
||||
JSONObject kv = kvsArr.getJSONObject(i);
|
||||
if (kv.containsKey("description") && kv.containsKey("files")) {
|
||||
Map<String, String> bodyMap = new HashMap<>();
|
||||
|
||||
String name = kv.getString("description");
|
||||
JSONArray fileArr = kv.getJSONArray("files");
|
||||
String value = "";
|
||||
for (int j = 0; j < fileArr.size(); j++) {
|
||||
JSONObject fileObj = fileArr.getJSONObject(j);
|
||||
if (fileObj.containsKey("name")) {
|
||||
value += fileObj.getString("name") + " ;";
|
||||
}
|
||||
}
|
||||
|
||||
bodyMap.put("name", name);
|
||||
bodyMap.put("value", value);
|
||||
|
||||
bodyParamList.add(bodyMap);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setResponseBodyFormData(JSONArray.toJSONString(bodyParamList));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 赋值响应码
|
||||
if (responseJsonObj.containsKey("statusCode")) {
|
||||
JSONArray responseStatusDataArr = new JSONArray();
|
||||
JSONArray statusArr = responseJsonObj.getJSONArray("statusCode");
|
||||
for (int index = 0; index < statusArr.size(); index++) {
|
||||
JSONObject statusObj = statusArr.getJSONObject(index);
|
||||
if (statusObj.containsKey("name") && statusObj.containsKey("value")) {
|
||||
responseStatusDataArr.add(statusObj);
|
||||
}
|
||||
}
|
||||
apiInfoDTO.setResponseCode(responseStatusDataArr.toJSONString());
|
||||
}
|
||||
}
|
||||
return apiInfoDTO;
|
||||
}
|
||||
}
|
|
@ -46,10 +46,6 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
|
|||
@Resource
|
||||
TestPlanProjectService testPlanProjectService;
|
||||
@Resource
|
||||
private ApiTestCaseService apiTestCaseService;
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
@Resource
|
||||
private ProjectService projectService;
|
||||
|
||||
public ApiScenarioModuleService() {
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.apache.jorphan.collections.ListedHashTree;
|
|||
import org.aspectj.util.FileUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -72,7 +72,7 @@ public class ApiTestCaseService {
|
|||
@Resource
|
||||
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
|
||||
@Resource
|
||||
TestPlanApiCaseMapper testPlanApiCaseMapper;
|
||||
private TestPlanApiCaseMapper testPlanApiCaseMapper;
|
||||
|
||||
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
|
||||
|
||||
|
@ -136,7 +136,7 @@ public class ApiTestCaseService {
|
|||
public ApiTestCase create(SaveApiTestCaseRequest request, List<MultipartFile> bodyFiles) {
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
ApiTestCase test = createTest(request);
|
||||
createBodyFiles(test, bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
return test;
|
||||
}
|
||||
|
||||
|
@ -152,31 +152,10 @@ public class ApiTestCaseService {
|
|||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
request.setBodyUploadIds(null);
|
||||
ApiTestCase test = updateTest(request);
|
||||
createBodyFiles(test, bodyUploadIds, bodyFiles);
|
||||
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
|
||||
return test;
|
||||
}
|
||||
|
||||
private void createBodyFiles(ApiTestCase test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
||||
if (bodyUploadIds.size() > 0) {
|
||||
String dir = BODY_FILE_DIR + "/" + test.getId();
|
||||
File testDir = new File(dir);
|
||||
if (!testDir.exists()) {
|
||||
testDir.mkdirs();
|
||||
}
|
||||
for (int i = 0; i < bodyUploadIds.size(); i++) {
|
||||
MultipartFile item = bodyFiles.get(i);
|
||||
File file = new File(testDir + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename());
|
||||
try (InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(file)) {
|
||||
file.createNewFile();
|
||||
FileUtil.copyStream(in, out);
|
||||
} catch (IOException e) {
|
||||
LogUtil.error(e);
|
||||
MSException.throwException(Translator.get("upload_fail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(String testId) {
|
||||
extTestPlanTestCaseMapper.deleteByTestCaseID(testId);
|
||||
deleteFileByTestId(testId);
|
||||
|
@ -279,19 +258,14 @@ public class ApiTestCaseService {
|
|||
}
|
||||
}
|
||||
|
||||
private void saveFile(String testId, MultipartFile file) {
|
||||
final FileMetadata fileMetadata = fileService.saveFile(file);
|
||||
ApiTestFile apiTestFile = new ApiTestFile();
|
||||
apiTestFile.setTestId(testId);
|
||||
apiTestFile.setFileId(fileMetadata.getId());
|
||||
apiTestFileMapper.insert(apiTestFile);
|
||||
}
|
||||
|
||||
private void deleteFileByTestId(String testId) {
|
||||
ApiTestFileExample ApiTestFileExample = new ApiTestFileExample();
|
||||
ApiTestFileExample.createCriteria().andTestIdEqualTo(testId);
|
||||
final List<ApiTestFile> ApiTestFiles = apiTestFileMapper.selectByExample(ApiTestFileExample);
|
||||
apiTestFileMapper.deleteByExample(ApiTestFileExample);
|
||||
if (CollectionUtils.isNotEmpty(ApiTestFiles)) {
|
||||
apiTestFileMapper.deleteByExample(ApiTestFileExample);
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(ApiTestFiles)) {
|
||||
final List<String> fileIds = ApiTestFiles.stream().map(ApiTestFile::getFileId).collect(Collectors.toList());
|
||||
|
@ -386,6 +360,12 @@ public class ApiTestCaseService {
|
|||
return apiTestCaseMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public List<ApiTestCaseWithBLOBs> selectCasesBydApiIds(List<String> apiIds) {
|
||||
ApiTestCaseExample example = new ApiTestCaseExample();
|
||||
example.createCriteria().andApiDefinitionIdIn(apiIds);
|
||||
return apiTestCaseMapper.selectByExampleWithBLOBs(example);
|
||||
}
|
||||
|
||||
public Map<String, String> getRequest(ApiTestCaseRequest request) {
|
||||
List<ApiTestCaseWithBLOBs> list = extApiTestCaseMapper.getRequest(request);
|
||||
return list.stream().collect(Collectors.toMap(ApiTestCaseWithBLOBs::getId, ApiTestCaseWithBLOBs::getRequest));
|
||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.api.dto.SaveHistoricalDataUpgrade;
|
|||
import io.metersphere.api.dto.automation.ScenarioStatus;
|
||||
import io.metersphere.api.dto.definition.request.MsScenario;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertionDuration;
|
||||
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
|
||||
import io.metersphere.api.dto.definition.request.controller.MsIfController;
|
||||
import io.metersphere.api.dto.definition.request.extract.MsExtract;
|
||||
|
@ -84,6 +85,7 @@ public class HistoricalDataUpgradeService {
|
|||
scenario.setReferenced("Upgrade");
|
||||
scenario.setId(oldScenario.getId());
|
||||
scenario.setResourceId(UUID.randomUUID().toString());
|
||||
scenario.setHeaders(oldScenario.getHeaders());
|
||||
LinkedList<MsTestElement> testElements = new LinkedList<>();
|
||||
int index = 1;
|
||||
for (Request request : oldScenario.getRequests()) {
|
||||
|
@ -202,6 +204,23 @@ public class HistoricalDataUpgradeService {
|
|||
if (StringUtils.isEmpty(msAssertions.getName())) {
|
||||
msAssertions.setName("Assertions");
|
||||
}
|
||||
// 给初始值
|
||||
if (msAssertions.getDuration() == null) {
|
||||
msAssertions.setDuration(new MsAssertionDuration());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(msAssertions.getJsr223())) {
|
||||
msAssertions.setJsr223(new LinkedList<>());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(msAssertions.getXpath2())) {
|
||||
msAssertions.setXpath2(new LinkedList<>());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(msAssertions.getJsonPath())) {
|
||||
msAssertions.setJsonPath(new LinkedList<>());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(msAssertions.getRegex())) {
|
||||
msAssertions.setRegex(new LinkedList<>());
|
||||
}
|
||||
|
||||
msAssertions.setType("Assertions");
|
||||
msAssertions.setIndex(index + "");
|
||||
msAssertions.setResourceId(UUID.randomUUID().toString());
|
||||
|
@ -216,6 +235,16 @@ public class HistoricalDataUpgradeService {
|
|||
if (StringUtils.isEmpty(extract.getName())) {
|
||||
extract.setName("Extract");
|
||||
}
|
||||
// 默认给初始值
|
||||
if (CollectionUtils.isEmpty(extract.getJson())) {
|
||||
extract.setJson(new LinkedList<>());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(extract.getXpath())) {
|
||||
extract.setXpath(new LinkedList<>());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(extract.getRegex())) {
|
||||
extract.setRegex(new LinkedList<>());
|
||||
}
|
||||
extract.setType("Extract");
|
||||
extract.setIndex(index + "");
|
||||
extract.setHashTree(new LinkedList<>());
|
||||
|
|
|
@ -7,7 +7,7 @@ import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
|||
import io.metersphere.api.dto.definition.ApiSwaggerUrlDTO;
|
||||
import io.metersphere.base.domain.ApiDefinition;
|
||||
import io.metersphere.base.domain.ApiDefinitionExample;
|
||||
import io.metersphere.base.domain.ApiModuleExample;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -36,4 +36,6 @@ public interface ExtApiDefinitionMapper {
|
|||
ApiDefinition getNextNum(@Param("projectId") String projectId);
|
||||
|
||||
List<ApiDefinitionResult> listRelevance(@Param("request")ApiDefinitionRequest request);
|
||||
|
||||
List<String> selectIds(@Param("request") BaseQueryRequest query);
|
||||
}
|
|
@ -210,85 +210,7 @@
|
|||
from api_definition
|
||||
left join project on api_definition.project_id = project.id
|
||||
left join user on api_definition.user_id = user.id
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.combine"/>
|
||||
<property name="name" value="request.name"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="request.name != null">
|
||||
and (api_definition.name like CONCAT('%', #{request.name},'%')
|
||||
or api_definition.tags like CONCAT('%', #{request.name},'%')
|
||||
or api_definition.num like CONCAT('%', #{request.name},'%'))
|
||||
</if>
|
||||
<if test="request.protocol != null">
|
||||
AND api_definition.protocol = #{request.protocol}
|
||||
</if>
|
||||
<if test="request.workspaceId != null">
|
||||
AND project.workspace_id = #{request.workspaceId}
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
AND project.id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.id != null">
|
||||
AND api_definition.id = #{request.id}
|
||||
</if>
|
||||
<if test="request.userId != null">
|
||||
AND api_definition.user_id = #{request.userId}
|
||||
</if>
|
||||
<if test="request.createTime >0">
|
||||
AND api_definition.create_time >= #{request.createTime}
|
||||
</if>
|
||||
<if test="request.moduleId != null">
|
||||
AND api_definition.module_id = #{request.moduleId}
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
AND api_definition.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
AND api_definition.module_id in
|
||||
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
|
||||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='status'">
|
||||
and api_definition.status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='method'">
|
||||
and api_definition.method in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='user_id'">
|
||||
and api_definition.user_id in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.apiCaseCoverage == 'uncoverage' ">
|
||||
and api_definition.id not in
|
||||
(SELECT api_definition_id FROM api_test_case)
|
||||
</if>
|
||||
<if test="request.apiCaseCoverage == 'coverage' ">
|
||||
and api_definition.id in
|
||||
(SELECT api_definition_id FROM api_test_case)
|
||||
</if>
|
||||
|
||||
|
||||
</where>
|
||||
<include refid="queryWhereCondition"/>
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
|
@ -446,4 +368,93 @@
|
|||
WHERE sch.`enable` = true
|
||||
AND apiScene.project_id = #{0,jdbcType=VARCHAR}
|
||||
</select>
|
||||
<select id="selectIds" resultType="java.lang.String">
|
||||
select api_definition.id
|
||||
from api_definition
|
||||
left join project on api_definition.project_id = project.id
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.combine"/>
|
||||
<property name="name" value="request.name"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="request.name != null">
|
||||
and (api_definition.name like CONCAT('%', #{request.name},'%')
|
||||
or api_definition.tags like CONCAT('%', #{request.name},'%')
|
||||
or api_definition.num like CONCAT('%', #{request.name},'%'))
|
||||
</if>
|
||||
<if test="request.protocol != null">
|
||||
AND api_definition.protocol = #{request.protocol}
|
||||
</if>
|
||||
<if test="request.workspaceId != null">
|
||||
AND project.workspace_id = #{request.workspaceId}
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
AND project.id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.id != null">
|
||||
AND api_definition.id = #{request.id}
|
||||
</if>
|
||||
<if test="request.userId != null">
|
||||
AND api_definition.user_id = #{request.userId}
|
||||
</if>
|
||||
<if test="request.createTime >0">
|
||||
AND api_definition.create_time >= #{request.createTime}
|
||||
</if>
|
||||
<if test="request.moduleId != null">
|
||||
AND api_definition.module_id = #{request.moduleId}
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
AND api_definition.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
AND api_definition.module_id in
|
||||
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
|
||||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='status'">
|
||||
and api_definition.status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='method'">
|
||||
and api_definition.method in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='user_id'">
|
||||
and api_definition.user_id in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.apiCaseCoverage == 'uncoverage' ">
|
||||
and api_definition.id not in
|
||||
(SELECT api_definition_id FROM api_test_case)
|
||||
</if>
|
||||
<if test="request.apiCaseCoverage == 'coverage' ">
|
||||
and api_definition.id in
|
||||
(SELECT api_definition_id FROM api_test_case)
|
||||
</if>
|
||||
|
||||
|
||||
</where>
|
||||
</sql>
|
||||
</mapper>
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.api.dto.ApiDocumentRequest;
|
||||
import io.metersphere.api.dto.ApiDocumentSimpleInfoDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtApiDocumentMapper {
|
||||
List<ApiDocumentSimpleInfoDTO> findApiDocumentSimpleInfoByRequest(@Param("request") ApiDocumentRequest request);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?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">
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtApiDocumentMapper">
|
||||
<select id="findApiDocumentSimpleInfoByRequest" resultType="io.metersphere.api.dto.ApiDocumentSimpleInfoDTO">
|
||||
SELECT api.id,api.name FROM Api_definition api
|
||||
<where>
|
||||
<if test="request.projectId != null">
|
||||
api.project_Id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
AND api.module_id in
|
||||
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
|
||||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY api.create_time DESC
|
||||
</select>
|
||||
</mapper>
|
|
@ -6,6 +6,7 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult;
|
|||
import io.metersphere.base.domain.ApiScenario;
|
||||
import io.metersphere.base.domain.ApiScenarioExample;
|
||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -34,4 +35,6 @@ public interface ExtApiScenarioMapper {
|
|||
List<String> selectIdsNotExistsInPlan(String projectId, String planId);
|
||||
|
||||
ApiScenario getNextNum(@Param("projectId") String projectId);
|
||||
|
||||
List<String> selectIdsByQuery(@Param("request") ApiScenarioRequest request);
|
||||
}
|
||||
|
|
|
@ -134,6 +134,11 @@
|
|||
from api_scenario
|
||||
left join project on api_scenario.project_id = project.id
|
||||
left join user on api_scenario.user_id = user.id
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
|
@ -144,8 +149,8 @@
|
|||
|
||||
<if test="request.name != null">
|
||||
and (api_scenario.name like CONCAT('%', #{request.name},'%')
|
||||
or api_scenario.tags like CONCAT('%', #{request.name},'%')
|
||||
or api_scenario.num like CONCAT('%', #{request.name},'%'))
|
||||
or api_scenario.tags like CONCAT('%', #{request.name},'%')
|
||||
or api_scenario.num like CONCAT('%', #{request.name},'%'))
|
||||
</if>
|
||||
<if test="request.workspaceId != null">
|
||||
AND project.workspace_id = #{request.workspaceId}
|
||||
|
@ -223,19 +228,13 @@
|
|||
</if>
|
||||
<if test="request.notInTestPlan == true ">
|
||||
and api_scenario.id not in (
|
||||
select pc.api_scenario_id
|
||||
from test_plan_api_scenario pc
|
||||
where pc.test_plan_id = #{request.planId}
|
||||
select pc.api_scenario_id
|
||||
from test_plan_api_scenario pc
|
||||
where pc.test_plan_id = #{request.planId}
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
api_scenario.${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
</sql>
|
||||
|
||||
<select id="selectByTagId" resultType="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
||||
select * from api_scenario where tags like CONCAT('%', #{id},'%')
|
||||
|
@ -321,4 +320,12 @@
|
|||
SELECT * FROM api_scenario WHERE api_scenario.project_id = #{projectId} ORDER BY num DESC LIMIT 1;
|
||||
</select>
|
||||
|
||||
<select id="selectIdsByQuery" resultType="java.lang.String">
|
||||
select api_scenario.id
|
||||
from api_scenario
|
||||
left join project on api_scenario.project_id = project.id
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,34 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.aspectj.util.FileUtil;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
public class FileUtils {
|
||||
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
|
||||
|
||||
public static void createBodyFiles(List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
||||
if (CollectionUtils.isNotEmpty(bodyUploadIds) && CollectionUtils.isNotEmpty(bodyFiles)) {
|
||||
File testDir = new File(BODY_FILE_DIR);
|
||||
if (!testDir.exists()) {
|
||||
testDir.mkdirs();
|
||||
}
|
||||
for (int i = 0; i < bodyUploadIds.size(); i++) {
|
||||
MultipartFile item = bodyFiles.get(i);
|
||||
File file = new File(BODY_FILE_DIR + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename());
|
||||
try (InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(file)) {
|
||||
file.createNewFile();
|
||||
FileUtil.copyStream(in, out);
|
||||
} catch (IOException e) {
|
||||
LogUtil.error(e);
|
||||
MSException.throwException(Translator.get("upload_fail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
@ -28,7 +31,7 @@ public class ServiceUtils {
|
|||
* @param func 查询id列表的数据库查询
|
||||
* @return
|
||||
*/
|
||||
public static void getSelectAllIds(BaseQueryRequest queryRequest, Function<BaseQueryRequest, List<String>> func) {
|
||||
public static<T> void getSelectAllIds( T batchRequest, BaseQueryRequest queryRequest, Function<BaseQueryRequest, List<String>> func) {
|
||||
if (queryRequest.isSelectAll()) {
|
||||
List<String> ids = func.apply(queryRequest);
|
||||
if (!ids.isEmpty()) {
|
||||
|
@ -37,6 +40,13 @@ public class ServiceUtils {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
queryRequest.setIds(ids);
|
||||
try {
|
||||
Method setIds = batchRequest.getClass().getDeclaredMethod("setIds", List.class);
|
||||
setIds.invoke(batchRequest, ids);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException("请求没有setIds方法");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
||||
@RestControllerAdvice
|
||||
|
@ -30,6 +31,12 @@ public class RestControllerExceptionHandler {
|
|||
}
|
||||
|
||||
|
||||
@ExceptionHandler(SQLException.class)
|
||||
public ResultHolder sqlExceptionHandler(HttpServletRequest request, HttpServletResponse response, MSException e) {
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
return ResultHolder.error("SQL error happened, please check logs.");
|
||||
}
|
||||
|
||||
@ExceptionHandler(MSException.class)
|
||||
public ResultHolder msExceptionHandler(HttpServletRequest request, HttpServletResponse response, MSException e) {
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
|
|
|
@ -22,6 +22,15 @@ public class BaseQueryRequest {
|
|||
|
||||
private List<String> nodeIds;
|
||||
|
||||
/**
|
||||
* selectAll:选择的数据是否是全部数据(全部数据是不受分页影响的数据)
|
||||
* filters: 数据状态
|
||||
* name:如果是全部数据,那么表格如果历经查询,查询参数是什么
|
||||
* moduleIds: 哪些模块的数据
|
||||
* unSelectIds:是否在页面上有未勾选的数据,有的话他们的ID是哪些。
|
||||
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要。为了让程序能明确批量的范围。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 是否选中所有数据
|
||||
*/
|
||||
|
|
|
@ -56,7 +56,7 @@ public class ApiScenarioTestJob extends MsScheduleJob {
|
|||
request.setProjectId(projectID);
|
||||
request.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
|
||||
request.setExecuteType(ExecuteType.Saved.name());
|
||||
request.setScenarioIds(this.scenarioIds);
|
||||
request.setIds(this.scenarioIds);
|
||||
request.setReportUserID(this.userId);
|
||||
|
||||
apiAutomationService.run(request);
|
||||
|
|
|
@ -29,7 +29,6 @@ public class SwaggerUrlImportJob extends MsScheduleJob {
|
|||
request.setSwaggerUrl(swaggerUrlProject.getSwaggerUrl());
|
||||
request.setModuleId(swaggerUrlProject.getModuleId());
|
||||
request.setPlatform("Swagger2");
|
||||
request.setSaved(true);
|
||||
request.setUserId(jobDataMap.getString("userId"));
|
||||
request.setType("schedule");
|
||||
apiDefinitionService.apiTestImport(null, request);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package io.metersphere.performance.engine.producer;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class LoadTestProducer {
|
||||
|
||||
@Value("${kafka.topic}")
|
||||
private String topic;
|
||||
@Resource
|
||||
private KafkaTemplate<String, Object> kafkaTemplate;
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
public void sendMessage(String reportId) {
|
||||
Metric metric = new Metric();
|
||||
metric.setReportId(reportId);
|
||||
metric.setThreadName("tearDown Thread Group"); // 发送停止消息
|
||||
try {
|
||||
this.kafkaTemplate.send(topic, objectMapper.writeValueAsString(metric));
|
||||
} catch (JsonProcessingException e) {
|
||||
LogUtil.error("发送停止消息失败", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package io.metersphere.performance.engine.producer;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class Metric {
|
||||
@JsonProperty("test.id")
|
||||
private String testId;
|
||||
@JsonProperty("test.name")
|
||||
private String testName;
|
||||
@JsonProperty("test.startTime")
|
||||
private Long clusterStartTime;
|
||||
@JsonProperty("test.reportId")
|
||||
private String reportId;
|
||||
@JsonProperty("ContentType")
|
||||
private String contentType;
|
||||
@JsonProperty("IdleTime")
|
||||
private Integer idleTime;
|
||||
@JsonProperty("ElapsedTime")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
|
||||
private Date elapsedTime;
|
||||
@JsonProperty("ErrorCount")
|
||||
private Integer errorCount;
|
||||
@JsonProperty("Timestamp")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
|
||||
private Date timestamp;
|
||||
@JsonProperty("URL")
|
||||
private String url;
|
||||
@JsonProperty("SampleStartTime")
|
||||
private String sampleStartTime;
|
||||
@JsonProperty("Success")
|
||||
private Boolean success;
|
||||
@JsonProperty("Bytes")
|
||||
private Integer bytes;
|
||||
@JsonProperty("SentBytes")
|
||||
private Integer sentBytes;
|
||||
@JsonProperty("AllThreads")
|
||||
private Integer allThreads;
|
||||
@JsonProperty("TestElement.name")
|
||||
private String testElementName;
|
||||
@JsonProperty("DataType")
|
||||
private String dataType;
|
||||
@JsonProperty("ResponseTime")
|
||||
private Integer responseTime;
|
||||
@JsonProperty("SampleCount")
|
||||
private Integer sampleCount;
|
||||
@JsonProperty("FailureMessage")
|
||||
private String failureMessage;
|
||||
@JsonProperty("ConnectTime")
|
||||
private Integer connectTime;
|
||||
@JsonProperty("ResponseCode")
|
||||
private String responseCode;
|
||||
@JsonProperty("TestStartTime")
|
||||
private Long testStartTime;
|
||||
@JsonProperty("AssertionResults")
|
||||
private List<Object> assertionResults;
|
||||
@JsonProperty("Latency")
|
||||
private Integer latency;
|
||||
@JsonProperty("InjectorHostname")
|
||||
private String injectorHostname;
|
||||
@JsonProperty("GrpThreads")
|
||||
private Integer grpThreads;
|
||||
@JsonProperty("SampleEndTime")
|
||||
private String sampleEndTime;
|
||||
@JsonProperty("BodySize")
|
||||
private Long bodySize;
|
||||
@JsonProperty("ThreadName")
|
||||
private String threadName;
|
||||
@JsonProperty("SampleLabel")
|
||||
private String sampleLabel;
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ import io.metersphere.i18n.Translator;
|
|||
import io.metersphere.job.sechedule.PerformanceTestJob;
|
||||
import io.metersphere.performance.engine.Engine;
|
||||
import io.metersphere.performance.engine.EngineFactory;
|
||||
import io.metersphere.performance.engine.producer.LoadTestProducer;
|
||||
import io.metersphere.service.FileService;
|
||||
import io.metersphere.service.QuotaService;
|
||||
import io.metersphere.service.ScheduleService;
|
||||
|
@ -75,6 +76,8 @@ public class PerformanceTestService {
|
|||
private TestCaseService testCaseService;
|
||||
@Resource
|
||||
private TestResourcePoolMapper testResourcePoolMapper;
|
||||
@Resource
|
||||
private LoadTestProducer loadTestProducer;
|
||||
|
||||
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
|
@ -437,6 +440,8 @@ public class PerformanceTestService {
|
|||
reportService.deleteReport(reportId);
|
||||
} else {
|
||||
stopEngine(reportId);
|
||||
// 发送测试停止消息
|
||||
loadTestProducer.sendMessage(reportId);
|
||||
// 停止测试之后设置报告的状态
|
||||
reportService.updateStatus(reportId, PerformanceTestStatus.Completed.name());
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.metersphere.track.controller;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.track.issue.PlatformUser;
|
||||
import io.metersphere.track.issue.ZentaoBuild;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.service.IssuesService;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.track.issue;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.commons.constants.IssuesManagePlatform;
|
|||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.EncryptUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.commonmark.node.Node;
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.base.domain.TestCaseIssues;
|
|||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -7,9 +7,9 @@ import io.metersphere.base.domain.*;
|
|||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.RestTemplateUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.ResultHolder;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
@ -194,9 +194,9 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
HttpHeaders header = auth(account, password);
|
||||
|
||||
if (httpMethod.equals(HttpMethod.GET)) {
|
||||
responseJson = RestTemplateUtils.get(url, header);
|
||||
responseJson = TapdRestUtils.get(url, header);
|
||||
} else {
|
||||
responseJson = RestTemplateUtils.post(url, params, header);
|
||||
responseJson = TapdRestUtils.post(url, params, header);
|
||||
}
|
||||
|
||||
ResultHolder result = JSON.parseObject(responseJson, ResultHolder.class);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package io.metersphere.commons.utils;
|
||||
package io.metersphere.track.issue;
|
||||
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
@ -8,7 +10,7 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
public class RestTemplateUtils {
|
||||
public class TapdRestUtils {
|
||||
|
||||
private static RestTemplate restTemplate;
|
||||
|
|
@ -7,6 +7,8 @@ import io.metersphere.base.domain.*;
|
|||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.track.issue;
|
||||
package io.metersphere.track.issue.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.track.domain;
|
||||
package io.metersphere.track.issue.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.track.issue;
|
||||
package io.metersphere.track.issue.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.track.request.testcase;
|
||||
|
||||
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -15,5 +14,5 @@ public class TestCaseBatchRequest extends TestCaseWithBLOBs {
|
|||
private List<OrderRequest> orders;
|
||||
private String projectId;
|
||||
|
||||
private BaseQueryRequest condition;
|
||||
private QueryTestCaseRequest condition;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import io.metersphere.notice.service.NoticeSendService;
|
|||
import io.metersphere.service.IntegrationService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.track.issue.*;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
|
@ -180,14 +180,16 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(planId);
|
||||
projectIds.forEach(id -> {
|
||||
Project project = projectMapper.selectByPrimaryKey(id);
|
||||
String name = project.getName();
|
||||
List<TestCaseNodeDTO> nodeList = getNodeDTO(id, planId);
|
||||
TestCaseNodeDTO testCaseNodeDTO = new TestCaseNodeDTO();
|
||||
testCaseNodeDTO.setId(project.getId());
|
||||
testCaseNodeDTO.setName(name);
|
||||
testCaseNodeDTO.setLabel(name);
|
||||
testCaseNodeDTO.setChildren(nodeList);
|
||||
list.add(testCaseNodeDTO);
|
||||
if (project != null) {
|
||||
String name = project.getName();
|
||||
List<TestCaseNodeDTO> nodeList = getNodeDTO(id, planId);
|
||||
TestCaseNodeDTO testCaseNodeDTO = new TestCaseNodeDTO();
|
||||
testCaseNodeDTO.setId(project.getId());
|
||||
testCaseNodeDTO.setName(name);
|
||||
testCaseNodeDTO.setLabel(name);
|
||||
testCaseNodeDTO.setChildren(nodeList);
|
||||
list.add(testCaseNodeDTO);
|
||||
}
|
||||
});
|
||||
|
||||
return list;
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.alibaba.excel.EasyExcelFactory;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.dto.definition.ApiBatchRequest;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
||||
|
@ -528,33 +529,25 @@ public class TestCaseService {
|
|||
|
||||
|
||||
public void editTestCaseBath(TestCaseBatchRequest request) {
|
||||
getSelectAllIds(request);
|
||||
TestCaseExample testCaseExample = new TestCaseExample();
|
||||
testCaseExample.createCriteria().andIdIn(request.getIds());
|
||||
|
||||
TestCaseExample example = this.getBatchExample(request);
|
||||
TestCaseWithBLOBs testCase = new TestCaseWithBLOBs();
|
||||
BeanUtils.copyBean(testCase, request);
|
||||
testCase.setUpdateTime(System.currentTimeMillis());
|
||||
testCaseMapper.updateByExampleSelective(
|
||||
testCase,
|
||||
testCaseExample);
|
||||
|
||||
testCaseMapper.updateByExampleSelective(testCase, example);
|
||||
}
|
||||
|
||||
public void deleteTestCaseBath(TestCaseBatchRequest request) {
|
||||
getSelectAllIds(request);
|
||||
TestCaseExample example = this.getBatchExample(request);
|
||||
deleteTestPlanTestCaseBath(request.getIds());
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
testCaseMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
public void getSelectAllIds(TestCaseBatchRequest request) {
|
||||
if (request.getCondition().isSelectAll()) {
|
||||
ServiceUtils.getSelectAllIds(request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
request.setIds(request.getCondition().getIds());
|
||||
}
|
||||
public TestCaseExample getBatchExample(TestCaseBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
return example;
|
||||
}
|
||||
|
||||
public void deleteTestPlanTestCaseBath(List<String> caseIds) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -26,23 +27,15 @@ public class TestPlanProjectService {
|
|||
private TestPlanMapper testPlanMapper;
|
||||
|
||||
public List<String> getProjectIdsByPlanId(String planId) {
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
||||
TestPlanProjectExample example = new TestPlanProjectExample();
|
||||
example.createCriteria().andTestPlanIdEqualTo(planId);
|
||||
List<String> projectIds = testPlanProjectMapper.selectByExample(example)
|
||||
.stream()
|
||||
.map(TestPlanProject::getProjectId)
|
||||
.collect(Collectors.toList());
|
||||
if (testPlan != null && StringUtils.isNotBlank(testPlan.getProjectId())) {
|
||||
if (!projectIds.contains(testPlan.getProjectId())) {
|
||||
projectIds.add(testPlan.getProjectId());
|
||||
}
|
||||
TestPlan plan = testPlanMapper.selectByPrimaryKey(planId);
|
||||
String workspaceId = plan.getWorkspaceId();
|
||||
if (StringUtils.isNotBlank(workspaceId)) {
|
||||
ProjectExample example = new ProjectExample();
|
||||
example.createCriteria().andWorkspaceIdEqualTo(workspaceId);
|
||||
List<Project> projects = projectMapper.selectByExample(example);
|
||||
return projects.stream().map(Project::getId).collect(Collectors.toList());
|
||||
}
|
||||
if (projectIds.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return projectIds;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<Project> getProjectByPlanId(TestCaseRelevanceRequest request) {
|
||||
|
@ -62,15 +55,16 @@ public class TestPlanProjectService {
|
|||
}
|
||||
|
||||
public List<String> getPlanIdByProjectId(String projectId) {
|
||||
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
|
||||
testPlanProjectExample.createCriteria().andProjectIdEqualTo(projectId);
|
||||
List<TestPlanProject> testPlanProjects = testPlanProjectMapper.selectByExample(testPlanProjectExample);
|
||||
if (CollectionUtils.isEmpty(testPlanProjects)) {
|
||||
TestPlanExample testPlanExample = new TestPlanExample();
|
||||
testPlanExample.createCriteria().andProjectIdEqualTo(projectId);
|
||||
List<TestPlan> testPlans = testPlanMapper.selectByExample(testPlanExample);
|
||||
|
||||
if (CollectionUtils.isEmpty(testPlans)) {
|
||||
return null;
|
||||
}
|
||||
return testPlanProjects
|
||||
return testPlans
|
||||
.stream()
|
||||
.map(TestPlanProject::getTestPlanId)
|
||||
.map(TestPlan::getId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ public class TestPlanScenarioCaseService {
|
|||
scenarioIds.add(apiScenario.getApiScenarioId());
|
||||
scenarioIdApiScarionMap.put(apiScenario.getApiScenarioId(),apiScenario.getId());
|
||||
}
|
||||
request.setScenarioIds(scenarioIds);
|
||||
request.setIds(scenarioIds);
|
||||
request.setScenarioTestPlanIdMap(scenarioIdApiScarionMap);
|
||||
request.setRunMode(ApiRunMode.SCENARIO_PLAN.name());
|
||||
return apiAutomationService.run(request);
|
||||
|
|
|
@ -119,15 +119,6 @@ public class TestPlanService {
|
|||
}
|
||||
|
||||
String testPlanId = UUID.randomUUID().toString();
|
||||
|
||||
List<String> projectIds = testPlan.getProjectIds();
|
||||
projectIds.forEach(id -> {
|
||||
TestPlanProject testPlanProject = new TestPlanProject();
|
||||
testPlanProject.setProjectId(id);
|
||||
testPlanProject.setTestPlanId(testPlanId);
|
||||
testPlanProjectMapper.insertSelective(testPlanProject);
|
||||
});
|
||||
|
||||
testPlan.setId(testPlanId);
|
||||
testPlan.setStatus(TestPlanStatus.Prepare.name());
|
||||
testPlan.setCreateTime(System.currentTimeMillis());
|
||||
|
@ -166,7 +157,6 @@ public class TestPlanService {
|
|||
}
|
||||
|
||||
public int editTestPlan(TestPlanDTO testPlan) {
|
||||
editTestPlanProject(testPlan);
|
||||
checkTestPlanExist(testPlan);
|
||||
TestPlan res = testPlanMapper.selectByPrimaryKey(testPlan.getId()); // 先查一次库
|
||||
if (!res.getStatus().equals(testPlan.getStatus())) { // 若有改变才更新时间
|
||||
|
@ -213,70 +203,6 @@ public class TestPlanService {
|
|||
return i;
|
||||
}
|
||||
|
||||
private void editTestPlanProject(TestPlanDTO testPlan) {
|
||||
// 将要进行关联的项目ID
|
||||
List<String> projectIds = testPlan.getProjectIds();
|
||||
// 如果将要关联的项目ID中包含测试计划所属ID则进行剔除
|
||||
if (!CollectionUtils.isEmpty(projectIds)) {
|
||||
if (projectIds.contains(testPlan.getProjectId())) {
|
||||
projectIds.remove(testPlan.getProjectId());
|
||||
}
|
||||
}
|
||||
// todo 优化; TestPlanList intoPlan 方法会触发此更新
|
||||
if (StringUtils.isNotBlank(testPlan.getProjectId())) {
|
||||
TestPlanProjectExample testPlanProjectExample1 = new TestPlanProjectExample();
|
||||
testPlanProjectExample1.createCriteria().andTestPlanIdEqualTo(testPlan.getId());
|
||||
List<TestPlanProject> testPlanProjects = testPlanProjectMapper.selectByExample(testPlanProjectExample1);
|
||||
// 已经关联的项目idList
|
||||
List<String> dbProjectIds = testPlanProjects.stream().map(TestPlanProject::getProjectId).collect(Collectors.toList());
|
||||
// 修改后传过来的项目idList,如果还未关联,进行关联
|
||||
projectIds.forEach(projectId -> {
|
||||
if (!dbProjectIds.contains(projectId)) {
|
||||
TestPlanProject testPlanProject = new TestPlanProject();
|
||||
testPlanProject.setTestPlanId(testPlan.getId());
|
||||
testPlanProject.setProjectId(projectId);
|
||||
testPlanProjectMapper.insert(testPlanProject);
|
||||
}
|
||||
});
|
||||
|
||||
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
|
||||
TestPlanProjectExample.Criteria criteria1 = testPlanProjectExample.createCriteria();
|
||||
criteria1.andTestPlanIdEqualTo(testPlan.getId());
|
||||
if (!CollectionUtils.isEmpty(projectIds)) {
|
||||
criteria1.andProjectIdNotIn(projectIds);
|
||||
}
|
||||
testPlanProjectMapper.deleteByExample(testPlanProjectExample);
|
||||
|
||||
// 关联的项目下的用例idList
|
||||
List<String> caseIds = null;
|
||||
// 测试计划所属项目下的用例不解除关联
|
||||
projectIds.add(testPlan.getProjectId());
|
||||
if (!CollectionUtils.isEmpty(projectIds)) {
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andProjectIdIn(projectIds);
|
||||
List<TestCase> caseList = testCaseMapper.selectByExample(example);
|
||||
caseIds = caseList.stream().map(TestCase::getId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 取消关联项目下的用例和计划的关系
|
||||
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
|
||||
TestPlanTestCaseExample.Criteria criteria = testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(testPlan.getId());
|
||||
if (!CollectionUtils.isEmpty(caseIds)) {
|
||||
criteria.andCaseIdNotIn(caseIds);
|
||||
}
|
||||
testPlanTestCaseMapper.deleteByExample(testPlanTestCaseExample);
|
||||
|
||||
List<String> relevanceProjectIds = new ArrayList<>();
|
||||
relevanceProjectIds.add(testPlan.getProjectId());
|
||||
if (!CollectionUtils.isEmpty(testPlan.getProjectIds())) {
|
||||
relevanceProjectIds.addAll(testPlan.getProjectIds());
|
||||
}
|
||||
testPlanApiCaseService.deleteByRelevanceProjectIds(testPlan.getId(), relevanceProjectIds);
|
||||
testPlanScenarioCaseService.deleteByRelevanceProjectIds(testPlan.getId(), relevanceProjectIds);
|
||||
testPlanLoadCaseService.deleteByRelevanceProjectIds(testPlan.getId(), relevanceProjectIds);
|
||||
}
|
||||
}
|
||||
|
||||
//计划内容
|
||||
private Map<String, Object> getTestPlanParamMap(TestPlan testPlan) {
|
||||
Long startTime = testPlan.getPlannedStartTime();
|
||||
|
@ -331,7 +257,6 @@ public class TestPlanService {
|
|||
public int deleteTestPlan(String planId) {
|
||||
TestPlan testPlan = getTestPlan(planId);
|
||||
deleteTestCaseByPlanId(planId);
|
||||
testPlanProjectService.deleteTestPlanProjectByPlanId(planId);
|
||||
testPlanApiCaseService.deleteByPlanId(planId);
|
||||
testPlanScenarioCaseService.deleteByPlanId(planId);
|
||||
|
||||
|
|
|
@ -277,12 +277,16 @@ public class XmindCaseParser {
|
|||
|
||||
String tc = title.replace(":", ":");
|
||||
String[] tcArr = tc.split(":");
|
||||
if (tcArr.length != 2) {
|
||||
if (tcArr.length < 1) {
|
||||
process.add(Translator.get("test_case_name") + Translator.get("incorrect_format"), title);
|
||||
return;
|
||||
}
|
||||
// 用例名称
|
||||
testCase.setName(this.replace(tcArr[1], TC_REGEX));
|
||||
StringBuffer name = new StringBuffer();
|
||||
for (int i = 1; i < tcArr.length; i++) {
|
||||
name.append(tcArr[i]);
|
||||
}
|
||||
testCase.setName(name.toString());
|
||||
testCase.setNodePath(nodePath);
|
||||
|
||||
// 用例等级和用例性质处理
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b35af517d888268abd3a8f2b58d6ea94335138a5
|
||||
Subproject commit 44bcc9893033900f95c99068cd4edec740465dfe
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE schedule
|
||||
MODIFY COLUMN id VARCHAR(255);
|
||||
ALTER TABLE message_task
|
||||
MODIFY COLUMN id VARCHAR(255);
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE schedule
|
||||
MODIFY COLUMN resource_id VARCHAR(255);
|
||||
ALTER TABLE message_task
|
||||
MODIFY COLUMN test_id VARCHAR(255);
|
|
@ -8,6 +8,7 @@
|
|||
@setModuleOptions="setModuleOptions"
|
||||
@setNodeTree="setNodeTree"
|
||||
@enableTrash="enableTrash"
|
||||
@exportAPI="exportAPI"
|
||||
:type="'edit'"
|
||||
ref="nodeTree"/>
|
||||
</ms-aside-container>
|
||||
|
@ -267,6 +268,9 @@
|
|||
},
|
||||
enableTrash(data) {
|
||||
this.trashEnable = data;
|
||||
},
|
||||
exportAPI() {
|
||||
this.$refs.apiScenarioList.exportApi();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table ms-select-all-fixed"
|
||||
@sort-change="sort"
|
||||
@filter-change="filter"
|
||||
@select-all="select" @select="select"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelect"
|
||||
@header-dragend="headerDragend"
|
||||
:height="screenHeight"
|
||||
v-loading="loading">
|
||||
|
@ -24,7 +25,7 @@
|
|||
|
||||
<el-table-column v-if="!referenced" width="30" min-width="30" :resizable="false" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<show-more-btn :is-show="isSelect(scope.row)" :buttons="buttons" :size="selectDataCounts"/>
|
||||
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-for="(item, index) in tableLabel">
|
||||
|
@ -170,6 +171,7 @@ import MsTableHeader from "@/business/components/common/components/MsTableHeader
|
|||
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
|
||||
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
|
||||
import MsTag from "../../../common/components/MsTag";
|
||||
import {downloadFile, getCurrentProjectID, getUUID} from "@/common/js/utils";
|
||||
import {getCurrentProjectID, getCurrentUser, getUUID} from "@/common/js/utils";
|
||||
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||
import MsTableMoreBtn from "./TableMoreBtn";
|
||||
|
@ -182,11 +184,20 @@ import PriorityTableItem from "../../../track/common/tableItems/planview/Priorit
|
|||
import PlanStatusTableItem from "../../../track/common/tableItems/plan/PlanStatusTableItem";
|
||||
import BatchEdit from "../../../track/case/components/BatchEdit";
|
||||
import {API_SCENARIO_LIST, TEST_CASE_LIST, TEST_PLAN_LIST, WORKSPACE_ID} from "../../../../../common/js/constants";
|
||||
import {PROJECT_NAME, WORKSPACE_ID} from "../../../../../common/js/constants";
|
||||
import EnvironmentSelect from "../../definition/components/environment/EnvironmentSelect";
|
||||
import BatchMove from "../../../track/case/components/BatchMove";
|
||||
import {_filter, _sort} from "@/common/js/tableUtils";
|
||||
import {Api_Scenario_List, Track_Test_Case} from "@/business/components/common/model/JsonData";
|
||||
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
|
||||
import {
|
||||
_filter,
|
||||
_handleSelect,
|
||||
_handleSelectAll,
|
||||
_sort,
|
||||
getSelectDataCounts,
|
||||
setUnSelectIds, toggleAllSelection
|
||||
} from "@/common/js/tableUtils";
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioList",
|
||||
|
@ -276,7 +287,7 @@ export default {
|
|||
}
|
||||
],
|
||||
isSelectAllDate: false,
|
||||
unSelection: [],
|
||||
selectRows: new Set(),
|
||||
selectDataCounts: 0,
|
||||
typeArr: [
|
||||
{id: 'level', name: this.$t('test_track.case.priority')},
|
||||
|
@ -355,6 +366,7 @@ export default {
|
|||
this.search();
|
||||
},
|
||||
search() {
|
||||
this.selectRows = new Set();
|
||||
this.getLabel()
|
||||
this.condition.moduleIds = this.selectNodeIds;
|
||||
if (this.trashEnable) {
|
||||
|
@ -524,11 +536,9 @@ export default {
|
|||
}
|
||||
},
|
||||
buildBatchParam(param) {
|
||||
param.scenarioIds = this.selection;
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
param.projectId = getCurrentProjectID();
|
||||
param.selectAllDate = this.isSelectAllDate;
|
||||
param.unSelectIds = this.unSelection;
|
||||
param = Object.assign(param, this.condition);
|
||||
param.condition = this.condition;
|
||||
},
|
||||
handleBatchExecute() {
|
||||
this.infoDb = false;
|
||||
|
@ -542,16 +552,21 @@ export default {
|
|||
this.batchReportId = run.id;
|
||||
});
|
||||
},
|
||||
select(selection) {
|
||||
this.selection = selection.map(s => s.id);
|
||||
|
||||
//统计应当展示选择了多少行
|
||||
this.selectRowsCount(this.selection)
|
||||
|
||||
this.$emit('selection', selection);
|
||||
handleSelectAll(selection) {
|
||||
_handleSelectAll(this, selection, this.tableData, this.selectRows);
|
||||
setUnSelectIds(this.tableData, this.condition, this.selectRows);
|
||||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
},
|
||||
isSelect(row) {
|
||||
return this.selection.includes(row.id)
|
||||
handleSelect(selection, row) {
|
||||
_handleSelect(this, selection, row, this.selectRows);
|
||||
setUnSelectIds(this.tableData, this.condition, this.selectRows);
|
||||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
},
|
||||
isSelectDataAll(data) {
|
||||
this.condition.selectAll = data;
|
||||
setUnSelectIds(this.tableData, this.condition, this.selectRows);
|
||||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
toggleAllSelection(this.$refs.scenarioTable, this.tableData, this.selectRows);
|
||||
},
|
||||
edit(row) {
|
||||
let data = JSON.parse(JSON.stringify(row));
|
||||
|
@ -592,28 +607,6 @@ export default {
|
|||
this.infoDb = true;
|
||||
this.reportId = row.reportId;
|
||||
},
|
||||
//是否选择了全部数据
|
||||
isSelectDataAll(dataType) {
|
||||
this.isSelectAllDate = dataType;
|
||||
this.selectRowsCount(this.selection);
|
||||
//如果已经全选,不需要再操作了
|
||||
if (this.selection.length != this.tableData.length) {
|
||||
this.$refs.scenarioTable.toggleAllSelection(true);
|
||||
}
|
||||
},
|
||||
//选择数据数量统计
|
||||
selectRowsCount(selection) {
|
||||
let selectedIDs = selection;
|
||||
let allIDs = this.tableData.map(s => s.id);
|
||||
this.unSelection = allIDs.filter(function (val) {
|
||||
return selectedIDs.indexOf(val) === -1
|
||||
});
|
||||
if (this.isSelectAllDate) {
|
||||
this.selectDataCounts = this.total - this.unSelection.length;
|
||||
} else {
|
||||
this.selectDataCounts = this.selection.length;
|
||||
}
|
||||
},
|
||||
//判断是否只显示本周的数据。 从首页跳转过来的请求会带有相关参数
|
||||
isSelectThissWeekData() {
|
||||
let dataRange = this.$route.params.dataSelectRange;
|
||||
|
@ -666,6 +659,20 @@ export default {
|
|||
openScenario(item) {
|
||||
this.$emit('openScenario', item)
|
||||
},
|
||||
exportApi() {
|
||||
let param = {};
|
||||
this.buildBatchParam(param);
|
||||
this.loading = true;
|
||||
if (param.ids === undefined || param.ids.length < 1) {
|
||||
this.$warning(this.$t("api_test.automation.scenario.check_case"));
|
||||
return;
|
||||
}
|
||||
this.result = this.$post("/api/automation/export", param, response => {
|
||||
this.loading = false;
|
||||
let obj = response.data;
|
||||
downloadFile("Metersphere_Scenario_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -11,16 +11,20 @@
|
|||
@edit="edit"
|
||||
@drag="drag"
|
||||
@remove="remove"
|
||||
@refresh="list"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
ref="nodeTree">
|
||||
|
||||
<template v-slot:header>
|
||||
<el-input :placeholder="$t('test_track.module.search')" v-model="condition.filterText" size="small">
|
||||
<template v-slot:append>
|
||||
<el-button v-if="!isReadOnly" icon="el-icon-folder-add" @click="addScenario" v-tester/>
|
||||
</template>
|
||||
</el-input>
|
||||
<module-trash-button v-if="!isReadOnly" :condition="condition" :exe="enableTrash"/>
|
||||
<api-scenario-module-header
|
||||
:condition="condition"
|
||||
:current-module="currentModule"
|
||||
:is-read-only="isReadOnly"
|
||||
:project-id="projectId"
|
||||
@exportAPI="exportAPI"
|
||||
@addScenario="addScenario"
|
||||
@refreshTable="$emit('refreshTable')"
|
||||
@refresh="refresh"/>
|
||||
</template>
|
||||
|
||||
</ms-node-tree>
|
||||
|
@ -34,24 +38,26 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import SelectMenu from "../../../track/common/SelectMenu";
|
||||
import MsAddBasisScenario from "@/business/components/api/automation/scenario/AddBasisScenario";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
import MsNodeTree from "../../../track/common/NodeTree";
|
||||
import {buildNodePath} from "../../definition/model/NodeTree";
|
||||
import ModuleTrashButton from "../../definition/components/module/ModuleTrashButton";
|
||||
import SelectMenu from "../../../track/common/SelectMenu";
|
||||
import MsAddBasisScenario from "@/business/components/api/automation/scenario/AddBasisScenario";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
import MsNodeTree from "../../../track/common/NodeTree";
|
||||
import {buildNodePath} from "../../definition/model/NodeTree";
|
||||
import ModuleTrashButton from "../../definition/components/module/ModuleTrashButton";
|
||||
import ApiScenarioModuleHeader from "@/business/components/api/automation/scenario/module/ApiScenarioModuleHeader";
|
||||
|
||||
export default {
|
||||
name: 'MsApiScenarioModule',
|
||||
components: {
|
||||
ModuleTrashButton,
|
||||
MsNodeTree,
|
||||
MsAddBasisScenario,
|
||||
SelectMenu,
|
||||
},
|
||||
props: {
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
export default {
|
||||
name: 'MsApiScenarioModule',
|
||||
components: {
|
||||
ApiScenarioModuleHeader,
|
||||
ModuleTrashButton,
|
||||
MsNodeTree,
|
||||
MsAddBasisScenario,
|
||||
SelectMenu,
|
||||
},
|
||||
props: {
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false
|
||||
}
|
||||
|
@ -174,9 +180,9 @@
|
|||
this.$emit("nodeSelectEvent", node, nodeIds, pNodes);
|
||||
}
|
||||
},
|
||||
// exportAPI() {
|
||||
// this.$emit('exportAPI');
|
||||
// },
|
||||
exportAPI() {
|
||||
this.$emit('exportAPI');
|
||||
},
|
||||
// debug() {
|
||||
// this.$emit('debug');
|
||||
// },
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
</el-col>
|
||||
<el-col :span="3" class="ms-col-one ms-font">
|
||||
<el-link class="head" @click="showScenarioParameters">{{$t('api_test.automation.scenario_total')}}</el-link>
|
||||
:{{this.currentScenario.variables!=undefined?this.currentScenario.variables.length: 0}}
|
||||
:{{getVariableSize()}}
|
||||
</el-col>
|
||||
<el-col :span="3" class="ms-col-one ms-font">
|
||||
<el-checkbox v-model="enableCookieShare">共享cookie</el-checkbox>
|
||||
|
@ -196,7 +196,7 @@
|
|||
</el-drawer>
|
||||
|
||||
<!--场景公共参数-->
|
||||
<ms-variable-list @setVariables="setVariables" ref="scenarioParameters"/>
|
||||
<ms-variable-list @setVariables="setVariables" ref="scenarioParameters" class="ms-sc-variable-header"/>
|
||||
<!--外部导入-->
|
||||
<api-import ref="apiImport" :saved="false" @refresh="apiImport"/>
|
||||
</div>
|
||||
|
@ -427,8 +427,9 @@
|
|||
getIdx(index) {
|
||||
return index - 0.33
|
||||
},
|
||||
setVariables(v) {
|
||||
setVariables(v, headers) {
|
||||
this.currentScenario.variables = v;
|
||||
this.currentScenario.headers = headers;
|
||||
if (this.path.endsWith("/update")) {
|
||||
// 直接更新场景防止编辑内容丢失
|
||||
this.editScenario();
|
||||
|
@ -503,7 +504,7 @@
|
|||
this.sort();
|
||||
},
|
||||
nodeClick(data, node) {
|
||||
if (data.referenced != 'REF' && data.referenced != 'Deleted') {
|
||||
if (data.referenced != 'REF' && data.referenced != 'Deleted' && !data.disabled) {
|
||||
this.operatingElements = ELEMENTS.get(data.type);
|
||||
} else {
|
||||
this.operatingElements = [];
|
||||
|
@ -679,7 +680,7 @@
|
|||
this.editScenario();
|
||||
this.debugData = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario",
|
||||
variables: this.currentScenario.variables, referenced: 'Created', enableCookieShare: this.enableCookieShare,
|
||||
variables: this.currentScenario.variables, referenced: 'Created', enableCookieShare: this.enableCookieShare, headers: this.currentScenario.headers,
|
||||
environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition
|
||||
};
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
|
@ -863,6 +864,9 @@
|
|||
if (!this.currentScenario.variables) {
|
||||
this.currentScenario.variables = [];
|
||||
}
|
||||
if (!this.currentScenario.headers) {
|
||||
this.currentScenario.headers = [];
|
||||
}
|
||||
if (this.currentScenario.id) {
|
||||
this.result = this.$get("/api/automation/getApiScenario/" + this.currentScenario.id, response => {
|
||||
if (response.data) {
|
||||
|
@ -887,6 +891,9 @@
|
|||
}
|
||||
})
|
||||
}
|
||||
if (obj.headers) {
|
||||
this.currentScenario.headers = obj.headers;
|
||||
}
|
||||
this.enableCookieShare = obj.enableCookieShare;
|
||||
this.scenarioDefinition = obj.hashTree;
|
||||
}
|
||||
|
@ -905,8 +912,9 @@
|
|||
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
||||
// 构建一个场景对象 方便引用处理
|
||||
let scenario = {
|
||||
id: this.currentScenario.id, enableCookieShare: this.enableCookieShare, name: this.currentScenario.name, variables: this.currentScenario.variables,
|
||||
type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition
|
||||
id: this.currentScenario.id, enableCookieShare: this.enableCookieShare, name: this.currentScenario.name, type: "scenario",
|
||||
variables: this.currentScenario.variables, headers: this.currentScenario.headers,
|
||||
referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition
|
||||
};
|
||||
this.currentScenario.scenarioDefinition = scenario;
|
||||
if (this.currentScenario.tags instanceof Array) {
|
||||
|
@ -924,7 +932,7 @@
|
|||
this.loading = false;
|
||||
},
|
||||
showScenarioParameters() {
|
||||
this.$refs.scenarioParameters.open(this.currentScenario.variables);
|
||||
this.$refs.scenarioParameters.open(this.currentScenario.variables, this.currentScenario.headers);
|
||||
},
|
||||
apiImport(importData) {
|
||||
if (importData && importData.data) {
|
||||
|
@ -934,6 +942,16 @@
|
|||
this.sort();
|
||||
this.reload();
|
||||
}
|
||||
},
|
||||
getVariableSize() {
|
||||
let size = 0;
|
||||
if (this.currentScenario.variables) {
|
||||
size += this.currentScenario.variables.length;
|
||||
}
|
||||
if (this.currentScenario.headers && this.currentScenario.headers.length > 1) {
|
||||
size += this.currentScenario.headers.length - 1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1066,4 +1084,7 @@
|
|||
content: "\e722";
|
||||
font-size: 20px;
|
||||
}
|
||||
.ms-sc-variable-header >>> .el-dialog__body {
|
||||
padding: 0px 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
let scenarioIds = [];
|
||||
scenarioIds.push(row.id);
|
||||
run.projectId = getCurrentProjectID();
|
||||
run.scenarioIds = scenarioIds;
|
||||
run.ids = scenarioIds;
|
||||
run.id = getUUID();
|
||||
run.name = row.name;
|
||||
this.$post(url, run, response => {
|
||||
|
|
|
@ -107,7 +107,8 @@
|
|||
},
|
||||
methods: {
|
||||
active() {
|
||||
this.$set(this.data, 'active', !this.data.active);
|
||||
// 这种写法性能极差,不要再放开了
|
||||
//this.$set(this.data, 'active', !this.data.active);
|
||||
this.$emit('active');
|
||||
},
|
||||
copyRow() {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="request.protocol === 'HTTP'">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-if="request.url" v-model="request.url" style="width: 85%;margin-top: 10px" size="small">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-if="request.url" v-model="request.url" style="width: 85%;margin-top: 10px" size="small" @blur="urlChange">
|
||||
<el-select v-model="request.method" slot="prepend" style="width: 100px" size="small">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-input>
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-else v-model="request.path" style="width: 85%;margin-top: 10px" size="small">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-else v-model="request.path" style="width: 85%;margin-top: 10px" size="small" @blur="pathChange">
|
||||
<el-select v-model="request.method" slot="prepend" style="width: 100px" size="small">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
|
@ -18,14 +18,14 @@
|
|||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('api_test.request.tcp.server')" prop="server">
|
||||
<el-input class="server-input" v-model="request.server" maxlength="300" show-word-limit size="small"/>
|
||||
<el-input class="server-input" v-model="request.server" maxlength="300" show-word-limit size="small"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.request.tcp.port')" prop="port" label-width="60px">
|
||||
<el-input-number v-model="request.port" controls-position="right" :min="0" :max="65535" size="small"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.request.tcp.port')" prop="port" label-width="60px">
|
||||
<el-input-number v-model="request.port" controls-position="right" :min="0" :max="65535" size="small"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
|
@ -33,17 +33,55 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {REQ_METHOD} from "@/business/components/api/definition/model/JsonData";
|
||||
import {REQ_METHOD} from "@/business/components/api/definition/model/JsonData";
|
||||
import {KeyValue} from "../../../definition/model/ApiTestModel";
|
||||
|
||||
export default {
|
||||
name: "CustomizeReqInfo",
|
||||
props: ['request', 'isCustomizeReq'],
|
||||
data() {
|
||||
return {
|
||||
reqOptions: REQ_METHOD,
|
||||
export default {
|
||||
name: "CustomizeReqInfo",
|
||||
props: ['request', 'isCustomizeReq'],
|
||||
data() {
|
||||
return {
|
||||
reqOptions: REQ_METHOD,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pathChange() {
|
||||
if (!this.request.path || this.request.path.indexOf('?') === -1) return;
|
||||
let url = this.getURL(this.addProtocol(this.request.path));
|
||||
if (url) {
|
||||
this.request.path = decodeURIComponent(this.request.path.substr(0, this.request.path.indexOf("?")));
|
||||
}
|
||||
},
|
||||
urlChange() {
|
||||
if (!this.request.url || this.request.url.indexOf('?') === -1) return;
|
||||
let url = this.getURL(this.addProtocol(this.request.url));
|
||||
if (url) {
|
||||
this.request.url = decodeURIComponent(this.request.url.substr(0, this.request.url.indexOf("?")));
|
||||
}
|
||||
},
|
||||
addProtocol(url) {
|
||||
if (url) {
|
||||
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
|
||||
return "https://" + url;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
},
|
||||
getURL(urlStr) {
|
||||
try {
|
||||
let url = new URL(urlStr);
|
||||
url.searchParams.forEach((value, key) => {
|
||||
if (key && value) {
|
||||
this.request.arguments.splice(0, 0, new KeyValue({name: key, required: false, value: value}));
|
||||
}
|
||||
});
|
||||
return url;
|
||||
} catch (e) {
|
||||
this.$error(this.$t('api_test.request.url_invalid'), 2000);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
v-loading="loading"
|
||||
@copy="copyRow"
|
||||
@remove="remove"
|
||||
@active="active"
|
||||
:is-show-name-input="!isDeletedOrRef"
|
||||
:data="request"
|
||||
:draggable="true"
|
||||
|
@ -34,7 +35,16 @@
|
|||
<ms-dubbo-basis-parameters :request="request" v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'" :showScript="false"/>
|
||||
|
||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult"/>
|
||||
<div v-if="request.result">
|
||||
<el-tabs v-model="request.activeName" closable class="ms-tabs">
|
||||
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in request.result.scenarios" :key="index">
|
||||
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
||||
<api-response-component v-if="result.name===request.name" :result="result"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult" v-else/>
|
||||
|
||||
<!-- 保存操作 -->
|
||||
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)" v-if="!request.referenced">
|
||||
|
@ -155,7 +165,7 @@
|
|||
return true
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
remove() {
|
||||
|
@ -238,8 +248,8 @@
|
|||
this.request.customizeReq = this.isCustomizeReq;
|
||||
let debugData = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario",
|
||||
variables: this.currentScenario.variables, referenced: 'Created', enableCookieShare: this.enableCookieShare,
|
||||
environmentId: this.currentEnvironmentId, hashTree: [this.request]
|
||||
variables: this.currentScenario.variables, referenced: 'Created', headers: this.currentScenario.headers,
|
||||
enableCookieShare: this.enableCookieShare, environmentId: this.currentEnvironmentId, hashTree: [this.request]
|
||||
};
|
||||
this.runData.push(debugData);
|
||||
/*触发执行操作*/
|
||||
|
@ -247,6 +257,7 @@
|
|||
},
|
||||
runRefresh(data) {
|
||||
this.request.requestResult = data;
|
||||
this.request.result = undefined;
|
||||
this.loading = false;
|
||||
},
|
||||
reload() {
|
||||
|
@ -289,4 +300,9 @@
|
|||
.icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.ms-tabs >>> .el-icon-close:before {
|
||||
content: "";
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
v-loading="loading"
|
||||
@copy="copyRow"
|
||||
@remove="remove"
|
||||
@active="active"
|
||||
:data="scenario"
|
||||
:show-collapse="false"
|
||||
:is-show-name-input="!isDeletedOrRef"
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
<api-base-component
|
||||
@copy="copyRow"
|
||||
@remove="remove"
|
||||
@active="active"
|
||||
:data="jsr223Processor"
|
||||
:draggable="draggable"
|
||||
:color="color"
|
||||
:background-color="backgroundColor"
|
||||
:title="title">
|
||||
:title="title" v-loading="loading">
|
||||
|
||||
<jsr233-processor-content
|
||||
:jsr223-processor="jsr223Processor"
|
||||
|
@ -50,6 +51,9 @@
|
|||
backgroundColor: String,
|
||||
node: {},
|
||||
},
|
||||
data() {
|
||||
return {loading: false}
|
||||
},
|
||||
methods: {
|
||||
remove() {
|
||||
this.$emit('remove', this.jsr223Processor, this.node);
|
||||
|
@ -57,6 +61,16 @@
|
|||
copyRow() {
|
||||
this.$emit('copyRow', this.jsr223Processor, this.node);
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
active() {
|
||||
this.jsr223Processor.active = !this.jsr223Processor.active;
|
||||
this.reload();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -79,17 +79,17 @@
|
|||
<el-input-number size="small" v-model="controller.whileController.timeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="3000" :step="1000"/>
|
||||
<span class="ms-span ms-radio">ms</span>
|
||||
</div>
|
||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||
<div>
|
||||
<el-tabs v-model="activeName" closable class="ms-tabs">
|
||||
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in requestResult.scenarios" :key="index">
|
||||
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
||||
<api-response-component :result="result"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<!--<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>-->
|
||||
<!--<div>-->
|
||||
<!--<el-tabs v-model="activeName" closable class="ms-tabs">-->
|
||||
<!--<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in requestResult.scenarios" :key="index">-->
|
||||
<!--<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">-->
|
||||
<!--<api-response-component :result="result"/>-->
|
||||
<!--</div>-->
|
||||
<!--</el-tab-pane>-->
|
||||
<!--</el-tabs>-->
|
||||
|
||||
</div>
|
||||
<!--</div>-->
|
||||
|
||||
</api-base-component>
|
||||
|
||||
|
@ -117,7 +117,7 @@
|
|||
},
|
||||
},
|
||||
created() {
|
||||
this.initResult();
|
||||
// this.initResult();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -202,12 +202,11 @@
|
|||
this.$warning("当前循环下没有请求,不能执行")
|
||||
return;
|
||||
}
|
||||
this.controller.active = true;
|
||||
this.loading = true;
|
||||
this.debugData = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario",
|
||||
variables: this.currentScenario.variables, referenced: 'Created', enableCookieShare: this.enableCookieShare,
|
||||
environmentId: this.currentEnvironmentId, hashTree: [this.controller]
|
||||
variables: this.currentScenario.variables, headers: this.currentScenario.headers,
|
||||
referenced: 'Created', enableCookieShare: this.enableCookieShare, environmentId: this.currentEnvironmentId, hashTree: [this.controller]
|
||||
};
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
},
|
||||
|
@ -224,7 +223,7 @@
|
|||
},
|
||||
changeRadio() {
|
||||
this.controller.active = true;
|
||||
this.initResult();
|
||||
//this.initResult();
|
||||
this.reload();
|
||||
},
|
||||
change(value) {
|
||||
|
@ -258,6 +257,20 @@
|
|||
this.success = this.requestResult.scenarios && this.requestResult.scenarios != null ? this.requestResult.scenarios.length - this.error : 0;
|
||||
}
|
||||
},
|
||||
setResult(hashTree) {
|
||||
if (hashTree) {
|
||||
hashTree.forEach(item => {
|
||||
if (item.type === "HTTPSamplerProxy" || item.type === "DubboSampler" || item.type === "JDBCSampler" || item.type === "TCPSampler") {
|
||||
item.result = this.requestResult;
|
||||
item.activeName = this.activeName;
|
||||
item.requestResult = undefined;
|
||||
}
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
this.setResult(item.hashTree);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getReport() {
|
||||
if (this.reportId) {
|
||||
let url = "/api/scenario/report/get/" + this.reportId;
|
||||
|
@ -285,11 +298,15 @@
|
|||
break;
|
||||
}
|
||||
this.getFails();
|
||||
this.activeName = this.requestResult && this.requestResult.scenarios && this.requestResult.scenarios != null && this.requestResult.scenarios.length > 0 ? this.requestResult.scenarios[0].name : "";
|
||||
// 把请求结果分给各个请求
|
||||
this.setResult(this.controller.hashTree);
|
||||
this.$emit('refReload');
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
this.loading = false;
|
||||
this.activeName = this.requestResult && this.requestResult.scenarios && this.requestResult.scenarios != null && this.requestResult.scenarios.length > 0 ? this.requestResult.scenarios[0].name : "";
|
||||
this.reload();
|
||||
} else {
|
||||
setTimeout(this.getReport, 2000)
|
||||
}
|
||||
|
@ -333,11 +350,6 @@
|
|||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.ms-tabs >>> .el-icon-close:before {
|
||||
content: "";
|
||||
|
||||
}
|
||||
|
||||
.icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-input :placeholder="$t('test_track.module.search')" v-model="condition.filterText" size="small">
|
||||
<template v-slot:append>
|
||||
<el-dropdown v-if="!isReadOnly" size="small" split-button type="primary" class="ms-api-button" @click="handleCommand('add-api')"
|
||||
v-tester
|
||||
@command="handleCommand">
|
||||
<el-button icon="el-icon-folder-add" @click="addScenario"></el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="import">{{ $t('api_test.api_import.label') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="export">{{ $t('report.export') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
</el-input>
|
||||
<module-trash-button v-if="!isReadOnly" :condition="condition" :exe="enableTrash"/>
|
||||
|
||||
<api-import :model="'scenario'" ref="apiImport" :moduleOptions="moduleOptions" @refresh="$emit('refresh')"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {buildNodePath} from "@/business/components/api/definition/model/NodeTree";
|
||||
import ModuleTrashButton from "@/business/components/api/definition/components/module/ModuleTrashButton";
|
||||
import ApiImport from "@/business/components/api/definition/components/import/ApiImport";
|
||||
|
||||
export default {
|
||||
name: "ApiScenarioModuleHeader",
|
||||
components: {ApiImport, ModuleTrashButton},
|
||||
data() {
|
||||
return {
|
||||
moduleOptions: {}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
condition: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
currentModule: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false
|
||||
}
|
||||
},
|
||||
projectId: String
|
||||
},
|
||||
methods: {
|
||||
handleCommand(e) {
|
||||
switch (e) {
|
||||
case "import":
|
||||
if (!this.projectId) {
|
||||
this.$warning(this.$t('commons.check_project_tip'));
|
||||
return;
|
||||
}
|
||||
this.result = this.$get("/api/automation/module/list/" + this.projectId + "/", response => {
|
||||
if (response.data != undefined && response.data != null) {
|
||||
this.data = response.data;
|
||||
let moduleOptions = [];
|
||||
this.data.forEach(node => {
|
||||
buildNodePath(node, {path: ''}, moduleOptions);
|
||||
});
|
||||
this.moduleOptions = moduleOptions
|
||||
}
|
||||
});
|
||||
this.$refs.apiImport.open(this.currentModule);
|
||||
break;
|
||||
default:
|
||||
if (!this.projectId) {
|
||||
this.$warning(this.$t('commons.check_project_tip'));
|
||||
return;
|
||||
}
|
||||
this.$emit('exportAPI');
|
||||
break;
|
||||
}
|
||||
},
|
||||
addScenario() {
|
||||
this.$emit('addScenario');
|
||||
},
|
||||
refresh() {
|
||||
this.$emit('refresh');
|
||||
},
|
||||
enableTrash() {
|
||||
this.condition.trashEnable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.read-only {
|
||||
width: 150px !important;
|
||||
}
|
||||
|
||||
.filter-input {
|
||||
width: 174px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,57 +1,88 @@
|
|||
<template>
|
||||
<el-dialog :title="$t('api_test.scenario.variables')" :close-on-click-modal="false"
|
||||
<el-dialog title="场景变量" :close-on-click-modal="false"
|
||||
:visible.sync="visible" class="visible-dialog" width="60%"
|
||||
@close="close" v-loading="loading">
|
||||
<div>
|
||||
<el-input placeholder="变量名称搜索" style="width: 50%;margin: 0px 0px 10px" v-model="selectVariable" size="small" @change="filter" @keyup.enter="filter">
|
||||
<el-select v-model="searchType" slot="prepend" placeholder="类型" style="width: 90px" @change="filter">
|
||||
<el-option value="CONSTANT" label="常量"></el-option>
|
||||
<el-option value="LIST" label="列表"></el-option>
|
||||
<el-option value="CSV" label="CSV"></el-option>
|
||||
<el-option value="COUNTER" label="计数器"></el-option>
|
||||
<el-option value="RANDOM" label="随机数"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<div style="border:1px #DCDFE6 solid; min-height: 400px;border-radius: 4px ;width: 100% ;">
|
||||
<el-table ref="table" border :data="variables" class="adjust-table" @select-all="select" @select="select"
|
||||
v-loading="loading" @row-click="edit" height="400px" :row-class-name="tableRowClassName">
|
||||
<el-table-column type="selection" width="38"/>
|
||||
<el-table-column prop="num" label="ID" sortable/>
|
||||
<el-table-column prop="name" :label="$t('api_test.variable_name')" sortable show-overflow-tooltip/>
|
||||
<el-table-column prop="type" :label="$t('test_track.case.type')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{types.get(scope.row.type)}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="value" :label="$t('api_test.value')" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ms-edit-constant v-if="editData.type=='CONSTANT'" ref="parameters" :editData.sync="editData"/>
|
||||
<ms-edit-counter v-if="editData.type=='COUNTER'" ref="counter" :editData.sync="editData"/>
|
||||
<ms-edit-random v-if="editData.type=='RANDOM'" ref="random" :editData.sync="editData"/>
|
||||
<ms-edit-list-value v-if="editData.type=='LIST'" ref="listValue" :editData="editData"/>
|
||||
<ms-edit-csv v-if="editData.type=='CSV'" ref="csv" :editData.sync="editData"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('api_test.scenario.variables')" name="variable">
|
||||
<div style="margin-top: 10px">
|
||||
<el-row style="margin-bottom: 10px">
|
||||
<el-col :span="8">
|
||||
<el-input placeholder="变量名称搜索" v-model="selectVariable" size="small" @change="filter" @keyup.enter="filter">
|
||||
<el-select v-model="searchType" slot="prepend" placeholder="类型" style="width: 90px" @change="filter">
|
||||
<el-option value="CONSTANT" label="常量"></el-option>
|
||||
<el-option value="LIST" label="列表"></el-option>
|
||||
<el-option value="CSV" label="CSV"></el-option>
|
||||
<el-option value="COUNTER" label="计数器"></el-option>
|
||||
<el-option value="RANDOM" label="随机数"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-dropdown split-button type="primary" @command="handleClick" @click="handleClick('CONSTANT')" size="small" style="margin-left: 10px">
|
||||
{{$t('commons.add')}}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="CONSTANT">常量</el-dropdown-item>
|
||||
<el-dropdown-item command="LIST">列表</el-dropdown-item>
|
||||
<el-dropdown-item command="CSV">CSV</el-dropdown-item>
|
||||
<el-dropdown-item command="COUNTER">计数器</el-dropdown-item>
|
||||
<el-dropdown-item command="RANDOM">随机数</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button size="small" style="margin-left: 10px" @click="deleteVariable">{{$t('commons.delete')}}</el-button>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<div style="border:1px #DCDFE6 solid; min-height: 400px;border-radius: 4px ;width: 100% ;">
|
||||
<el-table ref="table" border :data="variables" class="adjust-table" @select-all="select" @select="select"
|
||||
v-loading="loading" @row-click="edit" height="400px" :row-class-name="tableRowClassName">
|
||||
<el-table-column type="selection" width="38"/>
|
||||
<el-table-column prop="num" label="ID" sortable/>
|
||||
<el-table-column prop="name" :label="$t('api_test.variable_name')" sortable show-overflow-tooltip/>
|
||||
<el-table-column prop="type" :label="$t('test_track.case.type')">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{types.get(scope.row.type)}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="value" :label="$t('api_test.value')" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ms-edit-constant v-if="editData.type=='CONSTANT'" ref="parameters" :editData.sync="editData"/>
|
||||
<ms-edit-counter v-if="editData.type=='COUNTER'" ref="counter" :editData.sync="editData"/>
|
||||
<ms-edit-random v-if="editData.type=='RANDOM'" ref="random" :editData.sync="editData"/>
|
||||
<ms-edit-list-value v-if="editData.type=='LIST'" ref="listValue" :editData="editData"/>
|
||||
<ms-edit-csv v-if="editData.type=='CSV'" ref="csv" :editData.sync="editData"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.scenario.headers')" name="headers">
|
||||
<!-- 请求头-->
|
||||
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.request.headers')" placement="top-start" slot="label">
|
||||
<span>{{$t('api_test.request.headers')}}
|
||||
<div class="el-step__icon is-text ms-api-col ms-variable-header" v-if="headers.length>1">
|
||||
<div class="el-step__icon-inner">{{headers.length-1}}</div>
|
||||
</div>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-row>
|
||||
<el-link class="ms-variable-link" @click="batchAdd" style="color: #783887"> {{$t("commons.batch_add")}}</el-link>
|
||||
</el-row>
|
||||
<div style="min-height: 400px">
|
||||
<ms-api-key-value :items="headers"/>
|
||||
<batch-add-parameter @batchSave="batchSave" ref="batchAddParameter"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<el-button style="margin-right:10px" @click="deleteVariable">{{$t('commons.delete')}}</el-button>
|
||||
<el-dropdown split-button type="primary" @command="handleClick" @click="handleClick('CONSTANT')" placement="top-end">
|
||||
{{$t('commons.add')}}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="CONSTANT">常量</el-dropdown-item>
|
||||
<el-dropdown-item command="LIST">列表</el-dropdown-item>
|
||||
<el-dropdown-item command="CSV">CSV</el-dropdown-item>
|
||||
<el-dropdown-item command="COUNTER">计数器</el-dropdown-item>
|
||||
<el-dropdown-item command="RANDOM">随机数</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button type="primary" @click="save">{{$t('commons.confirm')}}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -67,6 +98,9 @@
|
|||
import MsEditListValue from "./EditListValue";
|
||||
import MsEditCsv from "./EditCsv";
|
||||
import {getUUID} from "@/common/js/utils";
|
||||
import MsApiKeyValue from "../../../definition/components/ApiKeyValue";
|
||||
import BatchAddParameter from "../../../definition/components/basis/BatchAddParameter";
|
||||
import {KeyValue} from "../../../definition/model/ApiTestModel";
|
||||
|
||||
export default {
|
||||
name: "MsVariableList",
|
||||
|
@ -78,11 +112,15 @@
|
|||
MsEditCounter,
|
||||
MsEditRandom,
|
||||
MsEditListValue,
|
||||
MsEditCsv
|
||||
MsEditCsv,
|
||||
MsApiKeyValue,
|
||||
BatchAddParameter
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
variables: [],
|
||||
headers: [],
|
||||
activeName: "variable",
|
||||
searchType: "",
|
||||
selectVariable: "",
|
||||
condition: {},
|
||||
|
@ -103,6 +141,26 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
batchAdd() {
|
||||
this.$refs.batchAddParameter.open();
|
||||
},
|
||||
batchSave(data) {
|
||||
if (data) {
|
||||
let params = data.split("\n");
|
||||
let keyValues = [];
|
||||
params.forEach(item => {
|
||||
let line = item.split(/,|,/);
|
||||
let required = false;
|
||||
if (line[1] === '必填' || line[1] === 'true') {
|
||||
required = true;
|
||||
}
|
||||
keyValues.push(new KeyValue({name: line[0], required: required, value: line[2], description: line[3], type: "text", valid: false, file: false, encode: true, enable: true, contentType: "text/plain"}));
|
||||
})
|
||||
keyValues.forEach(item => {
|
||||
this.headers.unshift(item);
|
||||
})
|
||||
}
|
||||
},
|
||||
handleClick(command) {
|
||||
this.editData = {};
|
||||
this.editData.type = command;
|
||||
|
@ -135,12 +193,16 @@
|
|||
isSelect(row) {
|
||||
return this.selection.includes(row.id)
|
||||
},
|
||||
open: function (variables) {
|
||||
open: function (variables, headers) {
|
||||
this.variables = variables;
|
||||
this.headers = headers;
|
||||
this.visible = true;
|
||||
this.editData = {type: "CONSTANT"};
|
||||
this.addParameters(this.editData);
|
||||
},
|
||||
save() {
|
||||
this.visible = false;
|
||||
},
|
||||
close() {
|
||||
this.visible = false;
|
||||
let saveVariables = [];
|
||||
|
@ -152,7 +214,7 @@
|
|||
})
|
||||
this.selectVariable = "";
|
||||
this.searchType = "";
|
||||
this.$emit('setVariables', saveVariables);
|
||||
this.$emit('setVariables', saveVariables, this.headers);
|
||||
},
|
||||
deleteVariable() {
|
||||
let ids = Array.from(this.selection);
|
||||
|
@ -209,4 +271,16 @@
|
|||
.ms-variable-hidden-row {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ms-variable-header {
|
||||
background: #783887;
|
||||
color: white;
|
||||
height: 18px;
|
||||
border-radius: 42%;
|
||||
}
|
||||
|
||||
.ms-variable-link {
|
||||
float: right;
|
||||
margin-right: 45px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
:name="item.name">
|
||||
<!-- 列表集合 -->
|
||||
<ms-api-list
|
||||
v-if="item.type === 'list' && isApiListEnable"
|
||||
v-if="item.type === 'list' && activeDom==='api' "
|
||||
:module-tree="nodeTree"
|
||||
:module-options="moduleOptions"
|
||||
:current-protocol="currentProtocol"
|
||||
|
@ -35,29 +35,42 @@
|
|||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:active-dom="activeDom"
|
||||
:queryDataType="queryDataType"
|
||||
:selectDataRange="selectDataRange"
|
||||
@changeSelectDataRangeAll="changeSelectDataRangeAll"
|
||||
@editApi="editApi"
|
||||
@handleCase="handleCase"
|
||||
@showExecResult="showExecResult"
|
||||
@activeDomChange="activeDomChange"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiList"/>
|
||||
<!--测试用例列表-->
|
||||
<api-case-simple-list
|
||||
v-if="item.type === 'list' && !isApiListEnable"
|
||||
v-if="item.type === 'list' && activeDom==='testCase' "
|
||||
:current-protocol="currentProtocol"
|
||||
:visible="visible"
|
||||
:currentRow="currentRow"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:active-dom="activeDom"
|
||||
:queryDataType="queryDataType"
|
||||
@changeSelectDataRangeAll="changeSelectDataRangeAll"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@activeDomChange="activeDomChange"
|
||||
@handleCase="handleCase"
|
||||
@showExecResult="showExecResult"
|
||||
ref="apiList"/>
|
||||
<api-documents-page class="api-doc-page"
|
||||
v-if="item.type === 'list' && activeDom==='doc' "
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:active-dom="activeDom"
|
||||
:project-id="projectId"
|
||||
:module-ids="selectNodeIds"
|
||||
@activeDomChange="activeDomChange"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
/>
|
||||
|
||||
<!-- 添加/编辑测试窗口-->
|
||||
<div v-else-if="item.type=== 'ADD'" class="ms-api-div">
|
||||
|
@ -114,24 +127,25 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MsApiList from './components/list/ApiList';
|
||||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsAsideContainer from "../../common/components/MsAsideContainer";
|
||||
import MsApiConfig from "./components/ApiConfig";
|
||||
import MsDebugHttpPage from "./components/debug/DebugHttpPage";
|
||||
import MsDebugJdbcPage from "./components/debug/DebugJdbcPage";
|
||||
import MsDebugTcpPage from "./components/debug/DebugTcpPage";
|
||||
import MsDebugDubboPage from "./components/debug/DebugDubboPage";
|
||||
import MsApiList from './components/list/ApiList';
|
||||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsAsideContainer from "../../common/components/MsAsideContainer";
|
||||
import MsApiConfig from "./components/ApiConfig";
|
||||
import MsDebugHttpPage from "./components/debug/DebugHttpPage";
|
||||
import MsDebugJdbcPage from "./components/debug/DebugJdbcPage";
|
||||
import MsDebugTcpPage from "./components/debug/DebugTcpPage";
|
||||
import MsDebugDubboPage from "./components/debug/DebugDubboPage";
|
||||
|
||||
import MsRunTestHttpPage from "./components/runtest/RunTestHTTPPage";
|
||||
import MsRunTestTcpPage from "./components/runtest/RunTestTCPPage";
|
||||
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
|
||||
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
|
||||
import {downloadFile, getCurrentUser, getUUID, getCurrentProjectID} from "@/common/js/utils";
|
||||
import MsApiModule from "./components/module/ApiModule";
|
||||
import ApiCaseSimpleList from "./components/list/ApiCaseSimpleList";
|
||||
import {PROJECT_NAME} from "../../../../common/js/constants";
|
||||
import MsRunTestHttpPage from "./components/runtest/RunTestHTTPPage";
|
||||
import MsRunTestTcpPage from "./components/runtest/RunTestTCPPage";
|
||||
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
|
||||
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
|
||||
import {getCurrentProjectID, getCurrentUser, getUUID} from "@/common/js/utils";
|
||||
import MsApiModule from "./components/module/ApiModule";
|
||||
import ApiCaseSimpleList from "./components/list/ApiCaseSimpleList";
|
||||
|
||||
import ApiDocumentsPage from "@/business/components/api/definition/components/list/ApiDocumentsPage";
|
||||
|
||||
export default {
|
||||
name: "ApiDefinition",
|
||||
|
@ -142,8 +156,10 @@
|
|||
this.changeRedirectParam(redirectIDParam);
|
||||
if (routeParam === 'apiTestCase') {
|
||||
this.isApiListEnableChange(false);
|
||||
this.activeDomChange("testCase");
|
||||
} else {
|
||||
this.isApiListEnableChange(true);
|
||||
this.activeDomChange("api");
|
||||
}
|
||||
return routeParam;
|
||||
},
|
||||
|
@ -163,7 +179,8 @@
|
|||
MsDebugDubboPage,
|
||||
MsRunTestTcpPage,
|
||||
MsRunTestSqlPage,
|
||||
MsRunTestDubboPage
|
||||
MsRunTestDubboPage,
|
||||
ApiDocumentsPage
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
|
@ -194,6 +211,7 @@
|
|||
closable: false
|
||||
}],
|
||||
isApiListEnable: true,
|
||||
activeDom: "testCase",
|
||||
syncTabs: [],
|
||||
projectId: "",
|
||||
nodeTree: []
|
||||
|
@ -231,6 +249,9 @@
|
|||
isApiListEnableChange(data) {
|
||||
this.isApiListEnable = data;
|
||||
},
|
||||
activeDomChange(tabType){
|
||||
this.activeDom = tabType;
|
||||
},
|
||||
addTab(tab) {
|
||||
if (tab.name === 'add') {
|
||||
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug");
|
||||
|
@ -340,36 +361,7 @@
|
|||
this.$warning('用例列表暂不支持导出,请切换成接口列表');
|
||||
return;
|
||||
}
|
||||
let obj = {projectName: this.projectId, protocol: this.currentProtocol}
|
||||
if (this.$refs.apiList[0].selectRows && this.$refs.apiList[0].selectRows.size > 0) {
|
||||
let arr = Array.from(this.$refs.apiList[0].selectRows);
|
||||
obj.data = arr;
|
||||
this.buildApiPath(obj.data);
|
||||
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
|
||||
} else {
|
||||
let condition = {};
|
||||
let url = "/api/definition/list/all";
|
||||
condition.filters = new Map(
|
||||
[
|
||||
["status", ["Prepare", "Underway", "Completed"]],
|
||||
]
|
||||
);
|
||||
condition.projectId = this.projectId;
|
||||
this.$post(url, condition, response => {
|
||||
obj.data = response.data;
|
||||
this.buildApiPath(obj.data);
|
||||
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
|
||||
});
|
||||
}
|
||||
},
|
||||
buildApiPath(apis) {
|
||||
apis.forEach((api) => {
|
||||
this.moduleOptions.forEach(item => {
|
||||
if (api.moduleId === item.id) {
|
||||
api.modulePath = item.path;
|
||||
}
|
||||
});
|
||||
});
|
||||
this.$refs.apiList[0].exportApi();
|
||||
},
|
||||
refresh(data) {
|
||||
this.$refs.apiList[0].initTable(data);
|
||||
|
|
|
@ -17,29 +17,29 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsEditCompleteHttpApi from "./complete/EditCompleteHTTPApi";
|
||||
import MsEditCompleteTcpApi from "./complete/EditCompleteTCPApi";
|
||||
import MsEditCompleteDubboApi from "./complete/EditCompleteDubboApi";
|
||||
import MsEditCompleteSqlApi from "./complete/EditCompleteSQLApi";
|
||||
import MsEditCompleteHttpApi from "./complete/EditCompleteHTTPApi";
|
||||
import MsEditCompleteTcpApi from "./complete/EditCompleteTCPApi";
|
||||
import MsEditCompleteDubboApi from "./complete/EditCompleteDubboApi";
|
||||
import MsEditCompleteSqlApi from "./complete/EditCompleteSQLApi";
|
||||
|
||||
import {ResponseFactory, Body} from "../model/ApiTestModel";
|
||||
import {getUUID, getCurrentProjectID} from "@/common/js/utils";
|
||||
import {createComponent, Request} from "./jmeter/components";
|
||||
import Sampler from "./jmeter/components/sampler/sampler";
|
||||
import {WORKSPACE_ID} from '@/common/js/constants';
|
||||
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
||||
import {Body} from "../model/ApiTestModel";
|
||||
import {getUUID} from "@/common/js/utils";
|
||||
import {createComponent, Request} from "./jmeter/components";
|
||||
import Sampler from "./jmeter/components/sampler/sampler";
|
||||
import {WORKSPACE_ID} from '@/common/js/constants';
|
||||
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "ApiConfig",
|
||||
components: {MsEditCompleteHttpApi, MsEditCompleteTcpApi, MsEditCompleteDubboApi, MsEditCompleteSqlApi},
|
||||
data() {
|
||||
return {
|
||||
reqUrl: "",
|
||||
request: Sampler,
|
||||
config: {},
|
||||
response: {},
|
||||
maintainerOptions: [],
|
||||
}
|
||||
export default {
|
||||
name: "ApiConfig",
|
||||
components: {MsEditCompleteHttpApi, MsEditCompleteTcpApi, MsEditCompleteDubboApi, MsEditCompleteSqlApi},
|
||||
data() {
|
||||
return {
|
||||
reqUrl: "",
|
||||
request: Sampler,
|
||||
config: {},
|
||||
response: {},
|
||||
maintainerOptions: [],
|
||||
}
|
||||
},
|
||||
props: {
|
||||
currentApi: {},
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
})
|
||||
},
|
||||
active() {
|
||||
// item.active = !item.active;
|
||||
this.assertions.active = !this.assertions.active;
|
||||
this.reload();
|
||||
},
|
||||
remove() {
|
||||
|
|
|
@ -54,8 +54,7 @@
|
|||
import {CASE_ORDER} from "../../model/JsonData";
|
||||
import {API_CASE_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||
import MsBatchEdit from "../basis/BatchEdit";
|
||||
// import {CASE_PRIORITY, REQ_METHOD} from "../../model/JsonData";
|
||||
import {CASE_PRIORITY,API_METHOD_COLOUR, API_STATUS, REQ_METHOD, TCP_METHOD, SQL_METHOD, DUBBO_METHOD} from "../../model/JsonData";
|
||||
import {CASE_PRIORITY, REQ_METHOD, TCP_METHOD, SQL_METHOD, DUBBO_METHOD} from "../../model/JsonData";
|
||||
|
||||
export default {
|
||||
name: 'ApiCaseList',
|
||||
|
@ -270,10 +269,13 @@
|
|||
this.singleLoading = true;
|
||||
this.singleRunId = row.id;
|
||||
row.request.name = row.id;
|
||||
row.request.useEnvironment = this.environment.id;
|
||||
this.runData.push(row.request);
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
this.$get('/api/definition/get/' + row.request.id, response => {
|
||||
row.request.path = response.data.path; // 取的path是对应接口的path,因此查库以获得
|
||||
row.request.useEnvironment = this.environment.id;
|
||||
this.runData.push(row.request);
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
});
|
||||
},
|
||||
|
||||
batchRun() {
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
<div class="card-container" v-loading="loading">
|
||||
<el-card class="card-content">
|
||||
<el-dropdown split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
<el-button v-if="scenario" style="float: right;margin-right: 20px" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button>
|
||||
<el-dropdown v-else split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
@command="handleCommand" size="small" style="float: right;margin-right: 20px">
|
||||
{{$t('commons.test')}}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button v-if="scenario" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button>
|
||||
<el-dropdown split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
@command="handleCommand" size="small" v-if="testCase===undefined && !scenario">
|
||||
{{$t('commons.test')}}
|
||||
|
@ -198,7 +199,7 @@
|
|||
},
|
||||
urlChange() {
|
||||
if (!this.debugForm.url) return;
|
||||
let url = this.getURL(this.debugForm.url);
|
||||
let url = this.getURL(this.addProtocol(this.debugForm.url));
|
||||
if (url && url.pathname) {
|
||||
if (this.debugForm.url.indexOf('?') != -1) {
|
||||
this.debugForm.url = decodeURIComponent(this.debugForm.url.substr(0, this.debugForm.url.indexOf("?")));
|
||||
|
@ -209,7 +210,14 @@
|
|||
}
|
||||
|
||||
},
|
||||
|
||||
addProtocol(url) {
|
||||
if (url) {
|
||||
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
|
||||
return "https://" + url;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
},
|
||||
getURL(urlStr) {
|
||||
try {
|
||||
let url = new URL(urlStr);
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
<div class="card-container" v-loading="loading">
|
||||
<el-card class="card-content">
|
||||
<el-dropdown split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
<el-button v-if="scenario" style="float: right;margin-right: 20px" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button>
|
||||
|
||||
<el-dropdown v-else split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
@command="handleCommand" size="small" style="float: right;margin-right: 20px">
|
||||
{{$t('commons.test')}}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
|
@ -49,7 +51,7 @@
|
|||
|
||||
export default {
|
||||
name: "ApiConfig",
|
||||
components: {MsRequestResultTail, MsResponseResult, MsRequestMetric, MsResponseText, MsRun, MsBasisParameters, MsJmxStep,MsApiCaseList},
|
||||
components: {MsRequestResultTail, MsResponseResult, MsRequestMetric, MsResponseText, MsRun, MsBasisParameters, MsJmxStep, MsApiCaseList},
|
||||
props: {
|
||||
currentProtocol: String,
|
||||
scenario: Boolean,
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
<el-input-number v-model="request.port" controls-position="right" :min="0" :max="65535" size="small"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-dropdown split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
<el-button v-if="scenario" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button>
|
||||
|
||||
<el-dropdown v-else split-button type="primary" class="ms-api-buttion" @click="handleCommand"
|
||||
@command="handleCommand" size="small" style="float: right;margin-right: 20px">
|
||||
{{$t('commons.test')}}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="wrapper">
|
||||
<div class="section" style="width:80%;margin-left: 8px" v-for="(item, index) in list" :key="index">
|
||||
<div class="border" style="width:100%;height:200px;font-size:30px;text-align:center;color:black;">
|
||||
<el-divider><i class="el-icon-mobile-phone">111</i></el-divider>
|
||||
{{item.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="nac" style="height:500px;"></div>
|
||||
<nav style="position:fixed;right:30px;top:100px;">
|
||||
<span class="nav1 hand" v-for="(item, index) in navList" :key="index" @click="jump(index)"
|
||||
:class="index==0?'current':''">{{item}}</span>
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import $ from 'jquery';
|
||||
|
||||
export default {
|
||||
name:"MsAnchor",
|
||||
data() {
|
||||
return {
|
||||
scroll: '',
|
||||
list: [{
|
||||
name: "第一条wwwwwwww",
|
||||
backgroundcolor: "#90B2A3"
|
||||
}, {
|
||||
name: "第二条eeeeeeee",
|
||||
backgroundcolor: "#A593B2"
|
||||
}, {
|
||||
name: "第三条",
|
||||
backgroundcolor: "#A7B293"
|
||||
}, {
|
||||
name: "第四条",
|
||||
backgroundcolor: "#0F2798"
|
||||
}, {
|
||||
name: "第五条",
|
||||
backgroundcolor: "#0A464D"
|
||||
}],
|
||||
navList: [11111111, 2111111111111, 31111, 4111111, 5111111111]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dataScroll: function () {
|
||||
this.scroll = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
},
|
||||
jump(index) {
|
||||
let jump = document.getElementsByClassName('section');
|
||||
// 获取需要滚动的距离
|
||||
let total = jump[index].offsetTop;
|
||||
// Chrome
|
||||
document.body.scrollTop = total;
|
||||
// Firefox
|
||||
document.documentElement.scrollTop = total;
|
||||
// Safari
|
||||
window.pageYOffset = total;
|
||||
// $('html, body').animate({
|
||||
// 'scrollTop': total
|
||||
// }, 400);
|
||||
},
|
||||
loadSroll: function () {
|
||||
// var self = this;
|
||||
// var $navs = $(".nav1");
|
||||
// var sections = document.getElementsByClassName('section');
|
||||
// for (var i = sections.length - 1; i >= 0; i--) {
|
||||
// if (self.scroll >= sections[i].offsetTop - 100) {
|
||||
// $navs.eq(i).addClass("current").siblings().removeClass("current")
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
scroll: function () {
|
||||
this.loadSroll()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('scroll', this.dataScroll);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nav1 {
|
||||
display: block;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.navs1 .active {
|
||||
color: #847ec3;
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.hand {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.current {
|
||||
color: #fff;
|
||||
background: #847ec3;
|
||||
}
|
||||
|
||||
.border {
|
||||
border: 1px solid #eee;
|
||||
border-top: 0
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,422 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main>
|
||||
<div ref="apiDocInfoDiv">
|
||||
<div style="margin-bottom: 50px">
|
||||
<div style="font-size: 17px">
|
||||
{{apiInfo.name}}
|
||||
<span class="apiStatusTag">
|
||||
<api-status :value="apiInfo.status"/>
|
||||
</span>
|
||||
</div>
|
||||
<!--api请求信息-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="tip">请求信息</div>
|
||||
</el-row>
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="simpleFontClass">
|
||||
<el-tag size="medium"
|
||||
:style="{'background-color': getColor(apiInfo.method), border: getColor(apiInfo.method),borderRadius:'0px', marginRight:'20px'}">
|
||||
{{ apiInfo.method }}
|
||||
</el-tag>
|
||||
{{apiInfo.uri}}
|
||||
</div>
|
||||
</el-row>
|
||||
<!--api请求头-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
请求头:
|
||||
<div v-if="getJsonArr(apiInfo.requestHead).length==0">
|
||||
无
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.requestHead)" row-key="name" class="test-content adjust-table">
|
||||
<el-table-column prop="name"
|
||||
label="名称"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
label="值"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--URL参数-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
URL参数:
|
||||
<div v-if="getJsonArr(apiInfo.urlParams).length==0">
|
||||
无
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table border
|
||||
:data="getJsonArr(apiInfo.urlParams)" row-key="name" class="test-content adjust-table">
|
||||
<el-table-column prop="name"
|
||||
label="名称"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="isEnable"
|
||||
label="是否必填"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
label="值"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
label="描述"
|
||||
min-width="450px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--api请求体 以及表格-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
请求体
|
||||
</div>
|
||||
<div class="smallFontClass">
|
||||
类型:{{apiInfo.requestBodyParamType}}
|
||||
</div>
|
||||
<div>
|
||||
<el-table border v-if="apiInfo.requestBodyParamType=='kv'"
|
||||
:data="getJsonArr(apiInfo.requestBodyFormData)" row-key="id" class="test-content adjust-table">
|
||||
<el-table-column prop="name"
|
||||
label="名称"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="contentType"
|
||||
label="类型"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
label="描述"
|
||||
min-width="450px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column label="必需"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<div v-if="scope.enable">是</div>
|
||||
<div v-else-if="!scope.enable">否</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="value"
|
||||
label="默认值"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--范例展示-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
范例展示
|
||||
</div>
|
||||
<div class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;">
|
||||
{{ apiInfo.requestBodyStrutureData }}
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应信息-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="tip">响应信息</div>
|
||||
</el-row>
|
||||
<el-row class="apiInfoRow">
|
||||
|
||||
</el-row>
|
||||
<!--响应头-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
响应头:
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.responseHead)" row-key="name" class="test-content adjust-table">
|
||||
<el-table-column prop="name"
|
||||
label="名称"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
label="值"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应体-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
响应体
|
||||
</div>
|
||||
<div class="smallFontClass">
|
||||
类型:{{apiInfo.responseBodyParamType}}
|
||||
</div>
|
||||
<div>
|
||||
<el-table border v-if="apiInfo.responseBodyParamType=='kv'"
|
||||
:data="getJsonArr(apiInfo.responseBodyFormData)" row-key="id" class="test-content adjust-table">
|
||||
<el-table-column prop="name"
|
||||
label="名称"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="contentType"
|
||||
label="类型"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
label="描述"
|
||||
min-width="450px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column label="必需"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<div v-if="scope.enable">是</div>
|
||||
<div v-else-if="!scope.enable">否</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="value"
|
||||
label="默认值"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应状态码-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
响应状态码:
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.responseCode)" row-key="name" class="test-content adjust-table">
|
||||
<el-table-column prop="name"
|
||||
label="名称"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
label="值"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
<!-- 右侧列表 -->
|
||||
<el-aside width="200px">
|
||||
<div ref="apiDocList">
|
||||
<el-steps style="height: 40%" direction="vertical" :active="apiStepIndex">
|
||||
<el-step v-for="(apiInfo) in apiSimpleInfoArray" :key="apiInfo.id" @click.native="clickStep(apiInfo.id)">
|
||||
<el-link slot="title">{{apiInfo.name}}</el-link>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsAnchor from "./Anchor";
|
||||
import {API_METHOD_COLOUR} from "@/business/components/api/definition/model/JsonData";
|
||||
import {jsonToMap} from "@/common/js/utils";
|
||||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||
import {buildNodePath} from "@/business/components/api/definition/model/NodeTree";
|
||||
export default {
|
||||
name: "ApiDocumentItem",
|
||||
components: {
|
||||
MsAnchor,ApiStatus,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
apiStepIndex:0,
|
||||
apiSimpleInfoArray:[],
|
||||
apiInfo:{
|
||||
method:"无",
|
||||
uri:"无",
|
||||
name:"无",
|
||||
id:"",
|
||||
requestHead:"无",
|
||||
urlParams:"无",
|
||||
requestBodyParamType:"无",
|
||||
requestBodyFormData:'[]',
|
||||
requestBodyStrutureData:"",
|
||||
responseHead:"无",
|
||||
responseBody:"",
|
||||
responseBodyParamType:"无",
|
||||
responseBodyFormData:"无",
|
||||
responseBodyStrutureData:"无",
|
||||
responseCode:"无",
|
||||
},
|
||||
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||
clientHeight:'',//坚挺浏览器高度
|
||||
}
|
||||
},
|
||||
props: {
|
||||
projectId:String,
|
||||
moduleIds:Array,
|
||||
},
|
||||
activated() {
|
||||
this.initApiDocSimpleList();
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;//获取浏览器可视区域高度
|
||||
let that = this;
|
||||
window.onresize = function(){
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.initApiDocSimpleList();
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;//获取浏览器可视区域高度
|
||||
let that = this;
|
||||
window.onresize = function(){
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
window.onresize = function(){
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
if(that.$refs.apiDocInfoDiv){
|
||||
that.$refs.apiDocInfoDiv.style.minHeight = this.clientHeight - 300 + 'px';
|
||||
that.$refs.apiDocList.style.minHeight = this.clientHeight - 300 + 'px';
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
documentId: function () {
|
||||
return this.$route.params.documentId;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.params.documentId'() {
|
||||
},
|
||||
moduleIds(){
|
||||
this.initApiDocSimpleList();
|
||||
},
|
||||
clientHeight(){ //如果clientHeight 发生改变,这个函数就会运行
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeFixed(clientHeight){
|
||||
if(this.$refs.apiDocInfoDiv){
|
||||
this.$refs.apiDocInfoDiv.style.height = clientHeight -300 + 'px';
|
||||
this.$refs.apiDocInfoDiv.style.overflow = 'auto';
|
||||
this.$refs.apiDocList.style.height = clientHeight -300 + 'px';
|
||||
|
||||
}
|
||||
},
|
||||
initApiDocSimpleList(){
|
||||
let simpleRequest = {};
|
||||
if(this.projectId!=null && this.projectId!= ""){
|
||||
simpleRequest.projectId=this.projectId;
|
||||
}
|
||||
if(this.documentId!=null && this.documentId!= ""){
|
||||
simpleRequest.documentId=this.documentId;
|
||||
}
|
||||
if(this.moduleIds.length>0){
|
||||
simpleRequest.moduleIds=this.moduleIds;
|
||||
}
|
||||
|
||||
let simpleInfoUrl = "/api/document/selectApiSimpleInfo";
|
||||
this.$post(simpleInfoUrl, simpleRequest, response => {
|
||||
this.apiSimpleInfoArray = response.data;
|
||||
this.apiStepIndex = 0;
|
||||
if(this.apiSimpleInfoArray.length>0){
|
||||
this.selectApiInfo(this.apiSimpleInfoArray[0].id);
|
||||
}
|
||||
});
|
||||
},
|
||||
selectApiInfo(apiId){
|
||||
let simpleInfoUrl = "/api/document/selectApiInfoById/"+apiId;
|
||||
this.$get(simpleInfoUrl, response => {
|
||||
this.apiInfo = response.data;
|
||||
});
|
||||
},
|
||||
clickStep(apiId){
|
||||
for (let index = 0; index < this.apiSimpleInfoArray.length; index++) {
|
||||
if(apiId == this.apiSimpleInfoArray[index].id){
|
||||
this.apiStepIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.selectApiInfo(apiId);
|
||||
},
|
||||
stepClick(stepIndex){
|
||||
this.apiStepIndex = stepIndex;
|
||||
},
|
||||
getColor(enable, method) {
|
||||
return this.methodColorMap.get(method);
|
||||
},
|
||||
getJsonArr(jsonString){
|
||||
let returnJsonArr = [];
|
||||
if(jsonString == '无'){
|
||||
return returnJsonArr;
|
||||
}
|
||||
|
||||
let jsonArr = JSON.parse(jsonString);
|
||||
//遍历,把必填项空的数据去掉
|
||||
for(var index = 0;index < jsonArr.length;index++){
|
||||
var item = jsonArr[index];
|
||||
if(item.name!="" && item.name!=null){
|
||||
returnJsonArr.push(item);
|
||||
}
|
||||
}
|
||||
return returnJsonArr;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.simpleFontClass{
|
||||
font-size: 14px;
|
||||
}
|
||||
.blackFontClass{
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
.smallFontClass{
|
||||
font-size: 13px;
|
||||
margin: 20px 0px;
|
||||
}
|
||||
.tip {
|
||||
padding: 3px 5px;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
}
|
||||
.apiInfoRow{
|
||||
margin: 20px 10px;
|
||||
}
|
||||
.apiStatusTag{
|
||||
margin: 20px 5px;
|
||||
}
|
||||
.showDataDiv{
|
||||
background-color: #F5F7F9;
|
||||
margin: 20px 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
步骤条中,已经完成后的节点样式和里面a标签的样式
|
||||
*/
|
||||
/deep/ .el-step__head.is-finish {
|
||||
color: #C0C4CC;
|
||||
border-color: #C0C4CC;
|
||||
}
|
||||
/deep/ .el-step__title.is-finish /deep/ .el-link.el-link--default{
|
||||
color: #C0C4CC;
|
||||
}
|
||||
/*
|
||||
步骤条中,当前节点样式和当前a标签的样式
|
||||
*/
|
||||
/deep/ .el-step__head.is-process {
|
||||
color: #783887;
|
||||
border-color: #783887;
|
||||
}
|
||||
/deep/ .el-step__title.is-process /deep/ .el-link.el-link--default {
|
||||
color: #783887;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -2,12 +2,13 @@
|
|||
<api-base-component
|
||||
@copy="copyRow"
|
||||
@remove="remove"
|
||||
@active="active"
|
||||
:data="extract"
|
||||
:draggable="draggable"
|
||||
color="#015478"
|
||||
background-color="#E6EEF2"
|
||||
:title="$t('api_test.definition.request.extract_param')">
|
||||
<div style="margin: 20px">
|
||||
<div style="margin: 20px" v-loading="loading">
|
||||
<div class="extract-description">
|
||||
{{$t('api_test.request.extract.description')}}
|
||||
</div>
|
||||
|
@ -25,7 +26,7 @@
|
|||
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type" :list="list" v-if="type" :callback="after"/>
|
||||
</el-col>
|
||||
|
||||
<el-button v-if="!type" :disabled="true" type="primary" size="small">Add</el-button>
|
||||
<el-button v-if="!type" :disabled="true" type="primary" size="small">{{$t('commons.add')}}</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
|
@ -99,8 +100,8 @@
|
|||
this.loading = false
|
||||
})
|
||||
},
|
||||
active(item) {
|
||||
item.active = !item.active;
|
||||
active() {
|
||||
this.extract.active = !this.extract.active;
|
||||
this.reload();
|
||||
},
|
||||
suggestJsonOpen() {
|
||||
|
@ -157,6 +158,10 @@
|
|||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/deep/ .el-card__body {
|
||||
padding: 15px;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
<div class="header-bar">
|
||||
<div>{{ $t('api_test.api_import.data_format') }}</div>
|
||||
<el-radio-group v-model="selectedPlatformValue">
|
||||
<el-radio v-for="(item, index) in platforms" :key="index" :label="item.value">{{ item.name }}</el-radio>
|
||||
<span v-for="(item, index) in platforms" :key="index">
|
||||
<el-radio v-if="!isScenarioModel || item.name != 'Swagger'" :label="item.value">{{ item.name }}</el-radio>
|
||||
</span>
|
||||
</el-radio-group>
|
||||
|
||||
<div class="operate-button">
|
||||
|
@ -26,14 +28,14 @@
|
|||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.import_mode')">
|
||||
<el-form-item v-if="!isScenarioModel" :label="$t('commons.import_mode')">
|
||||
<el-select size="small" v-model="formData.modeId" class="project-select" clearable>
|
||||
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="isSwagger2">
|
||||
<el-switch
|
||||
v-model="swaggerUrlEable"
|
||||
v-model="swaggerUrlEnable"
|
||||
:active-text="$t('api_test.api_import.swagger_url_import')">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
@ -42,7 +44,7 @@
|
|||
<el-col :span="1">
|
||||
<el-divider direction="vertical"/>
|
||||
</el-col>
|
||||
<el-col :span="12" v-show="isSwagger2 && swaggerUrlEable" style="margin-top: 40px">
|
||||
<el-col :span="12" v-show="isSwagger2 && swaggerUrlEnable" style="margin-top: 40px">
|
||||
<el-form-item :label="'Swagger URL'" prop="swaggerUrl" class="swagger-url">
|
||||
<el-input size="small" v-model="formData.swaggerUrl" clearable show-word-limit/>
|
||||
</el-form-item>
|
||||
|
@ -56,7 +58,7 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12"
|
||||
v-if="selectedPlatformValue != 'Swagger2' || (selectedPlatformValue == 'Swagger2' && !swaggerUrlEable)">
|
||||
v-if="selectedPlatformValue != 'Swagger2' || (selectedPlatformValue == 'Swagger2' && !swaggerUrlEnable)">
|
||||
<el-upload
|
||||
class="api-upload"
|
||||
drag
|
||||
|
@ -93,7 +95,6 @@ import MsDialogFooter from "../../../../common/components/MsDialogFooter";
|
|||
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||
import {getCurrentProjectID} from "../../../../../../common/js/utils";
|
||||
import ScheduleImport from "@/business/components/api/definition/components/import/ImportScheduleEdit";
|
||||
import {buildNodePath} from "@/business/components/api/definition/model/NodeTree";
|
||||
|
||||
export default {
|
||||
name: "ApiImport",
|
||||
|
@ -103,12 +104,16 @@ export default {
|
|||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
moduleOptions: {}
|
||||
moduleOptions: {},
|
||||
model: {
|
||||
type: String,
|
||||
default: 'definition'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
swaggerUrlEable: false,
|
||||
swaggerUrlEnable: false,
|
||||
swaggerSynchronization: false,
|
||||
showEnvironmentSelect: true,
|
||||
modeOptions: [{
|
||||
|
@ -176,6 +181,9 @@ export default {
|
|||
computed: {
|
||||
isSwagger2() {
|
||||
return this.selectedPlatformValue === 'Swagger2';
|
||||
},
|
||||
isScenarioModel() {
|
||||
return this.model === 'scenario';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -222,12 +230,16 @@ export default {
|
|||
save() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
if ((this.selectedPlatformValue != 'Swagger2' || (this.selectedPlatformValue == 'Swagger2' && !this.swaggerUrlEable)) && !this.formData.file) {
|
||||
if ((this.selectedPlatformValue != 'Swagger2' || (this.selectedPlatformValue == 'Swagger2' && !this.swaggerUrlEnable)) && !this.formData.file) {
|
||||
this.$warning(this.$t('commons.please_upload'));
|
||||
return;
|
||||
}
|
||||
let url = '/api/definition/import';
|
||||
if (this.isScenarioModel) {
|
||||
url = '/api/automation/import';
|
||||
}
|
||||
let param = this.buildParam();
|
||||
this.result = this.$fileUpload('/api/definition/import', param.file, null, this.buildParam(), response => {
|
||||
this.result = this.$fileUpload(url, param.file, null, this.buildParam(), response => {
|
||||
let res = response.data;
|
||||
this.$success(this.$t('test_track.case.import.success'));
|
||||
this.visible = false;
|
||||
|
@ -243,7 +255,7 @@ export default {
|
|||
Object.assign(param, this.formData);
|
||||
param.platform = this.selectedPlatformValue;
|
||||
param.saved = this.saved;
|
||||
console.log(this.formData.moduleId)
|
||||
param.model = this.model;
|
||||
if (this.currentModule) {
|
||||
param.moduleId = this.formData.moduleId
|
||||
this.moduleOptions.filter(item => {
|
||||
|
@ -254,7 +266,7 @@ export default {
|
|||
param.modeId = this.formData.modeId
|
||||
}
|
||||
param.projectId = getCurrentProjectID();
|
||||
if (!this.swaggerUrlEable) {
|
||||
if (!this.swaggerUrlEnable) {
|
||||
param.swaggerUrl = undefined;
|
||||
}
|
||||
return param;
|
||||
|
@ -300,6 +312,10 @@ export default {
|
|||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.el-radio {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.header-bar, .format-tip, .el-form {
|
||||
border: solid #E1E1E1 1px;
|
||||
margin: 10px 0;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<api-list-container
|
||||
<api-list-container-with-doc
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:active-dom="activeDom"
|
||||
@activeDomChange="activeDomChange"
|
||||
@isApiListEnableChange="isApiListEnableChange">
|
||||
<el-link type="primary" style="float:right;margin-top: 5px" @click="open">{{$t('commons.adv_search.title')}}</el-link>
|
||||
|
||||
|
@ -116,7 +118,7 @@
|
|||
:type=type></header-custom>
|
||||
<ms-table-pagination :change="initTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</api-list-container>
|
||||
</api-list-container-with-doc>
|
||||
|
||||
<api-case-list @showExecResult="showExecResult" @refresh="initTable" :currentApi="selectCase" ref="caseList"/>
|
||||
<!--批量编辑-->
|
||||
|
@ -148,6 +150,9 @@ import {API_METHOD_COLOUR, CASE_PRIORITY, DUBBO_METHOD, REQ_METHOD, SQL_METHOD,
|
|||
|
||||
import {getBodyUploadFiles, getCurrentProjectID, getCurrentUser} from "@/common/js/utils";
|
||||
import ApiListContainer from "./ApiListContainer";
|
||||
import {getBodyUploadFiles, getCurrentProjectID} from "@/common/js/utils";
|
||||
// import ApiListContainer from "./ApiListContainer";
|
||||
import ApiListContainerWithDoc from "@/business/components/api/definition/components/list/ApiListContainerWithDoc";
|
||||
import PriorityTableItem from "../../../../track/common/tableItems/planview/PriorityTableItem";
|
||||
import MsApiCaseTableExtendBtns from "../reference/ApiCaseTableExtendBtns";
|
||||
import MsReferenceView from "../reference/ReferenceView";
|
||||
|
@ -177,6 +182,18 @@ export default {
|
|||
MsTablePagination,
|
||||
MsTag,
|
||||
MsApiCaseList,
|
||||
name: "ApiCaseSimpleList",
|
||||
components: {
|
||||
MsTableHeaderSelectPopover,
|
||||
MsSetEnvironment,
|
||||
ApiCaseList,
|
||||
PriorityTableItem,
|
||||
ApiListContainerWithDoc,
|
||||
MsTableOperatorButton,
|
||||
MsTableOperator,
|
||||
MsTablePagination,
|
||||
MsTag,
|
||||
MsApiCaseList,
|
||||
MsContainer,
|
||||
MsBottomContainer,
|
||||
ShowMoreBtn,
|
||||
|
@ -187,9 +204,6 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
type: API_CASE_LIST,
|
||||
headerItems: Api_Case_List,
|
||||
tableLabel: Api_Case_List,
|
||||
condition: {
|
||||
components: API_CASE_CONFIGS
|
||||
},
|
||||
|
@ -235,6 +249,7 @@ export default {
|
|||
props: {
|
||||
currentProtocol: String,
|
||||
selectNodeIds: Array,
|
||||
activeDom:String,
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
@ -297,6 +312,9 @@ export default {
|
|||
isApiListEnableChange(data) {
|
||||
this.$emit('isApiListEnableChange', data);
|
||||
},
|
||||
activeDomChange(tabType){
|
||||
this.$emit("activeDomChange",tabType);
|
||||
},
|
||||
initTable() {
|
||||
this.getLabel()
|
||||
this.selectRows = new Set();
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
<template>
|
||||
<div>
|
||||
<api-list-container-with-doc
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:active-dom="activeDom"
|
||||
@activeDomChange="activeDomChange"
|
||||
@isApiListEnableChange="isApiListEnableChange">
|
||||
|
||||
<api-document-item :project-id="projectId" :module-ids="moduleIds"/>
|
||||
|
||||
</api-list-container-with-doc>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ApiListContainerWithDoc from "@/business/components/api/definition/components/list/ApiListContainerWithDoc";
|
||||
import ApiDocumentItem from "@/business/components/api/definition/components/document/ApiDocumentItem";
|
||||
|
||||
export default {
|
||||
name: "ApiDocumentsPage",
|
||||
components: {
|
||||
ApiListContainerWithDoc,
|
||||
ApiDocumentItem,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
projectId:String,
|
||||
moduleIds:Array,
|
||||
activeDom:String,
|
||||
isApiListEnable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
created: function () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
isApiListEnableChange(data){
|
||||
this.$emit("isApiListEnableChange",data);
|
||||
},
|
||||
activeDomChange(data){
|
||||
this.$emit("activeDomChange",data);
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<api-list-container
|
||||
<api-list-container-with-doc
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:active-dom="activeDom"
|
||||
@activeDomChange="activeDomChange"
|
||||
@isApiListEnableChange="isApiListEnableChange">
|
||||
|
||||
<el-link type="primary" @click="open" style="float: right;margin-top: 5px">{{ $t('commons.adv_search.title') }}
|
||||
|
@ -194,7 +196,7 @@
|
|||
</el-table>
|
||||
<ms-table-pagination :change="initTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</api-list-container>
|
||||
</api-list-container-with-doc>
|
||||
<ms-api-case-list @refresh="initTable" @showExecResult="showExecResult" :currentApi="selectApi" ref="caseList"/>
|
||||
<!--批量编辑-->
|
||||
<ms-batch-edit ref="batchEdit" @batchEdit="batchEdit" :typeArr="typeArr" :value-arr="valueArr"/>
|
||||
|
@ -219,6 +221,8 @@ import MsBottomContainer from "../BottomContainer";
|
|||
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
||||
import MsBatchEdit from "../basis/BatchEdit";
|
||||
import {API_METHOD_COLOUR, API_STATUS, DUBBO_METHOD, REQ_METHOD, SQL_METHOD, TCP_METHOD} from "../../model/JsonData";
|
||||
import {downloadFile, getCurrentProjectID} from "@/common/js/utils";
|
||||
import {PROJECT_NAME, WORKSPACE_ID} from '@/common/js/constants';
|
||||
import {getCurrentProjectID, getCurrentUser} from "@/common/js/utils";
|
||||
import {API_LIST, TEST_CASE_LIST, WORKSPACE_ID} from '@/common/js/constants';
|
||||
import ApiListContainer from "./ApiListContainer";
|
||||
|
@ -228,6 +232,15 @@ import MsTableAdvSearchBar from "@/business/components/common/components/search/
|
|||
import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||
import MsTipButton from "@/business/components/common/components/MsTipButton";
|
||||
import CaseBatchMove from "@/business/components/api/definition/components/basis/BatchMove";
|
||||
import ApiListContainerWithDoc from "@/business/components/api/definition/components/list/ApiListContainerWithDoc";
|
||||
import {
|
||||
_filter,
|
||||
_handleSelect,
|
||||
_handleSelectAll,
|
||||
_sort,
|
||||
getSelectDataCounts, initCondition,
|
||||
setUnSelectIds, toggleAllSelection
|
||||
} from "@/common/js/tableUtils";
|
||||
import {_filter, _sort} from "@/common/js/tableUtils";
|
||||
import {Api_List, Track_Test_Case} from "@/business/components/common/model/JsonData";
|
||||
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
|
||||
|
@ -240,7 +253,7 @@ export default {
|
|||
CaseBatchMove,
|
||||
ApiStatus,
|
||||
MsTableHeaderSelectPopover,
|
||||
ApiListContainer,
|
||||
ApiListContainerWithDoc,
|
||||
MsTableButton,
|
||||
MsTableOperatorButton,
|
||||
MsTableOperator,
|
||||
|
@ -314,8 +327,6 @@ export default {
|
|||
total: 0,
|
||||
screenHeight: document.documentElement.clientHeight - 270,//屏幕高度,
|
||||
environmentId: undefined,
|
||||
selectAll: false,
|
||||
unSelection: [],
|
||||
selectDataCounts: 0,
|
||||
}
|
||||
},
|
||||
|
@ -323,6 +334,7 @@ export default {
|
|||
currentProtocol: String,
|
||||
selectNodeIds: Array,
|
||||
isSelectThisWeek: String,
|
||||
activeDom:String,
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
@ -386,15 +398,16 @@ export default {
|
|||
handleBatchMove() {
|
||||
this.$refs.testCaseBatchMove.open(this.moduleTree, [], this.moduleOptions);
|
||||
},
|
||||
|
||||
isApiListEnableChange(data) {
|
||||
this.$emit('isApiListEnableChange', data);
|
||||
},
|
||||
activeDomChange(tabType){
|
||||
this.$emit("activeDomChange",tabType);
|
||||
},
|
||||
initTable() {
|
||||
this.getLabel()
|
||||
this.selectRows = new Set();
|
||||
this.selectAll = false;
|
||||
this.unSelection = [];
|
||||
initCondition(this.condition);
|
||||
this.selectDataCounts = 0;
|
||||
this.condition.moduleIds = this.selectNodeIds;
|
||||
this.condition.projectId = getCurrentProjectID();
|
||||
|
@ -431,7 +444,6 @@ export default {
|
|||
this.genProtocalFilter(this.condition.protocol);
|
||||
this.total = response.data.itemCount;
|
||||
this.tableData = response.data.listObject;
|
||||
this.unSelection = response.data.listObject.map(s => s.id);
|
||||
this.tableData.forEach(item => {
|
||||
if (item.tags && item.tags.length > 0) {
|
||||
item.tags = JSON.parse(item.tags);
|
||||
|
@ -510,45 +522,21 @@ export default {
|
|||
});
|
||||
});
|
||||
},
|
||||
handleSelect(selection, row) {
|
||||
row.hashTree = [];
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
let arr = Array.from(this.selectRows);
|
||||
// 选中1个以上的用例时显示更多操作
|
||||
if (this.selectRows.size === 1) {
|
||||
this.$set(arr[0], "showMore", true);
|
||||
} else if (this.selectRows.size === 2) {
|
||||
arr.forEach(row => {
|
||||
this.$set(row, "showMore", true);
|
||||
})
|
||||
}
|
||||
this.selectRowsCount(this.selectRows)
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
if (selection.length === 1) {
|
||||
selection.hashTree = [];
|
||||
this.selectRows.add(selection[0]);
|
||||
} else {
|
||||
this.tableData.forEach(item => {
|
||||
item.hashTree = [];
|
||||
this.$set(item, "showMore", true);
|
||||
this.selectRows.add(item);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.selectRows.clear();
|
||||
this.tableData.forEach(row => {
|
||||
this.$set(row, "showMore", false);
|
||||
})
|
||||
}
|
||||
this.selectRowsCount(this.selectRows)
|
||||
_handleSelectAll(this, selection, this.tableData, this.selectRows);
|
||||
setUnSelectIds(this.tableData, this.condition, this.selectRows);
|
||||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
},
|
||||
handleSelect(selection, row) {
|
||||
_handleSelect(this, selection, row, this.selectRows);
|
||||
setUnSelectIds(this.tableData, this.condition, this.selectRows);
|
||||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
},
|
||||
isSelectDataAll(data) {
|
||||
this.condition.selectAll = data;
|
||||
setUnSelectIds(this.tableData, this.condition, this.selectRows);
|
||||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
toggleAllSelection(this.$refs.apiDefinitionTable, this.tableData, this.selectRows);
|
||||
},
|
||||
search() {
|
||||
this.changeSelectDataRangeAll();
|
||||
|
@ -580,14 +568,7 @@ export default {
|
|||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let deleteParam = {};
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
deleteParam.dataIds = ids;
|
||||
deleteParam.projectId = getCurrentProjectID();
|
||||
deleteParam.selectAllDate = this.isSelectAllDate;
|
||||
deleteParam.unSelectIds = this.unSelection;
|
||||
deleteParam = Object.assign(deleteParam, this.condition);
|
||||
this.$post('/api/definition/deleteBatchByParams/', deleteParam, () => {
|
||||
this.$post('/api/definition/deleteBatchByParams/', this.buildBatchParam(), () => {
|
||||
this.selectRows.clear();
|
||||
this.initTable();
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
|
@ -600,14 +581,7 @@ export default {
|
|||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
let deleteParam = {};
|
||||
deleteParam.dataIds = ids;
|
||||
deleteParam.projectId = getCurrentProjectID();
|
||||
deleteParam.selectAllDate = this.isSelectAllDate;
|
||||
deleteParam.unSelectIds = this.unSelection;
|
||||
deleteParam = Object.assign(deleteParam, this.condition);
|
||||
this.$post('/api/definition/removeToGcByParams/', deleteParam, () => {
|
||||
this.$post('/api/definition/removeToGcByParams/', this.buildBatchParam(), () => {
|
||||
this.selectRows.clear();
|
||||
this.initTable();
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
|
@ -631,27 +605,27 @@ export default {
|
|||
this.$refs.batchEdit.open();
|
||||
},
|
||||
batchEdit(form) {
|
||||
let arr = Array.from(this.selectRows);
|
||||
let ids = arr.map(row => row.id);
|
||||
let param = {};
|
||||
let param = this.buildBatchParam();
|
||||
param[form.type] = form.value;
|
||||
param.ids = ids;
|
||||
|
||||
param.projectId = getCurrentProjectID();
|
||||
param.selectAllDate = this.isSelectAllDate;
|
||||
param.unSelectIds = this.unSelection;
|
||||
param = Object.assign(param, this.condition);
|
||||
|
||||
this.$post('/api/definition/batch/editByParams', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.initTable();
|
||||
});
|
||||
},
|
||||
buildBatchParam() {
|
||||
let param = {};
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
param.projectId = getCurrentProjectID();
|
||||
param.condition = this.condition;
|
||||
return param;
|
||||
},
|
||||
moveSave(param) {
|
||||
let arr = Array.from(this.selectRows);
|
||||
let ids = arr.map(row => row.id);
|
||||
param.ids = ids;
|
||||
param.projectId = getCurrentProjectID();
|
||||
param.moduleId=param.nodeId;
|
||||
param.condition = this.condition;
|
||||
param.selectAllDate = this.isSelectAllDate;
|
||||
param.unSelectIds = this.unSelection;
|
||||
param = Object.assign(param, this.condition);
|
||||
|
@ -706,26 +680,6 @@ export default {
|
|||
showExecResult(row) {
|
||||
this.$emit('showExecResult', row);
|
||||
},
|
||||
selectRowsCount(selection) {
|
||||
let selectedIDs = this.getIds(selection);
|
||||
let allIDs = this.tableData.map(s => s.id);
|
||||
this.unSelection = allIDs.filter(function (val) {
|
||||
return selectedIDs.indexOf(val) === -1
|
||||
});
|
||||
if (this.isSelectAllDate) {
|
||||
this.selectDataCounts = this.total - this.unSelection.length;
|
||||
} else {
|
||||
this.selectDataCounts = selection.size;
|
||||
}
|
||||
},
|
||||
isSelectDataAll(dataType) {
|
||||
this.isSelectAllDate = dataType;
|
||||
this.selectRowsCount(this.selectRows)
|
||||
//如果已经全选,不需要再操作了
|
||||
if (this.selectRows.size != this.tableData.length) {
|
||||
this.$refs.apiDefinitionTable.toggleAllSelection(true);
|
||||
}
|
||||
},
|
||||
//判断是否只显示本周的数据。 从首页跳转过来的请求会带有相关参数
|
||||
getSelectDataRange() {
|
||||
let dataRange = this.$route.params.dataSelectRange;
|
||||
|
@ -744,6 +698,25 @@ export default {
|
|||
let ids = rowArray.map(s => s.id);
|
||||
return ids;
|
||||
},
|
||||
exportApi() {
|
||||
let param = this.buildBatchParam();
|
||||
param.protocol = this.currentProtocol;
|
||||
this.result = this.$post("/api/definition/export", param, response => {
|
||||
let obj = response.data;
|
||||
obj.protocol = this.currentProtocol;
|
||||
this.buildApiPath(obj.data);
|
||||
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
|
||||
});
|
||||
},
|
||||
buildApiPath(apis) {
|
||||
apis.forEach((api) => {
|
||||
this.moduleOptions.forEach(item => {
|
||||
if (api.moduleId === item.id) {
|
||||
api.modulePath = item.path;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
sort(column) {
|
||||
// 每次只对一个字段排序
|
||||
if (this.condition.orders) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue