feat(接口测试): 非TCP请求的前后置脚本去掉报文处理脚本代码

--bug=1007769 --user=宋天阳 【github#7525】环境配置的全局前置脚本或者HTTP请求,用代码模版 生成的
“报文头添加长度” 代码块,执行报错 https://www.tapd.cn/55049933/s/1120185
This commit is contained in:
song-tianyang 2022-03-17 16:33:37 +08:00 committed by xiaomeinvG
parent e5ac4e32ab
commit 7b7b7ccfb0
5 changed files with 278 additions and 254 deletions

View File

@ -1,270 +1,276 @@
<template> <template>
<div> <div>
<el-row type="flex" :gutter="10"> <el-row type="flex" :gutter="10">
<el-col :span="codeSpan" class="script-content"> <el-col :span="codeSpan" class="script-content">
<ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223ProcessorData.scriptLanguage]" <ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223ProcessorData.scriptLanguage]"
:read-only="isReadOnly" :read-only="isReadOnly"
:data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="['java','python']" :data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="['java','python']"
ref="codeEdit"/> ref="codeEdit"/>
</el-col> </el-col>
<div style="width: 14px;margin-right: 5px;"> <div style="width: 14px;margin-right: 5px;">
<div style="height: 12px;width: 12px; line-height:12px;"> <div style="height: 12px;width: 12px; line-height:12px;">
<i :class="showMenu ? 'el-icon-remove-outline' : 'el-icon-circle-plus-outline'" <i :class="showMenu ? 'el-icon-remove-outline' : 'el-icon-circle-plus-outline'"
class="show-menu" class="show-menu"
@click="switchMenu"></i> @click="switchMenu"></i>
</div>
</div> </div>
<el-col :span="menuSpan" class="script-index" v-if="isReadOnly !== true"> </div>
<ms-dropdown :default-command="jsr223ProcessorData.scriptLanguage" :commands="languages" <el-col :span="menuSpan" class="script-index" v-if="isReadOnly !== true">
style="margin-bottom: 5px;margin-left: 15px;" <ms-dropdown :default-command="jsr223ProcessorData.scriptLanguage" :commands="languages"
@command="languageChange"/> style="margin-bottom: 5px;margin-left: 15px;"
<script-nav-menu ref="scriptNavMenu" :language="jsr223ProcessorData.scriptLanguage" :menus="codeTemplates" @command="languageChange"/>
@handleCode="handleCodeTemplate"/> <script-nav-menu ref="scriptNavMenu" :language="jsr223ProcessorData.scriptLanguage" :menus="codeTemplates"
</el-col> @handleCode="handleCodeTemplate"/>
</el-row> </el-col>
</div> </el-row>
</div>
</template> </template>
<script> <script>
import MsCodeEdit from "../../../definition/components/MsCodeEdit"; import MsCodeEdit from "../../../definition/components/MsCodeEdit";
import MsDropdown from "../../../../common/components/MsDropdown"; import MsDropdown from "../../../../common/components/MsDropdown";
import CustomFunctionRelate from "@/business/components/project/menu/function/CustomFunctionRelate"; import CustomFunctionRelate from "@/business/components/project/menu/function/CustomFunctionRelate";
import ApiFuncRelevance from "@/business/components/project/menu/function/ApiFuncRelevance"; import ApiFuncRelevance from "@/business/components/project/menu/function/ApiFuncRelevance";
import ScriptNavMenu from "@/business/components/project/menu/function/ScriptNavMenu"; import ScriptNavMenu from "@/business/components/project/menu/function/ScriptNavMenu";
export default {
name: "Jsr233ProcessorContent", export default {
components: {MsDropdown, MsCodeEdit, CustomFunctionRelate, ApiFuncRelevance, ScriptNavMenu}, name: "Jsr233ProcessorContent",
data() { components: {MsDropdown, MsCodeEdit, CustomFunctionRelate, ApiFuncRelevance, ScriptNavMenu},
return { data() {
jsr223ProcessorData: {}, return {
codeTemplates: [ jsr223ProcessorData: {},
codeTemplates: [
{
title: this.$t('project.code_segment.api_test'),
children: [
{ {
title: this.$t('project.code_segment.api_test'), title: this.$t('project.code_segment.import_api_test'),
children: [ command: "api_definition",
{
title: this.$t('project.code_segment.import_api_test'),
command: "api_definition",
},
{
title: this.$t('project.code_segment.new_api_test'),
command: "new_api_request",
}
]
}, },
{ {
title: this.$t('project.code_segment.custom_value'), title: this.$t('project.code_segment.new_api_test'),
children: [ command: "new_api_request",
{
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_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
},
]
},
{
title: this.$t('project.code_segment.project_env'),
children: [
{
title: this.$t('api_test.request.processor.param_environment_set_global_variable'),
value: 'vars.put(${__metersphere_env_id}+"key","value");\n'+'vars.put("key","value")',
},
]
},
{
title: this.$t('project.code_segment.code_segment'),
children: [
{
title: this.$t('project.code_segment.insert_segment'),
command: "custom_function",
}
]
},
{
title: this.$t('project.code_segment.exception_handle'),
children: [
{
title: this.$t('project.code_segment.stop_test'),
value: 'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());'
},
]
},
{
title: this.$t('project.code_segment.report_handle'),
children: [
{
title: this.$t('api_test.request.processor.code_add_report_length'),
value: 'String report = ctx.getCurrentSampler().getRequestData();\n' +
'if(report!=null){\n' +
' //补足8位长度前置补0\n' +
' String reportlengthStr = String.format("%08d",report.length());\n' +
' report = reportlengthStr+report;\n' +
' ctx.getCurrentSampler().setRequestData(report);\n' +
'}',
},
{
title: this.$t('api_test.request.processor.code_hide_report_length'),
value: '//Get response data\n' +
'String returnData = prev.getResponseDataAsString();\n' +
'if(returnData!=null&&returnData.length()>8){\n' +
'//remove 8 report length \n' +
' String subStringData = returnData.substring(8,returnData.length());\n' +
' if(subStringData.startsWith("<")){\n' +
' returnData = subStringData;\n' +
' prev.setResponseData(returnData);\n' +
' }\n' +
'}',
disabled: this.isPreProcessor
},
]
} }
], ]
isCodeEditAlive: true, },
languages: [ {
'beanshell', "python", "groovy", "nashornScript", "rhinoScript" title: this.$t('project.code_segment.custom_value'),
], children: [
codeEditModeMap: { {
beanshell: 'java', title: this.$t('api_test.request.processor.code_template_get_variable'),
python: 'python', value: 'vars.get("variable_name")',
groovy: 'java', },
nashornScript: 'javascript', {
rhinoScript: 'javascript', title: this.$t('api_test.request.processor.code_template_set_variable'),
}, value: 'vars.put("variable_name", "variable_value")',
codeSpan: 20, },
menuSpan: 4, {
showMenu: true, 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
},
]
},
{
title: this.$t('project.code_segment.project_env'),
children: [
{
title: this.$t('api_test.request.processor.param_environment_set_global_variable'),
value: 'vars.put(${__metersphere_env_id}+"key","value");\n' + 'vars.put("key","value")',
},
]
},
{
title: this.$t('project.code_segment.code_segment'),
children: [
{
title: this.$t('project.code_segment.insert_segment'),
command: "custom_function",
}
]
},
{
title: this.$t('project.code_segment.exception_handle'),
children: [
{
title: this.$t('project.code_segment.stop_test'),
value: 'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());'
},
]
},
{
title: this.$t('project.code_segment.report_handle'),
hideScript: this.isHideScript(),
children: [
{
title: this.$t('api_test.request.processor.code_add_report_length'),
value: 'String report = ctx.getCurrentSampler().getRequestData();\n' +
'if(report!=null){\n' +
' //补足8位长度前置补0\n' +
' String reportlengthStr = String.format("%08d",report.length());\n' +
' report = reportlengthStr+report;\n' +
' ctx.getCurrentSampler().setRequestData(report);\n' +
'}',
},
{
title: this.$t('api_test.request.processor.code_hide_report_length'),
value: '//Get response data\n' +
'String returnData = prev.getResponseDataAsString();\n' +
'if(returnData!=null&&returnData.length()>8){\n' +
'//remove 8 report length \n' +
' String subStringData = returnData.substring(8,returnData.length());\n' +
' if(subStringData.startsWith("<")){\n' +
' returnData = subStringData;\n' +
' prev.setResponseData(returnData);\n' +
' }\n' +
'}',
disabled: this.isPreProcessor,
},
]
} }
],
isCodeEditAlive: true,
languages: [
'beanshell', "python", "groovy", "nashornScript", "rhinoScript"
],
codeEditModeMap: {
beanshell: 'java',
python: 'python',
groovy: 'java',
nashornScript: 'javascript',
rhinoScript: 'javascript',
}, },
created() { codeSpan: 20,
this.jsr223ProcessorData = this.jsr223Processor; menuSpan: 4,
}, showMenu: true,
props: {
isReadOnly: {
type: Boolean,
default:
false
},
jsr223Processor: {
type: Object,
},
isPreProcessor: {
type: Boolean,
default:
false
},
node: {},
},
watch: {
jsr223Processor() {
this.reload();
}
}
,
methods: {
addTemplate(template) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = "";
}
this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';';
}
this.reload();
},
reload() {
this.isCodeEditAlive = false;
this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223ProcessorData.scriptLanguage = language;
this.$emit("languageChange");
},
addCustomFuncScript(script) {
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script ?
this.jsr223ProcessorData.script + '\n\n' + script : script;
this.reload();
},
switchMenu() {
this.showMenu = !this.showMenu;
if (this.showMenu) {
this.codeSpan = 20;
this.menuSpan = 4;
} else {
this.codeSpan = 24;
this.menuSpan = 0;
}
},
handleCodeTemplate(code) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = code;
} else {
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script + '\n' + code;
}
this.reload();
},
}
} }
},
created() {
this.jsr223ProcessorData = this.jsr223Processor;
},
props: {
isReadOnly: {
type: Boolean,
default:
false
},
jsr223Processor: {
type: Object,
},
protocol: String,
isPreProcessor: {
type: Boolean,
default:
false
},
node: {},
},
watch: {
jsr223Processor() {
this.reload();
}
},
methods: {
addTemplate(template) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = "";
}
this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';';
}
this.reload();
},
isHideScript() {
return this.protocol !== 'TCP';
},
reload() {
this.isCodeEditAlive = false;
this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223ProcessorData.scriptLanguage = language;
this.$emit("languageChange");
},
addCustomFuncScript(script) {
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script ?
this.jsr223ProcessorData.script + '\n\n' + script : script;
this.reload();
},
switchMenu() {
this.showMenu = !this.showMenu;
if (this.showMenu) {
this.codeSpan = 20;
this.menuSpan = 4;
} else {
this.codeSpan = 24;
this.menuSpan = 0;
}
},
handleCodeTemplate(code) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = code;
} else {
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script + '\n' + code;
}
this.reload();
},
}
}
</script> </script>
<style scoped> <style scoped>
.ace_editor { .ace_editor {
border-radius: 5px; border-radius: 5px;
} }
.script-content { .script-content {
height: calc(100vh - 570px); height: calc(100vh - 570px);
min-height: 440px; min-height: 440px;
} }
.script-index { .script-index {
padding: 0 20px; padding: 0 20px;
width: 230px; width: 230px;
} }
.template-title { .template-title {
margin-bottom: 5px; margin-bottom: 5px;
font-weight: bold; font-weight: bold;
font-size: 15px; font-size: 15px;
} }
.document-url { .document-url {
margin-top: 10px; margin-top: 10px;
} }
.instructions-icon { .instructions-icon {
margin-left: 5px; margin-left: 5px;
} }
.ms-dropdown { .ms-dropdown {
margin-bottom: 20px; margin-bottom: 20px;
} }
.show-menu { .show-menu {
text-align:center; text-align: center;
font-weight: bold; font-weight: bold;
color:#935aa1; color: #935aa1;
font-size: 18px; font-size: 18px;
cursor: pointer; cursor: pointer;
} }
.show-menu:hover {
color:#935aa1; .show-menu:hover {
} color: #935aa1;
}
</style> </style>

