feat(接口自动化): 内置函数构造器优化,参数设置支持选择提取参数

--story=1004200 --user=周骏弘 内置函数构造器优化 https://www.tapd.cn/55049933/s/1082243
This commit is contained in:
junhong 2021-12-20 10:05:33 +08:00 committed by 刘瑞斌
parent 4b8aa3c44b
commit 9685d988d0
21 changed files with 517 additions and 88 deletions

View File

@ -196,9 +196,10 @@
@node-expand="nodeExpand"
@node-collapse="nodeCollapse"
:allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" draggable ref="stepTree" v-if="showHideTree">
<span class="custom-tree-node father" slot-scope="{ node, data}" style="width: 96%">
<span class="custom-tree-node father" slot-scope="{node, data}" style="width: 96%">
<!-- 步骤组件-->
<ms-component-config
:scenario-definition="scenarioDefinition"
:message="message"
:type="data.type"
:scenario="data"
@ -218,7 +219,8 @@
@runScenario="runDebug"
@stopScenario="stop"
@setDomain="setDomain"
@openScenario="openScenario"/>
@openScenario="openScenario"
@editScenarioAdvance="editScenarioAdvance"/>
</span>
</el-tree>
</div>
@ -244,6 +246,12 @@
</el-row>
</div>
<!--参数设置-->
<ms-api-variable-advance ref="scenarioVariableAdvance"
:append-to-body="true"
:current-item="currentItem"
:scenario-definition="scenarioDefinition"/>
<!--接口列表-->
<scenario-api-relevance @save="pushApiOrCase" @close="setHideBtn" ref="scenarioApiRelevance" v-if="type!=='detail'"/>
@ -323,6 +331,7 @@
@openScenario="openScenario"
@runScenario="runDebug"
@stopScenario="stop"
@editScenarioAdvance="editScenarioAdvance"
ref="maximizeScenario"/>
</ms-drawer>
<ms-change-history ref="changeHistory"/>
@ -388,7 +397,8 @@ export default {
MsDrawer: () => import("../../../common/components/MsDrawer"),
MsSelectTree: () => import("../../../common/select-tree/SelectTree"),
MsChangeHistory: () => import("../../../history/ChangeHistory"),
MsTaskCenter: () => import("../../../task/TaskCenter")
MsTaskCenter: () => import("../../../task/TaskCenter"),
MsApiVariableAdvance: () => import("./../../definition/components/ApiVariableAdvance"),
},
data() {
return {
@ -477,6 +487,7 @@ export default {
showFollow: false,
envGroupId: "",
environmentType: ENV_TYPE.JSON,
currentItem: {},
versionData: []
}
},
@ -1400,7 +1411,7 @@ export default {
}
this.$store.state.scenarioMap.set(this.currentScenario.id, 0);
//
this.$store.state.scenarioMap.set("currentScenarioId", this.currentScenario.variables);
this.$store.state.scenarioMap.set("currentScenarioVariables", this.currentScenario.variables);
})
}
},
@ -1650,6 +1661,11 @@ export default {
}
}
},
editScenarioAdvance(data) {
//
this.currentItem = data;
this.$refs.scenarioVariableAdvance.open();
},
getVersionHistory() {
this.$get('/api/automation/versions/' + this.currentScenario.id, response => {
this.versionData = response.data;

View File

@ -30,7 +30,7 @@
</span>
<div class="header-right" @click.stop>
<div v-if="!ifFromVariableAdvance" class="header-right" @click.stop>
<slot name="message"></slot>
<slot name="debugStepCode"></slot>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn">
@ -118,7 +118,11 @@ export default {
return true
}
},
title: String
title: String,
ifFromVariableAdvance: {
type: Boolean,
default: false,
}
},
watch: {
'$store.state.selectStep': function () {

View File

@ -11,7 +11,8 @@
:background-color="displayColor.backgroundColor"
:is-max="isMax"
:show-btn="showBtn"
:title="displayTitle">
:title="displayTitle"
:if-from-variable-advance="ifFromVariableAdvance">
<template v-slot:afterTitle v-if="(request.refType==='API'|| request.refType==='CASE')&&isSameSpace">
<span v-if="isShowNum" @click="clickResource(request)">{{ " ID: " + request.num + "" }}</span>
@ -38,7 +39,7 @@
{{ request.requestResult[0].success && reqSuccess ? 'success' : 'error' }}
</span>
</template>
<template v-slot:button>
<template v-slot:button v-if="!ifFromVariableAdvance">
<el-tooltip :content="$t('api_test.run')" placement="top" v-if="!loading">
<el-button @click="run" icon="el-icon-video-play" style="padding: 5px" class="ms-btn" size="mini" circle/>
</el-tooltip>
@ -53,10 +54,14 @@
<!--请求内容-->
<template v-slot:request>
<legend style="width: 100%">
<div v-if="!ifFromVariableAdvance">
<customize-req-info :is-customize-req="isCustomizeReq" :request="request" @setDomain="setDomain"/>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form
v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
:scenario-definition="scenarioDefinition"
@editScenarioAdvance="editScenarioAdvance"
:isShowEnable="true"
:referenced="true"
:headers="request.headers "
@ -84,6 +89,8 @@
:request="request"
:is-read-only="isCompReadOnly"
:showScript="false"/>
</div>
</legend>
</template>
<!-- 执行结果内容 -->
@ -139,6 +146,7 @@ import ApiBaseComponent from "../common/ApiBaseComponent";
import ApiResponseComponent from "./ApiResponseComponent";
import CustomizeReqInfo from "@/business/components/api/automation/scenario/common/CustomizeReqInfo";
import TemplateComponent from "@/business/components/track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
import {ENV_TYPE} from "@/common/js/constants";
import {getUrl} from "@/business/components/api/automation/scenario/component/urlhelper";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
@ -169,7 +177,13 @@ export default {
envMap: Map,
message: String,
environmentGroupId: String,
environmentType: String
environmentType: String,
scenarioDefinition: Array,
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
components: {
TemplateComponent,
@ -697,7 +711,10 @@ export default {
}
}
});
}
},
editScenarioAdvance(data) {
this.$emit('editScenarioAdvance', data);
},
}
}
</script>

