feat(接口测试): 处理变量
This commit is contained in:
parent
01e22c9f1a
commit
b63c136fb5
|
@ -3,7 +3,7 @@
|
|||
<span class="kv-description" v-if="description">
|
||||
{{ description }}
|
||||
</span>
|
||||
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||
<div class="kv-row" v-for="(item, index) in parameters" :key="index">
|
||||
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||
<el-col>
|
||||
<el-input v-if="!suggestions" :disabled="isReadOnly" v-model="item.name" size="small" maxlength="200"
|
||||
|
@ -39,23 +39,19 @@
|
|||
:visible.sync="itemValueVisible"
|
||||
class="advanced-item-value"
|
||||
width="70%">
|
||||
<el-tabs tab-position="top" style="height: 50vh;">
|
||||
<el-tabs tab-position="top" style="height: 50vh;" @tab-click="selectTab">
|
||||
<el-tab-pane :label="$t('api_test.request.parameters_advance_mock')">
|
||||
<el-row type="flex" :gutter="20" style="overflow-x: auto;">
|
||||
<el-col :span="6">
|
||||
<el-autocomplete
|
||||
:disabled="isReadOnly"
|
||||
size="small"
|
||||
class="input-with-autocomplete"
|
||||
v-model="itemValue"
|
||||
:fetch-suggestions="funcSearch"
|
||||
:placeholder="valueText"
|
||||
value-key="name"
|
||||
highlight-first-item
|
||||
@select="change">
|
||||
</el-autocomplete>
|
||||
<el-row type="flex" :gutter="20">
|
||||
<el-col :span="6" class="col-height">
|
||||
<div>
|
||||
<el-input size="small" v-model="filterText"
|
||||
:placeholder="$t('api_test.request.parameters_mock_filter_tips')"/>
|
||||
<el-tree class="filter-tree" ref="tree" :data="mockFuncs" :props="treeProps"
|
||||
default-expand-all @node-click="selectVariable"
|
||||
:filter-node-method="filterNode"></el-tree>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6" v-for="(itemFunc, itemIndex) in itemFuncs" :key="itemIndex">
|
||||
<el-col :span="6" v-for="(itemFunc, itemIndex) in mockVariableFuncs" :key="itemIndex">
|
||||
<div v-for="(func, funcIndex) in funcs"
|
||||
:key="`${itemIndex}-${funcIndex}`">
|
||||
<el-row>
|
||||
|
@ -75,28 +71,50 @@
|
|||
</el-tab-pane>
|
||||
<el-tab-pane label="变量">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-col :span="6" class="col-height">
|
||||
<div v-if="environment">
|
||||
<el-tree :data="environmentParams" :props="{ children: 'children', label: 'name'}"></el-tree>
|
||||
<p>{{ $t('api_test.environment.environment') }}</p>
|
||||
<el-tree :data="environmentParams" :props="treeProps" @node-click="selectVariable"></el-tree>
|
||||
</div>
|
||||
<div v-if="scenario">
|
||||
<el-tree :data="scenarioParams" :props="{ children: 'children', label: 'name'}"></el-tree>
|
||||
<p>{{ $t('api_test.scenario.scenario') }}</p>
|
||||
<el-tree :data="scenarioParams" :props="treeProps" @node-click="selectVariable"></el-tree>
|
||||
</div>
|
||||
<div v-if="preRequestParams">
|
||||
<p>{{ $t('api_test.request.parameters_pre_request') }}</p>
|
||||
<el-tree :data="preRequestParams" :props="treeProps" @node-click="selectVariable"></el-tree>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6" v-for="(itemFunc, itemIndex) in jmeterVariableFuncs" :key="itemIndex" class="col-height">
|
||||
<div>
|
||||
<div v-for="(func, funcIndex) in jmeterFuncs"
|
||||
:key="`${itemIndex}-${funcIndex}`">
|
||||
<el-row>
|
||||
<el-radio size="mini" v-model="itemFunc.name" :label="func.name"
|
||||
@change="methodChange(itemFunc, func)"/>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<el-input :placeholder="valueText" size="small"
|
||||
v-model="itemValue"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="padding-top: 10px;">
|
||||
<el-row type="flex" align="middle">
|
||||
<el-col :span="12">
|
||||
<el-button size="small" type="primary" plain @click="saveAdvanced()">
|
||||
{{ $t('commons.save') }}
|
||||
</el-button>
|
||||
<el-button size="small" type="info" plain @click="addFunc()">
|
||||
<el-button size="small" type="info" plain @click="addFunc()" v-if="currentTab === 0">
|
||||
{{ $t('api_test.request.parameters_advance_add_func') }}
|
||||
</el-button>
|
||||
<el-button size="small" type="success" plain @click="showPreview()">
|
||||
<el-button size="small" type="success" plain @click="showPreview()" v-if="currentTab === 0">
|
||||
{{ $t('api_test.request.parameters_preview') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
|
@ -110,8 +128,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {KeyValue, Scenario} from "../model/ScenarioModel";
|
||||
import {MOCKJS_FUNC} from "@/common/js/constants";
|
||||
import {HttpRequest, KeyValue, Scenario} from "../model/ScenarioModel";
|
||||
import {JMETER_FUNC, MOCKJS_FUNC} from "@/common/js/constants";
|
||||
import {calculate} from "@/business/components/api/test/model/ScenarioModel";
|
||||
|
||||
export default {
|
||||
|
@ -121,7 +139,7 @@ export default {
|
|||
keyPlaceholder: String,
|
||||
valuePlaceholder: String,
|
||||
description: String,
|
||||
items: Array,
|
||||
request: HttpRequest,
|
||||
environment: Object,
|
||||
scenario: Scenario,
|
||||
isReadOnly: {
|
||||
|
@ -131,27 +149,53 @@ export default {
|
|||
suggestions: Array
|
||||
},
|
||||
mounted() {
|
||||
if (this.request) {
|
||||
this.parameters = this.request.parameters;
|
||||
}
|
||||
if (this.scenario) {
|
||||
let variables = this.scenario.variables;
|
||||
this.scenarioParams = [
|
||||
{
|
||||
name: this.scenario.name,
|
||||
children: variables.filter(v => v.name),
|
||||
children: variables.filter(v => v.name).map(v => {
|
||||
return {name: v.name, value: '${' + v.name + '}'}
|
||||
}),
|
||||
}
|
||||
];
|
||||
}
|
||||
if (this.environment) {
|
||||
let variables = JSON.parse(this.environment.variables);
|
||||
this.environmentParams = [
|
||||
{
|
||||
name: this.environment.name,
|
||||
children: variables.filter(v => v.name),
|
||||
if (this.environment) {
|
||||
let variables = JSON.parse(this.environment.variables);
|
||||
this.environmentParams = [
|
||||
{
|
||||
name: this.environment.name,
|
||||
children: variables.filter(v => v.name).map(v => {
|
||||
return {name: v.name, value: '${' + v.name + '}'}
|
||||
}),
|
||||
}
|
||||
];
|
||||
}
|
||||
let i = this.scenario.requests.indexOf(this.request);
|
||||
this.preRequests = this.scenario.requests.slice(0, i);
|
||||
this.preRequests.forEach(r => {
|
||||
let js = r.extract.json.map(v => {
|
||||
return {name: v.variable, value: v.value}
|
||||
});
|
||||
let xs = r.extract.xpath.map(v => {
|
||||
return {name: v.variable, value: v.value}
|
||||
});
|
||||
let rx = r.extract.regex.map(v => {
|
||||
return {name: v.variable, value: v.value}
|
||||
});
|
||||
let vs = [...js, ...xs, ...rx];
|
||||
if (vs.length > 0) {
|
||||
this.preRequestParams.push({name: r.name, children: vs});
|
||||
}
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filterText: '',
|
||||
itemValueVisible: false,
|
||||
itemValue: null,
|
||||
funcs: [
|
||||
|
@ -178,14 +222,26 @@ export default {
|
|||
{name: "number"}
|
||||
],
|
||||
itemValuePreview: null,
|
||||
itemFuncs: [],
|
||||
currentFunc: "",
|
||||
mockFuncs: MOCKJS_FUNC,
|
||||
mockVariableFuncs: [],
|
||||
jmeterVariableFuncs: [],
|
||||
currentTab: 0,
|
||||
mockFuncs: MOCKJS_FUNC.map(f => {
|
||||
return {name: f.name, value: f.name}
|
||||
}),
|
||||
jmeterFuncs: JMETER_FUNC,
|
||||
environmentParams: [],
|
||||
scenarioParams: [],
|
||||
parameters: [],
|
||||
preRequests: [],
|
||||
preRequestParams: [],
|
||||
treeProps: {children: 'children', label: 'name'}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
filterText(val) {
|
||||
this.$refs.tree.filter(val);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
keyText() {
|
||||
return this.keyPlaceholder || this.$t("api_test.key");
|
||||
|
@ -197,16 +253,16 @@ export default {
|
|||
|
||||
methods: {
|
||||
remove: function (index) {
|
||||
this.items.splice(index, 1);
|
||||
this.$emit('change', this.items);
|
||||
this.parameters.splice(index, 1);
|
||||
this.$emit('change', this.parameters);
|
||||
},
|
||||
change: function () {
|
||||
let isNeedCreate = true;
|
||||
let removeIndex = -1;
|
||||
this.items.forEach((item, index) => {
|
||||
this.parameters.forEach((item, index) => {
|
||||
if (!item.name && !item.value) {
|
||||
// 多余的空行
|
||||
if (index !== this.items.length - 1) {
|
||||
if (index !== this.parameters.length - 1) {
|
||||
removeIndex = index;
|
||||
}
|
||||
// 没有空行,需要创建空行
|
||||
|
@ -214,13 +270,13 @@ export default {
|
|||
}
|
||||
});
|
||||
if (isNeedCreate) {
|
||||
this.items.push(new KeyValue());
|
||||
this.parameters.push(new KeyValue());
|
||||
}
|
||||
this.$emit('change', this.items);
|
||||
this.$emit('change', this.parameters);
|
||||
// TODO 检查key重复
|
||||
},
|
||||
isDisable: function (index) {
|
||||
return this.items.length - 1 === index;
|
||||
return this.parameters.length - 1 === index;
|
||||
},
|
||||
querySearch(queryString, cb) {
|
||||
let suggestions = this.suggestions;
|
||||
|
@ -243,6 +299,17 @@ export default {
|
|||
return (func.name.toLowerCase().indexOf(queryString.toLowerCase()) > -1);
|
||||
};
|
||||
},
|
||||
filterNode(value, data) {
|
||||
if (!value) return true;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
},
|
||||
selectVariable(node) {
|
||||
this.itemValue = node.value;
|
||||
},
|
||||
selectTab(tab) {
|
||||
this.currentTab = +tab.index;
|
||||
this.itemValue = null;
|
||||
},
|
||||
showPreview() {
|
||||
// 找到变量本身
|
||||
if (!this.itemValue) {
|
||||
|
@ -253,7 +320,7 @@ export default {
|
|||
this.itemValue = this.itemValue.substring(0, index).trim();
|
||||
}
|
||||
|
||||
this.itemFuncs.forEach(f => {
|
||||
this.mockVariableFuncs.forEach(f => {
|
||||
if (!f.name) {
|
||||
return;
|
||||
}
|
||||
|
@ -266,19 +333,19 @@ export default {
|
|||
this.itemValuePreview = calculate(this.itemValue);
|
||||
},
|
||||
methodChange(itemFunc, func) {
|
||||
let index = this.itemFuncs.indexOf(itemFunc);
|
||||
this.itemFuncs = this.itemFuncs.slice(0, index);
|
||||
let index = this.mockVariableFuncs.indexOf(itemFunc);
|
||||
this.mockVariableFuncs = this.mockVariableFuncs.slice(0, index);
|
||||
// 这里要用 deep copy
|
||||
this.itemFuncs.push(JSON.parse(JSON.stringify(func)));
|
||||
this.mockVariableFuncs.push(JSON.parse(JSON.stringify(func)));
|
||||
this.showPreview();
|
||||
},
|
||||
addFunc() {
|
||||
if (this.itemFuncs.length > 4) {
|
||||
if (this.mockVariableFuncs.length > 4) {
|
||||
this.$info(this.$t('api_test.request.parameters_advance_add_func_limit'));
|
||||
return;
|
||||
}
|
||||
if (this.itemFuncs.length > 0) {
|
||||
let func = this.itemFuncs[this.itemFuncs.length - 1];
|
||||
if (this.mockVariableFuncs.length > 0) {
|
||||
let func = this.mockVariableFuncs[this.mockVariableFuncs.length - 1];
|
||||
if (!func.name) {
|
||||
this.$warning(this.$t('api_test.request.parameters_advance_add_func_error'));
|
||||
return;
|
||||
|
@ -292,24 +359,24 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
this.itemFuncs.push({name: '', params: []});
|
||||
this.mockVariableFuncs.push({name: '', params: []});
|
||||
},
|
||||
advanced(item) {
|
||||
this.currentItem = item;
|
||||
this.itemValueVisible = true;
|
||||
this.itemValue = '';
|
||||
this.itemValuePreview = null;
|
||||
this.itemFuncs = [];
|
||||
this.mockVariableFuncs = [];
|
||||
},
|
||||
saveAdvanced() {
|
||||
this.currentItem.value = this.itemValue;
|
||||
this.itemValueVisible = false;
|
||||
this.itemFuncs = [];
|
||||
this.mockVariableFuncs = [];
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.items.length === 0) {
|
||||
this.items.push(new KeyValue());
|
||||
if (this.parameters.length === 0) {
|
||||
this.parameters.push(new KeyValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -340,4 +407,8 @@ export default {
|
|||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.col-height {
|
||||
height: 40vh;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -45,9 +45,11 @@
|
|||
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('api_test.request.parameters')" name="parameters">
|
||||
<ms-api-variable :is-read-only="isReadOnly" :items="request.parameters"
|
||||
<ms-api-variable :is-read-only="isReadOnly"
|
||||
:request="request"
|
||||
:environment="request.environment"
|
||||
:scenario="scenario"
|
||||
:extract="request.extract"
|
||||
:description="$t('api_test.request.parameters_desc')"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.headers')" name="headers">
|
||||
|
|
|
@ -368,6 +368,7 @@ export default {
|
|||
please_save_test: "Please Save Test First",
|
||||
},
|
||||
scenario: {
|
||||
scenario: "Scenario",
|
||||
dubbo: "Dubbo Config",
|
||||
config: "Scenario Config",
|
||||
input_name: "Please enter the scenario name",
|
||||
|
@ -402,7 +403,8 @@ export default {
|
|||
parameters_filter_tips: "Only support MockJs function result preview",
|
||||
parameters_advance: "Advanced parameter settings",
|
||||
parameters_preview: "Preview",
|
||||
parameters_preview_warning: "Please enter the template first",
|
||||
parameters_mock_filter_tips: "Please enter keywords to filter",
|
||||
parameters_pre_request: "Pre-request extraction",
|
||||
parameters_advance_mock: "Mock Data",
|
||||
parameters_advance_add_func: "Add Function",
|
||||
parameters_advance_add_func_limit: "Support up to 5 functions",
|
||||
|
|
|
@ -369,6 +369,7 @@ export default {
|
|||
please_save_test: "请先保存测试",
|
||||
},
|
||||
scenario: {
|
||||
scenario: "场景",
|
||||
dubbo: "Dubbo配置",
|
||||
config: "场景配置",
|
||||
input_name: "请输入场景名称",
|
||||
|
@ -405,7 +406,8 @@ export default {
|
|||
parameters_filter_tips: "只支持 MockJs 函数结果预览",
|
||||
parameters_advance: "高级参数设置",
|
||||
parameters_preview: "预览",
|
||||
parameters_preview_warning: "请先输入模版",
|
||||
parameters_mock_filter_tips: "请输入关键字进行过滤",
|
||||
parameters_pre_request: "前置请求提取",
|
||||
parameters_advance_mock: "Mock 数据",
|
||||
parameters_advance_add_func: "添加函数",
|
||||
parameters_advance_add_func_limit: "最多支持5个函数",
|
||||
|
|
|
@ -367,6 +367,7 @@ export default {
|
|||
please_save_test: "請先保存測試",
|
||||
},
|
||||
scenario: {
|
||||
scenario: "場景",
|
||||
dubbo: "Dubbo配寘",
|
||||
creator: "創建人",
|
||||
config: "場景配寘",
|
||||
|
@ -402,7 +403,8 @@ export default {
|
|||
parameters_filter_tips: "只支持MockJs函數結果預覽",
|
||||
parameters_advance: "高級參數設置",
|
||||
parameters_preview: "預覽",
|
||||
parameters_preview_warning: "請先輸入模版",
|
||||
parameters_mock_filter_tips: "請輸入關鍵字進行過濾",
|
||||
parameters_pre_request: "前置請求提取",
|
||||
parameters_advance_mock: "Mock 數據",
|
||||
parameters_advance_add_func: "添加函數",
|
||||
parameters_advance_add_func_limit: "最多支持5個函數",
|
||||
|
|
Loading…
Reference in New Issue