Merge remote-tracking branch 'origin/master'

This commit is contained in:
song.tianyang 2021-01-21 13:37:11 +08:00
commit 8c4756b3a1
19 changed files with 423 additions and 219 deletions

View File

@ -0,0 +1,20 @@
package io.metersphere.commons.utils;
import java.net.URL;
import java.net.URLConnection;
public class UrlTestUtils {
public static boolean testUrlWithTimeOut(String urlString, int timeOutMillSeconds) {
try {
URL url = new URL(urlString);
URLConnection co = url.openConnection();
co.setConnectTimeout(timeOutMillSeconds);
co.connect();
return true;
} catch (Exception e) {
LogUtil.error(e);
return false;
}
}
}

View File

@ -6,6 +6,7 @@ import io.metersphere.base.domain.TestResource;
import io.metersphere.commons.constants.ResourceStatusEnum; import io.metersphere.commons.constants.ResourceStatusEnum;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.UrlTestUtils;
import io.metersphere.config.JmeterProperties; import io.metersphere.config.JmeterProperties;
import io.metersphere.config.KafkaProperties; import io.metersphere.config.KafkaProperties;
import io.metersphere.controller.ResultHolder; import io.metersphere.controller.ResultHolder;
@ -15,6 +16,7 @@ import io.metersphere.i18n.Translator;
import io.metersphere.performance.engine.AbstractEngine; import io.metersphere.performance.engine.AbstractEngine;
import io.metersphere.performance.engine.request.StartTestRequest; import io.metersphere.performance.engine.request.StartTestRequest;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.HashMap; import java.util.HashMap;
@ -77,6 +79,12 @@ public class DockerTestEngine extends AbstractEngine {
metersphereUrl = baseInfo.getUrl(); metersphereUrl = baseInfo.getUrl();
} }
// docker 不能从 localhost 中下载文件
if (StringUtils.contains(metersphereUrl, "http://localhost")
|| !UrlTestUtils.testUrlWithTimeOut(metersphereUrl, 1000)) {
MSException.throwException(Translator.get("run_load_test_file_init_error"));
}
Map<String, String> env = new HashMap<>(); Map<String, String> env = new HashMap<>();
env.put("RATIO", "" + ratio); env.put("RATIO", "" + ratio);
env.put("RESOURCE_INDEX", "" + resourceIndex); env.put("RESOURCE_INDEX", "" + resourceIndex);
@ -123,4 +131,5 @@ public class DockerTestEngine extends AbstractEngine {
} }
}); });
} }
} }

@ -1 +1 @@
Subproject commit 7f7808c6f0457dd2df6b19a1622558f3f8122646 Subproject commit 132f406fac7fb4d841210343eb98c09f78317f18

View File

@ -34,7 +34,7 @@ edit_load_test_not_found=Cannot edit test, test not found=
run_load_test_not_found=Cannot run test, test not found= run_load_test_not_found=Cannot run test, test not found=
run_load_test_file_not_found=Unable to run test, unable to get test file meta information, test ID= run_load_test_file_not_found=Unable to run test, unable to get test file meta information, test ID=
run_load_test_file_content_not_found=Cannot run test, cannot get test file content, test ID= run_load_test_file_content_not_found=Cannot run test, cannot get test file content, test ID=
run_load_test_file_init_error=Failed to run test, failed to initialize run environment, test ID= run_load_test_file_init_error=Failed to run test, please check current end point configuration
load_test_is_running=Load test is running, please wait. load_test_is_running=Load test is running, please wait.
load_test_kafka_invalid=Kafka is not available, please check the configuration load_test_kafka_invalid=Kafka is not available, please check the configuration
cannot_edit_load_test_running=Cannot modify the running test cannot_edit_load_test_running=Cannot modify the running test

View File

@ -34,7 +34,7 @@ edit_load_test_not_found=无法编辑测试,未找到测试:
run_load_test_not_found=无法运行测试,未找到测试: run_load_test_not_found=无法运行测试,未找到测试:
run_load_test_file_not_found=无法运行测试无法获取测试文件元信息测试ID run_load_test_file_not_found=无法运行测试无法获取测试文件元信息测试ID
run_load_test_file_content_not_found=无法运行测试无法获取测试文件内容测试ID run_load_test_file_content_not_found=无法运行测试无法获取测试文件内容测试ID
run_load_test_file_init_error=无法运行测试,初始化运行环境失败测试ID run_load_test_file_init_error=无法运行测试,请检查当前站点配置
load_test_is_running=测试正在运行, 请等待 load_test_is_running=测试正在运行, 请等待
load_test_kafka_invalid=Kafka 不可用,请检查配置 load_test_kafka_invalid=Kafka 不可用,请检查配置
cannot_edit_load_test_running=不能修改正在运行的测试 cannot_edit_load_test_running=不能修改正在运行的测试

