refactor(接口自动化): 场景导入 ms,postman 基本完成

This commit is contained in:
fit2-zhao 2021-02-02 17:46:00 +08:00
parent c94aab0219
commit c74e88c3f3
13 changed files with 689 additions and 20 deletions

View File

@ -2,14 +2,15 @@ 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.automation.parse.ScenarioImport;
import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
@ -43,6 +44,13 @@ public class ApiAutomationController {
return PageUtils.setPageInfo(page, apiAutomationService.list(request));
}
@PostMapping("/list/all")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
public List<ApiScenarioWithBLOBs> list(@RequestBody ApiScenarioRequest request) {
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
return apiAutomationService.get(request);
}
@PostMapping(value = "/create")
public ApiScenario create(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
return apiAutomationService.create(request, bodyFiles);
@ -146,5 +154,12 @@ 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 ScenarioImport scenarioImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ApiTestImportRequest request) {
return apiAutomationService.scenarioImport(file, request);
}
}

View File

@ -0,0 +1,205 @@
package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
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.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.PostmanRequestBodyMode;
import io.metersphere.commons.constants.VariableTypeConstants;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class MsPostmanParser extends ScenarioImportAbstractParser {
@Override
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ScenarioImport scenarioImport = new ScenarioImport();
// 场景步骤
LinkedList<MsTestElement> apiScenarioWithBLOBs = new LinkedList<>();
PostmanCollectionInfo info = postmanCollection.getInfo();
ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
scenario.setName(info.getName());
MsScenario msScenario = new MsScenario();
msScenario.setName(info.getName());
this.projectId = request.getProjectId();
parseItem(postmanCollection.getItem(), variables, msScenario, apiScenarioWithBLOBs);
// 生成场景对象
List<ApiScenarioWithBLOBs> scenarioWithBLOBs = new LinkedList<>();
paseScenario(scenarioWithBLOBs, msScenario, request);
scenarioImport.setData(scenarioWithBLOBs);
return scenarioImport;
}
private void paseScenario(List<ApiScenarioWithBLOBs> scenarioWithBLOBsList, MsScenario msScenario, ApiTestImportRequest request) {
ApiScenarioModule module = buildModule(getSelectModule(request.getModuleId()), msScenario.getName());
ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
scenarioWithBLOBs.setName(msScenario.getName());
scenarioWithBLOBs.setProjectId(request.getProjectId());
if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) {
scenarioWithBLOBs.setStepTotal(msScenario.getHashTree().size());
}
if (module != null) {
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
scenarioWithBLOBs.setModulePath("/" + module.getName());
}
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
scenarioWithBLOBs.setScenarioDefinition(JSON.toJSONString(msScenario));
scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, MsScenario scenario, LinkedList<MsTestElement> results) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
parseItem(childItems, variables, scenario, results);
} else {
MsHTTPSamplerProxy request = parsePostman(item);
if (request != null) {
results.add(request);
}
}
}
scenario.setVariables(parseScenarioVariable(variables));
scenario.setHashTree(results);
}
private MsHTTPSamplerProxy parsePostman(PostmanItem requestItem) {
PostmanRequest requestDesc = requestItem.getRequest();
if (requestDesc == null) {
return null;
}
requestDesc.getAuth(); // todo 认证方式等待优化
PostmanUrl url = requestDesc.getUrl();
MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url.getRaw(), requestDesc.getMethod());
if (StringUtils.isNotBlank(request.getPath())) {
String path = request.getPath().split("\\?")[0];
path = path.replace("{{", "${");
path = path.replace("}}", "}");
request.setPath(path);
} else {
request.setPath("/");
}
parseBody(request.getBody(), requestDesc);
request.setArguments(parseKeyValue(url.getQuery()));
request.setHeaders(parseKeyValue(requestDesc.getHeader()));
addBodyHeader(request);
addPreScript(request, requestItem.getEvent());
return request;
}
private void addPreScript(MsHTTPSamplerProxy request, List<PostmanEvent> event) {
if (request != null && CollectionUtils.isNotEmpty(event)) {
StringBuilder scriptStr = new StringBuilder();
event = event.stream()
.filter(item -> item.getScript() != null)
.collect(Collectors.toList());
event.forEach(item -> {
PostmanScript script = item.getScript();
if (script != null) {
List<String> exec = script.getExec();
if (CollectionUtils.isNotEmpty(exec)) {
exec.forEach(col -> {
if (StringUtils.isNotEmpty(col)) {
scriptStr.append(col + "/n");
}
});
}
}
});
if (StringUtils.isNotBlank(scriptStr)) {
MsJSR223PreProcessor jsr223PreProcessor = new MsJSR223PreProcessor();
jsr223PreProcessor.setName("JSR223PreProcessor");
jsr223PreProcessor.setScriptLanguage("javascript");
jsr223PreProcessor.setScript(scriptStr.toString());
LinkedList<MsTestElement> hashTree = new LinkedList<>();
hashTree.add(jsr223PreProcessor);
request.setHashTree(hashTree);
}
}
}
private List<KeyValue> parseKeyValue(List<PostmanKeyValue> postmanKeyValues) {
if (postmanKeyValues == null) {
return null;
}
List<KeyValue> keyValues = new ArrayList<>();
postmanKeyValues.forEach(item -> keyValues.add(new KeyValue(item.getKey(), item.getValue(), item.getDescription(), item.getContentType())));
return keyValues;
}
private List<ScenarioVariable> parseScenarioVariable(List<PostmanKeyValue> postmanKeyValues) {
if (postmanKeyValues == null) {
return null;
}
List<ScenarioVariable> keyValues = new ArrayList<>();
postmanKeyValues.forEach(item -> keyValues.add(new ScenarioVariable(item.getKey(), item.getValue(), item.getDescription(), VariableTypeConstants.CONSTANT.name())));
return keyValues;
}
private void parseBody(Body body, PostmanRequest requestDesc) {
JSONObject postmanBody = requestDesc.getBody();
if (postmanBody == null) {
return;
}
String bodyMode = postmanBody.getString("mode");
if (StringUtils.isNotEmpty(bodyMode) && StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
parseRawBody(body, postmanBody, bodyMode);
} else if (StringUtils.isNotEmpty(bodyMode) && StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) {
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(postmanBody.getString(bodyMode), PostmanKeyValue.class);
body.setKvs(parseKeyValue(postmanKeyValues));
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FORM_DATA.value())) {
body.setType(Body.FORM_DATA);
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.URLENCODED.value())) {
body.setType(Body.WWW_FROM);
}
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FILE.value())) {
body.setType(Body.BINARY);
body.setKvs(new ArrayList<>());
}
}
private void parseRawBody(Body body, JSONObject postmanBody, String bodyMode) {
body.setRaw(postmanBody.getString(bodyMode));
body.setType(MsRequestBodyType.RAW.value());
JSONObject options = postmanBody.getJSONObject("options");
if (options != null) {
JSONObject raw = options.getJSONObject(PostmanRequestBodyMode.RAW.value());
if (raw != null && raw.getString("language") != null) {
String bodyType = "";
switch (raw.getString("language")) {
case "json":
bodyType = Body.JSON;
break;
case "xml":
bodyType = Body.XML;
break;
default:
bodyType = Body.RAW;
}
body.setType(bodyType);
}
}
}
}

