feat(接口测试): 环境配置增加hosts

This commit is contained in:
fit2-zhao 2020-09-04 19:35:50 +08:00
parent a8684f4c7b
commit 59aeb11fa1
14 changed files with 499 additions and 247 deletions

View File

@ -1,10 +1,11 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -15,5 +16,6 @@ public class ApiTestEnvironmentWithBLOBs extends ApiTestEnvironment implements S
private String customData;
private String hosts;
private static final long serialVersionUID = 1L;
}

View File

@ -14,6 +14,7 @@
<result column="variables" jdbcType="LONGVARCHAR" property="variables" />
<result column="headers" jdbcType="LONGVARCHAR" property="headers" />
<result column="custom_data" jdbcType="LONGVARCHAR" property="customData" />
<result column="hosts" jdbcType="LONGVARCHAR" property="hosts" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -77,7 +78,7 @@
id, `name`, project_id, protocol, socket, `domain`, port
</sql>
<sql id="Blob_Column_List">
`variables`, headers, custom_data
`variables`, headers, custom_data,hosts
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.ApiTestEnvironmentExample" resultMap="ResultMapWithBLOBs">
select
@ -131,11 +132,11 @@
insert into api_test_environment (id, `name`, project_id,
protocol, socket, `domain`,
port, `variables`, headers,
custom_data)
custom_data,hosts)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR},
#{protocol,jdbcType=VARCHAR}, #{socket,jdbcType=VARCHAR}, #{domain,jdbcType=VARCHAR},
#{port,jdbcType=INTEGER}, #{variables,jdbcType=LONGVARCHAR}, #{headers,jdbcType=LONGVARCHAR},
#{customData,jdbcType=LONGVARCHAR})
#{customData,jdbcType=LONGVARCHAR},#{hosts,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs">
insert into api_test_environment
@ -170,6 +171,10 @@
<if test="customData != null">
custom_data,
</if>
<if test="hosts != null">
hosts,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@ -202,6 +207,9 @@
<if test="customData != null">
#{customData,jdbcType=LONGVARCHAR},
</if>
<if test="hosts != null">
#{hosts,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.ApiTestEnvironmentExample" resultType="java.lang.Long">
@ -243,6 +251,9 @@
<if test="record.customData != null">
custom_data = #{record.customData,jdbcType=LONGVARCHAR},
</if>
<if test="record.hosts != null">
hosts = #{hosts,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -259,7 +270,8 @@
port = #{record.port,jdbcType=INTEGER},
`variables` = #{record.variables,jdbcType=LONGVARCHAR},
headers = #{record.headers,jdbcType=LONGVARCHAR},
custom_data = #{record.customData,jdbcType=LONGVARCHAR}
custom_data = #{record.customData,jdbcType=LONGVARCHAR},
hosts = #{hosts,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -307,6 +319,9 @@
<if test="customData != null">
custom_data = #{customData,jdbcType=LONGVARCHAR},
</if>
<if test="hosts != null">
hosts = #{hosts,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
@ -320,7 +335,8 @@
port = #{port,jdbcType=INTEGER},
`variables` = #{variables,jdbcType=LONGVARCHAR},
headers = #{headers,jdbcType=LONGVARCHAR},
custom_data = #{customData,jdbcType=LONGVARCHAR}
custom_data = #{customData,jdbcType=LONGVARCHAR},
hosts = #{hosts,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.ApiTestEnvironment">

View File

