Merge branch 'v1.6'

This commit is contained in:
Captain.B 2021-01-06 10:04:27 +08:00
commit f3dc01d3a9
20 changed files with 88 additions and 33 deletions

6
Jenkinsfile vendored
View File

@ -5,9 +5,9 @@ pipeline {
} }
} }
options { quietPeriod(600) } options { quietPeriod(600) }
parameters { environment {
string(name: 'IMAGE_NAME', defaultValue: 'metersphere', description: '构建后的 Docker 镜像名称') IMAGE_NAME = 'metersphere'
string(name: 'IMAGE_PREFIX', defaultValue: 'registry.cn-qingdao.aliyuncs.com/metersphere', description: '构建后的 Docker 镜像带仓库名的前缀') IMAGE_PREFIX = 'registry.cn-qingdao.aliyuncs.com/metersphere'
} }
stages { stages {
stage('Build/Test') { stage('Build/Test') {

View File

@ -324,8 +324,11 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
if (responseAssertionResult.isPass()) { if (responseAssertionResult.isPass()) {
requestResult.addPassAssertions(); requestResult.addPassAssertions();
} }
//xpath 提取错误会添加断言错误
if (!responseAssertionResult.getMessage().contains("The required item type of the first operand of")) {
responseResult.getAssertions().add(responseAssertionResult); responseResult.getAssertions().add(responseAssertionResult);
} }
}
responseResult.setConsole(getConsole()); responseResult.setConsole(getConsole());
return requestResult; return requestResult;

View File

@ -1,5 +1,6 @@
package io.metersphere.api.jmeter; package io.metersphere.api.jmeter;
import com.alibaba.fastjson.JSON;
import io.github.ningyu.jmeter.plugin.dubbo.sample.DubboSample; import io.github.ningyu.jmeter.plugin.dubbo.sample.DubboSample;
import org.apache.jmeter.extractor.JSR223PostProcessor; import org.apache.jmeter.extractor.JSR223PostProcessor;
import org.apache.jmeter.extractor.RegexExtractor; import org.apache.jmeter.extractor.RegexExtractor;
@ -32,10 +33,27 @@ public class JMeterVars {
*/ */
public static void addVars(Integer testId, JMeterVariables vars, String extract) { public static void addVars(Integer testId, JMeterVariables vars, String extract) {
JMeterVariables vs = new JMeterVariables(); JMeterVariables vs = new JMeterVariables();
if (!StringUtils.isEmpty(extract) && vars != null) { if (!StringUtils.isEmpty(extract) && vars != null) {
List<String> extracts = Arrays.asList(extract.split(";")); List<String> extracts = Arrays.asList(extract.split(";"));
Optional.ofNullable(extracts).orElse(new ArrayList<>()).forEach(item -> { Optional.ofNullable(extracts).orElse(new ArrayList<>()).forEach(item -> {
String nrKey = item + "_matchNr";
Object nr = vars.get(nrKey);
if (nr != null) {
int nrv = 0;
try {
nrv = Integer.valueOf(String.valueOf(nr));
} catch (Exception e) {
}
if (nrv > 0) {
List<Object> data = new ArrayList<>();
for (int i = 1; i < nrv + 1; i++) {
data.add(vars.get(item + "_" + i));
}
String array = JSON.toJSONString(data);
vars.put(item, array);
}
}
vs.put(item, vars.get(item) == null ? "" : vars.get(item)); vs.put(item, vars.get(item) == null ? "" : vars.get(item));
}); });
vs.remove("TESTSTART.MS"); // 标示变量移除 vs.remove("TESTSTART.MS"); // 标示变量移除

View File

@ -97,8 +97,10 @@ public class Swagger2Parser extends ApiImportAbstractParser {
String name = ""; String name = "";
if (StringUtils.isNotBlank(operation.getSummary())) { if (StringUtils.isNotBlank(operation.getSummary())) {
name = operation.getSummary(); name = operation.getSummary();
} else { } else if (StringUtils.isNotBlank(operation.getOperationId())) {
name = operation.getOperationId(); name = operation.getOperationId();
} else {
name = path;
} }
return buildApiDefinition(id, name, path, method); return buildApiDefinition(id, name, path, method);
} }

View File

@ -129,8 +129,10 @@ public class Swagger3Parser extends ApiImportAbstractParser {
String name = ""; String name = "";
if (StringUtils.isNotBlank(operation.getSummary())) { if (StringUtils.isNotBlank(operation.getSummary())) {
name = operation.getSummary(); name = operation.getSummary();
} else { } else if (StringUtils.isNotBlank(operation.getOperationId())) {
name = operation.getOperationId(); name = operation.getOperationId();
} else {
name = path;
} }
return buildApiDefinition(id, name, path, method); return buildApiDefinition(id, name, path, method);
} }

View File

@ -14,6 +14,7 @@ import io.metersphere.track.service.TestPlanApiCaseService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
@ -60,6 +61,9 @@ public class ApiDefinitionExecResultService {
} }
public void deleteByResourceIds(List<String> ids) { public void deleteByResourceIds(List<String> ids) {
if (CollectionUtils.isEmpty(ids)) {
return;
}
ApiDefinitionExecResultExample example = new ApiDefinitionExecResultExample(); ApiDefinitionExecResultExample example = new ApiDefinitionExecResultExample();
example.createCriteria().andResourceIdIn(ids); example.createCriteria().andResourceIdIn(ids);
apiDefinitionExecResultMapper.deleteByExample(example); apiDefinitionExecResultMapper.deleteByExample(example);

View File

@ -88,7 +88,7 @@ public class JmeterFileService {
if (!CollectionUtils.isEmpty(testData)) { if (!CollectionUtils.isEmpty(testData)) {
for (String k : testData.keySet()) { for (String k : testData.keySet()) {
String v = testData.get(k); String v = testData.get(k);
files.put("k", v.getBytes(StandardCharsets.UTF_8)); files.put(k, v.getBytes(StandardCharsets.UTF_8));
} }
} }
@ -97,7 +97,7 @@ public class JmeterFileService {
if (!CollectionUtils.isEmpty(jarFiles)) { if (!CollectionUtils.isEmpty(jarFiles)) {
for (String k : jarFiles.keySet()) { for (String k : jarFiles.keySet()) {
byte[] v = jarFiles.get(k); byte[] v = jarFiles.get(k);
files.put("k", v); files.put(k, v);
} }
} }

View File

@ -35,7 +35,7 @@
ref="codeEdit"/> ref="codeEdit"/>
</el-col> </el-col>
<el-col :span="4" class="script-index"> <el-col :span="4" class="script-index">
<ms-dropdown :default-command="jsr223ProcessorData.language" :commands="languages" @command="languageChange"/> <ms-dropdown :default-command="jsr223ProcessorData.scriptLanguage" :commands="languages" @command="languageChange"/>
<div class="template-title">{{$t('api_test.request.processor.code_template')}}</div> <div class="template-title">{{$t('api_test.request.processor.code_template')}}</div>
<div v-for="(template, index) in codeTemplates" :key="index" class="code-template"> <div v-for="(template, index) in codeTemplates" :key="index" class="code-template">
<el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link> <el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link>
@ -135,7 +135,7 @@
this.jsr223ProcessorData.script = ""; this.jsr223ProcessorData.script = "";
} }
this.jsr223ProcessorData.script += template.value; this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.language === 'beanshell') { if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';'; this.jsr223ProcessorData.script += ';';
} }
this.reload(); this.reload();
@ -151,7 +151,7 @@
this.$nextTick(() => (this.isCodeEditAlive = true)); this.$nextTick(() => (this.isCodeEditAlive = true));
}, },
languageChange(language) { languageChange(language) {
this.jsr223ProcessorData.language = language; this.jsr223ProcessorData.scriptLanguage = language;
}, },
changeActive() { changeActive() {
this.jsr223ProcessorData.active = !this.jsr223ProcessorData.active; this.jsr223ProcessorData.active = !this.jsr223ProcessorData.active;

View File

@ -7,6 +7,7 @@
<el-input placeholder="搜索" @blur="initTable" class="search-input" size="small" @keyup.enter.native="initTable" v-model="condition.name"/> <el-input placeholder="搜索" @blur="initTable" class="search-input" size="small" @keyup.enter.native="initTable" v-model="condition.name"/>
<el-table v-loading="result.loading" <el-table v-loading="result.loading"
border border
:data="tableData" row-key="id" class="test-content adjust-table" :data="tableData" row-key="id" class="test-content adjust-table"
@ -253,8 +254,8 @@
.search-input { .search-input {
float: right; float: right;
width: 300px; width: 30%;
/*margin-bottom: 20px;*/ margin-bottom: 20px;
margin-right: 20px; margin-right: 20px;
} }

View File

@ -15,7 +15,7 @@ export default class JSR223PostProcessor extends PostProcessor {
constructor(options = DEFAULT_OPTIONS) { constructor(options = DEFAULT_OPTIONS) {
super(options); super(options);
this.type = "JSR223PostProcessor"; this.type = "JSR223PostProcessor";
this.scriptLanguage = "java"; this.scriptLanguage = "beanshell";
this.parameters = []; this.parameters = [];
this.filename = undefined; this.filename = undefined;
this.cacheKey = true; this.cacheKey = true;

View File

@ -15,7 +15,7 @@ export default class JSR223PreProcessor extends PostProcessor {
constructor(options = DEFAULT_OPTIONS) { constructor(options = DEFAULT_OPTIONS) {
super(options); super(options);
this.type = "JSR223PreProcessor"; this.type = "JSR223PreProcessor";
this.scriptLanguage = "java"; this.scriptLanguage = "beanshell";
this.parameters = []; this.parameters = [];
this.filename = undefined; this.filename = undefined;
this.cacheKey = undefined; this.cacheKey = undefined;

View File

@ -80,6 +80,7 @@
<el-table-column <el-table-column
prop="casePassingRate" prop="casePassingRate"
:width="100"
:label="$t('api_test.definition.api_case_passing_rate')" :label="$t('api_test.definition.api_case_passing_rate')"
show-overflow-tooltip/> show-overflow-tooltip/>

View File

@ -122,7 +122,7 @@ export default {
<style scoped> <style scoped>
.protocol-select { .protocol-select {
width: 95px; width: 92px;
height: 30px; height: 30px;
} }

View File

@ -34,7 +34,7 @@
ref="codeEdit"/> ref="codeEdit"/>
</el-col> </el-col>
<el-col :span="4" class="script-index"> <el-col :span="4" class="script-index">
<ms-dropdown :default-command="jsr223ProcessorData.language" :commands="languages" @command="languageChange"/> <ms-dropdown :default-command="jsr223ProcessorData.scriptLanguage" :commands="languages" @command="languageChange"/>
<div class="template-title">{{$t('api_test.request.processor.code_template')}}</div> <div class="template-title">{{$t('api_test.request.processor.code_template')}}</div>
<div v-for="(template, index) in codeTemplates" :key="index" class="code-template"> <div v-for="(template, index) in codeTemplates" :key="index" class="code-template">
<el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link> <el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link>
@ -140,7 +140,7 @@
this.jsr223ProcessorData.script = ""; this.jsr223ProcessorData.script = "";
} }
this.jsr223ProcessorData.script += template.value; this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.language === 'beanshell') { if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';'; this.jsr223ProcessorData.script += ';';
} }
this.reload(); this.reload();
@ -156,7 +156,7 @@
this.$nextTick(() => (this.isCodeEditAlive = true)); this.$nextTick(() => (this.isCodeEditAlive = true));
}, },
languageChange(language) { languageChange(language) {
this.jsr223ProcessorData.language = language; this.jsr223ProcessorData.scriptLanguage = language;
}, },
changeActive() { changeActive() {
this.active = !this.active; this.active = !this.active;

View File

@ -5,7 +5,7 @@
</el-link> </el-link>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item> <el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
<el-dropdown-item :disabled="isCaseEdit" command="add_plan">{{ $t('api_test.automation.batch_add_plan') }}</el-dropdown-item> <!--<el-dropdown-item :disabled="isCaseEdit" command="add_plan">{{ $t('api_test.automation.batch_add_plan') }}</el-dropdown-item>-->
</el-dropdown-menu> </el-dropdown-menu>
<ms-reference-view ref="viewRef"/> <ms-reference-view ref="viewRef"/>
<!--测试计划--> <!--测试计划-->

View File

@ -842,8 +842,7 @@ export class JSR223Processor extends BaseConfig {
this.active = false; this.active = false;
this.type = "JSR223Processor"; this.type = "JSR223Processor";
this.script = undefined; this.script = undefined;
this.language = "beanshell"; this.scriptLanguage = "beanshell";
this.scriptLanguage = "java";
this.enable = true; this.enable = true;
this.hashTree = []; this.hashTree = [];
this.set(options); this.set(options);

View File

@ -118,7 +118,21 @@ export default {
}, },
copyRequest(index) { copyRequest(index) {
let request = this.scenario.requests[index]; let request = this.scenario.requests[index];
this.scenario.requests.push(new RequestFactory(request)); let item = new RequestFactory(request);
if (item.body && item.body.kvs) {
item.body.kvs.forEach(kv => {
let files = [];
if (kv.files) {
kv.files.forEach(file => {
let fileCopy = {};
Object.assign(fileCopy, file);
files.push(fileCopy);
})
}
kv.files = files;
});
}
this.scenario.requests.push(item);
}, },
disableRequest(index) { disableRequest(index) {
this.scenario.requests[index].enable = false; this.scenario.requests[index].enable = false;

View File

@ -59,7 +59,11 @@
<style scoped> <style scoped>
.el-dialog { .el-dialog {
min-height: 700px; min-height: 600px;
}
.tree-aside {
max-height: 600px;
} }
.el-dialog >>> .el-dialog__body { .el-dialog >>> .el-dialog__body {

View File

@ -9,7 +9,7 @@
<template> <template>
<ckeditor v-if="!isReportView" :editor="editor" v-model="preview.content" :config="editorConfig"></ckeditor> <ckeditor v-if="!isReportView" :editor="editor" v-model="preview.content" :config="editorConfig"></ckeditor>
<div v-if="isReportView" v-html="preview.content"></div> <div class="rich-text-content" v-if="isReportView" v-html="preview.content"></div>
</template> </template>
</common-component> </common-component>
@ -53,4 +53,11 @@
<style scoped> <style scoped>
.rich-text-content >>> .table td {
border: solid 1px #e6e6e6;
min-width: 2em;
padding: .4em;
}
</style> </style>

View File

@ -142,9 +142,9 @@ html,body {
border: 1px solid #DCDFE6; border: 1px solid #DCDFE6;
border-radius:5px; border-radius:5px;
padding: 0px; padding: 0px;
margin-top: 5px; margin-top: 10px;
display: inline-block; display: inline-block;
margin-top: 25px; /*margin-top: 25px;*/
width: 50px; width: 50px;
} }
@ -164,8 +164,8 @@ html,body {
.ms-select-all .el-icon-arrow-down { .ms-select-all .el-icon-arrow-down {
position: absolute; position: absolute;
display: inline-block; display: inline-block;
top: -3px; top: -7px;
left: -40px; left: -38px;
width: 30px; width: 30px;
} }
/* 表格全选样式 --> */ /* 表格全选样式 --> */