feat (接口自动化): 完成优化需求2

--story=1002974 --user=赵勇 2.环境匹配,模块支持... https://www.tapd.cn/55049933/s/1045479
This commit is contained in:
fit2-zhao 2021-09-10 15:40:02 +08:00 committed by fit2-zhao
parent 9b1c6b0978
commit 20127bc205
5 changed files with 138 additions and 29 deletions

View File

@ -328,7 +328,12 @@ public class ApiAutomationController {
@PostMapping(value = "/stop/batch")
public String stopBatch(@RequestBody List<TaskRequest> reportIds) {
return taskService.stop(reportIds);
return taskService.stop(reportIds);
}
@PostMapping("/setDomain")
public String setDomain(@RequestBody ApiScenarioEnvRequest request) {
return apiAutomationService.setDomain(request.getDefinition());
}
}

View File

@ -1,9 +1,10 @@
package io.metersphere.api.dto.definition.request;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.definition.request.controller.MsLoopController;
import io.metersphere.api.dto.definition.request.controller.MsTransactionController;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.dto.scenario.KeyValue;
@ -16,6 +17,8 @@ import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -23,6 +26,7 @@ import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.CSVDataSet;
import org.apache.jmeter.config.RandomVariableConfig;
import org.apache.jmeter.modifiers.CounterConfig;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree;
@ -286,4 +290,32 @@ public class ElementUtil {
dataFormatting(elementJSONArray);
}
}
public static void dataSetDomain(JSONArray hashTree, MsParameter msParameter) {
try {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
if (element != null && element.get("type").toString().equals("HTTPSamplerProxy")) {
MsHTTPSamplerProxy httpSamplerProxy = JSON.toJavaObject(element, MsHTTPSamplerProxy.class);
if (httpSamplerProxy != null
&& (!httpSamplerProxy.isCustomizeReq() || (httpSamplerProxy.isCustomizeReq() && httpSamplerProxy.getIsRefEnvironment()))) {
HashTree tmpHashTree = new HashTree();
httpSamplerProxy.toHashTree(tmpHashTree, null, msParameter);
if (tmpHashTree != null && tmpHashTree.getArray().length > 0) {
HTTPSamplerProxy object = (HTTPSamplerProxy) tmpHashTree.getArray()[0];
if (object != null && StringUtils.isNotEmpty(object.getDomain())) {
element.fluentPut("domain", StringUtils.isNotEmpty(object.getProtocol()) ? object.getProtocol() + "://" + object.getDomain() : object.getDomain());
}
}
}
}
if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataSetDomain(elementJSONArray, msParameter);
}
}
} catch (Exception e) {
LogUtil.error(e.getMessage());
}
}
}

View File

@ -600,6 +600,30 @@ public class ApiAutomationService {
return apiScenarioMapper.selectByPrimaryKey(id);
}
public String setDomain(String scenarioDefinition) {
JSONObject element = JSON.parseObject(scenarioDefinition);
ParameterConfig config = new ParameterConfig();
Map<String, EnvironmentConfig> envConfig = new HashMap<>(16);
Map<String, String> environmentMap = (Map<String, String>) element.get("environmentMap");
if (environmentMap != null && !environmentMap.isEmpty()) {
environmentMap.keySet().forEach(projectId -> {
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentMap.get(projectId));
if (environment != null && environment.getConfig() != null) {
EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
env.setApiEnvironmentid(environment.getId());
envConfig.put(projectId, env);
}
});
config.setConfig(envConfig);
}
if (config.getConfig() != null && !config.getConfig().isEmpty()) {
ElementUtil.dataSetDomain(element.getJSONArray("hashTree"), config);
}
return JSON.toJSONString(element);
}
public LinkedList<MsTestElement> getScenarioHashTree(String definition) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@ -2518,6 +2542,7 @@ public class ApiAutomationService {
/**
* 用例自定义排序
*
* @param request
*/
public void updateOrder(ResetOrderRequest request) {

View File

@ -450,6 +450,7 @@ export default {
messageWebSocket: {},
buttonData: [],
stepFilter: new STEP,
plugins: [],
}
},
created() {
@ -464,6 +465,7 @@ export default {
this.getWsProjects();
this.getMaintainerOptions();
this.getApiScenario();
this.getPlugins();
this.initPlugins();
this.buttonData = buttons(this);
},
@ -482,27 +484,53 @@ export default {
},
},
methods: {
setDomain() {
if (this.projectEnvMap && this.projectEnvMap.size > 0) {
let scenario = {
id: this.currentScenario.id,
enableCookieShare: this.enableCookieShare,
name: this.currentScenario.name,
type: "scenario",
clazzName: TYPE_TO_C.get("scenario"),
variables: this.currentScenario.variables,
headers: this.currentScenario.headers,
referenced: 'Created',
environmentMap: strMapToObj(this.projectEnvMap),
hashTree: this.scenarioDefinition,
onSampleError: this.onSampleError,
projectId: this.currentScenario.projectId ? this.currentScenario.projectId : this.projectId,
};
this.$post("/api/automation/setDomain", {definition: JSON.stringify(scenario)}, res => {
if (res.data) {
let data = JSON.parse(res.data);
this.scenarioDefinition = data.hashTree;
}
})
}
},
initPlugins() {
if (this.plugins) {
this.plugins.forEach(item => {
let plugin = {
title: item.name,
show: this.showButton(item.jmeterClazz),
titleColor: "#555855",
titleBgColor: "#F4F4FF",
icon: "colorize",
click: () => {
this.addComponent(item.name, item)
}
}
if (this.operatingElements && this.operatingElements.includes(item.jmeterClazz)) {
this.buttonData.push(plugin);
}
});
}
},
getPlugins() {
let url = "/plugin/list";
this.$get(url, response => {
let data = response.data;
if (data) {
data.forEach(item => {
let plugin = {
title: item.name,
show: this.showButton(item.jmeterClazz),
titleColor: "#555855",
titleBgColor: "#F4F4FF",
icon: "colorize",
click: () => {
this.addComponent(item.name, item)
}
}
if (this.operatingElements && this.operatingElements.includes(item.jmeterClazz)) {
this.buttonData.push(plugin);
}
});
}
this.plugins = response.data;
});
},
stop() {
@ -1279,6 +1307,7 @@ export default {
}
}
this.loading = false;
this.setDomain();
this.sort();
// resourceId
if (this.scenarioDefinition) {
@ -1352,6 +1381,7 @@ export default {
},
setProjectEnvMap(projectEnvMap) {
this.projectEnvMap = projectEnvMap;
this.setDomain();
},
getWsProjects() {
this.$get("/project/listAll", res => {

View File

@ -1,19 +1,26 @@
<template>
<div>
<div v-if="request.protocol === 'HTTP'">
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-if="request.url || isCustomizeReq" 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">
<div v-if="request.url || isCustomizeReq">
<el-select v-model="request.method" style="width: 100px" size="small">
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-input>
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-else v-model="request.path"
style="width: 85%;margin-top: 10px" size="small" @blur="pathChange">
<el-select v-model="request.method" slot="prepend" style="width: 100px" size="small">
<el-input v-model="request.domain" v-if="request.isRefEnvironment && request.domain" size="small" readonly style="width: 150px"/>
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-model="request.url"
style="width: 50%" size="small" @blur="urlChange">
</el-input>
<el-checkbox v-if="isCustomizeReq" class="is-ref-environment" v-model="request.isRefEnvironment">
{{ $t('api_test.request.refer_to_environment') }}
</el-checkbox>
</div>
<div v-else>
<el-select v-model="request.method" style="width: 100px" size="small">
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-input>
<el-checkbox v-if="isCustomizeReq" class="is-ref-environment" v-model="request.isRefEnvironment">{{ $t('api_test.request.refer_to_environment') }}</el-checkbox>
<el-input v-model="request.domain" v-if="request.domain" size="small" readonly style="width: 150px"/>
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" style="width: 50%"
v-model="request.path" size="small" @blur="pathChange"/>
</div>
</div>
<div v-if="request.protocol === 'TCP' && isCustomizeReq">
@ -122,6 +129,16 @@ export default {
width: 50%;
}
.scenario-step-request-name {
display: inline-block;
margin: 0 5px;
overflow-x: hidden;
padding-bottom: 0;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
width: 120px;
}
.is-ref-environment {
margin-left: 15px;
}