View File

@ -34,7 +34,7 @@ edit_load_test_not_found=無法編輯測試,未找到測試:
run_load_test_not_found=無法運行測試,未找到測試: run_load_test_not_found=無法運行測試,未找到測試:
run_load_test_file_not_found=無法運行測試無法獲取測試文件元信息測試ID run_load_test_file_not_found=無法運行測試無法獲取測試文件元信息測試ID
run_load_test_file_content_not_found=無法運行測試無法獲取測試文件內容測試ID run_load_test_file_content_not_found=無法運行測試無法獲取測試文件內容測試ID
run_load_test_file_init_error=無法運行測試,初始化運行環境失敗測試ID run_load_test_file_init_error=無法運行測試,請檢查當前站點配置
load_test_is_running=測試正在運行, 請等待 load_test_is_running=測試正在運行, 請等待
load_test_kafka_invalid=Kafka 不可用,請檢查配置 load_test_kafka_invalid=Kafka 不可用,請檢查配置
cannot_edit_load_test_running=不能修改正在運行的測試 cannot_edit_load_test_running=不能修改正在運行的測試

View File

@ -38,7 +38,6 @@
"vue-echarts": "^4.1.0", "vue-echarts": "^4.1.0",
"vue-float-action-button": "^0.6.6", "vue-float-action-button": "^0.6.6",
"vue-i18n": "^8.15.3", "vue-i18n": "^8.15.3",
"vue-input-tag": "^2.0.7",
"vue-jsonpath-picker": "^1.1.5", "vue-jsonpath-picker": "^1.1.5",
"vue-papa-parse": "^2.0.0", "vue-papa-parse": "^2.0.0",
"vue-pdf": "^4.2.0", "vue-pdf": "^4.2.0",

View File