View File

@ -0,0 +1,65 @@
package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
public class MsScenarioParser extends ScenarioImportAbstractParser {
@Override
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
this.projectId = request.getProjectId();
ScenarioImport scenarioImport = parseMsFormat(testStr, request);
return scenarioImport;
}
private ScenarioImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
ScenarioImport apiDefinitionImport = JSON.parseObject(testStr, ScenarioImport.class);
List<ApiScenarioWithBLOBs> data = apiDefinitionImport.getData();
if (CollectionUtils.isNotEmpty(data)) {
data.forEach(item -> {
if (StringUtils.isBlank(item.getModulePath())) {
item.setApiScenarioModuleId(null);
}
parseModule(item, importRequest);
item.setId(UUID.randomUUID().toString());
item.setProjectId(this.projectId);
});
}
return apiDefinitionImport;
}
private void parseModule(ApiScenarioWithBLOBs apiDefinition, ApiTestImportRequest importRequest) {
String modulePath = apiDefinition.getModulePath();
if (StringUtils.isEmpty(modulePath)) {
return;
}
if (modulePath.startsWith("/")) {
modulePath = modulePath.substring(1, modulePath.length());
}
if (modulePath.endsWith("/")) {
modulePath = modulePath.substring(0, modulePath.length() - 1);
}
List<String> modules = Arrays.asList(modulePath.split("/"));
ApiScenarioModule parent = getSelectModule(importRequest.getModuleId());
Iterator<String> iterator = modules.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
parent = buildModule(parent, item);
if (!iterator.hasNext()) {
apiDefinition.setApiScenarioModuleId(parent.getId());
}
}
}
}

View File

