feat(接口自动化): 创建场景

This commit is contained in:
fit2-zhao 2020-12-01 17:49:09 +08:00
parent f62ae2bd59
commit 184cd9659c
6 changed files with 948 additions and 5 deletions

View File

@ -0,0 +1,91 @@
<template>
<div v-loading="loading">
<el-card>
<el-row>
<div class="el-step__icon is-text ms-api-col" v-if="data.referenced">
<div class="el-step__icon-inner">{{data.$treeNodeId}}</div>
</div>
<div class="el-step__icon is-text ms-api-col-create" v-else>
<div class="el-step__icon-inner">{{data.$treeNodeId}}</div>
</div>
<i class="icon el-icon-arrow-right" :class="{'is-active': data.active}"
@click="active(data)"/>
<span>{{data.type!= 'create' ? data.name:''}} </span>
</el-row>
<!-- 请求参数-->
<el-collapse-transition>
<div v-if="data.active">
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<ms-api-request-form :headers="data.request.hashTree[0].headers " :request="data.request" v-if="data.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :request="data.request" :currentProject="currentProject" v-if="data.protocol==='TCP'"/>
<ms-sql-basis-parameters :request="data.request" :currentProject="currentProject" v-if="data.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :request="data.request" :currentProject="currentProject" v-if="data.protocol==='DUBBO'"/>
<!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)" v-if="!data.referenced">
{{$t('commons.save')}}
</el-button>
</div>
</el-collapse-transition>
</el-card>
</div>
</template>
<script>
import MsSqlBasisParameters from "../../definition/components/request/database/BasisParameters";
import MsTcpBasisParameters from "../../definition/components/request/tcp/BasisParameters";
import MsDubboBasisParameters from "../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../definition/components/request/http/ApiRequestForm";
export default {
name: "MsApiComponent",
props: {
data: {},
currentProject: {},
},
components: {MsSqlBasisParameters, MsTcpBasisParameters, MsDubboBasisParameters, MsApiRequestForm},
data() {
return {loading: false,}
},
methods: {
remove() {
this.$emit('remove', this.data);
},
active(item) {
item.active = !item.active;
this.reload();
},
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
})
},
}
}
</script>
<style scoped>
.ms-api-col {
background-color: #FCF1F1;
border-color: #F56C6C;
margin-right: 10px;
color: #F56C6C;
}
.ms-api-col-create {
background-color: #EBF2F2;
border-color: #008080;
margin-right: 10px;
color: #008080;
}
/deep/ .el-card__body {
padding: 15px;
}
.icon.is-active {
transform: rotate(90deg);
}
</style>

View File

@ -0,0 +1,60 @@
<template>
<div>
<el-card>
<el-row>
<div class="el-step__icon is-text ms-api-col" style="float: left">
<div class="el-step__icon-inner">{{timer.$treeNodeId}}</div>
</div>
<div>
<el-row :gutter="10" type="flex" align="middle">
<el-col :span="2">{{ $t('api_test.request.wait') }}</el-col>
<el-col :span="10">
<el-input-number class="width-100" size="small" v-model="timer.delay" :min="0" :step="1000"/>
</el-col>
<el-col :span="2">ms</el-col>
<el-col :span="8">
<el-switch v-model="timer.enable" :inactive-text="$t('api_test.scenario.enable_disable')"/>
</el-col>
<el-col :span="2">
<el-button size="mini" type="danger" icon="el-icon-delete" circle @click="remove"/>
</el-col>
</el-row>
</div>
</el-row>
</el-card>
</div>
</template>
<script>
export default {
name: "MsConstantTimer",
props: {
timer: {}
},
data() {
return {}
},
methods: {
remove() {
this.$emit('remove', this.timer);
}
}
}
</script>
<style scoped>
.width-100 {
width: 100%
}
.ms-api-col {
background-color: #F2F9EE;
border-color: #67C23A;
margin-right: 10px;
color: #67C23A;
}
/deep/ .el-card__body {
padding: 15px;
}
</style>

View File

