增加提取功能的JMX内容

This commit is contained in:
q4speed 2020-05-12 15:26:55 +08:00
parent bc294c354c
commit eddc19fa75
6 changed files with 165 additions and 22 deletions

View File

@ -122,7 +122,8 @@
})
},
cancel: function () {
this.$router.push('/api/test/list/all');
console.log(this.test.toJMX().xml)
// this.$router.push('/api/test/list/all');
},
getOptions: function (url) {
let formData = new FormData();

View File

@ -2,8 +2,17 @@
<div>
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
<el-col :span="10">
<el-input v-model="common.variable" maxlength="60" size="small" @input="change"
:placeholder="$t('api_test.request.extract.variable_name')"/>
<div class="variable">
<el-input v-model="common.variable" maxlength="60" size="small" @input="change"
:placeholder="$t('api_test.request.extract.variable_name')"/>
<div class="variable-combine" v-if="common.variable && edit">
<div class="value">{{common.value}}</div>
<el-tooltip :content="$t('api_test.request.extract.copied')" manual v-model="visible" placement="top"
:visible-arrow="false">
<i class="el-icon-copy-document copy" @click="copy"></i>
</el-tooltip>
</div>
</div>
</el-col>
<el-col>
<el-input v-model="common.expression" maxlength="255" size="small" :placeholder="expression"/>
@ -43,6 +52,12 @@
list: Array
},
data() {
return {
visible: false
}
},
methods: {
add() {
this.list.push(new ExtractCommon(this.extractType, this.common));
@ -58,6 +73,21 @@
this.common.variable = null;
this.common.expression = null;
this.common.value = null;
},
copy() {
let input = document.createElement("input");
document.body.appendChild(input);
input.value = this.common.value;
input.select();
if (input.setSelectionRange) {
input.setSelectionRange(0, input.value.length);
}
document.execCommand("copy");
document.body.removeChild(input);
this.visible = true;
setTimeout(() => {
this.visible = false;
}, 1000);
}
},
@ -79,6 +109,37 @@
</script>
<style scoped>
.variable {
position: relative;
}
.variable-combine {
color: #7F7F7F;
max-width: 80px;
line-height: 32px;
position: absolute;
top: 0;
right: 25px;
margin-right: -20px;
display: flex;
align-items: center;
}
.variable-combine .value {
display: inline-block;
max-width: 60px;
margin-right: 10px;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.variable-combine .copy {
font-size: 14px;
cursor: pointer;
color: #1E90FF;
}
.extract-btn {
width: 60px;
}

View File

@ -168,7 +168,7 @@ export class DefaultTestElement extends TestElement {
}
export class TestPlan extends DefaultTestElement {
constructor(testName) {
constructor(testName, args) {
super('TestPlan', 'TestPlanGui', 'TestPlan', testName || 'TestPlan');
this.boolProp("TestPlan.functional_mode", false);
@ -176,6 +176,7 @@ export class TestPlan extends DefaultTestElement {
this.boolProp("TestPlan.tearDown_on_shutdown", true);
this.stringProp("TestPlan.comments", "");
this.stringProp("TestPlan.user_define_classpath", "");
this.add(new ElementArguments(args, "TestPlan.user_defined_variables", "User Defined Variables"));
}
}
@ -382,25 +383,59 @@ export class BackendListener extends DefaultTestElement {
}
export class ElementArguments extends Element {
constructor(args) {
constructor(args, name, testName) {
super('elementProp', {
name: "arguments",
name: name || "arguments",
elementType: "Arguments",
guiclass: "ArgumentsPanel",
testclass: "Arguments",
testname: testName || "",
enabled: "true"
});
let collectionProp = this.collectionProp('Arguments.arguments');
args.forEach(arg => {
let elementProp = collectionProp.elementProp(arg.name, 'Argument');
elementProp.stringProp('Argument.name', arg.name);
elementProp.stringProp('Argument.value', arg.value);
elementProp.stringProp('Argument.metadata', "=");
});
if (args) {
args.forEach(arg => {
let elementProp = collectionProp.elementProp(arg.name, 'Argument');
elementProp.stringProp('Argument.name', arg.name);
elementProp.stringProp('Argument.value', arg.value);
elementProp.stringProp('Argument.metadata', "=");
});
}
}
}
export class Class {
export class RegexExtractor extends DefaultTestElement {
constructor(testName, props) {
super('RegexExtractor', 'RegexExtractorGui', 'RegexExtractor', testName || 'Regular Expression Extractor');
this.props = props || {}
this.stringProp('RegexExtractor.useHeaders', props.headers);
this.stringProp('RegexExtractor.refname', props.name);
this.stringProp('RegexExtractor.regex', props.expression);
this.stringProp('RegexExtractor.template', props.template);
this.stringProp('RegexExtractor.default', props.default);
this.stringProp('RegexExtractor.match_number', props.match);
}
}
export class JSONPostProcessor extends DefaultTestElement {
constructor(testName, props) {
super('JSONPostProcessor', 'JSONPostProcessorGui', 'JSONPostProcessor', testName || 'JSON Extractor');
this.props = props || {}
this.stringProp('JSONPostProcessor.referenceNames', props.name);
this.stringProp('JSONPostProcessor.jsonPathExprs', props.expression);
this.stringProp('JSONPostProcessor.match_numbers', props.match);
}
}
export class XPath2Extractor extends DefaultTestElement {
constructor(testName, props) {
super('XPath2Extractor', 'XPath2ExtractorGui', 'XPath2Extractor', testName || 'XPath2 Extractor');
this.props = props || {}
this.stringProp('XPathExtractor2.default', props.default);
this.stringProp('XPathExtractor2.refname', props.name);
this.stringProp('XPathExtractor2.xpathQuery', props.expression);
this.stringProp('XPathExtractor2.namespaces', props.namespaces);
this.stringProp('XPathExtractor2.matchNumber', props.match);
}
}

View File

@ -12,7 +12,7 @@ import {
ResponseCodeAssertion,
ResponseDataAssertion,
ResponseHeadersAssertion,
BackendListener
BackendListener, RegexExtractor, JSONPostProcessor, XPath2Extractor
} from "./JMX";
export const uuid = function () {
@ -414,6 +414,8 @@ class JMXGenerator {
this.addRequestAssertion(httpSamplerProxy, request);
this.addRequestExtractor(httpSamplerProxy, request);
threadGroup.put(httpSamplerProxy);
})
@ -486,6 +488,48 @@ class JMXGenerator {
}
}
addRequestExtractor(httpSamplerProxy, request) {
let extract = request.extract;
if (extract.regex.length > 0) {
extract.regex.filter(this.filter).forEach(regex => {
httpSamplerProxy.put(this.getExtractor(regex));
})
}
if (extract.json.length > 0) {
extract.json.filter(this.filter).forEach(json => {
httpSamplerProxy.put(this.getExtractor(json));
})
}
if (extract.xpath.length > 0) {
extract.xpath.filter(this.filter).forEach(xpath => {
httpSamplerProxy.put(this.getExtractor(xpath));
})
}
}
getExtractor(extractCommon) {
let props = {
name: extractCommon.variable,
expression: extractCommon.expression,
}
let testName = props.name
switch (extractCommon.type) {
case EXTRACT_TYPE.REGEX:
testName += " RegexExtractor";
props.headers = "false"; // 对应jMeter body
props.template = "$1$";
return new RegexExtractor(testName, props);
case EXTRACT_TYPE.JSON_PATH:
testName += " JSONExtractor";
return new JSONPostProcessor(testName, props);
case EXTRACT_TYPE.XPATH:
testName += " XPath2Evaluator";
return new XPath2Extractor(testName, props);
}
}
addBackendListener(threadGroup) {
let testName = 'API Backend Listener';
let className = 'io.metersphere.api.jmeter.APIBackendListenerClient';

View File

@ -95,16 +95,16 @@ export default {
'please_choose_member': 'Please Choose Member',
'search_by_name': 'Search by name',
'modify_personal_info': 'Modify Personal Information',
'edit_password':'Edit_Password',
'edit_information':'Edit_Information',
'edit_password': 'Edit_Password',
'edit_information': 'Edit_Information',
'input_name': 'Please enter a user name',
'input_email': 'Please enter a email',
'special_characters_are_not_supported': 'Special characters are not supported',
'mobile_number_format_is_incorrect': 'Mobile number format is incorrect',
'email_format_is_incorrect': 'Email format is incorrect',
'password_format_is_incorrect': 'Password format is incorrect (At least 8-16 characters, at least 1 uppercase letter, 1 lowercase letter and 1 number)',
'old_password':'Old Password',
'new_password':'New Password',
'old_password': 'Old Password',
'new_password': 'New Password',
},
user: {
'create': 'Create',
@ -252,6 +252,7 @@ export default {
regex_expression: "Regular expression",
json_path_expression: "JSONPath expression",
xpath_expression: "XPath expression",
copied: "Copied"
}
}
},

View File

@ -243,18 +243,19 @@ export default {
start_with: "以...开始",
end_with: "以...结束",
value: "值",
expression: "表达式",
expression: "Perl型正则表达式",
response_in_time: "响应时间在...毫秒以内",
},
extract: {
label: "提取",
select_type: "请选择类型",
description: "从响应中提取数据并将其存储在变量中,在后续请求中使用变量。",
description: "从响应结果中提取数据并将其存储在变量中,在后续请求中使用变量。",
regex: "正则",
variable_name: "变量名",
regex_expression: "正则表达式",
regex_expression: "Perl型正则表达式",
json_path_expression: "JSONPath表达式",
xpath_expression: "XPath表达式",
copied: "已拷贝"
}
}
},