View File

@ -18,6 +18,7 @@
:jsr223-processor="jsr223Processor" :jsr223-processor="jsr223Processor"
:is-pre-processor="isPreProcessor" :is-pre-processor="isPreProcessor"
:node="node" :node="node"
:protocol="protocol"
:is-read-only="this.jsr223Processor.disabled"/> :is-read-only="this.jsr223Processor.disabled"/>
</legend> </legend>
<template v-slot:debugStepCode> <template v-slot:debugStepCode>
@ -83,6 +84,7 @@ export default {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
protocol:String,
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: default:

View File

@ -57,7 +57,7 @@
<div class="el-step__icon-inner">{{ request.preSize }}</div> <div class="el-step__icon-inner">{{ request.preSize }}</div>
</div> </div>
</span> </span>
<ms-jmx-step :request="request" :apiId="request.id" :response="response" :tab-type="'pre'" <ms-jmx-step :request="request" :apiId="request.id" protocol="TCP" :response="response" :tab-type="'pre'"
ref="preStep"/> ref="preStep"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.post_operation')" name="postOperate" <el-tab-pane :label="$t('api_test.definition.request.post_operation')" name="postOperate"
@ -68,7 +68,7 @@
<div class="el-step__icon-inner">{{ request.postSize }}</div> <div class="el-step__icon-inner">{{ request.postSize }}</div>
</div> </div>
</span> </span>
<ms-jmx-step :request="request" :apiId="request.id" :response="response" :tab-type="'post'" <ms-jmx-step :request="request" :apiId="request.id" protocol="TCP" :response="response" :tab-type="'post'"
ref="postStep"/> ref="postStep"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.assertions_rule')" name="assertionsRule" <el-tab-pane :label="$t('api_test.definition.request.assertions_rule')" name="assertionsRule"
@ -79,7 +79,7 @@
<div class="el-step__icon-inner">{{ request.ruleSize }}</div> <div class="el-step__icon-inner">{{ request.ruleSize }}</div>
</div> </div>
</span> </span>
<ms-jmx-step :request="request" :apiId="request.id" :response="response" @reload="reloadBody" <ms-jmx-step :request="request" :apiId="request.id" protocol="TCP" :response="response" @reload="reloadBody"
:tab-type="'assertionsRule'" ref="assertionsRule"/> :tab-type="'assertionsRule'" ref="assertionsRule"/>
</el-tab-pane> </el-tab-pane>

View File

@ -18,7 +18,8 @@
:value="item.id"> :value="item.id">
</el-option> </el-option>
</el-select> </el-select>
<el-button size="mini" @click="add" type="primary" v-if="tabType !== 'assertionsRule'" :disabled="request.disabled"> <el-button size="mini" @click="add" type="primary" v-if="tabType !== 'assertionsRule'"
:disabled="request.disabled">
{{ $t('api_test.request.assertions.add') }} {{ $t('api_test.request.assertions.add') }}
</el-button> </el-button>
</p> </p>
@ -37,6 +38,7 @@
v-if="data.type==='JSR223PreProcessor'" v-if="data.type==='JSR223PreProcessor'"
@remove="remove" @remove="remove"
@copyRow="copyRow" @copyRow="copyRow"
:protocol="protocol"
:title="$t('api_test.definition.request.pre_script')" :title="$t('api_test.definition.request.pre_script')"
:jsr223-processor="data" :jsr223-processor="data"
color="#B8741A" color="#B8741A"
@ -53,7 +55,8 @@
color="#B8741A" color="#B8741A"
background-color="#F9F1EA"/> background-color="#F9F1EA"/>
<ms-constant-timer :inner-step="true" :timer="data" :node="node" v-if="data.type ==='ConstantTimer'" @remove="remove"/> <ms-constant-timer :inner-step="true" :timer="data" :node="node" v-if="data.type ==='ConstantTimer'"
@remove="remove"/>
</div> </div>
<div v-if="tabType ==='post'"> <div v-if="tabType ==='post'">
@ -62,6 +65,7 @@
v-if="data.type ==='JSR223PostProcessor'" v-if="data.type ==='JSR223PostProcessor'"
@copyRow="copyRow" @copyRow="copyRow"
@remove="remove" @remove="remove"
:protocol="protocol"
:is-read-only="false" :is-read-only="false"
:title="$t('api_test.definition.request.post_script')" :title="$t('api_test.definition.request.post_script')"
:jsr223-processor="data" :jsr223-processor="data"
@ -150,6 +154,7 @@ export default {
}, },
isShowEnable: Boolean, isShowEnable: Boolean,
jsonPathList: Array, jsonPathList: Array,
protocol: String,
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
@ -429,7 +434,18 @@ export default {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') { if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true; required = true;
} }
keyValues.push(new KeyValue({name: line[0], required: required, value: line[2], description: line[3], type: "text", valid: false, file: false, encode: true, enable: true, contentType: "text/plain"})); keyValues.push(new KeyValue({
name: line[0],
required: required,
value: line[2],
description: line[3],
type: "text",
valid: false,
file: false,
encode: true,
enable: true,
contentType: "text/plain"
}));
}) })
keyValues.forEach(item => { keyValues.forEach(item => {
switch (this.activeName) { switch (this.activeName) {

View File

@ -8,7 +8,7 @@
</el-link> </el-link>
</div> </div>
<div v-for="(menu, index) in menus" :key="index"> <div v-for="(menu, index) in menus" :key="index">
<span class="link-type"> <span class="link-type" v-if="!menu.hideScript">
<i class="icon el-icon-arrow-right" style="font-weight: bold; margin-right: 2px;" <i class="icon el-icon-arrow-right" style="font-weight: bold; margin-right: 2px;"
@click="active(menu)" :class="{'is-active': menu.open}"></i> @click="active(menu)" :class="{'is-active': menu.open}"></i>
<span @click="active(menu)" class="nav-menu-title nav-font">{{menu.title}}</span> <span @click="active(menu)" class="nav-menu-title nav-font">{{menu.title}}</span>
@ -17,7 +17,7 @@
<el-collapse-transition> <el-collapse-transition>
<div v-if="menu.open"> <div v-if="menu.open">
<div v-for="(child, key) in menu.children" :key="key" class="func-div"> <div v-for="(child, key) in menu.children" :key="key" class="func-div">
<el-link :disabled="child.disabled" @click="handleClick(child)" class="func-link nav-font">{{child.title}}</el-link> <el-link :disabled="child.disabled" @click="handleClick(child)" class="func-link nav-font">{{child.disabled}}{{child.title}}</el-link>
</div> </div>
</div> </div>
</el-collapse-transition> </el-collapse-transition>