@ -0,0 +1,12 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import lombok.Data;
import java.util.List;
@Data
public class ScenarioImport {
private String projectid;
private List<ApiScenarioWithBLOBs> data;
}

View File

@ -0,0 +1,169 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.api.dto.automation.ApiScenarioModuleDTO;
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.ApiScenarioModuleService;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class ScenarioImportAbstractParser implements ScenarioImportParser {
protected ApiScenarioModuleService apiModuleService;
protected String projectId;
protected ApiScenarioModule getSelectModule(String moduleId) {
apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
ApiScenarioModule module = new ApiScenarioModule();
ApiScenarioModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
if (moduleDTO != null) {
BeanUtils.copyBean(module, moduleDTO);
}
return module;
}
return null;
}
protected ApiScenarioModule buildModule(ApiScenarioModule parentModule, String name) {
apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
ApiScenarioModule module;
if (parentModule != null) {
module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1);
module.setParentId(parentModule.getId());
} else {
module = apiModuleService.getNewModule(name, this.projectId, 1);
}
createModule(module);
return module;
}
protected void createModule(ApiScenarioModule module) {
List<ApiScenarioModule> apiModules = apiModuleService.selectSameModule(module);
if (CollectionUtils.isEmpty(apiModules)) {
apiModuleService.addNode(module);
} else {
module.setId(apiModules.get(0).getId());
}
}
protected String getApiTestStr(InputStream source) {
StringBuilder testStr = null;
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
testStr = new StringBuilder();
String inputStr;
while ((inputStr = bufferedReader.readLine()) != null) {
testStr.append(inputStr);
}
} catch (Exception e) {
MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e);
} finally {
try {
if (source != null) {
source.close();
}
} catch (IOException e) {
MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e);
}
}
return testStr.toString();
}
private String formatPath(String url) {
try {
URL urlObject = new URL(url);
StringBuilder pathBuffer = new StringBuilder(urlObject.getPath());
if (StringUtils.isNotEmpty(urlObject.getQuery())) {
pathBuffer.append("?").append(urlObject.getQuery());
}
return pathBuffer.toString();
} catch (Exception ex) {
return url;
}
}
protected MsHTTPSamplerProxy buildRequest(String name, String path, String method) {
MsHTTPSamplerProxy request = new MsHTTPSamplerProxy();
request.setName(name);
// 路径去掉域名/IP 地址保留方法名称及参数
request.setPath(formatPath(path));
request.setMethod(method);
request.setProtocol(RequestType.HTTP);
request.setId(UUID.randomUUID().toString());
request.setHeaders(new ArrayList<>());
request.setArguments(new ArrayList<>());
request.setRest(new ArrayList<>());
request.setAuthManager(null);
Body body = new Body();
body.initKvs();
body.initBinary();
request.setBody(body);
return request;
}
protected void addHeader(List<KeyValue> headers, String key, String value, String description, String contentType, boolean required) {
boolean hasContentType = false;
for (KeyValue header : headers) {
if (StringUtils.equalsIgnoreCase(header.getName(), key)) {
hasContentType = true;
}
}
if (!hasContentType) {
headers.add(new KeyValue(key, value, description, contentType, required));
}
}
protected void addHeader(List<KeyValue> headers, String key, String value) {
addHeader(headers, key, value, "", "", true);
}
protected void addContentType(List<KeyValue> headers, String contentType) {
addHeader(headers, "Content-Type", contentType);
}
protected void addBodyHeader(MsHTTPSamplerProxy request) {
String contentType = "";
if (request.getBody() != null && StringUtils.isNotBlank(request.getBody().getType())) {
switch (request.getBody().getType()) {
case Body.JSON:
contentType = "application/json";
break;
case Body.WWW_FROM:
contentType = "application/x-www-form-urlencoded";
break;
case Body.XML:
contentType = "application/xml";
break;
case Body.BINARY:
contentType = "application/octet-stream";
break;
}
List<KeyValue> headers = request.getHeaders();
if (headers == null) {
headers = new ArrayList<>();
request.setHeaders(headers);
}
addContentType(request.getHeaders(), contentType);
}
}
}

View File

@ -0,0 +1,9 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.api.dto.ApiTestImportRequest;
import java.io.InputStream;
public interface ScenarioImportParser {
ScenarioImport parse(InputStream source, ApiTestImportRequest request);
}

View File

