feat(接口测试): 环境配置增加hosts
This commit is contained in:
parent
a8684f4c7b
commit
59aeb11fa1
|
@ -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;
|
||||
}
|
|
@ -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">
|
||||
|
|
|
@ -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 空指针问题
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `api_test_environment` ADD `hosts` longtext COMMENT 'hosts ';
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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: '属性值',
|
||||
|
|
|
@ -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: '屬性值',
|
||||
|
|
Loading…
Reference in New Issue