View File

@ -13,6 +13,7 @@
:show-btn="showBtn"
color="#606266"
background-color="#F4F4F5"
:if-from-variable-advance="ifFromVariableAdvance"
:title="$t('commons.scenario')">
<template v-slot:afterTitle v-if="isSameSpace">
@ -40,14 +41,14 @@
{{ getCode() }}
</span>
</template>
<template v-slot:scenarioEnable>
<template v-slot:scenarioEnable v-if="!ifFromVariableAdvance">
<el-tooltip :content="$t('commons.enable_scene_info')" placement="top">
<el-checkbox v-model="scenario.environmentEnable" @change="checkEnv" :disabled="scenario.disabled">
{{ $t('commons.enable_scene') }}
</el-checkbox>
</el-tooltip>
</template>
<template v-slot:button>
<template v-slot:button v-if="!ifFromVariableAdvance">
<el-tooltip :content="$t('api_test.run')" placement="top" v-if="!scenario.run">
<el-button :disabled="!scenario.enable" @click="run" icon="el-icon-video-play" style="padding: 5px" class="ms-btn" size="mini" circle/>
</el-tooltip>
@ -93,7 +94,11 @@ export default {
projectList: Array,
environmentType: String,
environmentGroupId: String,
envMap: Map
envMap: Map,
ifFromVariableAdvance: {
type: Boolean,
default: false,
}
},
watch: {
message() {

View File

@ -27,6 +27,8 @@
:env-map="envMap"
:message="message"
:api-id="apiId"
:scenario-definition="scenarioDefinition"
:if-from-variable-advance="ifFromVariableAdvance"
@suggestClick="suggestClick(node)"
@remove="remove"
@runScenario="runScenario"
@ -35,6 +37,8 @@
@refReload="refReload"
@openScenario="openScenario"
@setDomain="setDomain"
@savePreParams="savePreParams"
@editScenarioAdvance="editScenarioAdvance"
/>
</keep-alive>
</div>
@ -90,7 +94,13 @@ export default {
projectList: Array,
envMap: Map,
environmentType: String,
envGroupId: String
envGroupId: String,
scenarioDefinition: Array,
//
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
return {
@ -211,7 +221,6 @@ export default {
},
remove(row, node) {
this.$emit('remove', row, node);
},
copyRow(row, node) {
this.$emit('copyRow', row, node);
@ -234,7 +243,13 @@ export default {
},
setDomain() {
this.$emit("setDomain");
}
},
savePreParams(data) {
this.$emit("savePreParams", data);
},
editScenarioAdvance(data) {
this.$emit('editScenarioAdvance', data);
},
}
}
</script>

View File

@ -9,6 +9,7 @@
:show-btn="showBtn"
color="#E6A23C"
background-color="#FCF6EE"
:if-from-variable-advance="ifFromVariableAdvance"
:title="$t('api_test.automation.if_controller')">
<template v-slot:headerLeft>
@ -61,6 +62,10 @@
type: Boolean,
default: false,
},
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
return {
@ -133,7 +138,7 @@
if (value.indexOf("empty") > 0 && !!this.controller.value) {
this.controller.value = "";
}
}
},
},
computed: {
hasEmptyOperator() {

View File

@ -9,6 +9,7 @@
:is-max="isMax"
:show-btn="showBtn"
:background-color="backgroundColor"
:if-from-variable-advance="ifFromVariableAdvance"
:title="title" v-loading="loading">
<legend style="width: 100%">
@ -73,6 +74,10 @@ export default {
color: String,
backgroundColor: String,
node: {},
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
watch: {
message() {

View File

@ -1,7 +1,7 @@
<template>
<div>
<ms-run :debug="true" :environment="envMap" :reportId="reportId" :runMode="'DEFINITION'" :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">
<api-base-component :if-from-variable-advance="ifFromVariableAdvance" @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}" style="margin-right: 10px" v-if="!isMax"/>
@ -113,6 +113,10 @@ export default {
default: false,
},
envMap: Map,
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
return {

View File

@ -9,6 +9,7 @@
:show-btn="showBtn"
color="#6D317C"
background-color="#FCF6EE"
:if-from-variable-advance="ifFromVariableAdvance"
:title="$t('api_test.automation.transcation_controller')">
<template v-slot:debugStepCode>
<span v-if="node.data.testing" class="ms-test-running">
@ -52,6 +53,10 @@ export default {
type: Boolean,
default: false,
},
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
watch: {
message() {

View File

@ -88,7 +88,9 @@
:node="selectedNode"
:project-list="projectList"
:env-map="projectEnvMap"
:scenario-definition="scenarioDefinition"
:draggable="false"
@editScenarioAdvance="editScenarioAdvance"
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick" @refReload="refReload" @openScenario="openScenario"
v-if="selectedTreeNode && selectedNode"/>
<!-- 请求下还有的子步骤-->
@ -899,7 +901,10 @@ export default {
},
stopScenario(){
this.$emit('stopScenario');
}
},
editScenarioAdvance(data) {
this.$emit('editScenarioAdvance', data);
},
}
}
</script>

View File

@ -63,7 +63,7 @@
</el-col>
</el-row>
</div>
<ms-api-variable-advance :append-to-body="appendToBody" :current-item="currentItem" :parameters="keyValues" ref="variableAdvance"/>
<ms-api-variable-advance :scenario-definition="scenarioDefinition" :append-to-body="appendToBody" :current-item="currentItem" :parameters="keyValues" ref="variableAdvance"/>
</div>
</template>
@ -106,6 +106,7 @@
return false;
}
},
scenarioDefinition: Array
},
data() {
return {
@ -135,7 +136,12 @@
methods: {
advanced(item) {
this.currentItem = item;
this.$refs.variableAdvance.open();
//
if(this.scenarioDefinition != undefined){
this.$emit('editScenarioAdvance', this.currentItem);
}else{
this.$refs.variableAdvance.open();
}
},
funcFilter(queryString) {
return (func) => {

View File

@ -92,7 +92,9 @@
:append-to-body="appendDialogToBody"
:parameters="parameters"
:current-item="currentItem"
:scenario-definition="scenarioDefinition"
@advancedRefresh="reload"/>
<ms-api-variable-json :append-to-body="appendDialogToBody" ref="variableJson" @callback="callback"/>
<api-variable-setting :append-to-body="appendDialogToBody"
@ -141,7 +143,8 @@ export default {
default: true
},
suggestions: Array,
withMorSetting: Boolean
withMorSetting: Boolean,
scenarioDefinition: Array,
},
data() {
return {
@ -252,10 +255,14 @@ export default {
this.$refs.variableJson.open(item);
this.currentItem = item;
} else {
this.$refs.variableAdvance.open();
this.currentItem = item;
//
if(this.scenarioDefinition != undefined){
this.$emit('editScenarioAdvance', this.currentItem);
}else{
this.$refs.variableAdvance.open();
}
}
},
typeChange(item) {
if (item.type === 'file') {
@ -289,7 +296,7 @@ export default {
callback(item) {
this.currentItem.value = item;
this.currentItem = null;
}
},
},
created() {
if (this.parameters.length === 0 || this.parameters[this.parameters.length - 1].name) {

View File

@ -2,9 +2,9 @@
<el-dialog :title="$t('api_test.request.parameters_advance')"
:visible.sync="itemValueVisible"
:append-to-body="appendToBody"
:fullscreen="dialogVisible"
class="advanced-item-value"
width="100%"
:fullscreen="dialogVisible">
width="100%">
<el-tabs tab-position="top" style="height: 50vh;" @tab-click="selectTab">
<el-tab-pane :label="$t('api_test.request.parameters_advance_mock')">
@ -38,7 +38,7 @@
</el-tab-pane>
<!--场景自定义变量-->
<el-tab-pane :label="$t('api_test.automation.scenario_total')" name="variable">
<el-tab-pane :label="$t('api_test.automation.scenario_total')" name="variable" v-if="scenarioDefinition != undefined">
<div>
<el-row style="margin-bottom: 10px">
<div style="float: left">
@ -93,10 +93,6 @@
<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="18" class="col-height">
<div>
@ -112,34 +108,105 @@
</el-tab-pane>
<!--前置返回-->
<el-tab-pane :label="$t('api_test.definition.request.pre_return')" v-if="scenarioDefinition != undefined">
<ms-container :class="{'maximize-container': !asideHidden}" v-outside-click="outsideClick">
<ms-aside-container @setAsideHidden="setAsideHidden" style="padding-top: 0px">
<div v-loading="loading" v-show="!asideHidden">
<el-tree node-key="resourceId"
highlight-current
ref="preTree"
v-show="!asideHidden"
:props="props"
:data="scenarioDefinition"
:default-expanded-keys="expandedNode"
:expand-on-click-node="false"
@node-click="nodeClick"
@node-expand="nodeExpand"
@node-collapse="nodeCollapse" >
<span class="custom-tree-node father" slot-scope="{node, data}">
<!-- 步骤组件-->
<ms-component-config
:isMax="true"
:project-list="projectList"
:if-from-variable-advance="ifFromVariableAdvance"
:type="data.type"
:scenario="data"
:env-map="projectEnvMap"
:node="node"/>
</span>
</el-tree>
</div>
</ms-aside-container>
<!--右边元素-->
<ms-main-container>
<div>
<!-- 第一层当前节点内容-->
<ms-component-config
:if-from-variable-advance="ifFromVariableAdvance"
:type="selectedTreeNode.type"
:scenario="selectedTreeNode"
:node="selectedNode"
:env-map="projectEnvMap"
:draggable="false"
@savePreParams="savePreParams"
v-if="selectedTreeNode && selectedNode"/>
<!-- 请求下还有的子步骤-->
<div v-if="selectedTreeNode && selectedTreeNode.hashTree && showNode(selectedTreeNode)">
<div v-for="item in selectedTreeNode.hashTree" :key="item.id" class="ms-col-one">
<ms-component-config
:if-from-variable-advance="ifFromVariableAdvance"
:type="item.type"
:scenario="item"
:env-map="projectEnvMap"
:draggable="false"
@savePreParams="savePreParams"
v-if="selectedTreeNode && selectedNode && filterSonNode(item)"/>
</div>
</div>
</div>
<div v-if="scenarioPreRequestParams.length > 0" style="margin-bottom: 10px">
<p>{{ $t('api_test.definition.request.extract_params') }}</p>
<div v-for="(item, index) in scenarioPreRequestParams" :key="index" class="kv-row item">
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
<el-col class="item">
<el-input v-model="item.name" size="small" :readonly="true" @click.native="savePreParams(item.name)"/>
</el-col>
<el-col class="item">
<el-input v-model="item.value" size="small" :readonly="true" @click.native="savePreParams(item.name)"/>
</el-col>
</el-row>
</div>
</div>
</ms-main-container>
</ms-container>
</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()" v-if="currentTab === 0">
{{ $t('api_test.request.parameters_advance_add_func') }}
</el-button>
<el-button size="small" type="success" plain @click="showPreview()" v-if="currentTab === 0">
{{ $t('api_test.request.parameters_preview') }}
</el-button>
</el-col>
<el-col>
<div> {{ itemValuePreview }}</div>
<el-row type="flex" align="bottom">
<el-col :span="16">
<div style="position: fixed; bottom: 10px;">
<el-form>
<el-form-item>
<el-input :placeholder="valueText" size="small" v-model="itemValue"/>
</el-form-item>
</el-form>
<el-button size="small" type="primary" plain @click="saveAdvanced()">
{{ $t('commons.save') }}
</el-button>
<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()" v-if="currentTab === 0">
{{ $t('api_test.request.parameters_preview') }}
</el-button>
</div>
</el-col>
</el-row>
<div> {{ itemValuePreview }}</div>
</div>
</el-dialog>
</template>
@ -147,8 +214,11 @@
<script>
import {calculate, Scenario} from "../model/ApiTestModel";
import {JMETER_FUNC, MOCKJS_FUNC} from "@/common/js/constants";
import {buttons} from "../../automation/scenario/menu/Menu";
import {ENV_TYPE} from "@/common/js/constants";
import {STEP} from "../../automation/scenario/Setting";
import MsMainContainer from "../../../common/components/MsMainContainer";
import MsAsideContainer from "@/business/components/common/components/MsAsideContainer";
import MsContainer from "../../../common/components/MsContainer";
import OutsideClick from "@/common/js/outside-click";
export default {
name: "MsApiVariableAdvance",
@ -163,6 +233,13 @@
return false;
}
},
scenarioDefinition: Array,
},
components: {
MsMainContainer,
MsAsideContainer,
MsContainer,
MsComponentConfig: () => import("../../automation/scenario/component/ComponentConfig"),
},
data() {
return {
@ -172,6 +249,7 @@
scenarioParams: [],
preRequests: [],
preRequestParams: [],
scenarioPreRequestParams: [],
treeProps: {children: 'children', label: 'name'},
currentTab: 0,
itemValue: null,
@ -219,14 +297,32 @@
['CSV', 'CSV'],
['COUNTER', this.$t('api_test.automation.counter')],
['RANDOM', this.$t('api_test.automation.random')]
])
]),
//
props: {
label: "label",
children: "hashTree"
},
expandedNode: [],
stepFilter: new STEP,
operatingElements: [],
selectedTreeNode: undefined,
selectedNode: undefined,
projectList: [],
projectEnvMap: new Map,
ifFromVariableAdvance: false,
asideHidden: false,
scenarioRootTree: undefined,
insideClick: false,
}
},
computed: {
valueText() {
return this.valuePlaceholder || this.$t("api_test.value");
}
},
},
directives: {OutsideClick},
mounted() {
this.prepareData();
},
@ -236,14 +332,27 @@
}
},
methods: {
created() {
this.operatingElements = this.stepFilter.get("ALL");
},
open() {
if(this.$store.state.scenarioMap.get != undefined && this.$store.state.scenarioMap.get("currentScenarioVariables") != undefined){
this.variables = this.$store.state.scenarioMap.get("currentScenarioVariables");
}
if(this.scenarioDefinition != undefined){
//
this.ifFromVariableAdvance = true;
}
this.itemValueVisible = true;
if(this.$store.state.scenarioMap.get != undefined
&& this.$store.state.scenarioMap.get("currentScenarioId") != undefined){
this.variables = this.$store.state.scenarioMap.get("currentScenarioId");
//
if(this.ifFromVariableAdvance && this.$refs.preTree != undefined && this.currentTab == 3){
this.componentActive(this.$refs.preTree.root);
}
},
prepareData() {
prepareData(data) {
if(data != undefined || data != null){
this.scenario = data;
}
if (this.scenario) {
let variables = this.scenario.variables;
this.scenarioParams = [
@ -284,6 +393,75 @@
});
}
},
// key/value
getExtractDataByNode(data, node) {
if(!node.isLeaf){
if(node.childNodes.length > 0){
for(let i=0; i<node.childNodes.length; i++){
if(node.childNodes[i].isLeaf){ //
if(node.childNodes[i].data.type === 'Extract'){ //
let extractJsonParams = (node.childNodes[i].data.json).map(v => {
return {name: v.variable, value: v.value}
});
let extractRegexParams = (node.childNodes[i].data.regex).map(v => {
return {name: v.variable, value: v.value}
});
let extractXpathParams = (node.childNodes[i].data.xpath).map(v => {
return {name: v.variable, value: v.value}
});
let vs = [...extractJsonParams, ...extractRegexParams, ...extractXpathParams];
if (vs.length > 0) {
//
this.scenarioPreRequestParams = this.scenarioPreRequestParams.concat(extractJsonParams, extractRegexParams, extractXpathParams);
}
}
continue;
}else{
this.getExtractDataByNode(node.childNodes[i].data, node.childNodes[i]);
}
}
}
}
},
componentActive(node) {
if(this.ifFromVariableAdvance){
this.setLeafNodeUnVisible(node);
}
},
//
setLeafNodeUnVisible(node) {
if(!node.isLeaf){
if(node.childNodes.length > 0){
for(let i=0; i<node.childNodes.length; i++){
//
if(node.childNodes[i].isLeaf && node.childNodes[i].level > 1){
node.childNodes[i].visible = false;
if(node.childNodes[i].data.type === 'Extract' && node.data.type !== 'HTTPSamplerProxy'){
node.childNodes[i].visible = true;
}
}else{
//
if(node.childNodes[i].level == 1 && node.childNodes[i].data.type === 'ConstantTimer'){
node.childNodes[i].visible = false;
}
this.setLeafNodeUnVisible(node.childNodes[i]);
}
}
}
}
},
getAllExtractDataByNode(){
if(this.ifFromVariableAdvance){
this.selectedNode = undefined;
this.selectedTreeNode = undefined;
this.scenarioPreRequestParams = [];
if(this.$refs.preTree != undefined){
this.getExtractDataByNode(null, this.$refs.preTree.root);
}
}
},
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
@ -295,6 +473,11 @@
this.currentTab = +tab.index;
this.itemValue = null;
this.itemValuePreview = null;
if(this.ifFromVariableAdvance && this.currentTab === 3){
//
this.componentActive(this.$refs.preTree.root);
}
},
showPreview() {
//
@ -305,7 +488,6 @@
if (index > -1) {
this.itemValue = this.itemValue.substring(0, index).trim();
}
this.mockVariableFuncs.forEach(f => {
if (!f.name) {
return;
@ -315,7 +497,6 @@
this.itemValue += ":" + f.params.map(p => p.value).join(",");
}
});
this.itemValuePreview = calculate(this.itemValue);
},
methodChange(itemFunc, func) {
@ -364,7 +545,6 @@
this.mockVariableFuncs = [];
this.$emit('advancedRefresh', this.itemValue);
},
//
filter() {
let datas = [];
@ -406,14 +586,129 @@
edit(row) {
this.selection = [row.id];
this.itemValue = '${' + row.name + '}';
}
},
savePreParams(data) {
this.itemValue = '${' + data + '}';
},
//
nodeExpand(data) {
if (data.resourceId) {
this.expandedNode.push(data.resourceId);
}
},
nodeCollapse(data) {
if (data.resourceId) {
this.expandedNode.splice(this.expandedNode.indexOf(data.resourceId), 1);
}
},
nodeClick(data, node) {
if (data.referenced != 'REF' && data.referenced != 'Deleted' && !data.disabled) {
this.operatingElements = this.stepFilter.get(data.type);
} else {
this.operatingElements = [];
}
if (!this.operatingElements) {
this.operatingElements = this.stepFilter.get("ALL");
}
this.selectedTreeNode = data;
this.selectedNode = node;
this.$store.state.selectStep = data;
this.reload();
//
this.scenarioPreRequestParams = [];
this.getExtractDataByNode(data, node);
},
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
})
},
setAsideHidden(data) {
this.asideHidden = data;
},
showNode(node) {
for(let i=0; i<node.hashTree.length; i++){
// , HTTPSamplerProxy
if(node.hashTree[i].type == 'Extract' && node.type == 'HTTPSamplerProxy'
&& this.scenarioPreRequestParams.length > 0){
this.scenarioPreRequestParams = [];
break;
}
}
node.active = true;
if (node && this.stepFilter.get("AllSamplerProxy").indexOf(node.type) != -1) {
return true;
}
return false;
},
filterSonNode(item) {
if(item.type == 'Assertions' || item.type == 'ConstantTimer'
|| item.type == 'JDBCPreProcessor' || item.type == 'JDBCPostProcessor'){
return false;
}
return true;
},
outsideClick(e) {
//
this.getAllExtractDataByNode();
},
}
}
</script>
<style scoped>
.col-height {
height: 40vh;
overflow: auto;
}
.maximize-container .ms-aside-container {
min-width: 680px;
}
.ms-aside-container {
height: calc(100vh - 50px) !important;
}
.ms-open-btn-left {
margin-left: 35px;
}
.father .child {
display: none;
}
.father:hover .child {
display: block;
}
.ms-col-one {
margin-top: 10px;
}
.custom-tree-node {
width: 1000px;
}
.kv-row {
margin-top: 10px;
}
.extract-add {
padding: 10px;
border: #DCDFE6 solid 1px;
margin: 5px 0;
border-radius: 5px;
}
.extract-item {
width: 100%;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="variable-input">
<el-input :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
<el-input :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input" @click.native="savePreParams(value)"/>
<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">
@ -13,7 +13,6 @@
<script>
export default {
name: "MsApiVariableInput",
props: {
value: String,
size: String,
@ -33,14 +32,16 @@
type: Boolean,
default: false
},
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
return {
visible: false
}
},
methods: {
copy() {
let input = document.createElement("input");
@ -62,9 +63,13 @@
},
input(value) {
this.$emit('input', value);
}
},
savePreParams(value) {
if(this.ifFromVariableAdvance){
this.$emit('savePreParams', value);
}
},
},
computed: {
variable() {
return "${" + (this.showCopyTipWithMultiple ? (this.value + "_n") : this.value) + "}";

View File

@ -9,6 +9,7 @@
:show-btn="showBtn"
color="#015478"
background-color="#E6EEF2"
:if-from-variable-advance="ifFromVariableAdvance"
:title="$t('api_test.definition.request.extract_param')">
<div style="margin: 20px" v-loading="loading">
<div class="extract-description">
@ -26,7 +27,7 @@
</el-select>
</el-col>
<el-col :span="22">
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type" :list="list" v-if="type" :callback="after"/>
<ms-api-extract-common :if-from-variable-advance="ifFromVariableAdvance" :is-read-only="isReadOnly" :extract-type="type" :list="list" v-if="type" :callback="after"/>
</el-col>
<el-button v-if="!type" :disabled="true" type="primary" size="small">{{ $t('commons.add') }}</el-button>
@ -36,7 +37,7 @@
<api-json-path-suggest-button :open-tip="$t('api_test.request.extract.json_path_suggest')"
:clear-tip="$t('api_test.request.extract.json_path_clear')" @open="suggestJsonOpen" @clear="clearJson"/>
<ms-api-extract-edit :is-read-only="isReadOnly" :reloadData="reloadData" :extract="extract"/>
<ms-api-extract-edit :if-from-variable-advance="ifFromVariableAdvance" @savePreParams="savePreParams" :is-read-only="isReadOnly" :reloadData="reloadData" :extract="extract"/>
</div>
<ms-api-jsonpath-suggest :tip="$t('api_test.request.extract.suggest_tip')" @addSuggest="addJsonPathSuggest" ref="jsonpathSuggest"/>
</api-base-component>
@ -85,6 +86,10 @@
type: Boolean,
default: true,
},
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
return {
@ -133,7 +138,10 @@
},
clearJson() {
this.extract.json = [];
}
},
savePreParams(data) {
this.$emit("savePreParams", data);
},
},
computed: {
list() {

View File

@ -7,12 +7,12 @@
</el-select>
</el-col>
<el-col>
<ms-api-variable-input :is-read-only="isReadOnly" v-model="common.variable" size="small" maxlength="60"
<ms-api-variable-input :if-from-variable-advance="ifFromVariableAdvance" @savePreParams="savePreParams" :is-read-only="isReadOnly" v-model="common.variable" size="small" maxlength="60"
@change="change" :show-copy-tip-with-multiple="common.multipleMatching" show-word-limit :placeholder="$t('api_test.variable_name')"/>
</el-col>
<el-col>
<el-input :disabled="isReadOnly" v-model="common.expression" size="small" show-word-limit
:placeholder="expression"/>
:placeholder="expression" @click.native="savePreParams(common.variable)"/>
</el-col>
<el-col class="multiple_checkbox">
<el-checkbox v-model="common.multipleMatching" :disabled="isReadOnly">
@ -57,7 +57,11 @@
isReadOnly: {
type: Boolean,
default: false
}
},
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
@ -108,7 +112,12 @@
setTimeout(() => {
this.visible = false;
}, 1000);
}
},
savePreParams(data) {
if(this.ifFromVariableAdvance){
this.$emit('savePreParams', data);
}
},
},
computed: {

View File

@ -5,8 +5,8 @@
{{$t("api_test.request.extract.regex")}}
</div>
<div class="regex-item" v-for="(regex, index) in extract.regex" :key="index">
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type.REGEX" :list="extract.regex" :common="regex"
:edit="true" :index="index"/>
<ms-api-extract-common :if-from-variable-advance="ifFromVariableAdvance" :is-read-only="isReadOnly" :extract-type="type.REGEX" :list="extract.regex" :common="regex"
:edit="true" :index="index" @savePreParams="savePreParams"/>
</div>
</div>
@ -15,8 +15,8 @@
JSONPath
</div>
<div class="regex-item" v-for="(json, index) in extract.json" :key="index">
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type.JSON_PATH" :list="extract.json" :common="json"
:edit="true" :index="index"/>
<ms-api-extract-common :if-from-variable-advance="ifFromVariableAdvance" :is-read-only="isReadOnly" :extract-type="type.JSON_PATH" :list="extract.json" :common="json"
:edit="true" :index="index" @savePreParams="savePreParams"/>
</div>
</div>
@ -25,8 +25,8 @@
XPath
</div>
<div class="regex-item" v-for="(xpath, index) in extract.xpath" :key="index">
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type.XPATH" :list="extract.xpath" :common="xpath"
:edit="true" :index="index"/>
<ms-api-extract-common :if-from-variable-advance="ifFromVariableAdvance" :is-read-only="isReadOnly" :extract-type="type.XPATH" :list="extract.xpath" :common="xpath"
:edit="true" :index="index" @savePreParams="savePreParams"/>
</div>
</div>
</div>
@ -49,6 +49,10 @@
default: false
},
reloadData: String,
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
watch: {
reloadData() {
@ -63,6 +67,9 @@
this.loading = false
})
},
savePreParams(data) {
this.$emit("savePreParams", data);
},
},
data() {
return {

View File

@ -17,7 +17,7 @@
<el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-key-value :show-desc="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="headers" :need-mock="true"/>
<ms-api-key-value @editScenarioAdvance="editScenarioAdvance" :scenario-definition="scenarioDefinition" :show-desc="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="headers" :need-mock="true"/>
</el-tab-pane>
<!--query 参数-->
@ -31,7 +31,7 @@
<el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-variable :with-mor-setting="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :parameters="request.arguments"/>
<ms-api-variable @editScenarioAdvance="editScenarioAdvance" :scenario-definition="scenarioDefinition" :with-mor-setting="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :parameters="request.arguments"/>
</el-tab-pane>
<!--REST 参数-->
@ -47,7 +47,7 @@
<el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-variable :with-mor-setting="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :parameters="request.rest"/>
<ms-api-variable @editScenarioAdvance="editScenarioAdvance" :scenario-definition="scenarioDefinition" :with-mor-setting="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :parameters="request.rest"/>
</el-tab-pane>
<!--请求体-->
@ -146,6 +146,11 @@ export default {
default: false
},
type: String,
scenarioDefinition: Array,
ifFromVariableAdvance: {
type: Boolean,
default: false,
},
},
data() {
let validateURL = (rule, value, callback) => {
@ -393,7 +398,10 @@ export default {
this.assign(target, arguments[s]);
}
return target;
}
},
editScenarioAdvance(data) {
this.$emit('editScenarioAdvance', data);
},
}
}
</script>

View File

@ -1202,6 +1202,7 @@ export default {
all_post_script: "Postscript",
pre_sql: "JDBC Preprocessor",
pre_return: "pre return",
extract_params: "extract paramsvariable / value",
post_sql: "JDBC Postprocessor",
extract_param: "Extract parameters",
add_module: "Add module",

View File

@ -1208,6 +1208,7 @@ export default {
all_post_script: "全局后置脚本",
pre_sql: "前置SQL",
pre_return: "前置返回",
extract_params: "提取参数(变量名 / 值)",
post_sql: "后置SQL",
extract_param: "提取参数",
add_module: "创建模块",

View File

@ -1208,6 +1208,7 @@ export default {
all_post_script: "全局後置腳本",
pre_sql: "前置SQL",
pre_return: "前置返回",
extract_params: "提取參數(變量名 / 值)",
post_sql: "後置SQL",
extract_param: "提取參數",
add_module: "創建模塊",