@ -119,6 +119,9 @@
buildNodePath(node, {path: ''}, moduleOptions); buildNodePath(node, {path: ''}, moduleOptions);
}); });
this.$emit('setModuleOptions', moduleOptions); this.$emit('setModuleOptions', moduleOptions);
if (this.$refs.nodeTree) {
this.$refs.nodeTree.filter(this.condition.filterText);
}
} }
}); });
}, },
@ -142,6 +145,7 @@
}, (error) => { }, (error) => {
this.list(); this.list();
}); });
}, },
remove(nodeIds) { remove(nodeIds) {
this.$post("/api/automation/module/delete", nodeIds, () => { this.$post("/api/automation/module/delete", nodeIds, () => {

View File

@ -72,7 +72,7 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="7"> <el-col :span="7">
<el-form-item label="Tag" prop="tags"> <el-form-item :label="$t('api_test.automation.tag')" prop="tags">
<ms-input-tag :currentScenario="currentScenario" ref="tag"/> <ms-input-tag :currentScenario="currentScenario" ref="tag"/>
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

@ -1,68 +1,170 @@
<template> <template>
<input-tag v-model="data" placeholder="输入回车添加标签" class="ms-tag-input ms-input-div ms-input-tag-wrapper ms-input ms-input-remove"></input-tag> <div
class="el-input-tag input-tag-wrapper"
:class="[size ? 'el-input-tag--' + size : '']"
style="height: auto"
@click="foucusTagInput">
<el-tag
v-for="(tag, idx) in innerTags"
v-bind="$attrs"
type="info"
:key="tag"
:size="size"
:closable="!readOnly"
:disable-transitions="false"
@close="remove(idx)">
{{tag}}
</el-tag>
<input
v-if="!readOnly"
class="tag-input el-input"
v-model="newTag"
placeholder="输入回车添加"
@keydown.delete.stop="removeLastTag"
@keydown="addNew"
@blur="addNew"/>
</div>
</template> </template>
<script> <script>
import InputTag from 'vue-input-tag'
export default { export default {
name: "MsInputTag", name: 'MsInputTag',
components: {InputTag}, props: {
props: {currentScenario: {}}, currentScenario: {},
addTagOnKeys: {
type: Array,
default: () => [13, 188, 9]
},
readOnly: {
type: Boolean,
default: false
},
size: {type: String, default: "small"}
},
created() { created() {
if (!this.currentScenario.tags) { if (!this.currentScenario.tags) {
this.currentScenario.tags = []; this.currentScenario.tags = [];
} }
this.data = this.currentScenario.tags;
}, },
data() { data() {
return { return {
data: [], newTag: '',
innerTags: this.currentScenario.tags ? [...this.currentScenario.tags] : []
} }
}, },
watch: { watch: {
data() { innerTags() {
this.currentScenario.tags = this.data; this.currentScenario.tags = this.innerTags;
} }
}, },
methods: {} methods: {
foucusTagInput() {
if (this.readOnly || !this.$el.querySelector('.tag-input')) {
console.log()
} else {
this.$el.querySelector('.tag-input').focus()
}
},
addNew(e) {
if (e && (!this.addTagOnKeys.includes(e.keyCode)) && (e.type !== 'blur')) {
return
}
if (e) {
e.stopPropagation()
e.preventDefault()
}
let addSuucess = false
if (this.newTag.includes(',')) {
this.newTag.split(',').forEach(item => {
if (this.addTag(item.trim())) {
addSuucess = true
}
})
} else {
if (this.addTag(this.newTag.trim())) {
addSuucess = true
}
}
if (addSuucess) {
this.tagChange()
this.newTag = ''
}
},
addTag(tag) {
tag = tag.trim()
if (tag && !this.innerTags.includes(tag)) {
this.innerTags.push(tag)
return true
}
return false
},
remove(index) {
this.innerTags.splice(index, 1)
this.tagChange()
},
removeLastTag() {
if (this.newTag) {
return
}
this.innerTags.pop()
this.tagChange()
},
tagChange() {
this.$emit('input', this.innerTags)
}
}
} }
</script> </script>
<style scoped> <style scoped>
.input-tag-wrapper {
.ms-input-tag-wrapper >>> .vue-input-tag-wrapper { position: relative;
border-radius: 2px; font-size: 14px;
border: 1px solid #a5d24a;
color: #909399;
display: inline-block;
}
.ms-input-remove >>> .remove {
color: #909399;
}
.ms-input-div {
border-radius: 4px;
}
.ms-input >>> .input-tag {
display: inline-block;
font-size: 12px;
min-width: auto;
border-width: 1px;
border-style: solid;
border-radius: 4px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
white-space: nowrap;
background-color: #fff; background-color: #fff;
border-color: #909399; background-image: none;
color: #909399; border-radius: 4px;
width: auto; border: 1px solid #dcdfe6;
box-sizing: border-box;
color: #606266;
display: inline-block;
outline: none;
padding: 0 10px 0 5px;
transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
width: 100%;
}
height: 23px; .el-tag {
padding: 0 5px; margin-right: 4px;
line-height: 19px; }
.tag-input {
background: transparent;
border: 0;
color: #303133;
font-size: 12px;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
outline: none;
padding-left: 0;
width: 100px;
}
.el-input-tag {
height: 40px;
line-height: 40px;
}
.el-input-tag--mini {
height: 28px;
line-height: 28px;
font-size: 12px;
}
.el-input-tag--small {
line-height: 30px;
}
.el-input-tag--medium {
height: 36px;
line-height: 36px;
} }
</style> </style>

View File

@ -33,6 +33,9 @@
}, },
created() { created() {
this.getExecResult(); this.getExecResult();
if (this.apiItem.isActive) {
this.isActive = true;
}
}, },
methods: { methods: {
getExecResult() { getExecResult() {

View File

@ -40,7 +40,9 @@
</el-col> </el-col>
<el-col :span="4"> <el-col :span="4">
<ms-input-tag class="tag-item" :currentScenario="apiCase" ref="tag" @keyup.enter.native="saveTestCase(apiCase)"/> <div class="tag-item">
<ms-input-tag :currentScenario="apiCase" ref="tag" @keyup.enter.native="saveTestCase(apiCase)"/>
</div>
</el-col> </el-col>
<el-col :span="4"> <el-col :span="4">
@ -269,8 +271,9 @@
return true; return true;
} }
}, },
showExecResult(data) { showExecResult(item) {
this.$emit('showExecResult', data); item.active = false;
item.isActive = true;
}, },
getBodyUploadFiles(row) { getBodyUploadFiles(row) {
let bodyUploadFiles = []; let bodyUploadFiles = [];
@ -325,6 +328,6 @@
} }
.tag-item { .tag-item {
margin-right: 30px; margin-right: 20px;
} }
</style> </style>

View File

@ -53,12 +53,12 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="8"> <el-col :span="12">
<el-form-item :label="$t('commons.tag')" prop="tag"> <el-form-item :label="$t('commons.tag')" prop="tag">
<ms-input-tag :currentScenario="basicForm" ref="tag"/> <ms-input-tag :currentScenario="basicForm" ref="tag"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="16"> <el-col :span="12">
<el-form-item :label="$t('commons.description')" prop="description"> <el-form-item :label="$t('commons.description')" prop="description">
<el-input class="ms-http-textarea" <el-input class="ms-http-textarea"
v-model="basicForm.description" v-model="basicForm.description"

View File

@ -3,7 +3,7 @@
<div class="card-container"> <div class="card-container">
<el-card class="card-content" v-loading="httpForm.loading"> <el-card class="card-content" v-loading="httpForm.loading">
<el-form :model="httpForm" :rules="rule" ref="httpForm" :inline="true" label-position="right"> <el-form :model="httpForm" :rules="rule" ref="httpForm" label-width="80px" label-position="right">
<!-- 操作按钮 --> <!-- 操作按钮 -->
<div style="float: right;margin-right: 20px"> <div style="float: right;margin-right: 20px">
<el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button> <el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button>
@ -34,6 +34,20 @@
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="userId">
<el-select v-model="httpForm.userId"
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
class="ms-http-select">
<el-option
v-for="item in maintainerOptions"
:key="item.id"
:label="item.id + ' (' + item.name + ')'"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :label="$t('test_track.module.module')" prop="moduleId"> <el-form-item :label="$t('test_track.module.module')" prop="moduleId">
<el-select class="ms-http-select" size="small" v-model="httpForm.moduleId"> <el-select class="ms-http-select" size="small" v-model="httpForm.moduleId">
<div v-if="moduleOptions.length>0"> <div v-if="moduleOptions.length>0">
@ -51,21 +65,8 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="userId"> <el-col :span="7">
<el-select v-model="httpForm.userId"
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
class="ms-http-select">
<el-option
v-for="item in maintainerOptions"
:key="item.id"
:label="item.id + ' (' + item.name + ')'"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="$t('commons.status')" prop="status"> <el-form-item :label="$t('commons.status')" prop="status">
<el-select class="ms-http-select" size="small" v-model="httpForm.status"> <el-select class="ms-http-select" size="small" v-model="httpForm.status">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/> <el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
@ -73,7 +74,6 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<el-form-item :label="$t('commons.tag')" prop="tag"> <el-form-item :label="$t('commons.tag')" prop="tag">
@ -109,167 +109,167 @@
<script> <script>
import MsApiRequestForm from "../request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import MsResponseText from "../response/ResponseText"; import MsResponseText from "../response/ResponseText";
import {WORKSPACE_ID} from '../../../../../../common/js/constants'; import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {API_STATUS, REQ_METHOD} from "../../model/JsonData"; import {API_STATUS, REQ_METHOD} from "../../model/JsonData";
import {KeyValue} from "../../model/ApiTestModel"; import {KeyValue} from "../../model/ApiTestModel";
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag"; import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor"; import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor";
export default { export default {
name: "MsAddCompleteHttpApi", name: "MsAddCompleteHttpApi",
components: {MsJsr233Processor, MsResponseText, MsApiRequestForm, MsInputTag}, components: {MsJsr233Processor, MsResponseText, MsApiRequestForm, MsInputTag},
data() { data() {
let validateURL = (rule, value, callback) => { let validateURL = (rule, value, callback) => {
if (!this.httpForm.path.startsWith("/") || this.httpForm.path.match(/\s/) != null) { if (!this.httpForm.path.startsWith("/") || this.httpForm.path.match(/\s/) != null) {
callback(this.$t('api_test.definition.request.path_valid_info')); callback(this.$t('api_test.definition.request.path_valid_info'));
}
callback();
};
return {
rule: {
name: [
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
{max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
],
path: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}, {
validator: validateURL,
trigger: 'blur'
}],
userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
moduleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
},
httpForm: {environmentId: "", tags: []},
isShowEnable: false,
maintainerOptions: [],
currentModule: {},
reqOptions: REQ_METHOD,
options: API_STATUS,
}
},
props: {moduleOptions: {}, request: {}, response: {}, basisData: {}},
methods: {
runTest() {
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('runTest', this.httpForm);
} else {
return false;
} }
}) callback();
}, };
getMaintainerOptions() { return {
let workspaceId = localStorage.getItem(WORKSPACE_ID); rule: {
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => { name: [
this.maintainerOptions = response.data; {required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
}); {max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
}, ],
setParameter() { path: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}, {
this.httpForm.modulePath = this.getPath(this.httpForm.moduleId); validator: validateURL,
this.request.path = this.httpForm.path; trigger: 'blur'
this.request.method = this.httpForm.method; }],
this.httpForm.request.useEnvironment = undefined; userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
if (this.httpForm.tags instanceof Array) { moduleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
this.httpForm.tags = JSON.stringify(this.httpForm.tags); status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
},
httpForm: {environmentId: "", tags: []},
isShowEnable: false,
maintainerOptions: [],
currentModule: {},
reqOptions: REQ_METHOD,
options: API_STATUS,
} }
}, },
saveApi() { props: {moduleOptions: {}, request: {}, response: {}, basisData: {}},
this.$refs['httpForm'].validate((valid) => { methods: {
if (valid) { runTest() {
this.setParameter(); this.$refs['httpForm'].validate((valid) => {
this.$emit('saveApi', this.httpForm); if (valid) {
} else { this.setParameter();
return false; this.$emit('runTest', this.httpForm);
} } else {
}) return false;
},
createModules() {
this.$emit("createRootModelInTree");
},
getPath(id) {
if (id === null) {
return null;
}
let path = this.moduleOptions.filter(function (item) {
return item.id === id ? item.path : "";
});
return path[0].path;
},
urlChange() {
if (!this.httpForm.path || this.httpForm.path.indexOf('?') === -1) return;
let url = this.getURL(this.addProtocol(this.httpForm.path));
if (url) {
this.httpForm.path = decodeURIComponent(this.httpForm.path.substr(0,this.httpForm.path.indexOf("?")));
}
},
addProtocol(url) {
if (url) {
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
return "https://" + url;
}
}
return url;
},
getURL(urlStr) {
try {
let url = new URL(urlStr);
url.searchParams.forEach((value, key) => {
if (key && value) {
this.request.arguments.splice(0, 0, new KeyValue({name: key, required: false, value: value}));
} }
})
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.maintainerOptions = response.data;
}); });
},
setParameter() {
this.httpForm.modulePath = this.getPath(this.httpForm.moduleId);
this.request.path = this.httpForm.path;
this.request.method = this.httpForm.method;
this.httpForm.request.useEnvironment = undefined;
if (this.httpForm.tags instanceof Array) {
this.httpForm.tags = JSON.stringify(this.httpForm.tags);
}
},
saveApi() {
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('saveApi', this.httpForm);
} else {
return false;
}
})
},
createModules() {
this.$emit("createRootModelInTree");
},
getPath(id) {
if (id === null) {
return null;
}
let path = this.moduleOptions.filter(function (item) {
return item.id === id ? item.path : "";
});
return path[0].path;
},
urlChange() {
if (!this.httpForm.path || this.httpForm.path.indexOf('?') === -1) return;
let url = this.getURL(this.addProtocol(this.httpForm.path));
if (url) {
this.httpForm.path = decodeURIComponent(this.httpForm.path.substr(0, this.httpForm.path.indexOf("?")));
}
},
addProtocol(url) {
if (url) {
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
return "https://" + url;
}
}
return url; return url;
} catch (e) { },
this.$error(this.$t('api_test.request.url_invalid'), 2000); getURL(urlStr) {
} try {
let url = new URL(urlStr);
url.searchParams.forEach((value, key) => {
if (key && value) {
this.request.arguments.splice(0, 0, new KeyValue({name: key, required: false, value: value}));
}
});
return url;
} catch (e) {
this.$error(this.$t('api_test.request.url_invalid'), 2000);
}
},
}, },
},
created() { created() {
this.getMaintainerOptions(); this.getMaintainerOptions();
if (!this.basisData.environmentId) { if (!this.basisData.environmentId) {
this.basisData.environmentId = ""; this.basisData.environmentId = "";
}
this.httpForm = JSON.parse(JSON.stringify(this.basisData));
} }
this.httpForm = JSON.parse(JSON.stringify(this.basisData));
} }
}
</script> </script>
<style scoped> <style scoped>
.base-info .el-form-item { .base-info .el-form-item {
width: 100%; width: 100%;
} }
.base-info .el-form-item >>> .el-form-item__content { .base-info .el-form-item >>> .el-form-item__content {
width: 80%; width: 80%;
} }
.base-info .ms-http-select { .base-info .ms-http-select {
width: 100%; width: 100%;
} }
.tip { .tip {
padding: 3px 5px; padding: 3px 5px;
font-size: 16px; font-size: 16px;
border-radius: 4px; border-radius: 4px;
border-left: 4px solid #783887; border-left: 4px solid #783887;
margin: 20px 0; margin: 20px 0;
} }
.ms-http-textarea { .ms-http-textarea {
width: 400px; width: 100%;
} }
.ms-left-cell { .ms-left-cell {
margin-top: 100px; margin-top: 100px;
} }
.ms-left-buttion { .ms-left-buttion {
margin: 6px 0px 8px 30px; margin: 6px 0px 8px 30px;
} }
</style> </style>