@ -0,0 +1,18 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.commons.constants.ApiImportPlatform;
import org.apache.commons.lang3.StringUtils;
public class ScenarioImportParserFactory {
public static ScenarioImportParser getImportParser(String platform) {
if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) {
return new MsScenarioParser();
} else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) {
return new MsPostmanParser();
}
// else if (StringUtils.equals(ApiImportPlatform.Swagger2.name(), platform)) {
// return new Swagger2Parser();
// }
return null;
}
}

View File

@ -40,6 +40,13 @@ public class ScenarioVariable {
private String minNumber;
private String maxNumber;
public ScenarioVariable(String key, String value, String description, String type) {
this.name = key;
this.value = value;
this.description = description;
this.type = type;
}
public boolean isConstantValid() {
if (StringUtils.equals(this.type, VariableTypeConstants.CONSTANT.name()) && StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)) {
return true;

View File

@ -5,9 +5,13 @@ 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.automation.parse.ScenarioImport;
import io.metersphere.api.dto.automation.parse.ScenarioImportParser;
import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*;
@ -91,8 +95,19 @@ public class ApiAutomationService {
return list;
}
public List<ApiScenarioWithBLOBs> get(ApiScenarioRequest request) {
ApiScenarioExample example = new ApiScenarioExample();
if (CollectionUtils.isNotEmpty(request.getIds())) {
example.createCriteria().andIdIn(request.getIds());
} else {
example.createCriteria().andProjectIdEqualTo(request.getProjectId());
}
return apiScenarioMapper.selectByExampleWithBLOBs(example);
}
/**
* 初始化部分参数
*
* @param request
* @param setDefultOrders
* @param checkThisWeekData
@ -712,4 +727,89 @@ public class ApiAutomationService {
});
}
}
public List<ApiScenarioWithBLOBs> getWithBLOBs(ApiScenarioWithBLOBs request) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andStatusNotEqualTo("Trash").andIdNotEqualTo(request.getId());
return apiScenarioMapper.selectByExampleWithBLOBs(example);
}
private void _importCreate(List<ApiScenarioWithBLOBs> sameRequest, ApiScenarioMapper batchMapper, ApiScenarioWithBLOBs scenarioWithBLOBs, ApiTestImportRequest apiTestImportRequest) {
if (CollectionUtils.isEmpty(sameRequest)) {
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
batchMapper.insert(scenarioWithBLOBs);
} else {
//如果存在则修改
scenarioWithBLOBs.setId(sameRequest.get(0).getId());
batchMapper.updateByPrimaryKeyWithBLOBs(scenarioWithBLOBs);
}
}
private ApiScenarioWithBLOBs importCreate(ApiScenarioWithBLOBs request, ApiScenarioMapper batchMapper, ApiTestImportRequest apiTestImportRequest) {
final ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
BeanUtils.copyBean(scenarioWithBLOBs, request);
scenarioWithBLOBs.setCreateTime(System.currentTimeMillis());
scenarioWithBLOBs.setUpdateTime(System.currentTimeMillis());
scenarioWithBLOBs.setStatus(APITestStatus.Underway.name());
scenarioWithBLOBs.setProjectId(apiTestImportRequest.getProjectId());
if (StringUtils.isEmpty(request.getPrincipal())) {
scenarioWithBLOBs.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId());
}
if (request.getUserId() == null) {
scenarioWithBLOBs.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
} else {
scenarioWithBLOBs.setUserId(request.getUserId());
}
scenarioWithBLOBs.setDescription(request.getDescription());
List<ApiScenarioWithBLOBs> sameRequest = getWithBLOBs(scenarioWithBLOBs);
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
_importCreate(sameRequest, batchMapper, scenarioWithBLOBs, apiTestImportRequest);
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
if (CollectionUtils.isEmpty(sameRequest)) {
batchMapper.insert(scenarioWithBLOBs);
}
} else {
_importCreate(sameRequest, batchMapper, scenarioWithBLOBs, apiTestImportRequest);
}
return scenarioWithBLOBs;
}
private void editScenario(ApiTestImportRequest request, ScenarioImport apiImport) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioMapper batchMapper = sqlSession.getMapper(ApiScenarioMapper.class);
List<ApiScenarioWithBLOBs> 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++) {
ApiScenarioWithBLOBs item = data.get(i);
if (item.getName().length() > 255) {
item.setName(item.getName().substring(0, 255));
}
item.setNum(num++);
importCreate(item, batchMapper, request);
if (i % 300 == 0) {
sqlSession.flushStatements();
}
}
sqlSession.flushStatements();
}
public ScenarioImport scenarioImport(MultipartFile file, ApiTestImportRequest request) {
ScenarioImportParser apiImportParser = ScenarioImportParserFactory.getImportParser(request.getPlatform());
ScenarioImport apiImport = null;
try {
apiImport = Objects.requireNonNull(apiImportParser).parse(file == null ? null : file.getInputStream(), request);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("parse_data_error"));
}
if (apiImport != null) {
editScenario(request, apiImport);
}
return apiImport;
}
}

View File

@ -215,6 +215,33 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
return dto;
}
public ApiScenarioModule getNewModule(String name, String projectId, int level) {
ApiScenarioModule node = new ApiScenarioModule();
node.setCreateTime(System.currentTimeMillis());
node.setUpdateTime(System.currentTimeMillis());
node.setId(UUID.randomUUID().toString());
node.setLevel(level);
node.setName(name);
node.setProjectId(projectId);
return node;
}
public List<ApiScenarioModule> selectSameModule(ApiScenarioModule node) {
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
ApiScenarioModuleExample.Criteria criteria = example.createCriteria();
criteria.andNameEqualTo(node.getName())
.andProjectIdEqualTo(node.getProjectId());
if (StringUtils.isNotBlank(node.getParentId())) {
criteria.andParentIdEqualTo(node.getParentId());
} else {
criteria.andParentIdIsNull();
}
if (StringUtils.isNotBlank(node.getId())) {
criteria.andIdNotEqualTo(node.getId());
}
return apiScenarioModuleMapper.selectByExample(example);
}
@Override
public void updatePos(String id, Double pos) {
extApiScenarioModuleMapper.updatePos(id, pos);

View File

@ -1,5 +1,5 @@
<template>
<ms-container v-if="renderComponent">
<ms-container v-if="renderComponent" v-loading="loading">
<ms-aside-container>
<ms-api-scenario-module
@nodeSelectEvent="nodeChange"
@ -8,6 +8,7 @@
@setModuleOptions="setModuleOptions"
@setNodeTree="setNodeTree"
@enableTrash="enableTrash"
@exportAPI="exportAPI"
:type="'edit'"
ref="nodeTree"/>
</ms-aside-container>
@ -63,10 +64,11 @@
import MsAsideContainer from "@/business/components/common/components/MsAsideContainer";
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import MsApiScenarioList from "@/business/components/api/automation/scenario/ApiScenarioList";
import {getUUID} from "@/common/js/utils";
import {getUUID, downloadFile} from "@/common/js/utils";
import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule";
import MsEditApiScenario from "./scenario/EditApiScenario";
import {getCurrentProjectID} from "../../../../common/js/utils";
import {PROJECT_NAME} from "../../../../common/js/constants";
export default {
name: "ApiAutomation",
@ -101,6 +103,7 @@
currentModule: null,
moduleOptions: [],
tabs: [],
loading: false,
trashEnable: false,
selectNodeIds: [],
nodeTree: []
@ -126,6 +129,27 @@
}
},
methods: {
exportAPI() {
let obj = {projectName: localStorage.getItem(PROJECT_NAME)}
let condition = {projectId: getCurrentProjectID(), ids: this.$refs.apiScenarioList.selection};
let url = "/api/automation/list/all";
this.loading = true;
this.$post(url, condition, response => {
obj.data = response.data;
this.buildApiPath(obj.data);
this.loading = false;
downloadFile("Metersphere_Scenario_" + 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;
}
});
});
},
checkRedirectEditPage(redirectParam) {
if (redirectParam != null) {
let selectParamArr = redirectParam.split("edit:");

View File

@ -138,6 +138,7 @@
this.$refs.apiImport.open(this.currentModule);
break;
case "export":
this.$emit('exportAPI');
break;
}
},

View File

@ -35,6 +35,23 @@
<el-col :span="1">
<el-divider direction="vertical"/>
</el-col>
<el-col :span="12">
<el-upload
class="api-upload"
drag
action=""
:http-request="upload"
:limit="1"
:beforeUpload="uploadValidate"
:on-remove="handleRemove"
:file-list="fileList"
:on-exceed="handleExceed"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
<div class="el-upload__tip" slot="tip">{{ $t('api_test.api_import.file_size_limit') }}</div>
</el-upload>
</el-col>
</el-row>
</el-form>
@ -182,7 +199,7 @@
return;
}
let param = this.buildParam();
this.result = this.$fileUpload('/api/definition/import', param.file, null, this.buildParam(), response => {
this.result = this.$fileUpload('/api/automation/import', param.file, null, this.buildParam(), response => {
let res = response.data;
this.$success(this.$t('test_track.case.import.success'));
this.visible = false;