@ -18,19 +18,12 @@
package org.apache.jmeter.util;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import org.apache.jmeter.testbeans.TestBean;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.apache.jmeter.testbeans.TestBean;
import java.util.*;
import java.util.Map.Entry;
/**
* 解决JSR233加载 ScriptEngineFactory 空指针问题

View File

@ -0,0 +1 @@
ALTER TABLE `api_test_environment` ADD `hosts` longtext COMMENT 'hosts ';

View File

@ -1,8 +1,10 @@
<template>
<el-dialog :close-on-click-modal="false" :title="$t('api_test.environment.environment_config')" :visible.sync="visible" class="environment-dialog"
<el-dialog :close-on-click-modal="false" :title="$t('api_test.environment.environment_config')"
:visible.sync="visible" class="environment-dialog"
@close="close" append-to-body ref="environmentConfig">
<el-container v-loading="result.loading">
<ms-aside-item :enable-aside-hidden="false" :title="$t('api_test.environment.environment_list')" :data="environments" :item-operators="environmentOperators" :add-fuc="addEnvironment"
<ms-aside-item :enable-aside-hidden="false" :title="$t('api_test.environment.environment_list')"
:data="environments" :item-operators="environmentOperators" :add-fuc="addEnvironment"
:delete-fuc="deleteEnvironment" @itemSelected="environmentSelected" ref="environmentItems"/>
<environment-edit :environment="currentEnvironment" ref="environmentEdit" @close="close"/>
</el-container>
@ -10,136 +12,145 @@
</template>
<script>
import MsApiCollapse from "./collapse/ApiCollapse";
import MsApiCollapseItem from "./collapse/ApiCollapseItem";
import draggable from 'vuedraggable';
import MsContainer from "../../../common/components/MsContainer";
import MsAsideContainer from "../../../common/components/MsAsideContainer";
import MsMainContainer from "../../../common/components/MsMainContainer";
import MsAsideItem from "../../../common/components/MsAsideItem";
import EnvironmentEdit from "./environment/EnvironmentEdit";
import {listenGoBack, removeGoBackListener} from "../../../../../common/js/utils";
import MsApiCollapse from "./collapse/ApiCollapse";
import MsApiCollapseItem from "./collapse/ApiCollapseItem";
import draggable from 'vuedraggable';
import MsContainer from "../../../common/components/MsContainer";
import MsAsideContainer from "../../../common/components/MsAsideContainer";
import MsMainContainer from "../../../common/components/MsMainContainer";
import MsAsideItem from "../../../common/components/MsAsideItem";
import EnvironmentEdit from "./environment/EnvironmentEdit";
import {listenGoBack, removeGoBackListener} from "../../../../../common/js/utils";
export default {
name: "ApiEnvironmentConfig",
components: {
EnvironmentEdit,
MsAsideItem,
MsMainContainer, MsAsideContainer, MsContainer, MsApiCollapseItem, MsApiCollapse, draggable},
data() {
return {
result: {},
visible:false,
projectId: '',
environments: [],
currentEnvironment: {variables: [{}], headers: [{}], protocol: 'https', projectId: this.projectId},
environmentOperators: [
{
icon: 'el-icon-document-copy',
func: this.copyEnvironment
},
{
icon: 'el-icon-delete',
func: this.deleteEnvironment
}
]
export default {
name: "ApiEnvironmentConfig",
components: {
EnvironmentEdit,
MsAsideItem,
MsMainContainer, MsAsideContainer, MsContainer, MsApiCollapseItem, MsApiCollapse, draggable
},
data() {
return {
result: {},
visible: false,
projectId: '',
environments: [],
currentEnvironment: {variables: [{}], headers: [{}], protocol: 'https', projectId: this.projectId, hosts: [{}]},
environmentOperators: [
{
icon: 'el-icon-document-copy',
func: this.copyEnvironment
},
{
icon: 'el-icon-delete',
func: this.deleteEnvironment
}
]
}
},
methods: {
open: function (projectId) {
this.visible = true;
this.projectId = projectId;
this.getEnvironments();
listenGoBack(this.close);
},
deleteEnvironment(environment, index) {
if (environment.id) {
this.result = this.$get('/api/environment/delete/' + environment.id, () => {
this.$success(this.$t('commons.delete_success'));
this.getEnvironments();
});
}
else {
this.environments.splice(index, 1);
}
},
methods: {
open: function (projectId) {
this.visible = true;
this.projectId = projectId;
this.getEnvironments();
listenGoBack(this.close);
},
deleteEnvironment(environment, index) {
if (environment.id) {
this.result = this.$get('/api/environment/delete/' + environment.id, () => {
this.$success(this.$t('commons.delete_success'));
this.getEnvironments();
});
}
else {
this.environments.splice(index, 1);
}
},
copyEnvironment(environment) {
if (!environment.id) {
this.$warning(this.$t('commons.please_save'))
return;
}
let newEnvironment = {};
Object.assign(newEnvironment, environment);
newEnvironment.id = null;
newEnvironment.name = this.getNoRepeatName(newEnvironment.name);
if (!this.validateEnvironment(newEnvironment)) {
return;
}
this.$refs.environmentEdit._save(newEnvironment);
this.environments.push(newEnvironment);
this.$refs.environmentItems.itemSelected(this.environments.length -1 , newEnvironment);
},
validateEnvironment(environment) {
if (!environment.name || !!environment.name && environment.name.length > 64) {
this.$error(this.$t('commons.input_limit', [1, 64]));
return false;
}
if (!this.$refs.environmentEdit.validateSocket(environment.socket)) {
this.$error(this.$t('commons.formatErr'));
return false;
}
return true;
},
getNoRepeatName(name) {
for (let i in this.environments) {
if (this.environments[i].name === name) {
return this.getNoRepeatName(name + ' copy');
}
}
return name;
},
addEnvironment() {
let newEnvironment = this.getDefaultEnvironment();
this.environments.push(newEnvironment);
this.$refs.environmentItems.itemSelected(this.environments.length -1 , newEnvironment);
},
environmentSelected(environment) {
this.getEnvironment(environment);
},
getEnvironments() {
if (this.projectId) {
this.result = this.$get('/api/environment/list/' + this.projectId, response => {
this.environments = response.data;
if (this.environments.length > 0) {
this.$refs.environmentItems.itemSelected(0, this.environments[0]);
} else {
let item = this.getDefaultEnvironment();
this.environments.push(item);
this.$refs.environmentItems.itemSelected(0, item);
}
});
}
},
getEnvironment(environment) {
if (!(environment.variables instanceof Array)) {
environment.variables = JSON.parse(environment.variables);
}
if (!(environment.headers instanceof Array)) {
environment.headers = JSON.parse(environment.headers);
}
this.currentEnvironment = environment;
},
getDefaultEnvironment() {
return {variables: [{}], headers: [{}], protocol: 'https', projectId: this.projectId};
},
close() {
this.$emit('close');
this.visible = false;
this.$refs.environmentEdit.clearValidate();
removeGoBackListener(this.close);
copyEnvironment(environment) {
if (!environment.id) {
this.$warning(this.$t('commons.please_save'))
return;
}
let newEnvironment = {};
Object.assign(newEnvironment, environment);
newEnvironment.id = null;
newEnvironment.name = this.getNoRepeatName(newEnvironment.name);
if (!this.validateEnvironment(newEnvironment)) {
return;
}
this.$refs.environmentEdit._save(newEnvironment);
this.environments.push(newEnvironment);
this.$refs.environmentItems.itemSelected(this.environments.length - 1, newEnvironment);
},
validateEnvironment(environment) {
if (!environment.name || !!environment.name && environment.name.length > 64) {
this.$error(this.$t('commons.input_limit', [1, 64]));
return false;
}
if (!this.$refs.environmentEdit.validateSocket(environment.socket)) {
this.$error(this.$t('commons.formatErr'));
return false;
}
return true;
},
getNoRepeatName(name) {
for (let i in this.environments) {
if (this.environments[i].name === name) {
return this.getNoRepeatName(name + ' copy');
}
}
return name;
},
addEnvironment() {
let newEnvironment = this.getDefaultEnvironment();
this.environments.push(newEnvironment);
this.$refs.environmentItems.itemSelected(this.environments.length - 1, newEnvironment);
},
environmentSelected(environment) {
this.getEnvironment(environment);
},
getEnvironments() {
if (this.projectId) {
this.result = this.$get('/api/environment/list/' + this.projectId, response => {
this.environments = response.data;
if (this.environments.length > 0) {
this.$refs.environmentItems.itemSelected(0, this.environments[0]);
} else {
let item = this.getDefaultEnvironment();
this.environments.push(item);
this.$refs.environmentItems.itemSelected(0, item);
}
});
}
},
getEnvironment(environment) {
if (!(environment.variables instanceof Array)) {
environment.variables = JSON.parse(environment.variables);
}
if (!(environment.headers instanceof Array)) {
environment.headers = JSON.parse(environment.headers);
}
if(environment.hosts === undefined || environment.hosts ===null || environment.hosts ===''){
environment.hosts = [];
environment.enable =false;
}
else if (!(environment.hosts instanceof Array)) {
environment.hosts = JSON.parse(environment.hosts);
environment.enable =true;
}
this.currentEnvironment = environment;
},
getDefaultEnvironment() {
return {variables: [{}], headers: [{}], protocol: 'https', projectId: this.projectId, hosts: [{}]};
},
close() {
this.$emit('close');
this.visible = false;
this.$refs.environmentEdit.clearValidate();
removeGoBackListener(this.close);
}
}
}
</script>
<style scoped>

View File

@ -0,0 +1,159 @@
<template>
<div>
<el-card class="table-card">
<el-table :data="hostTable" style="width: 100%" @cell-dblclick="dblHostTable">
<el-table-column prop="ip" label="IP">
<template slot-scope="scope">
<el-input v-if="scope.row.status" v-model="scope.row.ip"></el-input>
<span v-else>{{scope.row.ip}}</span>
</template>
</el-table-column>
<el-table-column prop="domain" :label="$t('load_test.domain')">
<template slot-scope="scope">
<el-input v-if="scope.row.status" v-model="scope.row.domain"></el-input>
<span v-else>{{scope.row.domain}}</span>
</template>
</el-table-column>
<el-table-column prop="annotation" :label="$t('commons.annotation')">
<template slot-scope="scope">
<el-input v-if="scope.row.status" v-model="scope.row.annotation"></el-input>
<span v-else>{{scope.row.annotation}}</span>
</template>
</el-table-column>
<el-table-column :label="$t('commons.operating')">
<template v-slot:default="scope">
<span>
<el-button size="mini" p="$t('commons.remove')" icon="el-icon-close" circle @click="remove(scope.row)"
class="ht-btn-remove"/>
<el-button size="mini" p="$t('commons.save')" icon="el-icon-check" circle @click="confirm(scope.row)"
class="ht-btn-confirm"/>
</span>
</template>
</el-table-column>
</el-table>
<el-button size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" circle @click="add"
class="ht-btn-add"></el-button>
</el-card>
</div>
</template>
<script>
import MsApiVariableInput from "./ApiVariableInput";
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
export default {
name: "MsApiHostTable",
components: {MsApiVariableInput, MsTableOperatorButton},
props: {
hostTable: Array,
},
data() {
return {
currentPage: 1,
pageSize: 5,
total: 0,
}
},
created() {
this.init();
},
methods: {
remove: function (row) {
this.hostTable.splice(this.hostTable.indexOf(row), 1);
},
change: function () {
this.$emit('change', this.hostTable);
},
add: function (r) {
let row = {
ip: '',
domain: '',
status: 'edit',
annotation: '',
uuid: this.uuid(),
}
//
for (let i = this.hostTable.length - 1; i >= 0; i--) {
if (this.hostTable[i].status === '') {
row.ip = this.hostTable[i].ip;
row.domain = this.hostTable[i].domain;
row.annotation = this.hostTable[i].annotation;
break;
}
}
this.hostTable.push(row);
},
confirm: function (row) {
this.validateIp(row.ip) && this.validateDomain(row.domain) ? row.status = '' : row.status;
this.$emit('change', this.hostTable);
},
init: function () {
if (this.hostTable === undefined || this.hostTable.length === 0) {
let row = {
ip: '',
domain: '',
status: 'edit',
annotation: '',
uuid: this.uuid()
}
this.hostTable.push(row);
}
},
validateIp(ip) {
let regexp = /^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$/;
if (regexp.test(ip) == false) {
this.$warning(this.$t('load_test.input_ip'));
return false;
}
return true;
},
validateDomain(domain) {
let url = {};
try {
url = new URL(domain);
} catch (e) {
this.$warning(this.$t('load_test.input_domain'));
return false
}
return true;
},
dblHostTable:function(row){
row.status= 'edit';
},
uuid: function () {
return (((1 + Math.random()) * 0x100000) | 0).toString(16).substring(1);
},
}
}
</script>
<style scoped>
.ht-btn-remove {
font-size: 8px;
color: white;
background-color: #DCDFE6;
}
.ht-btn-confirm {
font-size: 8px;
color: white;
background-color: #1483F6;
}
.ht-btn-add {
margin-top: 10px;
font-size: 8px;
color: #1483F6;
border-color: #1483F6;
background-color: white;
}
</style>

View File

@ -5,7 +5,7 @@
</span>
<div class="kv-row" v-for="(item, index) in items" :key="index">
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
<el-col class="kv-checkbox">
<el-col v-if="isShowEnable" class="kv-checkbox">
<input type="checkbox" v-if="!isDisable(index)" @change="change" :value="item.uuid" v-model="checkedValues"
:disabled="isDisable(index) || isReadOnly"/>
</el-col>
@ -42,6 +42,7 @@
keyPlaceholder: String,
valuePlaceholder: String,
description: String,
isShowEnable: Boolean,
items: Array,
isReadOnly: {
type: Boolean,
@ -65,9 +66,11 @@
methods: {
remove: function (index) {
//
let checkIndex = this.checkedValues.indexOf(this.items[index].uuid);
checkIndex != -1 ? this.checkedValues.splice(checkIndex, 1) : this.checkedValues;
if (this.isShowEnable) {
//
let checkIndex = this.checkedValues.indexOf(this.items[index].uuid);
checkIndex != -1 ? this.checkedValues.splice(checkIndex, 1) : this.checkedValues;
}
//
this.items.splice(index, 1);
this.$emit('change', this.items);
@ -77,8 +80,9 @@
let removeIndex = -1;
this.items.forEach((item, index) => {
//
item.enable = this.checkedValues.indexOf(item.uuid) != -1 ? true : false;
if (this.isShowEnable) {
item.enable = this.checkedValues.indexOf(item.uuid) != -1 ? true : false;
}
if (!item.name && !item.value) {
//
if (index !== this.items.length - 1) {
@ -90,9 +94,11 @@
});
if (isNeedCreate) {
//
this.items[this.items.length - 1].enable = true;
// v-model
this.checkedValues.push(this.items[this.items.length - 1].uuid);
if (this.isShowEnable) {
this.items[this.items.length - 1].enable = true;
// v-model
this.checkedValues.push(this.items[this.items.length - 1].uuid);
}
this.items.push(new KeyValue());
}
this.$emit('change', this.items);
@ -118,7 +124,7 @@
created() {
if (this.items.length === 0) {
this.items.push(new KeyValue());
} else {
} else if (this.isShowEnable) {
this.items.forEach((item, index) => {
let uuid = this.uuid();
item.uuid = uuid;

View File

@ -1,13 +1,12 @@
<template>
<el-main v-loading="result.loading">
<el-form :model="environment" :rules="rules" ref="from">
<el-form :model="environment" :rules="rules" ref="environment">
<span>{{$t('api_test.environment.name')}}</span>
<el-form-item
prop="name">
<el-input v-model="environment.name" :placeholder="this.$t('commons.input_name')" clearable></el-input>
</el-form-item>
<span>{{$t('api_test.environment.socket')}}</span>
<el-form-item
prop="socket">
@ -21,6 +20,15 @@
</el-input>
</el-form-item>
<el-form-item>
<el-switch
v-model="envEnable"
inactive-text="hosts">
</el-switch>
</el-form-item>
<ms-api-host-table v-if="envEnable" :hostTable="environment.hosts"/>
<span>{{$t('api_test.environment.globalVariable')}}</span>
<ms-api-scenario-variables :show-variable="false" :items="environment.variables"/>
@ -32,111 +40,126 @@
@cancel="cancel"
@confirm="save()"/>
</div>
</el-form>
</el-main>
</template>
<script>
import MsApiScenarioVariables from "../ApiScenarioVariables";
import MsApiKeyValue from "../ApiKeyValue";
import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import {REQUEST_HEADERS} from "../../../../../../common/js/constants";
import {KeyValue} from "../../model/ScenarioModel";
import MsApiScenarioVariables from "../ApiScenarioVariables";
import MsApiKeyValue from "../ApiKeyValue";
import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import {REQUEST_HEADERS} from "../../../../../../common/js/constants";
import {KeyValue} from "../../model/ScenarioModel";
import MsApiHostTable from "../ApiHostTable";
export default {
name: "EnvironmentEdit",
components: {MsDialogFooter, MsApiKeyValue, MsApiScenarioVariables},
props: {
environment: {
type: Object,
default() {
return {variables: [{}], headers: [{}], protocol: 'https'};
}
export default {
name: "EnvironmentEdit",
components: {MsApiHostTable, MsDialogFooter, MsApiKeyValue, MsApiScenarioVariables},
props: {
environment: Object,
},
data() {
let socketValidator = (rule, value, callback) => {
if (!this.validateSocket(value)) {
callback(new Error(this.$t('commons.formatErr')));
} else {
callback();
}
},
data() {
let socketValidator = (rule, value, callback) => {
if (!this.validateSocket(value)) {
callback(new Error(this.$t('commons.formatErr')));
}
return {
result: {},
envEnable: false,
rules: {
name: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{max: 64, message: this.$t('commons.input_limit', [1, 64]), trigger: 'blur'}
],
socket: [{required: true, validator: socketValidator, trigger: 'blur'}],
},
headerSuggestions: REQUEST_HEADERS
}
},
watch: {
environment: function (o) {
this.envEnable = o.enable;
}
},
methods: {
save() {
this.$refs['environment'].validate((valid) => {
if (valid) {
this._save(this.environment);
} else {
callback();
return false;
}
};
return {
result: {},
rules: {
name :[
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{max: 64, message: this.$t('commons.input_limit', [1, 64]), trigger: 'blur'}
],
socket :[{required: true, validator: socketValidator, trigger: 'blur'}],
},
headerSuggestions: REQUEST_HEADERS
}
});
},
methods: {
save() {
this.$refs['from'].validate((valid) => {
if (valid) {
this._save(this.environment);
} else {
return false;
_save(environment) {
let param = this.buildParam(environment);
let url = '/api/environment/add';
if (param.id) {
url = '/api/environment/update';
}
this.result = this.$post(url, param, response => {
if (!param.id) {
environment.id = response.data;
}
this.$success(this.$t('commons.save_success'));
});
},
buildParam(environment) {
let param = {};
Object.assign(param, environment);
if (!(environment.variables instanceof String)) {
param.variables = JSON.stringify(environment.variables);
}
if (!(environment.headers instanceof String)) {
param.headers = JSON.stringify(environment.headers);
}
if (environment.hosts != undefined && !(environment.hosts instanceof String)) {
let hosts = JSON.parse(JSON.stringify(environment.hosts));
let validHosts = [];
// host
hosts.forEach(host => {
if (host.status === '') {
validHosts.push(host);
}
});
},
_save(environment) {
let param = this.buildParam(environment);
let url = '/api/environment/add';
if (param.id) {
url = '/api/environment/update';
}
this.result = this.$post(url, param, response => {
if (!param.id) {
environment.id = response.data;
}
this.$success(this.$t('commons.save_success'));
});
},
buildParam(environment) {
let param = {};
Object.assign(param, environment);
if (!(environment.variables instanceof String)) {
param.variables = JSON.stringify(environment.variables);
}
if (!(environment.headers instanceof String)) {
param.headers = JSON.stringify(environment.headers);
}
return param;
},
validateSocket(socket) {
if (!socket) return;
let urlStr = this.environment.protocol + '://' + socket;
let url = {};
try {
url = new URL(urlStr);
} catch (e) {
return false
}
this.environment.port = url.port;
this.environment.domain = decodeURIComponent(url.hostname);
if (url.port) {
this.environment.socket = this.environment.domain + ':' + url.port + url.pathname;
} else {
this.environment.socket = this.environment.domain + url.pathname;
}
return true;
},
cancel() {
this.$emit('close');
},
clearValidate() {
this.$refs["from"].clearValidate();
},
environment.hosts = validHosts;
param.hosts = JSON.stringify(validHosts);
}
if (!this.envEnable) {
param.hosts = null;
}
return param;
},
}
validateSocket(socket) {
if (!socket) return;
let urlStr = this.environment.protocol + '://' + socket;
let url = {};
try {
url = new URL(urlStr);
} catch (e) {
return false
}
this.environment.port = url.port;
this.environment.domain = decodeURIComponent(url.hostname);
if (url.port) {
this.environment.socket = this.environment.domain + ':' + url.port + url.pathname;
} else {
this.environment.socket = this.environment.domain + url.pathname;
}
return true;
},
cancel() {
this.$emit('close');
},
clearValidate() {
this.$refs["environment"].clearValidate();
},
},
}
</script>
<style scoped>

View File

@ -53,7 +53,7 @@
:description="$t('api_test.request.parameters_desc')"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.request.headers')" name="headers">
<ms-api-key-value :is-read-only="isReadOnly" :suggestions="headerSuggestions" :items="request.headers"/>
<ms-api-key-value :is-read-only="isReadOnly" :isShowEnable="true" :suggestions="headerSuggestions" :items="request.headers"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.request.body')" name="body" v-if="isNotGet">
<ms-api-body :is-read-only="isReadOnly"

View File

@ -498,6 +498,24 @@ export class HeaderManager extends DefaultTestElement {
}
}
export class DNSCacheManager extends DefaultTestElement {
constructor(testName,domain, hosts) {
super('DNSCacheManager', 'DNSCachePanel', 'DNSCacheManager', testName);
let collectionPropServers = this.collectionProp('DNSCacheManager.servers');
let collectionPropHosts = this.collectionProp('DNSCacheManager.hosts');
hosts.forEach(host => {
let elementProp = collectionPropHosts.elementProp('', 'StaticHost');
if (host && host.domain.trim() === domain.trim()) {
elementProp.stringProp('StaticHost.Name', host.domain);
elementProp.stringProp('StaticHost.Address', host.ip);
}
});
let boolProp = this.boolProp('DNSCacheManager.isCustomResolver', true);
}
}
export class Arguments extends DefaultTestElement {
constructor(testName, args) {
super('Arguments', 'ArgumentsPanel', 'Arguments', testName);

View File

@ -1,6 +1,7 @@
import {
Arguments, BeanShellPostProcessor, BeanShellPreProcessor,
CookieManager,
DNSCacheManager,
DubboSample,
DurationAssertion,
Element,
@ -870,6 +871,8 @@ class JMXGenerator {
this.addScenarioHeaders(threadGroup, scenario);
this.addScenarioCookieManager(threadGroup, scenario);
// 放在计划或线程组中,不建议放具体某个请求中
this.addDNSCacheManager(threadGroup, scenario.requests[0]);
scenario.requests.forEach(request => {
if (request.enable) {
@ -940,6 +943,17 @@ class JMXGenerator {
}
}
addDNSCacheManager(threadGroup, request) {
if (request.environment && request.environment.hosts) {
let name = request.name + " DNSCacheManager";
let hosts = JSON.parse(request.environment.hosts);
if (hosts.length > 0) {
let domain = request.environment.protocol+"://"+request.environment.domain;
threadGroup.put(new DNSCacheManager(name,domain ,hosts));
}
}
}
addScenarioHeaders(threadGroup, scenario) {
let environment = scenario.environment;
if (environment) {

View File

@ -10,6 +10,7 @@ export default {
current_project: 'Current Project',
name: 'Name',
description: 'Description',
annotation: 'Annotation',
clear: 'Clear',
save: 'Save',
save_success: 'Saved successfully',
@ -349,6 +350,8 @@ export default {
domain: 'Domain',
enable: 'Enable',
ip: 'IP',
input_ip: 'Please enter the correct IP address',
input_domain: 'Please enter the correct domain',
params: 'Parameters',
param_name: 'Name',
param_value: 'Value',

View File

@ -10,6 +10,7 @@ export default {
current_project: '当前项目',
name: '名称',
description: '描述',
annotation: '注释',
clear: '清空',
save: '保存',
save_success: '保存成功',
@ -348,6 +349,8 @@ export default {
domain: '域名',
enable: '是否启用',
ip: 'IP地址',
input_ip: '请输入正确的IP地址',
input_domain: '请输入正确的域名!',
params: '自定义属性',
param_name: '属性名',
param_value: '属性值',

View File

@ -10,6 +10,7 @@ export default {
current_project: '當前項目',
name: '名稱',
description: '描述',
annotation: '註釋',
clear: '清空',
save: '保存',
save_success: '保存成功',
@ -347,6 +348,8 @@ export default {
domain: '域名',
enable: '是否啟用',
ip: 'IP地址',
input_ip: '請輸入正確的IP地址',
input_domain: '請輸入正確的域名!',
params: '自定義屬性',
param_name: '屬性名',
param_value: '屬性值',