@ -1,21 +1,497 @@
<template>
<div> EditApiScenario</div>
<el-card class="card-content">
<div style="background-color: white;">
<p class="tip">{{$t('test_track.plan_view.base_info')}} </p>
<el-form :model="basicForm" label-position="right" label-width="80px" size="small" :rules="rules" ref="basicForm" style="margin-right: 20px">
<!-- 基础信息 -->
<el-row>
<el-col :span="12">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input class="ms-scenario-input" size="small" v-model="basicForm.name"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('test_track.module.module')" prop="moduleId">
<el-select class="ms-scenario-input" size="small" v-model="basicForm.moduleId">
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('commons.status')" prop="status">
<el-select class="ms-scenario-input" size="small" v-model="basicForm.status">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="principal">
<el-select v-model="basicForm.principal"
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
class="ms-scenario-input">
<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-row>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('test_track.case.priority')" prop="level">
<el-select class="ms-scenario-input" size="small" v-model="basicForm.level">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('api_test.automation.follow_people')" prop="followPeople">
<el-select v-model="basicForm.followPeople"
:placeholder="$t('api_test.automation.follow_people')" filterable size="small"
class="ms-scenario-input">
<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-row>
<el-row>
<el-col :span="12">
<el-form-item label="Tag" prop="tagId">
<el-select v-model="basicForm.tagId" size="small" class="ms-scenario-input" placeholder="Tag"
@change="tagChange" :multiple="true">
<el-option
v-for="item in maintainerOptions"
:key="item.id"
:label="item.id + ' (' + item.name + ')'"
:value="item.id"/>
<el-button size="mini" type="primary" @click="openTagConfig" class="ms-scenario-button">
{{ $t('api_test.automation.create_tag') }}
</el-button>
<template v-slot:empty>
<div>
<el-button size="mini" type="primary" @click="closeTagConfig" class="ms-scenario-button">
{{ $t('api_test.automation.create_tag') }}
</el-button>
</div>
</template>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('commons.description')" prop="description">
<el-input class="ms-http-textarea"
v-model="basicForm.description"
type="textarea"
:autosize="{ minRows: 2, maxRows: 10}"
:rows="2" size="small"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 场景步骤-->
<div v-loading="isReloadData">
<p class="tip">{{$t('api_test.automation.scenario_step')}} </p>
<el-row>
<el-col :span="21">
<div style="margin-left: 20px;border:1px #DCDFE6 solid;border-radius: 4px;margin-right: 10px">
<el-row style="margin: 5px">
<el-col :span="6" class="ms-col-one">
{{basicForm.name ===undefined || ''? $t('api_test.scenario.name') : basicForm.name}}
</el-col>
<el-col :span="5" class="ms-col-one">
{{$t('api_test.automation.step_total')}}:
</el-col>
<el-col :span="5" class="ms-col-one">
{{$t('api_test.automation.scenario_total')}}:
</el-col>
<el-col :span="6">
{{$t('api_test.definition.request.run_env')}}:
<el-select v-model="basicForm.environmentId" size="small" class="ms-htt-width"
:placeholder="$t('api_test.definition.request.run_env')"
@change="environmentChange" clearable>
<el-option v-for="(environment, index) in environments" :key="index"
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')"
:value="environment.id"/>
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig">
{{ $t('api_test.environment.environment_config') }}
</el-button>
<template v-slot:empty>
<div class="empty-environment">
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig">
{{ $t('api_test.environment.environment_config') }}
</el-button>
</div>
</template>
</el-select>
</el-col>
<el-col :span="2">
<el-button size="small" type="primary" @click="runDebug">{{$t('api_test.request.debug')}}</el-button>
</el-col>
</el-row>
</div>
<!-- 场景步骤内容 -->
<div style="margin-top: 10px">
<el-tree node-key="id" :data="scenarioDefinition" :allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" draggable v-loading="isReloadData">
<span class="custom-tree-node father" slot-scope="{ node, data}" style="width: 96%">
<template>
<!-- 场景 -->
<el-card @click.native="selectItem(data,$event)" v-if="data.type==='scenario'">
<el-row>
<div class="el-step__icon is-text ms-api-col" style="float: left">
<div class="el-step__icon-inner">{{data.$treeNodeId}}</div>
</div>
<div style="margin-left: 20px;float: left"> {{data.name}}</div>
</el-row>
</el-card>
<!--条件控制器-->
<ms-if-controller :controller="data" v-if="data.type==='IfController'" @remove="remove"/>
<!--等待控制器-->
<ms-constant-timer :timer="data" v-if="data.type==='ConstantTimer'" @remove="remove"/>
<!--自定义脚本-->
<ms-jsr233-processor v-if="data.type==='JSR223Processor'" @remove="remove" :title="$t('api_test.automation.customize_script')"
style-type="color: #7B4D12;background-color: #F1EEE9" :jsr223-processor="data"/>
<!--前置脚本-->
<ms-jsr233-processor v-if="data.type==='JSR223PreProcessor'" @remove="remove" :title="$t('api_test.definition.request.pre_script')"
style-type="color: #B8741A;background-color: #F9F1EA" :jsr223-processor="data"/>
<!--后置脚本-->
<ms-jsr233-processor v-if="data.type==='JSR223PostProcessor'" @remove="remove" :title="$t('api_test.definition.request.post_script')"
style-type="color: #783887;background-color: #F2ECF3" :jsr223-processor="data"/>
<!--断言规则-->
<ms-api-assertions v-if="data.type==='Assertions'" @remove="remove" customizeStyle="margin-top: 0px" :assertions="data"/>
<!--提取规则-->
<ms-api-extract @remove="remove" v-if="data.type==='Extract'" customizeStyle="margin-top: 0px" :extract="data"/>
<!--API 导入 -->
<ms-api-component :data="data" current-project="currentProject" v-if="data.type==='API' || data.type==='CASE'"/>
</template>
</span>
</el-tree>
</div>
</el-col>
<!-- 按钮列表 -->
<div>
<el-col :span="3" class="ms-left-cell">
<el-button type="primary" icon="el-icon-refresh" size="small" @click="showAll">{{$t('commons.show_all')}}</el-button>
<br/>
<div v-if="operatingElements.indexOf('API')>0 || operatingElements.indexOf('CASE')>0">
<el-button class="ms-right-buttion" size="small" style="color: #F56C6C;background-color: #FCF1F1" @click="apiListImport">+{{$t('api_test.automation.api_list_import')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('OT_IMPORT')>0">
<el-button class="ms-right-buttion" size="small" style="color: #409EFF;background-color: #EEF5FE" @click="addPre">+{{$t('api_test.automation.external_import')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('ConstantTimer')>0">
<el-button class="ms-right-buttion" size="small" style="color: #67C23A;background-color: #F2F9EE" @click="addPre">+{{$t('api_test.automation.wait_controller')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('IfController')>0">
<el-button class="ms-right-buttion" size="small" style="color: #E6A23C;background-color: #FCF6EE" @click="addPre">+{{$t('api_test.automation.if_controller')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('scenario')===0">
<el-button class="ms-right-buttion" size="small" style="color: #606266;background-color: #F4F4F5" @click="addPre">+{{$t('api_test.automation.scenario_import')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('JSR223Processor')>0">
<el-button class="ms-right-buttion" size="small" style="color: #7B4D12;background-color: #F1EEE9" @click="addPre">+{{$t('api_test.automation.customize_script')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('CustomizeReq')>0">
<el-button class="ms-right-buttion" size="small" style="color: #008080;background-color: #EBF2F2" @click="addPre">+{{$t('api_test.automation.customize_req')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('JSR223PreProcessor')>0">
<el-button class="ms-right-buttion" size="small" style="color: #B8741A;background-color: #F9F1EA" @click="addPre">+{{$t('api_test.definition.request.pre_script')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('JSR223PostProcessor')>0">
<el-button class="ms-right-buttion" size="small" style="color: #783887;background-color: #F2ECF3" @click="addPost">+{{$t('api_test.definition.request.post_script')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('Assertions')>0">
<el-button class="ms-right-buttion" size="small" style="color: #A30014;background-color: #F7E6E9" @click="addAssertions">+{{$t('api_test.definition.request.assertions_rule')}}</el-button>
</div>
<div v-if="operatingElements.indexOf('Extract')>0">
<el-button class="ms-right-buttion" size="small" style="color: #015478;background-color: #E6EEF2" @click="addExtract">+{{$t('api_test.definition.request.extract_param')}}</el-button>
</div>
</el-col>
</div>
</el-row>
</div>
<!--接口列表-->
<el-drawer :visible.sync="apiListVisible" direction="ltr" :with-header="false" :modal="false" size="90%">
<ms-api-definition :visible="true" :currentRow="currentRow"/>
<el-button style="float: right;margin: 20px" @click="addReferenceApi">{{$t('api_test.scenario.reference')}}</el-button>
</el-drawer>
</div>
</el-card>
</template>
<script>
import {API_STATUS} from "../../definition/model/JsonData";
import {WORKSPACE_ID} from '@/common/js/constants';
import {createComponent} from "../../definition/components/jmeter/components";
import {Assertions, Extract, IfController, JSR223Processor} from "../../definition/model/ApiTestModel";
import MsJsr233Processor from "./Jsr233Processor";
import {parseEnvironment} from "../../definition/model/EnvironmentModel";
import MsConstantTimer from "./ConstantTimer";
import MsIfController from "./IfController";
import MsApiAssertions from "../../definition/components/assertion/ApiAssertions";
import MsApiExtract from "../../definition/components/extract/ApiExtract";
import MsApiDefinition from "../../definition/ApiDefinition";
import MsApiComponent from "./ApiComponent";
import {ELEMENTS} from "./Setting";
export default {
name: "EditApiScenario",
components: {},
comments: {},
props: {
moduleOptions: Array,
currentProject: {}
},
components: {MsJsr233Processor, MsConstantTimer, MsIfController, MsApiAssertions, MsApiExtract, MsApiDefinition, MsApiComponent},
data() {
return {}
return {
rules: {
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'}
],
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'}],
},
basicForm: {},
environments: [],
maintainerOptions: [],
value: API_STATUS[0].id,
options: API_STATUS,
scenario: {},
isReloadData: false,
apiListVisible: false,
operatingElements: [],
currentRow: {cases: [], apis: []},
selectedTreeNode: {},
scenarioDefinition: [{index: 1, id: "xx", type: "scenario", name: "test"}, {index: 2, id: "2", type: "ConstantTimer"}]
}
},
created() {
this.scenarioDefinition.push(new IfController());
this.scenarioDefinition.push(new JSR223Processor());
this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PreProcessor"}));
this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PostProcessor"}));
this.scenarioDefinition.push(new Assertions());
this.scenarioDefinition.push(new Extract());
this.getMaintainerOptions();
},
watch: {},
methods: {}
methods: {
nodeClick(e) {
this.operatingElements = ELEMENTS.get(e.type);
this.selectedTreeNode = e;
this.reload();
},
showAll() {
this.operatingElements = ELEMENTS.get("ALL");
this.selectedTreeNode = undefined;
this.reload();
},
apiListImport() {
this.apiListVisible = true;
},
addReferenceApi() {
if (this.currentRow.cases.length === 0 && this.currentRow.apis.length === 0) {
this.$warning(this.$t('api_test.automation.reference_info'));
return;
}
this.currentRow.cases.forEach(item => {
item.referenced = true;
item.active = false;
if (this.selectedTreeNode != undefined) {
if (this.selectedTreeNode.children === undefined) {
this.selectedTreeNode.children = [];
}
this.selectedTreeNode.children.push(item);
} else {
this.scenarioDefinition.push(item);
}
})
this.currentRow.apis.forEach(item => {
item.referenced = true;
item.active = false;
item.request = JSON.parse(item.request);
if (this.selectedTreeNode != undefined) {
if (this.selectedTreeNode.children === undefined) {
this.selectedTreeNode.children = [];
}
this.selectedTreeNode.children.push(item);
} else {
this.scenarioDefinition.push(item);
}
})
this.apiListVisible = false;
this.reload();
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.maintainerOptions = response.data;
});
},
tagChange() {
},
openTagConfig() {
if (!this.currentProject) {
this.$error(this.$t('api_test.select_project'));
return;
}
this.$refs.environmentConfig.open(this.currentProject.id);
},
closeTagConfig() {
},
addPre() {
let jsr223PreProcessor = createComponent("JSR223PreProcessor");
this.request.hashTree.push(jsr223PreProcessor);
this.reload();
},
addPost() {
let jsr223PostProcessor = createComponent("JSR223PostProcessor");
this.request.hashTree.push(jsr223PostProcessor);
this.reload();
},
addAssertions() {
let assertions = new Assertions();
this.request.hashTree.push(assertions);
this.reload();
},
addExtract() {
let jsonPostProcessor = new Extract();
this.request.hashTree.push(jsonPostProcessor);
this.reload();
},
remove(row) {
this.scenarioDefinition.splice(this.scenarioDefinition.indexOf(row), 1);
this.reload();
},
reload() {
this.isReloadData = true
this.$nextTick(() => {
this.isReloadData = false
})
},
runDebug() {
},
getEnvironments() {
if (this.currentProject) {
this.$get('/api/environment/list/' + this.currentProject.id, response => {
this.environments = response.data;
this.environments.forEach(environment => {
parseEnvironment(environment);
});
let hasEnvironment = false;
for (let i in this.environments) {
if (this.environments[i].id === this.api.environmentId) {
this.api.environment = this.environments[i];
hasEnvironment = true;
break;
}
}
if (!hasEnvironment) {
this.api.environmentId = '';
this.api.environment = undefined;
}
});
} else {
this.api.environmentId = '';
this.api.environment = undefined;
}
},
openEnvironmentConfig() {
if (!this.currentProject) {
this.$error(this.$t('api_test.select_project'));
return;
}
this.$refs.environmentConfig.open(this.currentProject.id);
},
environmentChange(value) {
for (let i in this.environments) {
if (this.environments[i].id === value) {
this.api.request.useEnvironment = this.environments[i].id;
break;
}
}
},
environmentConfigClose() {
this.getEnvironments();
},
allowDrop(draggingNode, dropNode, type) {
if (ELEMENTS.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1) {
return true;
}
return false;
},
allowDrag() {
},
selectItem(v, e) {
console.log(v)
},
}
}
</script>
<style scoped>
.ms-scenario-input {
width: 100%;
}
.ms-scenario-button {
margin-left: 45%;
padding: 7px;
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
}
.ms-api-col {
background-color: #7C3985;
border-color: #7C3985;
margin-right: 10px;
color: white;
}
.ms-col-one {
margin-top: 6px;
}
.ms-right-buttion {
margin-top: 10px;
}
/deep/ .el-tree-node__content {
height: 100%;
margin-top: 8px;
vertical-align: center;
}
/deep/ .el-card__body {
padding: 15px;
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<el-card>
<el-row>
<div class="el-step__icon is-text ms-api-col" style="float: left">
<div class="el-step__icon-inner">{{controller.$treeNodeId}}</div>
</div>
<div>
<el-row :gutter="10" type="flex" align="middle">
<el-col :span="1">If</el-col>
<el-col :span="6">
<el-input size="small" v-model="controller.variable" :placeholder="$t('api_test.request.condition_variable')"/>
</el-col>
<el-col :span="5">
<el-select v-model="controller.operator" :placeholder="$t('commons.please_select')" size="small"
@change="change">
<el-option v-for="o in operators" :key="o.value" :label="$t(o.label)" :value="o.value"/>
</el-select>
</el-col>
<el-col :span="6">
<el-input size="small" v-model="controller.value" :placeholder="$t('api_test.value')" v-if="!hasEmptyOperator"/>
</el-col>
<el-col :span="4">
<el-switch v-model="controller.enable" :inactive-text="$t('api_test.scenario.enable_disable')"/>
</el-col>
<el-col :span="2">
<el-button size="mini" type="danger" icon="el-icon-delete" circle @click="remove"/>
</el-col>
</el-row>
</div>
</el-row>
</el-card>
</template>
<script>
export default {
name: "MsIfController",
props: {
controller: {}
},
data() {
return {
operators: {
EQ: {
label: "commons.adv_search.operators.equals",
value: "=="
},
NE: {
label: "commons.adv_search.operators.not_equals",
value: "!="
},
LIKE: {
label: "commons.adv_search.operators.like",
value: "=~"
},
NOT_LIKE: {
label: "commons.adv_search.operators.not_like",
value: "!~"
},
GT: {
label: "commons.adv_search.operators.gt",
value: ">"
},
LT: {
label: "commons.adv_search.operators.lt",
value: "<"
},
IS_EMPTY: {
label: "commons.adv_search.operators.is_empty",
value: "is empty"
},
IS_NOT_EMPTY: {
label: "commons.adv_search.operators.is_not_empty",
value: "is not empty"
}
}
}
},
methods: {
remove() {
this.$emit('remove', this.timer);
},
change(value) {
if (value.indexOf("empty") > 0 && !!this.controller.value) {
this.controller.value = "";
}
}
},
computed: {
hasEmptyOperator() {
return !!this.controller.operator && this.controller.operator.indexOf("empty") > 0;
}
}
}
</script>
<style scoped>
.ms-api-col {
background-color: #FCF6EE;
border-color: #E6A23C;
margin-right: 10px;
color: #E6A23C;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<el-card>
<el-row>
<div>
<el-button class="ms-left-buttion" size="small" :style="styleType" style="color: #B8741A;background-color: #F9F1EA">{{title}}</el-button>
<i class="icon el-icon-arrow-right" :class="{'is-active': active}" @click="changeActive" style="margin-left: 20px"/>
<el-input size="small" v-model="jsr223ProcessorData.name" class="ms-api-header-select" style="width: 380px"/>
<el-button size="small" style="float: right" @click="remove">移除</el-button>
</div>
</el-row>
<el-collapse-transition>
<div v-if="active">
<el-row style="margin:0px 10px 10px">
<el-col>
<div class="document-url">
<el-link href="https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_PostProcessor"
type="primary">{{$t('commons.reference_documentation')}}
</el-link>
<ms-instructions-icon :content="$t('api_test.request.processor.bean_shell_processor_tip')"/>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="20" class="script-content">
<ms-code-edit v-if="isCodeEditAlive" :mode="jsr223ProcessorData.scriptLanguage"
:read-only="isReadOnly"
:data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="['java','python']"
ref="codeEdit"/>
</el-col>
<el-col :span="4" class="script-index">
<ms-dropdown :default-command="jsr223ProcessorData.language" :commands="languages" @command="languageChange"/>
<div class="template-title">{{$t('api_test.request.processor.code_template')}}</div>
<div v-for="(template, index) in codeTemplates" :key="index" class="code-template">
<el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link>
</div>
</el-col>
</el-row>
</div>
</el-collapse-transition>
</el-card>
</template>
<script>
import MsCodeEdit from "../../../common/components/MsCodeEdit";
import MsInstructionsIcon from "../../../common/components/MsInstructionsIcon";
import MsDropdown from "../../../common/components/MsDropdown";
export default {
name: "MsJsr233Processor",
components: {MsDropdown, MsInstructionsIcon, MsCodeEdit},
data() {
return {
active: false,
jsr223ProcessorData: {},
codeTemplates: [
{
title: this.$t('api_test.request.processor.code_template_get_variable'),
value: 'vars.get("variable_name")',
},
{
title: this.$t('api_test.request.processor.code_template_set_variable'),
value: 'vars.put("variable_name", "variable_value")',
},
{
title: this.$t('api_test.request.processor.code_template_get_global_variable'),
value: 'props.get("variable_name")',
},
{
title: this.$t('api_test.request.processor.code_template_set_global_variable'),
value: 'props.put("variable_name", "variable_value")',
},
{
title: this.$t('api_test.request.processor.code_template_get_response_header'),
value: 'prev.getResponseHeaders()',
disabled: this.isPreProcessor
},
{
title: this.$t('api_test.request.processor.code_template_get_response_code'),
value: 'prev.getResponseCode()',
disabled: this.isPreProcessor
},
{
title: this.$t('api_test.request.processor.code_template_get_response_result'),
value: 'prev.getResponseDataAsString()',
disabled: this.isPreProcessor
}
],
isCodeEditAlive: true,
languages: [
'java', "python"
],
codeEditModeMap: {
beanshell: 'java',
python: 'python'
}
}
},
created() {
this.jsr223ProcessorData = this.jsr223Processor;
},
props: {
isReadOnly: {
type: Boolean,
default:
false
}
,
jsr223Processor: {
type: Object,
}
,
isPreProcessor: {
type: Boolean,
default:
false
}
,
title: String,
styleType:
String,
}
,
watch: {
jsr223Processor() {
this.reload();
}
}
,
methods: {
addTemplate(template) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = "";
}
this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.language === 'beanshell') {
this.jsr223ProcessorData.script += ';';
}
this.reload();
},
remove() {
this.$emit('remove', this.jsr223ProcessorData);
},
reload() {
this.isCodeEditAlive = false;
this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223ProcessorData.language = language;
},
changeActive() {
this.active = !this.active;
},
}
}
</script>
<style scoped>
.ace_editor {
border-radius: 5px;
}
.script-content {
height: calc(100vh - 570px);
}
.script-index {
padding: 0 20px;
}
.template-title {
margin-bottom: 5px;
font-weight: bold;
font-size: 15px;
}
.document-url {
margin-top: 10px;
}
.instructions-icon {
margin-left: 5px;
}
.ms-dropdown {
margin-bottom: 20px;
}
.ms-api-header-select {
margin-left: 20px;
min-width: 300px;
}
.icon.is-active {
transform: rotate(90deg);
}
</style>

View File

@ -0,0 +1,15 @@
export const ELEMENTS =new Map([
['ALL', ["scenario", "API", "CASE", "OT_IMPORT", "IfController", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['scenario', ["API", "CASE", "OT_IMPORT", "IfController", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['API', ["IfController", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
['CASE', ["IfController", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
['OT_IMPORT', []],
['IfController', ["API", "CASE", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['ConstantTimer', ["API", "CASE", "OT_IMPORT", "IfController", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['JSR223Processor', []],
['JSR223PreProcessor', []],
['JSR223PostProcessor', []],
['Assertions', []],
['Extract', []],
['CustomizeReq', ["API", "CASE", "OT_IMPORT", "IfController", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
])