View File

@ -0,0 +1,45 @@
<template>
<el-form class="tcp" :model="config" :rules="rules" ref="config" label-width="120px" :disabled="isReadOnly"
size="small">
<el-row :gutter="10">
<el-col :span="16">
<el-form-item :label="$t('api_test.request.tcp.server')" prop="server">
<el-input v-model="config.server" maxlength="300" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="$t('api_test.request.tcp.port')" prop="port" label-width="60px">
<el-input-number v-model="config.port" controls-position="right" :min="0" :max="65535" :controls="false"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
name: "EnvironmentTcpConfig",
props: {
config: {},
isReadOnly: {
type: Boolean,
default: false
},
},
data() {
return {
rules: {}
}
},
}
</script>
<style scoped>
.tcp >>> .el-input-number {
width: 100%;
}
</style>

View File

@ -126,6 +126,9 @@
buildNodePath(node, {path: ''}, moduleOptions); buildNodePath(node, {path: ''}, moduleOptions);
}); });
this.$emit('setModuleOptions', moduleOptions); this.$emit('setModuleOptions', moduleOptions);
if (this.$refs.nodeTree) {
this.$refs.nodeTree.filter(this.condition.filterText);
}
} }
}); });
}, },

View File

@ -101,10 +101,10 @@
this.mode = mode; this.mode = mode;
}, },
setBodyType() { setBodyType() {
if (!this.response.headers) { if (!this.response.responseResult.headers) {
return; return;
} }
if (this.response.headers.indexOf("Content-Type: application/json") > 0) { if (this.response.responseResult.headers.indexOf("Content-Type: application/json") > 0) {
if (this.$refs.modeDropdown) { if (this.$refs.modeDropdown) {
this.$refs.modeDropdown.handleCommand(BODY_FORMAT.JSON); this.$refs.modeDropdown.handleCommand(BODY_FORMAT.JSON);
this.msCodeReload(); this.msCodeReload();

View File

@ -137,7 +137,15 @@ export default {
return false; return false;
}, },
filter(val) { filter(val) {
this.$refs.tree.filter(val); if (!val) {
val = this.filterText;
} else {
// condition filterText
this.filterText = val;
}
this.$nextTick(() => {
this.$refs.tree.filter(val);
});
}, },
nodeExpand(data) { nodeExpand(data) {
if (data.id) { if (data.id) {
@ -149,10 +157,15 @@ export default {
this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1); this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1);
} }
}, },
edit(node, data) { edit(node, data, isAppend) {
this.$set(data, 'isEdit', true); this.$set(data, 'isEdit', true);
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.nameInput.focus(); this.$refs.nameInput.focus();
if (!isAppend) {
this.$nextTick(() => {
this.filter(this.filterText);
});
}
}); });
}, },
append(node, data) { append(node, data) {
@ -166,7 +179,7 @@ export default {
this.$set(data, 'children', []) this.$set(data, 'children', [])
} }
data.children.push(newChild); data.children.push(newChild);
this.edit(node, newChild); this.edit(node, newChild, true);
node.expanded = true; node.expanded = true;
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.nameInput.focus(); this.$refs.nameInput.focus();

View File

@ -51,6 +51,9 @@
if (this.projectId) { if (this.projectId) {
this.result = this.$get("/case/node/list/" + this.projectId, response => { this.result = this.$get("/case/node/list/" + this.projectId, response => {
this.treeNodes = response.data; this.treeNodes = response.data;
if (this.$refs.nodeTree) {
this.$refs.nodeTree.filter();
}
}); });
} }
}, },