Merge remote-tracking branch 'origin/master'

This commit is contained in:
wenyann 2021-02-19 18:27:44 +08:00
commit 9b2e1e5a52
29 changed files with 644 additions and 467 deletions

View File

@ -2,6 +2,7 @@ package io.metersphere.api.dto.definition.parse;
import io.metersphere.api.dto.definition.request.MsScenario; import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs; import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs; import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import lombok.Data; import lombok.Data;
@ -15,6 +16,7 @@ public class ApiDefinitionImport {
//导入场景 //导入场景
private MsScenario scenarioDefinition; private MsScenario scenarioDefinition;
private List<ApiScenarioWithBLOBs> scenarioDefinitionData;
// 新版本带用例导出 // 新版本带用例导出
private List<ApiTestCaseWithBLOBs> cases; private List<ApiTestCaseWithBLOBs> cases;

View File

@ -20,6 +20,8 @@ import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.Arguments; import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.save.SaveService; import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
@ -100,6 +102,9 @@ public class MsScenario extends MsTestElement {
el.toHashTree(tree, el.getHashTree(), config); el.toHashTree(tree, el.getHashTree(), config);
} }
} }
if (CollectionUtils.isNotEmpty(this.headers)) {
setHeader(tree, this.headers);
}
} }
public void setOldVariables(List<KeyValue> oldVariables) { public void setOldVariables(List<KeyValue> oldVariables) {
@ -109,6 +114,20 @@ public class MsScenario extends MsTestElement {
} }
} }
public void setHeader(HashTree tree, List<KeyValue> headers) {
if (CollectionUtils.isNotEmpty(headers)) {
HeaderManager headerManager = new HeaderManager();
headerManager.setEnabled(true);
headerManager.setName(this.getName() + "场景Headers");
headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName());
headerManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HeaderPanel"));
headers.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
headerManager.add(new Header(keyValue.getName(), keyValue.getValue()))
);
tree.add(headerManager);
}
}
private Arguments arguments(ParameterConfig config) { private Arguments arguments(ParameterConfig config) {
Arguments arguments = new Arguments(); Arguments arguments = new Arguments();
arguments.setEnabled(true); arguments.setEnabled(true);
@ -134,11 +153,6 @@ public class MsScenario extends MsTestElement {
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") 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; return arguments;
} }

View File

@ -102,7 +102,7 @@ public class MsLoopController extends MsTestElement {
return counterConfig; return counterConfig;
} }
private LoopController loopController() { private LoopController initLoopController() {
LoopController loopController = new LoopController(); LoopController loopController = new LoopController();
loopController.setEnabled(true); loopController.setEnabled(true);
loopController.setName("LoopController"); loopController.setName("LoopController");
@ -113,7 +113,7 @@ public class MsLoopController extends MsTestElement {
return loopController; return loopController;
} }
public String getCondition() { private String getCondition() {
String variable = "\"" + this.whileController.getVariable() + "\""; String variable = "\"" + this.whileController.getVariable() + "\"";
String operator = this.whileController.getOperator(); String operator = this.whileController.getOperator();
String value = "\"" + this.whileController.getValue() + "\""; String value = "\"" + this.whileController.getValue() + "\"";
@ -136,7 +136,7 @@ public class MsLoopController extends MsTestElement {
return "${__jexl3(" + variable + operator + value + ")}"; return "${__jexl3(" + variable + operator + value + ")}";
} }
private WhileController whileController() { private WhileController initWhileController() {
String condition = getCondition(); String condition = getCondition();
if (StringUtils.isEmpty(condition)) { if (StringUtils.isEmpty(condition)) {
return null; return null;
@ -150,7 +150,7 @@ public class MsLoopController extends MsTestElement {
return controller; return controller;
} }
private ForeachController foreachController() { private ForeachController initForeachController() {
ForeachController controller = new ForeachController(); ForeachController controller = new ForeachController();
controller.setEnabled(true); controller.setEnabled(true);
controller.setName("ForeachController"); controller.setName("ForeachController");
@ -175,13 +175,13 @@ public class MsLoopController extends MsTestElement {
runTime.setRuntime(timeout); runTime.setRuntime(timeout);
// 添加超时处理防止死循环 // 添加超时处理防止死循环
HashTree hashTree = tree.add(runTime); HashTree hashTree = tree.add(runTime);
return hashTree.add(whileController()); return hashTree.add(initWhileController());
} }
if (StringUtils.equals(this.loopType, LoopConstants.FOREACH.name()) && this.forEachController != null) { if (StringUtils.equals(this.loopType, LoopConstants.FOREACH.name()) && this.forEachController != null) {
return tree.add(foreachController()); return tree.add(initForeachController());
} }
if (StringUtils.equals(this.loopType, LoopConstants.LOOP_COUNT.name()) && this.countController != null) { if (StringUtils.equals(this.loopType, LoopConstants.LOOP_COUNT.name()) && this.countController != null) {
return tree.add(loopController()); return tree.add(initLoopController());
} }
return null; return null;
} }

View File

@ -39,7 +39,7 @@ public class MsParser extends ApiImportAbstractParser {
return parseMsFormat(testStr, request); return parseMsFormat(testStr, request);
} else { } else {
request.setPlatform(ApiImportPlatform.Plugin.name()); request.setPlatform(ApiImportPlatform.Plugin.name());
return parsePluginFormat(testObject, request); return parsePluginFormat(testObject, request, true);
} }
} }
@ -65,17 +65,20 @@ public class MsParser extends ApiImportAbstractParser {
apiDefinition.setRequest(JSONObject.toJSONString(requestObj)); apiDefinition.setRequest(JSONObject.toJSONString(requestObj));
} }
private ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) { protected ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest, Boolean isCreateModule) {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>(); List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiDefinitionImport apiImport = new ApiDefinitionImport(); ApiDefinitionImport apiImport = new ApiDefinitionImport();
apiImport.setProtocol(RequestType.HTTP); apiImport.setProtocol(RequestType.HTTP);
apiImport.setData(results); apiImport.setData(results);
testObject.keySet().forEach(tag -> { testObject.keySet().forEach(tag -> {
ApiModule parentModule = getSelectModule(importRequest.getModuleId()); ApiModule module = null;
ApiModule module = buildModule(parentModule, tag); if (isCreateModule) {
module = buildModule(getSelectModule(importRequest.getModuleId()), tag);
}
JSONObject requests = testObject.getJSONObject(tag); JSONObject requests = testObject.getJSONObject(tag);
String moduleId = module.getId();
requests.keySet().forEach(requestName -> { requests.keySet().forEach(requestName -> {
JSONObject requestObject = requests.getJSONObject(requestName); JSONObject requestObject = requests.getJSONObject(requestName);
@ -84,7 +87,7 @@ public class MsParser extends ApiImportAbstractParser {
MsHTTPSamplerProxy request = buildRequest(requestName, path, method); MsHTTPSamplerProxy request = buildRequest(requestName, path, method);
ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), requestName, path, method,importRequest); ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), requestName, path, method,importRequest);
apiDefinition.setModuleId(module.getId()); apiDefinition.setModuleId(moduleId);
apiDefinition.setProjectId(this.projectId); apiDefinition.setProjectId(this.projectId);
parseBody(requestObject, request.getBody()); parseBody(requestObject, request.getBody());
parseHeader(requestObject, request.getHeaders()); parseHeader(requestObject, request.getHeaders());

View File

@ -0,0 +1,71 @@
package io.metersphere.api.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.automation.ApiScenrioExportResult;
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.service.ApiModuleService;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.constants.ApiImportPlatform;
import io.metersphere.commons.utils.CommonBeanFactory;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.UUID;
public class ScenarioMsParser extends MsParser {
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
this.projectId = request.getProjectId();
if (testObject.get("projectId") != null) {
return parseMsFormat(testStr, request);
} else {
request.setPlatform(ApiImportPlatform.Plugin.name());
ApiDefinitionImport apiDefinitionImport = parsePluginFormat(testObject, request, false);
MsScenario msScenario = new MsScenario();
LinkedList<MsTestElement> msHTTPSamplerProxies = new LinkedList<>();
apiDefinitionImport.getData().forEach(res -> {
msHTTPSamplerProxies.add(JSONObject.parseObject(res.getRequest(), MsHTTPSamplerProxy.class));
});
msScenario.setHashTree(msHTTPSamplerProxies);
msScenario.setType("scenario");
msScenario.setName("test");
apiDefinitionImport.setScenarioDefinition(msScenario);
return apiDefinitionImport;
}
}
private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
ApiScenrioExportResult apiScenrioExportResult = JSON.parseObject(testStr, ApiScenrioExportResult.class);
apiScenrioExportResult.getData().forEach(scenario -> {
parseApiDefinition(scenario, importRequest);
});
ApiDefinitionImport apiDefinitionImport = new ApiDefinitionImport();
apiDefinitionImport.setScenarioDefinitionData(apiScenrioExportResult.getData());
return apiDefinitionImport;
}
private void parseApiDefinition(ApiScenarioWithBLOBs scenario, ApiTestImportRequest importRequest) {
String id = UUID.randomUUID().toString();
if (StringUtils.isBlank(scenario.getModulePath())) {
scenario.setApiScenarioModuleId(null);
}
// parseModule(scenario, importRequest);
scenario.setId(id);
scenario.setProjectId(this.projectId);
String scenarioDefinition = scenario.getScenarioDefinition();
JSONObject scenarioDefinitionObj = JSONObject.parseObject(scenarioDefinition);
scenarioDefinitionObj.put("id", id);
scenario.setScenarioDefinition(JSONObject.toJSONString(scenarioDefinitionObj));
}
}

View File

@ -10,7 +10,6 @@ import io.metersphere.api.dto.DeleteAPIReportRequest;
import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.JmxInfoDTO;
import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.datacount.ApiDataCountResult; 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.RunDefinitionRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.*; import io.metersphere.api.dto.definition.request.*;

View File

@ -44,7 +44,7 @@ import org.springframework.web.multipart.MultipartFile;
import sun.security.util.Cache; import sun.security.util.Cache;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.*; import java.io.File;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View File

@ -29,6 +29,7 @@ import io.metersphere.service.FileService;
import io.metersphere.service.QuotaService; import io.metersphere.service.QuotaService;
import io.metersphere.service.UserService; import io.metersphere.service.UserService;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
@ -38,11 +39,10 @@ import org.apache.jorphan.collections.ListedHashTree;
import org.aspectj.util.FileUtil; import org.aspectj.util.FileUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.*; import java.io.File;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View File

@ -407,6 +407,10 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
TestCaseNodeDTO nodeTree = request.getNodeTree(); TestCaseNodeDTO nodeTree = request.getNodeTree();
if (nodeTree == null) {
return;
}
List<TestCaseNode> updateNodes = new ArrayList<>(); List<TestCaseNode> updateNodes = new ArrayList<>();
buildUpdateTestCase(nodeTree, testCases, updateNodes, "/", "0", 1); buildUpdateTestCase(nodeTree, testCases, updateNodes, "/", "0", 1);

View File

@ -276,22 +276,19 @@ public class XmindCaseParser {
testCase.setType("functional"); testCase.setType("functional");
String tc = title.replace("", ":"); String tc = title.replace("", ":");
String[] tcArr = tc.split(":"); String[] tcArrs = tc.split(":");
if (tcArr.length < 1) { if (tcArrs.length < 1) {
process.add(Translator.get("test_case_name") + Translator.get("incorrect_format"), title); process.add(Translator.get("test_case_name") + Translator.get("incorrect_format"), title);
return; return;
} }
// 用例名称 // 用例名称
StringBuffer name = new StringBuffer(); String name = title.replace(tcArrs[0] + "", "").replace(tcArrs[0] + ":", "");
for (int i = 1; i < tcArr.length; i++) { testCase.setName(name);
name.append(tcArr[i]);
}
testCase.setName(name.toString());
testCase.setNodePath(nodePath); testCase.setNodePath(nodePath);
// 用例等级和用例性质处理 // 用例等级和用例性质处理
if (tcArr[0].indexOf("-") != -1) { if (tcArrs[0].indexOf("-") != -1) {
for (String item : tcArr[0].split("-")) { for (String item : tcArrs[0].split("-")) {
if (isAvailable(item, TC_REGEX)) { if (isAvailable(item, TC_REGEX)) {
continue; continue;
} else if (item.toUpperCase().startsWith("P")) { } else if (item.toUpperCase().startsWith("P")) {

View File

@ -206,11 +206,18 @@
<script> <script>
import {API_STATUS, PRIORITY} from "../../definition/model/JsonData"; import {API_STATUS, PRIORITY} from "../../definition/model/JsonData";
import {WORKSPACE_ID} from '@/common/js/constants'; import {WORKSPACE_ID} from '@/common/js/constants';
import {Assertions, Extract, IfController, JSR223Processor, ConstantTimer, LoopController} from "../../definition/model/ApiTestModel"; import {
Assertions,
ConstantTimer,
Extract,
IfController,
JSR223Processor,
LoopController
} from "../../definition/model/ApiTestModel";
import {parseEnvironment} from "../../definition/model/EnvironmentModel"; import {parseEnvironment} from "../../definition/model/EnvironmentModel";
import {ELEMENTS, ELEMENT_TYPE} from "./Setting"; import {ELEMENT_TYPE, ELEMENTS} from "./Setting";
import MsApiCustomize from "./ApiCustomize"; import MsApiCustomize from "./ApiCustomize";
import {getUUID, getCurrentProjectID} from "@/common/js/utils"; import {getCurrentProjectID, getUUID} from "@/common/js/utils";
import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig"; import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig";
import MsInputTag from "./MsInputTag"; import MsInputTag from "./MsInputTag";
import MsRun from "./DebugRun"; import MsRun from "./DebugRun";
@ -679,9 +686,15 @@
if (valid) { if (valid) {
this.editScenario(); this.editScenario();
this.debugData = { this.debugData = {
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", id: this.currentScenario.id,
variables: this.currentScenario.variables, referenced: 'Created', enableCookieShare: this.enableCookieShare, headers: this.currentScenario.headers, name: this.currentScenario.name,
environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition type: "scenario",
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); this.reportId = getUUID().substring(0, 8);
} }
@ -912,9 +925,15 @@
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId); this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
// 便 // 便
let scenario = { let scenario = {
id: this.currentScenario.id, enableCookieShare: this.enableCookieShare, name: this.currentScenario.name, type: "scenario", id: this.currentScenario.id,
variables: this.currentScenario.variables, headers: this.currentScenario.headers, enableCookieShare: this.enableCookieShare,
referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition 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; this.currentScenario.scenarioDefinition = scenario;
if (this.currentScenario.tags instanceof Array) { if (this.currentScenario.tags instanceof Array) {
@ -1084,6 +1103,7 @@
content: "\e722"; content: "\e722";
font-size: 20px; font-size: 20px;
} }
.ms-sc-variable-header >>> .el-dialog__body { .ms-sc-variable-header >>> .el-dialog__body {
padding: 0px 20px; padding: 0px 20px;
} }

View File

@ -1,12 +1,14 @@
<template> <template>
<div> <div>
<div v-if="request.protocol === 'HTTP'"> <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" @blur="urlChange"> <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-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-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
</el-select> </el-select>
</el-input> </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" @blur="pathChange"> <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-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-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
</el-select> </el-select>

View File

@ -29,10 +29,14 @@
<customize-req-info :is-customize-req="isCustomizeReq" :request="request"/> <customize-req-info :is-customize-req="isCustomizeReq" :request="request"/>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form :isShowEnable="true" :referenced="true" :headers="request.headers " :request="request" v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"/> <ms-api-request-form :isShowEnable="true" :referenced="true" :headers="request.headers " :request="request"
v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"/>
<ms-tcp-basis-parameters :request="request" v-if="request.protocol==='TCP'|| request.type==='TCPSampler'"/> <ms-tcp-basis-parameters :request="request" v-if="request.protocol==='TCP'|| request.type==='TCPSampler'"/>
<ms-sql-basis-parameters :request="request" v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'" :showScript="false"/> <ms-sql-basis-parameters :request="request" v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
<ms-dubbo-basis-parameters :request="request" v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'" :showScript="false"/> :showScript="false"/>
<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> <p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<div v-if="request.result"> <div v-if="request.result">
@ -47,7 +51,8 @@
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult" v-else/> <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"> <el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)"
v-if="!request.referenced">
{{ $t('commons.save') }} {{ $t('commons.save') }}
</el-button> </el-button>
@ -59,7 +64,6 @@
import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters"; import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters";
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters"; import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
import {REQ_METHOD} from "../../../definition/model/JsonData";
import MsRequestResultTail from "../../../definition/components/response/RequestResultTail"; import MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
import MsRun from "../../../definition/components/Run"; import MsRun from "../../../definition/components/Run";
import {getUUID} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";

View File

@ -100,7 +100,7 @@
import ApiBaseComponent from "../common/ApiBaseComponent"; import ApiBaseComponent from "../common/ApiBaseComponent";
import ApiResponseComponent from "./ApiResponseComponent"; import ApiResponseComponent from "./ApiResponseComponent";
import MsRun from "../DebugRun"; import MsRun from "../DebugRun";
import {getUUID, getCurrentProjectID} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
export default { export default {
name: "MsLoopController", name: "MsLoopController",
@ -204,9 +204,15 @@
} }
this.loading = true; this.loading = true;
this.debugData = { this.debugData = {
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", id: this.currentScenario.id,
variables: this.currentScenario.variables, headers: this.currentScenario.headers, name: this.currentScenario.name,
referenced: 'Created', enableCookieShare: this.enableCookieShare, environmentId: this.currentEnvironmentId, hashTree: [this.controller] type: "scenario",
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); this.reportId = getUUID().substring(0, 8);
}, },

View File

@ -7,7 +7,8 @@
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-row style="margin-bottom: 10px"> <el-row style="margin-bottom: 10px">
<el-col :span="8"> <el-col :span="8">
<el-input placeholder="变量名称搜索" v-model="selectVariable" size="small" @change="filter" @keyup.enter="filter"> <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-select v-model="searchType" slot="prepend" placeholder="类型" style="width: 90px" @change="filter">
<el-option value="CONSTANT" label="常量"></el-option> <el-option value="CONSTANT" label="常量"></el-option>
<el-option value="LIST" label="列表"></el-option> <el-option value="LIST" label="列表"></el-option>
@ -19,7 +20,8 @@
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-dropdown split-button type="primary" @command="handleClick" @click="handleClick('CONSTANT')" size="small" style="margin-left: 10px"> <el-dropdown split-button type="primary" @command="handleClick" @click="handleClick('CONSTANT')"
size="small" style="margin-left: 10px">
{{ $t('commons.add') }} {{ $t('commons.add') }}
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="CONSTANT">常量</el-dropdown-item> <el-dropdown-item command="CONSTANT">常量</el-dropdown-item>
@ -29,14 +31,16 @@
<el-dropdown-item command="RANDOM">随机数</el-dropdown-item> <el-dropdown-item command="RANDOM">随机数</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<el-button size="small" style="margin-left: 10px" @click="deleteVariable">{{$t('commons.delete')}}</el-button> <el-button size="small" style="margin-left: 10px" @click="deleteVariable">{{ $t('commons.delete') }}
</el-button>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<div style="border:1px #DCDFE6 solid; min-height: 400px;border-radius: 4px ;width: 100% ;"> <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" <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"> v-loading="loading" @row-click="edit" height="400px" :row-class-name="tableRowClassName">
<el-table-column type="selection" width="38"/> <el-table-column type="selection" width="38"/>
<el-table-column prop="num" label="ID" sortable/> <el-table-column prop="num" label="ID" sortable/>
@ -64,7 +68,8 @@
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.scenario.headers')" name="headers"> <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"> <el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.request.headers')" placement="top-start"
slot="label">
<span>{{ $t('api_test.request.headers') }} <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 is-text ms-api-col ms-variable-header" v-if="headers.length>1">
<div class="el-step__icon-inner">{{ headers.length - 1 }}</div> <div class="el-step__icon-inner">{{ headers.length - 1 }}</div>
@ -72,7 +77,8 @@
</span> </span>
</el-tooltip> </el-tooltip>
<el-row> <el-row>
<el-link class="ms-variable-link" @click="batchAdd" style="color: #783887"> {{$t("commons.batch_add")}}</el-link> <el-link class="ms-variable-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}
</el-link>
</el-row> </el-row>
<div style="min-height: 400px"> <div style="min-height: 400px">
<ms-api-key-value :items="headers"/> <ms-api-key-value :items="headers"/>
@ -154,7 +160,18 @@
if (line[1] === '必填' || line[1] === 'true') { if (line[1] === '必填' || line[1] === 'true') {
required = 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.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 => { keyValues.forEach(item => {
this.headers.unshift(item); this.headers.unshift(item);

View File

@ -2,7 +2,9 @@
<div class="card-container" v-loading="loading"> <div class="card-container" v-loading="loading">
<el-card class="card-content"> <el-card class="card-content">
<el-button v-if="scenario" style="float: right;margin-right: 20px" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button> <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" <el-dropdown v-else split-button type="primary" class="ms-api-buttion" @click="handleCommand"
@command="handleCommand" size="small" style="float: right;margin-right: 20px"> @command="handleCommand" size="small" style="float: right;margin-right: 20px">
{{ $t('commons.test') }} {{ $t('commons.test') }}
@ -36,7 +38,7 @@
<script> <script>
import MsResponseResult from "../response/ResponseResult"; import MsResponseResult from "../response/ResponseResult";
import MsRequestMetric from "../response/RequestMetric"; import MsRequestMetric from "../response/RequestMetric";
import {getUUID, getCurrentUser} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsResponseText from "../response/ResponseText"; import MsResponseText from "../response/ResponseText";
import MsRun from "../Run"; import MsRun from "../Run";
import {createComponent} from "../jmeter/components"; import {createComponent} from "../jmeter/components";
@ -48,7 +50,16 @@
export default { export default {
name: "ApiConfig", name: "ApiConfig",
components: {MsRequestResultTail, MsResponseResult, MsRequestMetric, MsResponseText, MsRun, MsBasisParameters, MsJmxStep, MsApiCaseList}, components: {
MsRequestResultTail,
MsResponseResult,
MsRequestMetric,
MsResponseText,
MsRun,
MsBasisParameters,
MsJmxStep,
MsApiCaseList
},
props: { props: {
currentProtocol: String, currentProtocol: String,
scenario: Boolean, scenario: Boolean,

View File

@ -15,7 +15,8 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button v-if="scenario" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button> <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" <el-dropdown split-button type="primary" class="ms-api-buttion" @click="handleCommand"
@command="handleCommand" size="small" v-if="testCase===undefined && !scenario"> @command="handleCommand" size="small" v-if="testCase===undefined && !scenario">
{{$t('commons.test')}} {{$t('commons.test')}}
@ -51,7 +52,7 @@
import MsApiRequestForm from "../request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import MsResponseResult from "../response/ResponseResult"; import MsResponseResult from "../response/ResponseResult";
import MsRequestMetric from "../response/RequestMetric"; import MsRequestMetric from "../response/RequestMetric";
import {getUUID, getCurrentUser} from "@/common/js/utils"; import {getCurrentUser, getUUID} from "@/common/js/utils";
import MsResponseText from "../response/ResponseText"; import MsResponseText from "../response/ResponseText";
import MsRun from "../Run"; import MsRun from "../Run";
import {createComponent} from "../jmeter/components"; import {createComponent} from "../jmeter/components";
@ -63,7 +64,16 @@
export default { export default {
name: "ApiConfig", name: "ApiConfig",
components: {MsRequestResultTail, MsResponseResult, MsApiRequestForm, MsRequestMetric, MsResponseText, MsRun, MsJmxStep, MsApiCaseList}, components: {
MsRequestResultTail,
MsResponseResult,
MsApiRequestForm,
MsRequestMetric,
MsResponseText,
MsRun,
MsJmxStep,
MsApiCaseList
},
props: { props: {
currentProtocol: String, currentProtocol: String,
testCase: {}, testCase: {},

View File

@ -2,7 +2,9 @@
<div class="card-container" v-loading="loading"> <div class="card-container" v-loading="loading">
<el-card class="card-content"> <el-card class="card-content">
<el-button v-if="scenario" style="float: right;margin-right: 20px" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button> <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" <el-dropdown v-else split-button type="primary" class="ms-api-buttion" @click="handleCommand"
@command="handleCommand" size="small" style="float: right;margin-right: 20px"> @command="handleCommand" size="small" style="float: right;margin-right: 20px">
@ -39,7 +41,7 @@
<script> <script>
import MsResponseResult from "../response/ResponseResult"; import MsResponseResult from "../response/ResponseResult";
import MsRequestMetric from "../response/RequestMetric"; import MsRequestMetric from "../response/RequestMetric";
import {getUUID, getCurrentUser} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsResponseText from "../response/ResponseText"; import MsResponseText from "../response/ResponseText";
import MsRun from "../Run"; import MsRun from "../Run";
import {createComponent} from "../jmeter/components"; import {createComponent} from "../jmeter/components";
@ -51,7 +53,16 @@
export default { export default {
name: "ApiConfig", name: "ApiConfig",
components: {MsRequestResultTail, MsResponseResult, MsRequestMetric, MsResponseText, MsRun, MsBasisParameters, MsJmxStep, MsApiCaseList}, components: {
MsRequestResultTail,
MsResponseResult,
MsRequestMetric,
MsResponseText,
MsRun,
MsBasisParameters,
MsJmxStep,
MsApiCaseList
},
props: { props: {
currentProtocol: String, currentProtocol: String,
scenario: Boolean, scenario: Boolean,

View File

@ -11,13 +11,15 @@
<el-input-number v-model="request.port" controls-position="right" :min="0" :max="65535" size="small"/> <el-input-number v-model="request.port" controls-position="right" :min="0" :max="65535" size="small"/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button v-if="scenario" size="small" type="primary" @click="handleCommand"> {{$t('commons.test')}}</el-button> <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" <el-dropdown v-else split-button type="primary" class="ms-api-buttion" @click="handleCommand"
@command="handleCommand" size="small" style="float: right;margin-right: 20px"> @command="handleCommand" size="small" style="float: right;margin-right: 20px">
{{ $t('commons.test') }} {{ $t('commons.test') }}
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="save_as">{{$t('api_test.definition.request.save_as_case')}}</el-dropdown-item> <el-dropdown-item command="save_as">{{ $t('api_test.definition.request.save_as_case') }}
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</el-form-item> </el-form-item>
@ -50,7 +52,7 @@
import MsApiRequestForm from "../request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import MsResponseResult from "../response/ResponseResult"; import MsResponseResult from "../response/ResponseResult";
import MsRequestMetric from "../response/RequestMetric"; import MsRequestMetric from "../response/RequestMetric";
import {getUUID, getCurrentUser} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsResponseText from "../response/ResponseText"; import MsResponseText from "../response/ResponseText";
import MsRun from "../Run"; import MsRun from "../Run";
import {createComponent} from "../jmeter/components"; import {createComponent} from "../jmeter/components";

View File

@ -15,7 +15,8 @@
<div class="extract-add"> <div class="extract-add">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="2"> <el-col :span="2">
<el-select :disabled="isReadOnly" class="extract-item" v-model="type" :placeholder="$t('api_test.request.extract.select_type')" <el-select :disabled="isReadOnly" class="extract-item" v-model="type"
:placeholder="$t('api_test.request.extract.select_type')"
size="small"> size="small">
<el-option :label="$t('api_test.request.extract.regex')" :value="options.REGEX"/> <el-option :label="$t('api_test.request.extract.regex')" :value="options.REGEX"/>
<el-option label="JSONPath" :value="options.JSON_PATH"/> <el-option label="JSONPath" :value="options.JSON_PATH"/>

View File

@ -44,7 +44,7 @@
</template> </template>
<script> <script>
import {getUUID, uuid} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsBottomContainer from "../BottomContainer"; import MsBottomContainer from "../BottomContainer";
@ -161,8 +161,9 @@ export default {
}, },
saveAsApi() { saveAsApi() {
let data = {}; let data = {};
this.api.request.id = uuid(); let req = this.api.request;
data.request = JSON.stringify(this.api.request); req.id = getUUID();
data.request = JSON.stringify(req);
data.method = this.api.method; data.method = this.api.method;
data.status = this.api.status; data.status = this.api.status;
data.userId = this.api.userId; data.userId = this.api.userId;

View File

@ -72,7 +72,7 @@
<script> <script>
import MsApiRequestForm from "../request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import {downloadFile, getUUID, getCurrentProjectID} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsRequestResultTail from "../response/RequestResultTail"; import MsRequestResultTail from "../response/RequestResultTail";

View File

@ -44,7 +44,7 @@
</template> </template>
<script> <script>
import {getUUID, uuid} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsBottomContainer from "../BottomContainer"; import MsBottomContainer from "../BottomContainer";
@ -160,8 +160,9 @@ export default {
}, },
saveAsApi() { saveAsApi() {
let data = {}; let data = {};
this.api.request.id = uuid(); let req = this.api.request;
data.request = JSON.stringify(this.api.request); req.id = getUUID();
data.request = JSON.stringify(req);
data.method = this.api.method; data.method = this.api.method;
data.status = this.api.status; data.status = this.api.status;
data.userId = this.api.userId; data.userId = this.api.userId;

View File

@ -55,7 +55,7 @@
<script> <script>
import MsApiRequestForm from "../request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import {getUUID, uuid} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsBottomContainer from "../BottomContainer"; import MsBottomContainer from "../BottomContainer";
@ -173,8 +173,9 @@ export default {
}, },
saveAsApi() { saveAsApi() {
let data = {}; let data = {};
this.api.request.id = uuid(); let req = this.api.request;
data.request = JSON.stringify(this.api.request); req.id = getUUID();
data.request = JSON.stringify(req);
data.method = this.api.method; data.method = this.api.method;
data.status = this.api.status; data.status = this.api.status;
data.userId = this.api.userId; data.userId = this.api.userId;