This commit is contained in:
fit2-zhao 2021-01-05 15:34:31 +08:00
commit b65c79424b
24 changed files with 178 additions and 97 deletions

View File

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

View File

@ -1,5 +1,6 @@
package io.metersphere.api.jmeter;
import com.alibaba.fastjson.JSON;
import io.github.ningyu.jmeter.plugin.dubbo.sample.DubboSample;
import org.apache.jmeter.extractor.JSR223PostProcessor;
import org.apache.jmeter.extractor.RegexExtractor;
@ -30,12 +31,29 @@ public class JMeterVars {
* @param vars
* @param extract
*/
public static void addVars(Integer testId, JMeterVariables vars, String extract) {
public static void addVars(Integer testId, JMeterVariables vars, String extract) {
JMeterVariables vs = new JMeterVariables();
if (!StringUtils.isEmpty(extract) && vars != null) {
List<String> extracts = Arrays.asList(extract.split(";"));
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.remove("TESTSTART.MS"); // 标示变量移除

View File

@ -18,7 +18,7 @@
<select id="list" resultType="io.metersphere.api.dto.definition.TestPlanApiCaseDTO">
select
t.id, t.environment_id, t.create_time, t.update_time,
c.id as case_id, c.project_id, c.name, c.api_definition_id, c.priority, c.description, c.create_user_id, c.update_user_id,
c.id as case_id, c.project_id, c.name, c.api_definition_id, c.priority, c.description, c.create_user_id, c.update_user_id, c.num,
a.module_id, a.path, a.protocol, t.status execResult
from
test_plan_api_case t

View File

@ -88,28 +88,22 @@ public interface ParamConstants {
}
}
enum MAIL {
SERVER("smtp.server", 1),
PORT("smtp.port", 2),
ACCOUNT("smtp.account", 3),
PASSWORD("smtp.password", 4),
SSL("smtp.ssl", 5),
TLS("smtp.tls", 6),
ANON("smtp.anon", 7);
enum MAIL implements ParamConstants{
SERVER("smtp.host"),
PORT("smtp.port"),
ACCOUNT("smtp.account"),
PASSWORD("smtp.password"),
SSL("smtp.ssl"),
TLS("smtp.tls"),
RECIPIENTS("smtp.recipient");
private String key;
private Integer value;
private String value;
private MAIL(String key, Integer value) {
this.key = key;
private MAIL(String value) {
this.value = value;
}
public String getKey() {
return this.key;
}
public Integer getValue() {
public String getValue() {
return this.value;
}
}

View File

@ -5,6 +5,7 @@ import io.metersphere.commons.constants.ParamConstants;
import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.ldap.domain.LdapInfo;
import io.metersphere.notice.domain.MailInfo;
import io.metersphere.service.SystemParameterService;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*;
@ -38,7 +39,7 @@ public class SystemParameterController {
@GetMapping("/mail/info")
@RequiresRoles(value = {RoleConstants.ADMIN})
public Object mailInfo() {
public MailInfo mailInfo() {
return SystemParameterService.mailInfo(ParamConstants.Classify.MAIL.getValue());
}

View File

@ -0,0 +1,15 @@
package io.metersphere.notice.domain;
import lombok.Data;
@Data
public class MailInfo {
private String host;
private String port;
private String account;
private String password;
private String ssl;
private String tls;
private String recipient;
}

View File

@ -11,15 +11,18 @@ import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.ldap.domain.LdapInfo;
import io.metersphere.notice.domain.MailInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.*;
@ -56,7 +59,7 @@ public class SystemParameterService {
parameters.forEach(parameter -> {
SystemParameterExample example = new SystemParameterExample();
if (parameter.getParamKey().equals(ParamConstants.MAIL.PASSWORD.getKey())) {
if (parameter.getParamKey().equals(ParamConstants.MAIL.PASSWORD.getValue())) {
if (!StringUtils.isBlank(parameter.getParamValue())) {
String string = EncryptUtils.aesEncrypt(parameter.getParamValue()).toString();
parameter.setParamValue(string);
@ -82,23 +85,16 @@ public class SystemParameterService {
public void testConnection(HashMap<String, String> hashMap) {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setDefaultEncoding("UTF-8");
javaMailSender.setHost(hashMap.get(ParamConstants.MAIL.SERVER.getKey()));
javaMailSender.setPort(Integer.valueOf(hashMap.get(ParamConstants.MAIL.PORT.getKey())));
javaMailSender.setUsername(hashMap.get(ParamConstants.MAIL.ACCOUNT.getKey()));
javaMailSender.setPassword(hashMap.get(ParamConstants.MAIL.PASSWORD.getKey()));
javaMailSender.setHost(hashMap.get(ParamConstants.MAIL.SERVER.getValue()));
javaMailSender.setPort(Integer.valueOf(hashMap.get(ParamConstants.MAIL.PORT.getValue())));
javaMailSender.setUsername(hashMap.get(ParamConstants.MAIL.ACCOUNT.getValue()));
javaMailSender.setPassword(hashMap.get(ParamConstants.MAIL.PASSWORD.getValue()));
Properties props = new Properties();
boolean isAnon = Boolean.parseBoolean(hashMap.get(ParamConstants.MAIL.ANON.getKey()));
if (isAnon) {
props.put("mail.smtp.auth", "false");
javaMailSender.setUsername(null);
javaMailSender.setPassword(null);
} else {
props.put("mail.smtp.auth", "true");
}
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.SSL.getKey()))) {
String recipients = hashMap.get(ParamConstants.MAIL.RECIPIENTS.getValue());
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.SSL.getValue()))) {
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
}
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.TLS.getKey()))) {
if (BooleanUtils.toBoolean(hashMap.get(ParamConstants.MAIL.TLS.getValue()))) {
props.put("mail.smtp.starttls.enable", "true");
}
props.put("mail.smtp.timeout", "30000");
@ -110,39 +106,53 @@ public class SystemParameterService {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("connection_failed"));
}
if(!StringUtils.isBlank(recipients)){
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = null;
try {
helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(javaMailSender.getUsername());
helper.setSubject("MeterSphere测试邮件 " );
helper.setText("这是一封测试邮件,邮件发送成功", true);
helper.setTo(recipients);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("connection_failed"));
}
}
}
public String getVersion() {
return System.getenv("MS_VERSION");
}
public Object mailInfo(String type) {
public MailInfo mailInfo(String type) {
List<SystemParameter> paramList = this.getParamList(type);
if (CollectionUtils.isEmpty(paramList)) {
paramList = new ArrayList<>();
ParamConstants.MAIL[] values = ParamConstants.MAIL.values();
for (ParamConstants.MAIL value : values) {
SystemParameter systemParameter = new SystemParameter();
if (value.equals(ParamConstants.MAIL.PASSWORD)) {
systemParameter.setType(ParamConstants.Type.PASSWORD.getValue());
} else {
systemParameter.setType(ParamConstants.Type.TEXT.getValue());
MailInfo mailInfo=new MailInfo ();
if (!CollectionUtils.isEmpty(paramList)) {
for (SystemParameter param : paramList) {
if (StringUtils.equals(param.getParamKey(),ParamConstants.MAIL.SERVER.getValue() )) {
mailInfo.setHost(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.PORT.getValue())) {
mailInfo.setPort(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.ACCOUNT.getValue())) {
mailInfo.setAccount(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.PASSWORD.getValue())) {
String password = EncryptUtils.aesDecrypt(param.getParamValue()).toString();
mailInfo.setPassword(password);
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.SSL.getValue())) {
mailInfo.setSsl(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.TLS.getValue())) {
mailInfo.setTls(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.RECIPIENTS.getValue())) {
mailInfo.setRecipient(param.getParamValue());
}
systemParameter.setParamKey(value.getKey());
systemParameter.setSort(value.getValue());
paramList.add(systemParameter);
}
} else {
paramList.stream().filter(param -> param.getParamKey().equals(ParamConstants.MAIL.PASSWORD.getKey())).forEach(param -> {
if (!StringUtils.isBlank(param.getParamValue())) {
String string = EncryptUtils.aesDecrypt(param.getParamValue()).toString();
param.setParamValue(string);
}
});
}
paramList.sort(Comparator.comparingInt(SystemParameter::getSort));
return paramList;
return mailInfo;
}
public void saveLdap(List<SystemParameter> parameters) {

@ -1 +1 @@
Subproject commit 9f4a9bbf46fc1333dbcccea21f83e27e3ec10b1f
Subproject commit 068127ce59ea8b016434ed52a9de4a7a4b13bdb4

View File

@ -35,7 +35,7 @@
ref="codeEdit"/>
</el-col>
<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 v-for="(template, index) in codeTemplates" :key="index" class="code-template">
<el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link>
@ -135,7 +135,7 @@
this.jsr223ProcessorData.script = "";
}
this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.language === 'beanshell') {
if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';';
}
this.reload();
@ -151,7 +151,7 @@
this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223ProcessorData.language = language;
this.jsr223ProcessorData.scriptLanguage = language;
},
changeActive() {
this.jsr223ProcessorData.active = !this.jsr223ProcessorData.active;

View File

@ -3,9 +3,10 @@
:is-api-list-enable="isApiListEnable"
@isApiListEnableChange="isApiListEnableChange">
<ms-environment-select :project-id="projectId" v-if="isTestPlan" :is-read-only="isReadOnly" @setEnvironment="setEnvironment"/>
<ms-environment-select :project-id="projectId" v-if="isTestPlan" :is-read-only="isReadOnly" @setEnvironment="setEnvironment"/>
<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"
border
@ -253,8 +254,8 @@
.search-input {
float: right;
width: 300px;
/*margin-bottom: 20px;*/
width: 30%;
margin-bottom: 20px;
margin-right: 20px;
}

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@
ref="codeEdit"/>
</el-col>
<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 v-for="(template, index) in codeTemplates" :key="index" class="code-template">
<el-link :disabled="template.disabled" @click="addTemplate(template)">{{template.title}}</el-link>
@ -140,7 +140,7 @@
this.jsr223ProcessorData.script = "";
}
this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.language === 'beanshell') {
if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';';
}
this.reload();
@ -156,7 +156,7 @@
this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223ProcessorData.language = language;
this.jsr223ProcessorData.scriptLanguage = language;
},
changeActive() {
this.active = !this.active;

View File

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

View File

@ -118,7 +118,21 @@ export default {
},
copyRequest(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) {
this.scenario.requests[index].enable = false;

View File

@ -36,17 +36,27 @@
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col>
<el-form-item :label="$t('system_parameter_setting.test_recipients')">
<el-input v-model="formInline.recipient" :placeholder="$t('system_parameter_setting.test_recipients')"
autocomplete="new-password" show-password type="text" ref="input">
</el-input>
<p style="color: #8a8b8d">({{ $t('system_parameter_setting.tip') }})</p>
</el-form-item>
</el-col>
</el-row>
<!---->
<div style="border: 0px;margin-bottom: 20px;margin-top: 20px">
<el-checkbox v-model="formInline.SSL" :label="$t('system_parameter_setting.SSL')"></el-checkbox>
<el-checkbox v-model="formInline.ssl" :label="$t('system_parameter_setting.SSL')"></el-checkbox>
</div>
<div style="border: 0px;margin-bottom: 20px">
<el-checkbox v-model="formInline.TLS" :label="$t('system_parameter_setting.TLS')"></el-checkbox>
<el-checkbox v-model="formInline.tls" :label="$t('system_parameter_setting.TLS')"></el-checkbox>
</div>
<div style="border: 0px;margin-bottom: 20px">
<!-- <div style="border: 0px;margin-bottom: 20px">
<el-checkbox v-model="formInline.ANON" :label="$t('system_parameter_setting.SMTP')"></el-checkbox>
</div>
</div>-->
<template v-slot:footer>
</template>
</el-form>
@ -114,13 +124,10 @@ export default {
},
query() {
this.result = this.$get("/system/mail/info", response => {
this.$set(this.formInline, "host", response.data[0].paramValue);
this.$set(this.formInline, "port", response.data[1].paramValue);
this.$set(this.formInline, "account", response.data[2].paramValue);
this.$set(this.formInline, "password", response.data[3].paramValue);
this.$set(this.formInline, "SSL", JSON.parse(response.data[4].paramValue));
this.$set(this.formInline, "TLS", JSON.parse(response.data[5].paramValue));
this.$set(this.formInline, "ANON", JSON.parse(response.data[6].paramValue));
this.formInline = response.data;
this.formInline.ssl = this.formInline.ssl === 'true';
this.formInline.tls = this.formInline.tls === 'true';
console.log(this.formInline)
this.$nextTick(() => {
this.$refs.formInline.clearValidate();
})
@ -137,13 +144,13 @@ export default {
},
testConnection(formInline) {
let param = {
"smtp.server": this.formInline.host,
"smtp.host": this.formInline.host,
"smtp.port": this.formInline.port,
"smtp.account": this.formInline.account,
"smtp.password": this.formInline.password,
"smtp.ssl": this.formInline.SSL,
"smtp.tls": this.formInline.TLS,
"smtp.anon": this.formInline.ANON,
"smtp.ssl": this.formInline.ssl,
"smtp.tls": this.formInline.tls,
"smtp.recipient": this.formInline.recipient,
};
this.$refs[formInline].validate((valid) => {
if (valid) {
@ -171,9 +178,10 @@ export default {
{paramKey: "smtp.port", paramValue: this.formInline.port, type: "text", sort: 2},
{paramKey: "smtp.account", paramValue: this.formInline.account, type: "text", sort: 3},
{paramKey: "smtp.password", paramValue: this.formInline.password, type: "password", sort: 4},
{paramKey: "smtp.ssl", paramValue: this.formInline.SSL, type: "text", sort: 5},
{paramKey: "smtp.tls", paramValue: this.formInline.TLS, type: "text", sort: 6},
{paramKey: "smtp.anon", paramValue: this.formInline.ANON, type: "text", sort: 7}
{paramKey: "smtp.ssl", paramValue: this.formInline.ssl, type: "text", sort: 5},
{paramKey: "smtp.tls", paramValue: this.formInline.tls, type: "text", sort: 6},
{paramKey: "smtp.recipient", paramValue: this.formInline.recipient, type: "text", sort: 8}
]
this.$refs[formInline].validate(valid => {

View File

@ -26,6 +26,7 @@
</template>
</el-table-column>
<el-table-column prop="num" label="ID" show-overflow-tooltip/>
<el-table-column prop="name" :label="$t('api_test.definition.api_name')" show-overflow-tooltip/>
<el-table-column

View File

@ -62,6 +62,10 @@
min-height: 700px;
}
.tree-aside {
max-height: 700px;
}
.el-dialog >>> .el-dialog__body {
padding: 10px 20px;
}

View File

@ -9,7 +9,7 @@
<template>
<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>
</common-component>
@ -53,4 +53,11 @@
<style scoped>
.rich-text-content >>> .table td {
border: solid 1px #e6e6e6;
min-width: 2em;
padding: .4em;
}
</style>

@ -1 +1 @@
Subproject commit 010ad7a5f072a5e9d368c756a2473bbd20781433
Subproject commit 7d43154a7c19732407a8e9ace8a7d1ea13c91f36

View File

@ -1252,6 +1252,8 @@ export default {
host: 'Host number cannot be empty',
port: 'Port cannot be empty',
account: 'Account cannot be empty',
test_recipients:'Test recipients',
tip:'Tip: use as test mail recipient only',
},
i18n: {

View File

@ -1253,6 +1253,8 @@ export default {
host: '主机号不能为空',
port: '端口号不能为空',
account: '账户不能为空',
test_recipients:'测试收件人',
tip:'提示:仅用来作为测试邮件收件人',
},
i18n: {
home: '首页',

View File

@ -1252,6 +1252,8 @@ export default {
host: '主機號不能為空',
port: '端口號不能為空',
account: '賬戶不能為空',
test_recipients:'測試收件人',
tip:'提示:僅用來作為測試郵件收件人',
},
i18n: {
home: '首頁',