Merge remote-tracking branch 'origin/master' into master
This commit is contained in:
commit
48c9af48c4
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -36,7 +37,7 @@ public class SaveApiScenarioRequest {
|
|||
|
||||
private String description;
|
||||
|
||||
private String scenarioDefinition;
|
||||
private MsTestElement scenarioDefinition;
|
||||
|
||||
List<String> bodyUploadIds;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.alibaba.fastjson.annotation.JSONType;
|
|||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||
|
@ -36,6 +37,9 @@ public class MsScenario extends MsTestElement {
|
|||
@JSONField(ordinal = 12)
|
||||
private String environmentId;
|
||||
|
||||
@JSONField(ordinal = 13)
|
||||
private List<KeyValue> variables;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
if (environmentId != null) {
|
||||
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||
|
|
|
@ -60,6 +60,14 @@ public class MsTestElement {
|
|||
@JSONField(ordinal = 3)
|
||||
private String label;
|
||||
@JSONField(ordinal = 4)
|
||||
private String resourceId;
|
||||
@JSONField(ordinal = 5)
|
||||
private String referenced;
|
||||
@JSONField(ordinal = 6)
|
||||
private boolean active;
|
||||
@JSONField(ordinal = 7)
|
||||
private String index;
|
||||
@JSONField(ordinal = 8)
|
||||
private LinkedList<MsTestElement> hashTree;
|
||||
|
||||
// 公共环境逐层传递,如果自身有环境 以自身引用环境为准否则以公共环境作为请求环境
|
||||
|
|
|
@ -5,12 +5,21 @@ import com.alibaba.fastjson.JSONArray;
|
|||
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.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.commons.constants.MsRequestBodyType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import io.metersphere.api.service.ApiModuleService;
|
||||
import io.metersphere.base.domain.ApiModule;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MsParser extends ApiImportAbstractParser {
|
||||
|
||||
|
@ -18,43 +27,72 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
|
||||
String testStr = getApiTestStr(source);
|
||||
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
|
||||
if (testObject.get("projectName") == null) {
|
||||
testStr = parsePluginFormat(testObject);
|
||||
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
|
||||
this.projectId = request.getProjectId();
|
||||
if (testObject.get("projectName") != null) {
|
||||
return parseMsFormat(testStr, request);
|
||||
} else {
|
||||
return parsePluginFormat(testObject);
|
||||
}
|
||||
ApiDefinitionImport apiImport = JSON.parseObject(testStr, ApiDefinitionImport.class);
|
||||
}
|
||||
|
||||
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();
|
||||
apiDefinition.setModuleId(null);
|
||||
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));
|
||||
});
|
||||
return apiDefinitionImport;
|
||||
}
|
||||
|
||||
private ApiDefinitionImport parsePluginFormat(JSONObject testObject) {
|
||||
List<ApiDefinitionResult> results = new ArrayList<>();
|
||||
ApiDefinitionImport apiImport = new ApiDefinitionImport();
|
||||
apiImport.setProtocol(RequestType.HTTP);
|
||||
apiImport.setData(results);
|
||||
testObject.keySet().forEach(tag -> {
|
||||
ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1);
|
||||
createModule(module);
|
||||
JSONObject requests = testObject.getJSONObject(tag);
|
||||
requests.keySet().forEach(requestName -> {
|
||||
|
||||
JSONObject requestObject = requests.getJSONObject(requestName);
|
||||
String path = requestObject.getString("url");
|
||||
String method = requestObject.getString("method");
|
||||
|
||||
MsHTTPSamplerProxy request = buildRequest(requestName, path, method);
|
||||
ApiDefinitionResult apiDefinition = buildApiDefinition(request.getId(), requestName, path, method);
|
||||
apiDefinition.setModuleId(module.getId());
|
||||
apiDefinition.setProjectId(this.projectId);
|
||||
|
||||
parseBody(requestObject, request.getBody());
|
||||
parseHeader(requestObject, request.getHeaders());
|
||||
apiDefinition.setRequest(JSONObject.toJSONString(request));
|
||||
results.add(apiDefinition);
|
||||
});
|
||||
});
|
||||
return apiImport;
|
||||
}
|
||||
|
||||
private String parsePluginFormat( JSONObject testObject) {
|
||||
//插件格式
|
||||
JSONArray scenarios = new JSONArray();
|
||||
testObject.keySet().forEach(scenarioName -> {
|
||||
JSONObject scenario = new JSONObject();
|
||||
scenario.put("name", scenarioName);
|
||||
JSONArray requestsObjects = new JSONArray();
|
||||
JSONObject requestsObject = testObject.getJSONObject(scenarioName);
|
||||
requestsObject.keySet().forEach(requestName -> {
|
||||
JSONObject requestObject = new JSONObject(true);
|
||||
JSONObject requestTmpObject = requestsObject.getJSONObject(requestName);
|
||||
//排序,确保type在第一个,否则转换失败
|
||||
if (StringUtils.isBlank(requestTmpObject.getString("type"))) {
|
||||
requestObject.put("type", RequestType.HTTP);
|
||||
}
|
||||
|
||||
requestTmpObject.keySet().forEach(key -> requestObject.put(key, requestTmpObject.get(key)));
|
||||
requestObject.put("name", requestName);
|
||||
parseBody(requestObject);
|
||||
requestsObjects.add(requestObject);
|
||||
});
|
||||
scenario.put("requests", requestsObjects);
|
||||
scenarios.add(scenario);
|
||||
});
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("scenarios", scenarios);
|
||||
return result.toJSONString();
|
||||
private void parseHeader(JSONObject requestObject, List<KeyValue> msHeaders) {
|
||||
JSONArray headers = requestObject.getJSONArray("headers");
|
||||
if (CollectionUtils.isNotEmpty(headers)) {
|
||||
for (int i = 0; i < headers.size(); i++) {
|
||||
JSONObject header = headers.getJSONObject(i);
|
||||
msHeaders.add(new KeyValue(header.getString("name"), header.getString("value")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseBody(JSONObject requestObject) {
|
||||
private void parseBody(JSONObject requestObject, Body msBody) {
|
||||
if (requestObject.containsKey("body")) {
|
||||
Object body = requestObject.get("body");
|
||||
if (body instanceof JSONArray) {
|
||||
|
@ -65,25 +103,18 @@ public class MsParser extends ApiImportAbstractParser {
|
|||
String tmp = bodies.getString(i);
|
||||
bodyStr.append(tmp);
|
||||
}
|
||||
JSONObject bodyObject = new JSONObject();
|
||||
bodyObject.put("raw", bodyStr);
|
||||
bodyObject.put("type", MsRequestBodyType.RAW.value());
|
||||
requestObject.put("body", bodyObject);
|
||||
msBody.setType(Body.RAW);
|
||||
msBody.setRaw(bodyStr.toString());
|
||||
}
|
||||
} else if (body instanceof JSONObject) {
|
||||
JSONObject bodyObj = requestObject.getJSONObject("body");
|
||||
if (bodyObj != null) {
|
||||
JSONArray kvs = new JSONArray();
|
||||
ArrayList<KeyValue> kvs = new ArrayList<>();
|
||||
bodyObj.keySet().forEach(key -> {
|
||||
JSONObject kv = new JSONObject();
|
||||
kv.put("name", key);
|
||||
kv.put("value", bodyObj.getString(key));
|
||||
kvs.add(kv);
|
||||
kvs.add(new KeyValue(key, bodyObj.getString(key)));
|
||||
});
|
||||
JSONObject bodyRes = new JSONObject();
|
||||
bodyRes.put("kvs", kvs);
|
||||
bodyRes.put("type", MsRequestBodyType.KV.value());
|
||||
requestObject.put("body", bodyRes);
|
||||
msBody.setKvs(kvs);
|
||||
msBody.setType(Body.WWW_FROM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,9 +156,9 @@ public class Swagger2Parser extends ApiImportAbstractParser {
|
|||
case "application/xml":
|
||||
bodyType = Body.XML;
|
||||
break;
|
||||
// case "": //todo binary 啥类型
|
||||
// bodyType = Body.BINARY;
|
||||
// break;
|
||||
case "":
|
||||
bodyType = Body.BINARY;
|
||||
break;
|
||||
default:
|
||||
bodyType = Body.RAW;
|
||||
}
|
||||
|
@ -235,7 +235,6 @@ public class Swagger2Parser extends ApiImportAbstractParser {
|
|||
refSet.add(simpleRef);
|
||||
if (model != null) {
|
||||
JSONObject bodyParameters = getBodyParameters(model.getProperties(), refSet);
|
||||
//body.setRaw(bodyParameters.toJSONString());
|
||||
return bodyParameters.toJSONString();
|
||||
}
|
||||
} else if (schema instanceof ArrayModel) {
|
||||
|
@ -250,7 +249,6 @@ public class Swagger2Parser extends ApiImportAbstractParser {
|
|||
Model model = definitions.get(simpleRef);
|
||||
JSONArray propertyList = new JSONArray();
|
||||
propertyList.add(getBodyParameters(model.getProperties(), refSet));
|
||||
// body.setRaw(propertyList.toString());
|
||||
return propertyList.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public class ApiAutomationService {
|
|||
scenario.setFollowPeople(request.getFollowPeople());
|
||||
scenario.setPrincipal(request.getPrincipal());
|
||||
scenario.setStepTotal(request.getStepTotal());
|
||||
scenario.setScenarioDefinition(request.getScenarioDefinition());
|
||||
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||
scenario.setCreateTime(System.currentTimeMillis());
|
||||
scenario.setUpdateTime(System.currentTimeMillis());
|
||||
if (StringUtils.isNotEmpty(request.getStatus())) {
|
||||
|
@ -137,7 +137,7 @@ public class ApiAutomationService {
|
|||
scenario.setFollowPeople(request.getFollowPeople());
|
||||
scenario.setPrincipal(request.getPrincipal());
|
||||
scenario.setStepTotal(request.getStepTotal());
|
||||
scenario.setScenarioDefinition(request.getScenarioDefinition());
|
||||
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||
scenario.setUpdateTime(System.currentTimeMillis());
|
||||
if (StringUtils.isNotEmpty(request.getStatus())) {
|
||||
scenario.setStatus(request.getStatus());
|
||||
|
|
|
@ -86,6 +86,7 @@ export default {
|
|||
background-color: rgb(44, 42, 72);
|
||||
color: rgb(245, 245, 245);
|
||||
font-size: 14px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
},
|
||||
editApi(row) {
|
||||
let name = this.request.name;
|
||||
Object.assign(this.request, JSON.parse(row.request));
|
||||
Object.assign(this.request, row.request);
|
||||
this.request.name = name;
|
||||
this.request.resourceId = getUUID();
|
||||
this.$emit('addCustomizeApi', this.request);
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
<template>
|
||||
<div>
|
||||
<span class="kv-description" v-if="description">
|
||||
{{description}}
|
||||
</span>
|
||||
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||
<el-col class="kv-checkbox">
|
||||
<input type="checkbox" v-if="!isDisable(index)" @change="change" :value="item.uuid" v-model="item.enable"
|
||||
:disabled="isDisable(index) || isReadOnly"/>
|
||||
</el-col>
|
||||
|
||||
<el-col>
|
||||
<ms-api-variable-input :show-copy="showCopy" :show-variable="showVariable" :is-read-only="isReadOnly" v-model="item.name" size="small" maxlength="200" @change="change"
|
||||
:placeholder="$t('api_test.variable_name')" show-word-limit/>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change"
|
||||
:placeholder="$t('api_test.value')" show-word-limit/>
|
||||
</el-col>
|
||||
<el-col class="kv-delete">
|
||||
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
|
||||
:disabled="isDisable(index) || isReadOnly"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {KeyValue} from "../../definition/model/ApiTestModel";
|
||||
import MsApiVariableInput from "./ApiVariableInput";
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioVariables",
|
||||
components: {MsApiVariableInput},
|
||||
props: {
|
||||
description: String,
|
||||
items: Array,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showVariable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCopy: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
remove: function (index) {
|
||||
this.items.splice(index, 1);
|
||||
this.$emit('change', this.items);
|
||||
},
|
||||
change: function () {
|
||||
let isNeedCreate = true;
|
||||
let removeIndex = -1;
|
||||
this.items.forEach((item, index) => {
|
||||
if (!item.name && !item.value) {
|
||||
// 多余的空行
|
||||
if (index !== this.items.length - 1) {
|
||||
removeIndex = index;
|
||||
}
|
||||
// 没有空行,需要创建空行
|
||||
isNeedCreate = false;
|
||||
}
|
||||
});
|
||||
if (isNeedCreate) {
|
||||
this.items.push(new KeyValue({enable: true}));
|
||||
}
|
||||
this.$emit('change', this.items);
|
||||
// TODO 检查key重复
|
||||
},
|
||||
isDisable: function (index) {
|
||||
return this.items.length - 1 === index;
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.items.length === 0) {
|
||||
this.items.push(new KeyValue({enable: true}));
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.kv-description {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.kv-checkbox {
|
||||
width: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.kv-row {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.kv-delete {
|
||||
width: 60px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,123 @@
|
|||
<template>
|
||||
<div class="variable-input" :class="{'show-copy': !showCopy}">
|
||||
<el-input class="el-input__inner_pd" :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||
<div :class="{'hidden': !showVariable}" class="variable-combine" v-if="value">
|
||||
<div v-if="showCopy" class="variable">{{variable}}</div>
|
||||
<el-tooltip v-if="showCopy" :content="$t('api_test.copied')" manual v-model="visible" placement="top" :visible-arrow="false">
|
||||
<i class="el-icon-copy-document copy" @click="copy"/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsApiVariableInput",
|
||||
|
||||
props: {
|
||||
value: String,
|
||||
size: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showVariable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCopy: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCopyTipWithMultiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
copy() {
|
||||
let input = document.createElement("input");
|
||||
document.body.appendChild(input);
|
||||
input.value = this.variable;
|
||||
input.select();
|
||||
if (input.setSelectionRange) {
|
||||
input.setSelectionRange(0, input.value.length);
|
||||
}
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(input);
|
||||
this.visible = true;
|
||||
setTimeout(() => {
|
||||
this.visible = false;
|
||||
}, 1000);
|
||||
},
|
||||
change(value) {
|
||||
this.$emit('change', value);
|
||||
},
|
||||
input(value) {
|
||||
this.$emit('input', value);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
variable() {
|
||||
return "${" + (this.showCopyTipWithMultiple ? (this.value + "_n") : this.value) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.variable-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.el-input__inner_pd >>> .el-input__inner {
|
||||
padding-right: 135px;
|
||||
}
|
||||
|
||||
.show-copy .el-input__inner_pd >>> .el-input__inner {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
|
||||
.variable-combine {
|
||||
color: #7F7F7F;
|
||||
max-width: 80px;
|
||||
line-height: 32px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 70px;
|
||||
margin-right: -20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.variable-combine .variable {
|
||||
display: inline-block;
|
||||
max-width: 60px;
|
||||
margin-right: 10px;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.variable-combine .copy {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: #1E90FF;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -125,10 +125,12 @@
|
|||
{{currentScenario.name ===undefined || ''? $t('api_test.scenario.name') : currentScenario.name}}
|
||||
</el-col>
|
||||
<el-col :span="4" class="ms-col-one">
|
||||
{{$t('api_test.automation.step_total')}}:{{scenarioDefinition.length}}
|
||||
{{$t('api_test.automation.step_total')}}:{{scenarioDefinition.length}}
|
||||
</el-col>
|
||||
<el-col :span="4" class="ms-col-one">
|
||||
{{$t('api_test.automation.scenario_total')}}:
|
||||
<el-link style="font-size: 13px" @click="showScenarioParameters">{{$t('api_test.automation.scenario_total')}}:
|
||||
{{this.currentScenario.variables!=undefined?this.currentScenario.variables.length-1: 0}}
|
||||
</el-link>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
{{$t('api_test.definition.request.run_env')}}:
|
||||
|
@ -263,6 +265,9 @@
|
|||
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject.id"/>
|
||||
</el-drawer>
|
||||
|
||||
<!--场景公共参数-->
|
||||
<ms-scenario-parameters :currentScenario="currentScenario" @addParameters="addParameters" ref="scenarioParameters"/>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
@ -288,6 +293,7 @@
|
|||
import MsImportApiScenario from "./ImportApiScenario";
|
||||
import MsApiScenarioComponent from "./ApiScenarioComponent";
|
||||
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||
import MsScenarioParameters from "./ScenarioParameters";
|
||||
|
||||
|
||||
export default {
|
||||
|
@ -297,7 +303,15 @@
|
|||
currentProject: {},
|
||||
currentScenario: {},
|
||||
},
|
||||
components: {ApiEnvironmentConfig, MsApiReportDetail, MsAddTag, MsRun, MsApiScenarioComponent, MsImportApiScenario, MsJsr233Processor, MsConstantTimer, MsIfController, MsApiAssertions, MsApiExtract, MsApiDefinition, MsApiComponent, MsApiCustomize},
|
||||
components: {
|
||||
ApiEnvironmentConfig, MsScenarioParameters,
|
||||
MsApiReportDetail, MsAddTag, MsRun,
|
||||
MsApiScenarioComponent, MsImportApiScenario,
|
||||
MsJsr233Processor, MsConstantTimer,
|
||||
MsIfController, MsApiAssertions,
|
||||
MsApiExtract, MsApiDefinition,
|
||||
MsApiComponent, MsApiCustomize
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
props: {
|
||||
|
@ -648,9 +662,6 @@
|
|||
if (valid) {
|
||||
this.setParameter();
|
||||
let bodyFiles = this.getBodyUploadFiles(this.currentScenario);
|
||||
console.log(bodyFiles)
|
||||
console.log(this.currentScenario.bodyUploadIds)
|
||||
|
||||
this.$fileUpload(this.path, null, bodyFiles, this.currentScenario, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.path = "/api/automation/update";
|
||||
|
@ -685,7 +696,7 @@
|
|||
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
||||
// 构建一个场景对象 方便引用处理
|
||||
let scenario = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
||||
this.currentScenario.scenarioDefinition = JSON.stringify(scenario);
|
||||
this.currentScenario.scenarioDefinition = scenario;
|
||||
this.currentScenario.tagId = JSON.stringify(this.currentScenario.tagId);
|
||||
if (this.currentModule != null) {
|
||||
this.currentScenario.modulePath = this.currentModule.method !== undefined ? this.currentModule.method : null;
|
||||
|
@ -695,6 +706,13 @@
|
|||
runRefresh() {
|
||||
this.debugVisible = true;
|
||||
this.isReloadData = false;
|
||||
},
|
||||
showScenarioParameters() {
|
||||
this.$refs.scenarioParameters.open(this.currentScenario.variables);
|
||||
},
|
||||
addParameters(data) {
|
||||
this.currentScenario.variables = data;
|
||||
this.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.scenario.variables')"
|
||||
:visible.sync="visible" class="environment-dialog" width="60%"
|
||||
@close="close">
|
||||
<el-container>
|
||||
<ms-api-scenario-variables :items="variables"
|
||||
:description="$t('api_test.scenario.kv_description')"/>
|
||||
</el-container>
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer
|
||||
@cancel="close"
|
||||
@confirm="saveParameters"/>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsApiScenarioVariables from "./ApiScenarioVariables";
|
||||
import {KeyValue} from "../../definition/model/ApiTestModel";
|
||||
import MsDialogFooter from "../../../common/components/MsDialogFooter";
|
||||
|
||||
export default {
|
||||
name: "MsScenarioParameters",
|
||||
components: {
|
||||
MsApiScenarioVariables,
|
||||
MsDialogFooter
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
variables: [new KeyValue()],
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open: function (v) {
|
||||
this.visible = true;
|
||||
if(v){
|
||||
this.variables = v;
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.visible = false;
|
||||
},
|
||||
saveParameters() {
|
||||
this.visible = false;
|
||||
this.$emit('addParameters', this.variables);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -190,6 +190,7 @@
|
|||
api: {
|
||||
type: Object
|
||||
},
|
||||
createCase: String,
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
@ -217,7 +218,6 @@
|
|||
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
// 初始化
|
||||
api() {
|
||||
|
@ -237,13 +237,35 @@
|
|||
this.currentRow.cases = [];
|
||||
}
|
||||
this.getApiTest();
|
||||
},
|
||||
createCase() {
|
||||
this.sysAddition();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getApiTest();
|
||||
this.getEnvironments();
|
||||
if (this.createCase) {
|
||||
this.sysAddition();
|
||||
} else {
|
||||
this.getApiTest();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sysAddition() {
|
||||
let condition = {};
|
||||
condition.projectId = this.api.projectId;
|
||||
condition.apiDefinitionId = this.api.id;
|
||||
condition.priority = this.priorityValue;
|
||||
condition.name = this.name;
|
||||
this.$post("/api/testcase/list", condition, response => {
|
||||
for (let index in response.data) {
|
||||
let test = response.data[index];
|
||||
test.request = JSON.parse(test.request);
|
||||
}
|
||||
this.apiCaseList = response.data;
|
||||
this.addCase();
|
||||
});
|
||||
},
|
||||
getResult(data) {
|
||||
if (RESULT_MAP.get(data)) {
|
||||
return RESULT_MAP.get(data);
|
||||
|
|
|
@ -91,35 +91,38 @@
|
|||
this.maintainerOptions = response.data;
|
||||
});
|
||||
},
|
||||
initSql() {
|
||||
setRequest() {
|
||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
||||
this.request = JSON.parse(this.currentApi.request);
|
||||
if (Object.prototype.toString.call(this.currentApi.request).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
|
||||
this.request = this.currentApi.request;
|
||||
} else {
|
||||
this.request = JSON.parse(this.currentApi.request);
|
||||
}
|
||||
this.currentApi.request = this.request;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
initSql() {
|
||||
if (!this.setRequest()) {
|
||||
this.request = createComponent("JDBCSampler");
|
||||
this.currentApi.request = this.request;
|
||||
}
|
||||
},
|
||||
initDubbo() {
|
||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
||||
this.request = JSON.parse(this.currentApi.request);
|
||||
this.currentApi.request = this.request;
|
||||
} else {
|
||||
if (!this.setRequest()) {
|
||||
this.request = createComponent("DubboSampler");
|
||||
this.currentApi.request = this.request;
|
||||
}
|
||||
},
|
||||
initTcp() {
|
||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
||||
this.request = JSON.parse(this.currentApi.request);
|
||||
this.currentApi.request = this.request;
|
||||
} else {
|
||||
if (!this.setRequest()) {
|
||||
this.request = createComponent("TCPSampler");
|
||||
this.currentApi.request = this.request;
|
||||
}
|
||||
},
|
||||
initHttp() {
|
||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
||||
this.request = JSON.parse(this.currentApi.request);
|
||||
this.currentApi.request = this.request;
|
||||
} else {
|
||||
if (!this.setRequest()) {
|
||||
this.request = createComponent("HTTPSamplerProxy");
|
||||
this.currentApi.request = this.request;
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
this.$refs.debugResult.reload();
|
||||
},
|
||||
saveAs() {
|
||||
let obj = {request: JSON.stringify(this.request)};
|
||||
let obj = {request: this.request};
|
||||
this.$emit('saveAs', obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
saveAs() {
|
||||
this.$refs['debugForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.debugForm.request = JSON.stringify(this.request);
|
||||
this.debugForm.request = this.request;
|
||||
this.debugForm.userId = getCurrentUser().id;
|
||||
this.debugForm.status = "Underway";
|
||||
this.debugForm.protocol = this.currentProtocol;
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
this.$refs.debugResult.reload();
|
||||
},
|
||||
saveAs() {
|
||||
let obj = {request: JSON.stringify(this.request)};
|
||||
let obj = {request: this.request};
|
||||
this.$emit('saveAs', obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
this.$refs.debugResult.reload();
|
||||
},
|
||||
saveAs() {
|
||||
let obj = {request: JSON.stringify(this.request)};
|
||||
let obj = {request: this.request};
|
||||
this.$emit('saveAs', obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<!-- 加载用例 -->
|
||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api"
|
||||
:currentProject="currentProject" :loaded="loaded" :refreshSign="refreshSign"
|
||||
:currentProject="currentProject" :loaded="loaded" :refreshSign="refreshSign" :createCase="createCase"
|
||||
ref="caseList"/>
|
||||
</el-drawer>
|
||||
>
|
||||
|
@ -78,6 +78,7 @@
|
|||
loaded: false,
|
||||
loading: false,
|
||||
currentRequest: {},
|
||||
createCase: "",
|
||||
refreshSign: "",
|
||||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||
reqOptions: REQ_METHOD,
|
||||
|
@ -153,9 +154,10 @@
|
|||
return bodyUploadFiles;
|
||||
},
|
||||
saveAsCase() {
|
||||
this.visible = false;
|
||||
//用于触发创建操作
|
||||
this.createCase = getUUID();
|
||||
this.visible = true;
|
||||
this.loaded = false;
|
||||
this.$refs.caseList.addCase();
|
||||
},
|
||||
saveAsApi() {
|
||||
let data = {};
|
||||
|
|
|
@ -70,9 +70,9 @@
|
|||
</el-card>
|
||||
|
||||
<!-- 加载用例 -->
|
||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%" ref="drawer">
|
||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
||||
:currentProject="currentProject" :loaded="loaded"
|
||||
:currentProject="currentProject" :loaded="loaded" :createCase="createCase"
|
||||
ref="caseList"/>
|
||||
</el-drawer>
|
||||
|
||||
|
@ -113,8 +113,9 @@
|
|||
api: {},
|
||||
loaded: false,
|
||||
loading: false,
|
||||
createCase: "",
|
||||
currentRequest: {},
|
||||
refreshSign:"",
|
||||
refreshSign: "",
|
||||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||
reqOptions: REQ_METHOD,
|
||||
environments: [],
|
||||
|
@ -194,7 +195,9 @@
|
|||
return bodyUploadFiles;
|
||||
},
|
||||
saveAsCase() {
|
||||
this.visible = false;
|
||||
//用于触发创建操作
|
||||
this.createCase = getUUID();
|
||||
this.visible = true;
|
||||
this.loaded = false;
|
||||
},
|
||||
saveAsApi() {
|
||||
|
@ -301,7 +304,8 @@
|
|||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
}
|
||||
/deep/.el-drawer{
|
||||
|
||||
/deep/ .el-drawer {
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -30,9 +30,10 @@
|
|||
<!-- 加载用例 -->
|
||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
||||
:currentProject="currentProject" :loaded="loaded"
|
||||
:currentProject="currentProject" :loaded="loaded" :createCase="createCase"
|
||||
ref="caseList"/>
|
||||
</el-drawer>>
|
||||
</el-drawer>
|
||||
>
|
||||
|
||||
<!-- 环境 -->
|
||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||
|
@ -79,6 +80,7 @@
|
|||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||
reqOptions: REQ_METHOD,
|
||||
refreshSign: "",
|
||||
createCase: "",
|
||||
environments: [],
|
||||
rules: {
|
||||
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
||||
|
@ -151,9 +153,9 @@
|
|||
return bodyUploadFiles;
|
||||
},
|
||||
saveAsCase() {
|
||||
this.visible = false;
|
||||
this.createCase = getUUID();
|
||||
this.visible = true;
|
||||
this.loaded = false;
|
||||
this.$refs.caseList.addCase();
|
||||
},
|
||||
saveAsApi() {
|
||||
let data = {};
|
||||
|
@ -249,7 +251,8 @@
|
|||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
}
|
||||
/deep/.el-drawer{
|
||||
|
||||
/deep/ .el-drawer {
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<!-- 加载用例 -->
|
||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
||||
:currentProject="currentProject" :loaded="loaded"
|
||||
:currentProject="currentProject" :loaded="loaded" :createCase="createCase"
|
||||
ref="caseList"/>
|
||||
</el-drawer>
|
||||
<!-- 环境 -->
|
||||
|
@ -80,6 +80,7 @@
|
|||
reqOptions: REQ_METHOD,
|
||||
environments: [],
|
||||
refreshSign: "",
|
||||
createCase: "",
|
||||
rules: {
|
||||
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
||||
url: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}],
|
||||
|
@ -151,9 +152,9 @@
|
|||
return bodyUploadFiles;
|
||||
},
|
||||
saveAsCase() {
|
||||
this.visible = false;
|
||||
this.createCase = getUUID();
|
||||
this.visible = true;
|
||||
this.loaded = false;
|
||||
this.$refs.caseList.addCase();
|
||||
},
|
||||
saveAsApi() {
|
||||
let data = {};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div id="menu-bar" v-if="isRouterAlive">
|
||||
<el-row type="flex">
|
||||
<el-col :span="10">
|
||||
<el-col :span="14">
|
||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||
|
||||
<el-submenu :class="{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
|
||||
|
@ -54,12 +54,12 @@
|
|||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-row type="flex" justify="center">
|
||||
<ms-create-test :to="'/api/test/create'"/>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="6"/>
|
||||
<el-col :span="4"/>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
.el-menu >>> .el-menu-item {
|
||||
box-sizing: border-box;
|
||||
height: 37px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue