提交 8855e495 编写于 作者: F fit2-zhao 提交者: fit2-zhao

fix(接口自动化,接口定义): 修复部分缺陷

上级 f3fe3ee2
......@@ -10,6 +10,7 @@ public class ApiTestCaseDTO extends ApiTestCase {
private String moduleId;
private String path;
private String protocol;
private String casePath;
private String updateUser;
private String createUser;
}
......@@ -46,6 +46,7 @@ import org.apache.jorphan.collections.ListedHashTree;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
......@@ -286,6 +287,18 @@ public abstract class MsTestElement {
}
return "";
}
public boolean isURL(String str) {
try {
new URL(str);
return true;
} catch (Exception e) {
// 支持包含变量的url
if (str.matches("^(http|https|ftp)://.*$") && str.matches(".*://\\$\\{.*$")) {
return true;
}
return false;
}
}
}
......
......@@ -38,7 +38,9 @@ import java.util.stream.Collectors;
@EqualsAndHashCode(callSuper = true)
@JSONType(typeName = "DubboSampler")
public class MsDubboSampler extends MsTestElement {
/** type 必须放最前面,以便能够转换正确的类 */
/**
* type 必须放最前面,以便能够转换正确的类
*/
private String type = "DubboSampler";
@JSONField(ordinal = 52)
......@@ -90,40 +92,35 @@ public class MsDubboSampler extends MsTestElement {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsDubboSampler proxy = null;
if (StringUtils.equals(this.getRefType(), "CASE")) {
ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId());
if (bloBs != null) {
this.setProjectId(bloBs.getProjectId());
MsDubboSampler proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsDubboSampler>() {
proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsDubboSampler>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(bloBs.getName());
this.setMethod(proxy.getMethod());
this.set_interface(proxy.get_interface());
this.setAttachmentArgs(proxy.getAttachmentArgs());
this.setArgs(proxy.getArgs());
this.setConsumerAndService(proxy.getConsumerAndService());
this.setRegistryCenter(proxy.getRegistryCenter());
this.setConfigCenter(proxy.getConfigCenter());
}
} else {
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId());
if (apiDefinition != null) {
this.setProjectId(apiDefinition.getProjectId());
MsDubboSampler proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsDubboSampler>() {
proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsDubboSampler>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(apiDefinition.getName());
this.setMethod(proxy.getMethod());
this.set_interface(proxy.get_interface());
this.setAttachmentArgs(proxy.getAttachmentArgs());
this.setArgs(proxy.getArgs());
this.setConsumerAndService(proxy.getConsumerAndService());
this.setRegistryCenter(proxy.getRegistryCenter());
this.setConfigCenter(proxy.getConfigCenter());
}
}
if (proxy != null) {
this.setHashTree(proxy.getHashTree());
this.setMethod(proxy.getMethod());
this.set_interface(proxy.get_interface());
this.setAttachmentArgs(proxy.getAttachmentArgs());
this.setArgs(proxy.getArgs());
this.setConsumerAndService(proxy.getConsumerAndService());
this.setRegistryCenter(proxy.getRegistryCenter());
this.setConfigCenter(proxy.getConfigCenter());
}
} catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex.getMessage());
......
......@@ -110,36 +110,33 @@ public class MsHTTPSamplerProxy extends MsTestElement {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsHTTPSamplerProxy proxy = null;
if (StringUtils.equals(this.getRefType(), "CASE")) {
ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId());
if (bloBs != null) {
this.setProjectId(bloBs.getProjectId());
MsHTTPSamplerProxy proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsHTTPSamplerProxy>() {
proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsHTTPSamplerProxy>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(bloBs.getName());
this.setMethod(proxy.getMethod());
this.setBody(proxy.getBody());
this.setRest(proxy.getRest());
this.setArguments(proxy.getArguments());
this.setHeaders(proxy.getHeaders());
}
} else {
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId());
if (apiDefinition != null) {
this.setName(apiDefinition.getName());
this.setProjectId(apiDefinition.getProjectId());
MsHTTPSamplerProxy proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsHTTPSamplerProxy>() {
proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsHTTPSamplerProxy>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(apiDefinition.getName());
this.setMethod(proxy.getMethod());
this.setBody(proxy.getBody());
this.setRest(proxy.getRest());
this.setArguments(proxy.getArguments());
this.setHeaders(proxy.getHeaders());
}
}
if (proxy != null) {
this.setHashTree(proxy.getHashTree());
this.setMethod(proxy.getMethod());
this.setBody(proxy.getBody());
this.setRest(proxy.getRest());
this.setArguments(proxy.getArguments());
this.setHeaders(proxy.getHeaders());
}
} catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex.getMessage());
......@@ -202,7 +199,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
}
}
}
try {
if (config.isEffective(this.getProjectId())) {
HttpConfig httpConfig = getHttpConfig(config.getConfig().get(this.getProjectId()).getHttpConfig(), tree);
......@@ -428,20 +424,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
tree.add(headerManager);
}
}
private boolean isURL(String str) {
try {
new URL(str);
return true;
} catch (Exception e) {
// 支持包含变量的url
if (str.matches("^(http|https|ftp)://.*$") && str.matches(".*://\\$\\{.*$")) {
return true;
}
return false;
}
}
/**
* 按照环境规则匹配环境
*
......@@ -453,7 +435,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
if (CollectionUtils.isNotEmpty(httpConfig.getConditions())) {
for (HttpConfigCondition item : httpConfig.getConditions()) {
if (item.getType().equals(ConditionType.PATH.name())) {
HttpConfig config = httpConfig.getPathCondition(this.getPath());
HttpConfig config = httpConfig.getPathCondition(this.getPath(), item);
if (config != null) {
isNext = false;
httpConfig = config;
......@@ -470,7 +452,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
apiDefinition = apiDefinitionService.get(this.getId());
}
if (apiDefinition != null) {
HttpConfig config = httpConfig.getModuleCondition(apiDefinition.getModuleId());
HttpConfig config = httpConfig.getModuleCondition(apiDefinition.getModuleId(), item);
if (config != null) {
isNext = false;
httpConfig = config;
......
......@@ -151,40 +151,35 @@ public class MsJDBCSampler extends MsTestElement {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsJDBCSampler proxy = null;
if (StringUtils.equals(this.getRefType(), "CASE")) {
ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId());
if (bloBs != null) {
this.setName(bloBs.getName());
this.setProjectId(bloBs.getProjectId());
MsJDBCSampler proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsJDBCSampler>() {
proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsJDBCSampler>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(bloBs.getName());
this.setDataSource(proxy.getDataSource());
this.setDataSourceId(proxy.getDataSourceId());
this.setQuery(proxy.getQuery());
this.setVariables(proxy.getVariables());
this.setVariableNames(proxy.getVariableNames());
this.setResultVariable(proxy.getResultVariable());
this.setQueryTimeout(proxy.getQueryTimeout());
}
} else {
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId());
if (apiDefinition != null) {
this.setProjectId(apiDefinition.getProjectId());
MsJDBCSampler proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsJDBCSampler>() {
proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsJDBCSampler>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(apiDefinition.getName());
this.setDataSource(proxy.getDataSource());
this.setDataSourceId(proxy.getDataSourceId());
this.setQuery(proxy.getQuery());
this.setVariables(proxy.getVariables());
this.setVariableNames(proxy.getVariableNames());
this.setResultVariable(proxy.getResultVariable());
this.setQueryTimeout(proxy.getQueryTimeout());
}
}
if (proxy != null) {
this.setHashTree(proxy.getHashTree());
this.setDataSource(proxy.getDataSource());
this.setDataSourceId(proxy.getDataSourceId());
this.setQuery(proxy.getQuery());
this.setVariables(proxy.getVariables());
this.setVariableNames(proxy.getVariableNames());
this.setResultVariable(proxy.getResultVariable());
this.setQueryTimeout(proxy.getQueryTimeout());
}
} catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex.getMessage());
......
......@@ -129,34 +129,32 @@ public class MsTCPSampler extends MsTestElement {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsTCPSampler proxy = null;
if (StringUtils.equals(this.getRefType(), "CASE")) {
ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId());
if (bloBs != null) {
this.setName(bloBs.getName());
this.setProjectId(bloBs.getProjectId());
MsTCPSampler proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsTCPSampler>() {
proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsTCPSampler>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(bloBs.getName());
this.setClassname(proxy.getClassname());
this.setServer(proxy.getServer());
this.setPort(proxy.getPort());
this.setRequest(proxy.getRequest());
}
} else {
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId());
if (apiDefinition != null) {
this.setName(apiDefinition.getName());
this.setProjectId(apiDefinition.getProjectId());
MsTCPSampler proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsTCPSampler>() {
proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsTCPSampler>() {
});
this.setHashTree(proxy.getHashTree());
this.setName(apiDefinition.getName());
this.setClassname(proxy.getClassname());
this.setServer(proxy.getServer());
this.setPort(proxy.getPort());
this.setRequest(proxy.getRequest());
}
}
if (proxy != null) {
this.setHashTree(proxy.getHashTree());
this.setClassname(proxy.getClassname());
this.setServer(proxy.getServer());
this.setPort(proxy.getPort());
this.setRequest(proxy.getRequest());
}
} catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex.getMessage());
......
package io.metersphere.api.dto.scenario;
import io.metersphere.commons.constants.ConditionType;
import io.metersphere.commons.utils.BeanUtils;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
......@@ -31,27 +30,21 @@ public class HttpConfig {
return config;
}
public HttpConfig getPathCondition(String path) {
List<HttpConfigCondition> conditions = this.getConditions().stream().filter(condition -> ConditionType.PATH.name().equals(condition.getType()) && CollectionUtils.isNotEmpty(condition.getDetails())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(conditions)) {
for (HttpConfigCondition item : conditions) {
List<KeyValue> details = item.getDetails().stream().filter(detail -> (detail.getValue().equals("contains") && StringUtils.contains(path, detail.getName())) || (detail.getValue().equals("equals") && StringUtils.equals(path, detail.getName()))).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(details)) {
return initHttpConfig(item);
}
public HttpConfig getPathCondition(String path, HttpConfigCondition configCondition) {
if (CollectionUtils.isNotEmpty(configCondition.getDetails())) {
List<KeyValue> details = configCondition.getDetails().stream().filter(detail -> (detail.getValue().equals("contains") && StringUtils.contains(path, detail.getName())) || (detail.getValue().equals("equals") && StringUtils.equals(path, detail.getName()))).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(details)) {
return initHttpConfig(configCondition);
}
}
return null;
}
public HttpConfig getModuleCondition(String moduleId) {
List<HttpConfigCondition> conditions = this.getConditions().stream().filter(condition -> ConditionType.MODULE.name().equals(condition.getType()) && CollectionUtils.isNotEmpty(condition.getDetails())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(conditions)) {
for (HttpConfigCondition item : conditions) {
List<KeyValue> details = item.getDetails().stream().filter(detail -> StringUtils.contains(detail.getValue(), moduleId)).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(details)) {
return initHttpConfig(item);
}
public HttpConfig getModuleCondition(String moduleId, HttpConfigCondition configCondition) {
if (CollectionUtils.isNotEmpty(configCondition.getDetails())) {
List<KeyValue> details = configCondition.getDetails().stream().filter(detail -> StringUtils.contains(detail.getValue(), moduleId)).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(details)) {
return initHttpConfig(configCondition);
}
}
return null;
......
......@@ -399,7 +399,7 @@ public class ApiAutomationService {
http.setUrl(apiDefinition.getPath());
}
if (http.isEnable()) {
if (StringUtils.isBlank(http.getUrl()) || !isURL(http.getUrl())) {
if (StringUtils.isBlank(http.getUrl()) || !tr.isURL(http.getUrl())) {
env.getProjectIds().add(http.getProjectId());
env.setFullUrl(false);
}
......@@ -430,7 +430,7 @@ public class ApiAutomationService {
// 校验是否是全路径
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) tr;
if (httpSamplerProxy.isEnable()) {
if (StringUtils.isBlank(httpSamplerProxy.getUrl()) || !isURL(httpSamplerProxy.getUrl())) {
if (StringUtils.isBlank(httpSamplerProxy.getUrl()) || !tr.isURL(httpSamplerProxy.getUrl())) {
env.getProjectIds().add(httpSamplerProxy.getProjectId());
env.setFullUrl(false);
}
......@@ -473,7 +473,7 @@ public class ApiAutomationService {
http.setUrl(apiDefinition.getPath());
}
if (http.isEnable()) {
if (StringUtils.isBlank(http.getUrl()) || !this.isURL(http.getUrl())) {
if (StringUtils.isBlank(http.getUrl()) || !tr.isURL(http.getUrl())) {
env.setFullUrl(false);
env.getProjectIds().add(http.getProjectId());
}
......@@ -504,7 +504,7 @@ public class ApiAutomationService {
// 校验是否是全路径
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) tr;
if (httpSamplerProxy.isEnable()) {
if (StringUtils.isBlank(httpSamplerProxy.getUrl()) || !isURL(httpSamplerProxy.getUrl())) {
if (StringUtils.isBlank(httpSamplerProxy.getUrl()) || !tr.isURL(httpSamplerProxy.getUrl())) {
env.setFullUrl(false);
env.getProjectIds().add(httpSamplerProxy.getProjectId());
}
......@@ -528,21 +528,7 @@ public class ApiAutomationService {
}
}
private boolean isURL(String str) {
try {
String regex = "^((https|http|ftp|rtsp|mms)?://)"
+ "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?"
+ "(([0-9]{1,3}\\.){3}[0-9]{1,3}" + "|" + "([0-9a-z_!~*'()-]+\\.)*"
+ "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\."
+ "[a-z]{2,6})"
+ "(:[0-9]{1,5})?"
+ "((/?)|"
+ "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
return str.matches(regex) || (str.matches("^(http|https|ftp)://.*$") && str.matches(".*://\\$\\{.*$"));
} catch (Exception e) {
return false;
}
}
public List<ApiScenarioWithBLOBs> getApiScenarios(List<String> ids) {
if (CollectionUtils.isNotEmpty(ids)) {
......@@ -857,7 +843,7 @@ public class ApiAutomationService {
}
/**
* 场景
* 场景
*
* @param request
* @return
......
......@@ -265,7 +265,7 @@
<select id="listSimple" resultType="io.metersphere.api.dto.definition.ApiTestCaseDTO">
select
t1.id, t1.project_id, t1.name, t1.api_definition_id, t1.priority, t1.description, t1.create_user_id, t1.update_user_id, t1.create_time, t1.update_time, t1.num,
a.module_id, a.path, a.protocol, t1.tags
a.module_id, a.path, a.protocol, t1.tags,TRIM('"' from JSON_EXTRACT(t1.request, '$.path') )as casePath
from
api_test_case t1
LEFT JOIN api_definition_exec_result t2 ON t1.last_result_id = t2.id
......
<template>
<div>
<ms-run :debug="true" :environment="envMap" :reportId="reportId" :run-data="debugData"
@runRefresh="runRefresh" ref="runTest"/>
<api-base-component
@copy="copyRow"
@remove="remove"
:data="controller"
:draggable="draggable"
:is-max="isMax"
:show-btn="showBtn"
color="#02A7F0"
background-color="#F4F4F5"
:title="$t('api_test.automation.loop_controller')" v-loading="loading">
<ms-run :debug="true" :environment="envMap" :reportId="reportId" :run-data="debugData" @runRefresh="runRefresh" ref="runTest"/>
<api-base-component @copy="copyRow" @active="active(controller)" @remove="remove" :data="controller" :draggable="draggable" :is-max="isMax" :show-btn="showBtn" color="#02A7F0" background-color="#F4F4F5" :title="$t('api_test.automation.loop_controller')" v-loading="loading">
<template v-slot:headerLeft>
<i class="icon el-icon-arrow-right" :class="{'is-active': controller.active}" @click="active(controller)" style="margin-right: 10px" v-if="!isMax"/>
......@@ -21,13 +11,13 @@
</template>
<template v-slot:message>
<span v-if="requestResult && requestResult.scenarios && requestResult.scenarios.length > 0 " style="color: #8c939d;margin-right: 10px">
循环{{requestResult.scenarios.length}}次 成功{{success}}次 失败{{error}}
</span>
<span v-if="requestResult && requestResult.scenarios && requestResult.scenarios.length > 0 " style="color: #8c939d;margin-right: 10px">
{{$t('api_test.automation.loop_name')}}{{requestResult.scenarios.length}}次 成功{{success}}次 失败{{error}}
</span>
</template>
<template v-slot:button>
<el-button @click="runDebug" :tip="$t('api_test.run')" icon="el-icon-video-play" style="background-color: #409EFF;color: white;padding: 5px" size="mini" circle/>
<el-button @click="runDebug" :tip="$t('api_test.run')" icon="el-icon-video-play" style="background-color: #409EFF;color: white;padding: 5px" size="mini" circle/>
</template>
<div v-if="controller.loopType==='LOOP_COUNT'" draggable>
<el-row>
......@@ -43,7 +33,7 @@
</el-col>
<el-col :span="8">
<span class="ms-span ms-radio">{{$t('loop.proceed')}}</span>
<el-tooltip class="item" effect="dark" content="默认为开启,当循环下只有一个请求时,可以开启/关闭;当循环下超过一个请求时,则只能开启。" placement="top">>
<el-tooltip class="item" effect="dark" :content="$t('api_test.automation.loop_content')" placement="top">>
<el-switch v-model="controller.countController.proceed" @change="switchChange"/>
</el-tooltip>
......@@ -54,13 +44,13 @@
<div v-else-if="controller.loopType==='FOREACH'" draggable>
<el-row>
<el-col :span="8">
<el-input placeholder="输出变量名称" v-model="controller.forEachController.returnVal" size="small"/>
<el-input :placeholder="$t('api_test.automation.loop_return_val')" v-model="controller.forEachController.returnVal" size="small"/>
</el-col>
<el-col :span="1" style="margin-top: 6px">
<span style="margin:10px 10px 10px">in</span>
</el-col>
<el-col :span="8">
<el-input placeholder="输入变量前缀" v-model="controller.forEachController.inputVal" size="small"/>
<el-input :placeholder="$t('api_test.automation.loop_input_val')" v-model="controller.forEachController.inputVal" size="small"/>
</el-col>
<el-col :span="7">
<span class="ms-span ms-radio">{{$t('loop.interval')}}</span>
......@@ -71,8 +61,7 @@
</div>
<div v-else draggable>
<el-input size="small" v-model="controller.whileController.variable" style="width: 20%" :placeholder="$t('api_test.request.condition_variable')"/>
<el-select v-model="controller.whileController.operator" :placeholder="$t('commons.please_select')" size="small"
@change="change" style="width: 10%;margin-left: 10px">
<el-select v-model="controller.whileController.operator" :placeholder="$t('commons.please_select')" size="small" @change="change" style="width: 10%;margin-left: 10px">
<el-option v-for="o in operators" :key="o.value" :label="$t(o.label)" :value="o.value"/>
</el-select>
<el-input size="small" v-model="controller.whileController.value" :placeholder="$t('api_test.value')" v-if="!hasEmptyOperator" style="width: 20%;margin-left: 20px"/>
......@@ -113,7 +102,7 @@
type: Boolean,
default: false,
},
envMap: Map
envMap: Map,
},
data() {
return {
......@@ -128,38 +117,38 @@
operators: {
EQ: {
label: "commons.adv_search.operators.equals",
value: "=="
value: "==",
},
NE: {
label: "commons.adv_search.operators.not_equals",
value: "!="
value: "!=",
},
LIKE: {
label: "commons.adv_search.operators.like",
value: "=~"
value: "=~",
},
NOT_LIKE: {
label: "commons.adv_search.operators.not_like",
value: "!~"
value: "!~",
},
GT: {
label: "commons.adv_search.operators.gt",
value: ">"
value: ">",
},
LT: {
label: "commons.adv_search.operators.lt",
value: "<"
value: "<",
},
IS_EMPTY: {
label: "commons.adv_search.operators.is_empty",
value: "is empty"
value: "is empty",
},
IS_NOT_EMPTY: {
label: "commons.adv_search.operators.is_not_empty",
value: "is not empty"
}
}
}
value: "is not empty",
},
},
};
},
methods: {
initResult() {
......@@ -183,25 +172,24 @@
},
switchChange() {
if (this.controller.hashTree && this.controller.hashTree.length > 1) {
this.$warning("当前循环下超过一个请求,不能关闭状态")
this.$warning(this.$t('api_test.automation.loop_message'));
this.controller.countController.proceed = true;
return;
}
// 递归遍历所有请求数量
if (this.controller.hashTree && this.controller.hashTree.length === 1
&& this.controller.hashTree[0].hashTree && this.controller.hashTree[0].hashTree.length > 0) {
if (this.controller.hashTree && this.controller.hashTree.length === 1 && this.controller.hashTree[0].hashTree && this.controller.hashTree[0].hashTree.length > 0) {
let count = 0;
this.controller.hashTree[0].hashTree.forEach(item => {
if (ELEMENTS.get("AllSamplerProxy").indexOf(item.type) != -1) {
this.controller.hashTree[0].hashTree.forEach((item) => {
if (ELEMENTS.get("AllSamplerProxy").indexOf(item.type) !== -1) {
count++;
}
if (item.hashTree && item.hashTree.length > 0) {
this.recursive(item.hashTree, count);
}
})
});
if (count > 1) {
this.$warning("当前循环下超过一个请求,不能关闭状态")
this.$warning(this.$t('api_test.automation.loop_message'));
this.controller.countController.proceed = true;
return;
}
......@@ -209,7 +197,7 @@
},
recursive(arr, count) {
for (let i in arr) {
if (ELEMENTS.get("AllSamplerProxy").indexOf(arr[i].type) != -1) {
if (ELEMENTS.get("AllSamplerProxy").indexOf(arr[i].type) !== -1) {
count++;
}
if (arr[i].hashTree && arr[i].hashTree.length > 0) {
......@@ -220,7 +208,7 @@
runDebug() {
if (!this.controller.hashTree || this.controller.hashTree.length < 1) {
this.$warning("当前循环下没有请求,不能执行")
this.$warning("当前循环下没有请求,不能执行");
return;
}
this.loading = true;
......@@ -230,19 +218,19 @@
type: "scenario",
variables: this.currentScenario.variables,
headers: this.currentScenario.headers,
referenced: 'Created',
referenced: "Created",
enableCookieShare: this.enableCookieShare,
environmentId: this.currentEnvironmentId,
hashTree: [this.controller]
hashTree: [this.controller],
};
this.reportId = getUUID().substring(0, 8);
},
remove() {
this.$emit('remove', this.controller, this.node);
this.$emit("remove", this.controller, this.node);
},
copyRow() {
this.$emit('copyRow', this.controller, this.node);
this.$emit("copyRow", this.controller, this.node);
},
active(item) {
item.active = !item.active;
......@@ -253,7 +241,6 @@
},
changeRadio() {
this.controller.active = true;
//this.initResult();
this.reload();
},
change(value) {
......@@ -262,10 +249,10 @@
}
},
reload() {
this.loading = true
this.loading = true;
this.$nextTick(() => {
this.loading = false
})
this.loading = false;
});
},
runRefresh() {
this.getReport();
......@@ -273,23 +260,23 @@
getFails() {
this.error = 0;
this.success = 0;
if (this.requestResult.scenarios && this.requestResult.scenarios != null) {
if (this.requestResult.scenarios && this.requestResult.scenarios !== null) {
this.requestResult.scenarios.forEach((scenario) => {
if (scenario.requestResults) {
scenario.requestResults.forEach(item => {
scenario.requestResults.forEach((item) => {
if (item.error > 0) {
this.error++;
return;
}
})
});
}
})
this.success = this.requestResult.scenarios && this.requestResult.scenarios != null ? this.requestResult.scenarios.length - this.error : 0;
});
this.success = this.requestResult.scenarios && this.requestResult.scenarios !== null ? this.requestResult.scenarios.length - this.error : 0;
}
},
setResult(hashTree) {
if (hashTree) {
hashTree.forEach(item => {
hashTree.forEach((item) => {
if (item.type === "HTTPSamplerProxy" || item.type === "DubboSampler" || item.type === "JDBCSampler" || item.type === "TCPSampler") {
item.result = this.requestResult;
item.activeName = this.activeName;
......@@ -298,13 +285,13 @@
if (item.hashTree && item.hashTree.length > 0) {
this.setResult(item.hashTree);
}
})
});
}
},
getReport() {
if (this.reportId) {
let url = "/api/scenario/report/get/" + this.reportId;
this.$get(url, response => {
this.$get(url, (response) => {
this.report = response.data || {};
if (response.data) {
if (this.isNotRunning) {
......@@ -328,21 +315,21 @@
break;
}
this.getFails();
this.activeName = this.requestResult && this.requestResult.scenarios && this.requestResult.scenarios != null && this.requestResult.scenarios.length > 0 ? this.requestResult.scenarios[0].name : "";
this.activeName = this.requestResult && this.requestResult.scenarios && this.requestResult.scenarios !== null && this.requestResult.scenarios.length > 0 ? this.requestResult.scenarios[0].name : "";
// 把请求结果分给各个请求
this.setResult(this.controller.hashTree);
this.$emit('refReload');
this.$emit("refReload");
} catch (e) {
throw e;
}
this.loading = false;
this.reload();
} else {
setTimeout(this.getReport, 2000)
setTimeout(this.getReport, 2000);
}
} else {
this.loading = false;
this.$error(this.$t('api_report.not_exist'));
this.$error(this.$t("api_report.not_exist"));
}
});
}
......@@ -354,10 +341,9 @@
},
isNotRunning() {
return "Running" !== this.report.status;
}
}
}
},
},
};
</script>
<style scoped>
......
......@@ -42,9 +42,11 @@
<el-row>
<el-col :span="12">
<div style="border:1px #DCDFE6 solid; min-height: 400px;border-radius: 4px ;width: 100% ;">
<el-table ref="table" border :data="variables" class="adjust-table" @select-all="select"
<el-table ref="table" border :data="variables" class="adjust-table" :row-class-name="tableRowClassName"
@select-all="select"
@select="select"
v-loading="loading" @row-click="edit" height="400px" :row-class-name="tableRowClassName">
@row-click="edit"
v-loading="loading" height="400px">
<el-table-column type="selection" width="38"/>
<el-table-column prop="num" label="ID" sortable width="60"/>
<el-table-column prop="name" :label="$t('api_test.variable_name')" sortable show-overflow-tooltip/>
......@@ -192,6 +194,9 @@
this.addParameters(this.editData);
},
edit(row) {
this.$refs.table.clearSelection();
this.$refs.table.toggleRowSelection(row);
this.selection = [row.id];
this.editData = row;
},
tableRowClassName(row) {
......
......@@ -176,7 +176,7 @@
apiCase.tags = JSON.parse(apiCase.tags);
this.$set(apiCase, 'selected', false);
}
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() != 'object') {
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() !== 'object') {
apiCase.request = JSON.parse(apiCase.request);
}
if (!apiCase.request.hashTree) {
......@@ -192,7 +192,7 @@
this.apiCaseList = [];
this.visible = false;
},
refreshModule(){
refreshModule() {
this.$emit('refreshModule');
},
runRefresh() {
......@@ -242,19 +242,23 @@
apiCase.tags = JSON.parse(apiCase.tags);
this.$set(apiCase, 'selected', false);
}
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() != 'object') {
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() !== 'object') {
apiCase.request = JSON.parse(apiCase.request);
}
if (!apiCase.request.hashTree) {
apiCase.request.hashTree = [];
}
const index = this.runData.findIndex(d => d.name === apiCase.id);
if (index !== -1) {
apiCase.active = true;
}
});
this.apiCaseList = data;
if (!this.useEnvironment && this.apiCaseList[0] && this.apiCaseList[0].request && this.apiCaseList[0].request.useEnvironment) {
this.useEnvironment = this.apiCaseList[0].request.useEnvironment;
this.environment = this.useEnvironment;
}
if (addCase && this.apiCaseList.length == 0 && !this.loaded) {
if (addCase && this.apiCaseList.length === 0 && !this.loaded) {
this.addCase();
}
});
......@@ -281,7 +285,7 @@
apiCase.tags = JSON.parse(apiCase.tags);
this.$set(apiCase, 'selected', false);
}
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() != 'object') {
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() !== 'object') {
apiCase.request = JSON.parse(apiCase.request);
}
if (!apiCase.request.hashTree) {
......@@ -320,7 +324,7 @@
if (!request.hashTree) {
request.hashTree = [];
}
if (request.backScript != null) {
if (request.backScript !== null) {
request.hashTree.push(request.backScript);
}
let uuid = getUUID();
......@@ -342,7 +346,7 @@
},
singleRun(row) {
if (this.currentApi.protocol != "DUBBO" && this.currentApi.protocol != "dubbo://" && !this.environment) {
if (this.currentApi.protocol !== "DUBBO" && this.currentApi.protocol !== "dubbo://" && !this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
......@@ -360,12 +364,12 @@
},
batchRun() {
if (this.currentApi.protocol != "DUBBO" && this.currentApi.protocol != "dubbo://" && !this.environment) {
if (this.currentApi.protocol !== "DUBBO" && this.currentApi.protocol !== "dubbo://" && !this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.envMap = new Map();
this.envMap.set(this.$store.state.projectId,this.environment);
this.envMap.set(this.$store.state.projectId, this.environment);
this.runData = [];
this.batchLoadingIds = [];
this.selectdCases = [];
......@@ -397,18 +401,18 @@
}
})
}
if (this.selectdCases.length == 0) {
if (this.selectdCases.length === 0) {
this.$warning("请选择用例!");
return;
}
// //根据不同的接口,注入不同的参数
if (this.currentApi.protocol == 'HTTP') {
if (this.currentApi.protocol === 'HTTP') {
this.valueArr.method = REQ_METHOD;
} else if (this.currentApi.protocol == 'TCP') {
} else if (this.currentApi.protocol === 'TCP') {
this.valueArr.method = TCP_METHOD;
} else if (this.currentApi.protocol == 'SQL') {
} else if (this.currentApi.protocol === 'SQL') {
this.valueArr.method = SQL_METHOD;
} else if (this.currentApi.protocol == 'DUBBO') {
} else if (this.currentApi.protocol === 'DUBBO') {
this.valueArr.method = DUBBO_METHOD;
}
......
......@@ -39,7 +39,7 @@
<template slot-scope="scope">
<!-- 为只读用户的话不能编辑 -->
<span style="cursor:pointer" v-if="isReadOnly"> {{ scope.row.num }} </span>
<el-tooltip content="编辑" v-else>
<el-tooltip :content="$t('commons.edit')" v-else>
<a style="cursor:pointer" @click="handleTestCase(scope.row)"> {{ scope.row.num }} </a>
</el-tooltip>
</template>
......@@ -67,7 +67,16 @@
sortable="custom"
prop="path"
min-width="180px"
:label="$t('api_test.definition.api_path')"
:label="'API'+ $t('api_test.definition.api_path')"
show-overflow-tooltip
:key="index"/>
<el-table-column
v-if="item.id == 'casePath'"
sortable="custom"
prop="casePath"
min-width="180px"
:label="$t('api_test.definition.request.case')+ $t('api_test.definition.api_path')"
show-overflow-tooltip
:key="index"/>
......
......@@ -2,7 +2,7 @@
<el-form :model="condition" :rules="rules" ref="httpConfig" class="ms-el-form-item__content">
<el-form-item prop="socket">
<span class="ms-env-span">{{$t('api_test.environment.socket')}}</span>
<el-input v-model="condition.socket" style="width: 80%" :placeholder="$t('api_test.request.url_description')" clearable size="small">
<el-input v-model="condition.socket" style="width: 80%" :placeholder="$t('api_test.request.url_description')" clearable size="small" :disabled="httpConfig.isMock">
<template v-slot:prepend>
<el-select v-model="condition.protocol" class="request-protocol-select" size="small">
<el-option label="http://" value="http"/>
......@@ -163,7 +163,7 @@
return value;
}
} else if (row && row.type === "PATH" && row.details.length > 0 && row.details[0].name) {
return row.details[0].value === "equals" ? this.$t("commons.adv_search.operators.equals") : this.$t("api_test.request.assertions.contains") + row.details[0].name;
return row.details[0].value === "equals" ? this.$t("commons.adv_search.operators.equals")+ row.details[0].name : this.$t("api_test.request.assertions.contains") + row.details[0].name;
} else {
return "";
}
......
......@@ -68,7 +68,7 @@ export class HttpConfig extends BaseConfig {
this.protocol = 'https';
this.port = undefined;
this.conditions = [];
this.defaultCondition = "NONE";
this.isMock = false;
this.set(options);
this.sets({headers: KeyValue}, options);
this.sets({conditions: KeyValue}, options);
......
......@@ -81,6 +81,7 @@
jsonData(data) {
let obj = {"root": data}
this.schema = obj;
this.body.jsonSchema = this.schema.root
}
}
}
......
......@@ -55,7 +55,8 @@ export const Api_Case_List = [
{id: 'num', label: "ID"},
{id: 'name', label: i18n.t('test_track.case.name')},
{id: 'priority', label: i18n.t('test_track.case.priority')},
{id: 'path', label: i18n.t('api_test.definition.api_path')},
{id: 'path', label: 'API'+i18n.t('api_test.definition.api_path')},
{id: 'casePath', label: i18n.t('api_test.definition.request.case')+i18n.t('api_test.definition.api_path')},
{id: 'tags', label: i18n.t('commons.tag')},
{id: 'createUser', label: "创建人"},
{id: 'updateTime', label: i18n.t('api_test.definition.api_last_time')},
......
......@@ -799,6 +799,11 @@ export default {
report_name_info: 'Please enter the registration name',
save_case_info: 'Please save the use case first',
reference_deleted: 'Reference deleted',
loop_name: "Loop",
loop_content: "The default is on, when there is only one request in the loop, it can be turned on/off; when there is more than one request in the loop, it can only be turned on。",
loop_return_val: "Define variable name",
loop_input_val: "Variable prefix",
loop_message: "There is more than one request in the current cycle and cannot be closed",
},
environment: {
name: "Environment Name",
......
......@@ -809,6 +809,11 @@ export default {
report_name_info: '请输入报告名称',
save_case_info: '请先保存用例',
reference_deleted: '引用已删除',
loop_name: "循环",
loop_content: "默认为开启,当循环下只有一个请求时,可以开启/关闭;当循环下超过一个请求时,则只能开启。",
loop_return_val: "定义变量名称",
loop_input_val: "变量前缀",
loop_message: "当前循环下超过一个请求,不能关闭状态",
},
environment: {
name: "环境名称",
......
......@@ -799,6 +799,11 @@ export default {
report_name_info: '請輸入報告名稱',
save_case_info: '請先保存用例',
reference_deleted: '引用已刪除',
loop_name: "循環",
loop_content: "默認為開啟,當循環下只有一個請求時,可以開啟/關閉;當循環下超過一個請求時,則只能開啟。",
loop_return_val: "定義變量名稱",
loop_input_val: "變量前綴",
loop_message: "當前循環下超過一個請求,不能關閉狀態",
},
environment: {
name: "環境名稱",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册