feat(项目设置): UI环境配置校验与提示信息完善

--story=1010692 --user=张大海 【UI测试】支持与环境管理打通 https://www.tapd.cn/55049933/s/1315234
This commit is contained in:
zhangdahai112 2022-12-14 17:51:14 +08:00 committed by zhangdahai112
parent e5a366de15
commit 5e1567b6b4
9 changed files with 183 additions and 105 deletions

View File

@ -3,7 +3,7 @@
<el-col :span="16"> <el-col :span="16">
<el-select v-model="selfQuantity" placeholder=" " size="mini" filterable default-first-option <el-select v-model="selfQuantity" placeholder=" " size="mini" filterable default-first-option
allow-create allow-create
class="timing_select" :disabled="selfChoose"> class="timing_select" :disabled="selfChoose" @change="chooseChange(true)">
<el-option <el-option
v-for="item in quantityOptions" v-for="item in quantityOptions"
:key="item" :key="item"
@ -12,7 +12,7 @@
</el-option> </el-option>
</el-select> </el-select>
<el-select v-model="selfUnit" placeholder=" " size="mini" <el-select v-model="selfUnit" placeholder=" " size="mini"
class="timing_select" :disabled="selfChoose"> class="timing_select" :disabled="selfChoose" @change="chooseChange(true)">
<el-option <el-option
v-for="item in unitOptions" v-for="item in unitOptions"
:key="item.value" :key="item.value"
@ -58,6 +58,7 @@ export default {
type: Array, type: Array,
default() { default() {
return [ return [
{value: "H", label: this.$t('commons.date_unit.hour')},
{value: "D", label: this.$t('commons.date_unit.day')}, {value: "D", label: this.$t('commons.date_unit.day')},
{value: "M", label: this.$t('commons.date_unit.month')}, {value: "M", label: this.$t('commons.date_unit.month')},
{value: "Y", label: this.$t('commons.date_unit.year')}, {value: "Y", label: this.$t('commons.date_unit.year')},
@ -66,8 +67,11 @@ export default {
} }
}, },
watch: { watch: {
expr(val) { expr: {
this.parseExpr(val); handler(val) {
this.parseExpr(val);
},
immediate: true
}, },
choose(val) { choose(val) {
this.selfChoose = val; this.selfChoose = val;

View File

@ -8,9 +8,9 @@
:class="{ 'el-icon-arrow-left pointer' : !active, 'el-icon-arrow-down pointer' : active}" :class="{ 'el-icon-arrow-left pointer' : !active, 'el-icon-arrow-down pointer' : active}"
@click="active=!active"></span> @click="active=!active"></span>
</el-tooltip> </el-tooltip>
<template v-if="active"> <div v-show="active">
<slot></slot> <slot></slot>
</template> </div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -84,6 +84,7 @@ export class HttpConfig extends BaseConfig {
this.protocol = 'https'; this.protocol = 'https';
this.port = undefined; this.port = undefined;
this.conditions = []; this.conditions = [];
this.cookie = options.cookie ? options.cookie : [new Cookie()];
this.isMock = false; this.isMock = false;
this.description = ""; this.description = "";
this.set(options); this.set(options);
@ -93,6 +94,7 @@ export class HttpConfig extends BaseConfig {
initOptions(options = {}) { initOptions(options = {}) {
options.headers = options.headers || [new KeyValue()]; options.headers = options.headers || [new KeyValue()];
options.cookie = options.cookie || [new Cookie()];
return options; return options;
} }
} }
@ -111,6 +113,20 @@ export class Host extends BaseConfig {
} }
} }
export class Cookie extends BaseConfig {
constructor(options = {}) {
super();
this.cookie = undefined;
this.expireTime = "1D";
this.updateTime = undefined;
this.relevanceId = undefined;
this.enable = false;
this.set(options);
}
}
/* ---------- Functions ------- */ /* ---------- Functions ------- */

View File

@ -136,7 +136,7 @@ import MsTableOperator from "metersphere-frontend/src/components/MsTableOperator
import MsTableOperatorButton from "metersphere-frontend/src/components/MsTableOperatorButton"; import MsTableOperatorButton from "metersphere-frontend/src/components/MsTableOperatorButton";
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination"; import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig"; import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
import {Environment, parseEnvironment} from "metersphere-frontend/src/model/EnvironmentModel"; import {Environment, parseEnvironment, HttpConfig} from "metersphere-frontend/src/model/EnvironmentModel";
import EnvironmentEdit from "./components/EnvironmentEdit"; import EnvironmentEdit from "./components/EnvironmentEdit";
import MsAsideItem from "metersphere-frontend/src/components/MsAsideItem"; import MsAsideItem from "metersphere-frontend/src/components/MsAsideItem";
import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer"; import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer";
@ -174,7 +174,7 @@ export default {
projectList: [], projectList: [],
condition: {}, // condition: {}, //
environments: [], environments: [],
currentEnvironment: new Environment(), currentEnvironment: new Environment({httpConfig: new HttpConfig()}),
result: {}, result: {},
loading: false, loading: false,
dialogVisible: false, dialogVisible: false,
@ -288,7 +288,7 @@ export default {
createEnv() { createEnv() {
this.dialogTitle = this.$t('api_test.environment.create'); this.dialogTitle = this.$t('api_test.environment.create');
this.dialogVisible = true; this.dialogVisible = true;
this.currentEnvironment = new Environment(); this.currentEnvironment = new Environment({httpConfig: new HttpConfig()});
this.currentEnvironment.projectId = this.currentProjectId; this.currentEnvironment.projectId = this.currentProjectId;
this.currentEnvironment.currentProjectId = this.currentProjectId; this.currentEnvironment.currentProjectId = this.currentProjectId;
this.ifCreate = true; this.ifCreate = true;

View File

@ -45,7 +45,7 @@
</el-input> </el-input>
</div> </div>
<!-- 接口测试配置 --> <!-- 接口测试配置 -->
<form-section :title="$t('commons.api')" :init-active=true> <form-section :title="$t('commons.api')" :init-active=true>
<p>{{ $t('api_test.request.headers') }}</p> <p>{{ $t('api_test.request.headers') }}</p>
<el-row> <el-row>
@ -71,12 +71,12 @@
</div> </div>
</form-section> </form-section>
<!-- UI 配置 --> <!-- UI 配置 -->
<form-section :title="$t('commons.ui_test')" :init-active="false"> <form-section :title="$t('commons.ui_test')" :init-active=false>
<el-row :gutter="10" style="padding-top: 10px;"> <el-row :gutter="10" style="padding-top: 10px;">
<el-col :span="6"> <el-col :span="6">
<!-- 浏览器驱动 --> <!-- 浏览器驱动 -->
<span style="margin-right: 10px;">{{$t("ui.browser")}}</span> <span style="margin-right: 10px;">{{ $t("ui.browser") }}</span>
<el-select <el-select
size="mini" size="mini"
v-model="httpConfig.browser" v-model="httpConfig.browser"
@ -104,7 +104,7 @@
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24"> <el-col :span="24">
<ms-ui-scenario-cookie-table :items="httpConfig.cookie"/> <ms-ui-scenario-cookie-table :items="httpConfig.cookie" ref="cookieTable"/>
</el-col> </el-col>
</el-row> </el-row>
</form-section> </form-section>
@ -174,9 +174,10 @@ export default {
name: "MsEnvironmentHttpConfig", name: "MsEnvironmentHttpConfig",
components: { components: {
MsUiScenarioCookieTable, MsUiScenarioCookieTable,
FormSection, MsApiKeyValue, MsSelectTree, MsTableOperatorButton, BatchAddParameter, MsInstructionsIcon}, FormSection, MsApiKeyValue, MsSelectTree, MsTableOperatorButton, BatchAddParameter, MsInstructionsIcon
},
props: { props: {
httpConfig: new HttpConfig({cookie: []}), httpConfig: new HttpConfig(),
projectId: String, projectId: String,
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
@ -185,9 +186,6 @@ export default {
}, },
created() { created() {
this.list(); this.list();
if (this.httpConfig && !this.httpConfig.cookie) {
this.$set(this.httpConfig, "cookie", []);
}
}, },
data() { data() {
let socketValidator = (rule, value, callback) => { let socketValidator = (rule, value, callback) => {
@ -220,7 +218,7 @@ export default {
port: 0, port: 0,
headers: [new KeyValue()], headers: [new KeyValue()],
headlessEnabled: true, headlessEnabled: true,
browser : 'CHROME' browser: 'CHROME'
}, },
beforeCondition: {}, beforeCondition: {},
browsers: [ browsers: [
@ -354,7 +352,7 @@ export default {
list() { list() {
if (this.projectId) { if (this.projectId) {
this.result = getApiModuleByProjectIdAndProtocol(this.projectId, "HTTP").then((response) => { this.result = getApiModuleByProjectIdAndProtocol(this.projectId, "HTTP").then((response) => {
if (response.data && response.data !== null) { if (response.data && response.data !== null) {
this.moduleOptions = response.data; this.moduleOptions = response.data;
} }
}); });
@ -507,6 +505,9 @@ export default {
this.$refs["httpConfig"].validate((valid) => { this.$refs["httpConfig"].validate((valid) => {
isValidate = valid; isValidate = valid;
}); });
if (this.$refs.cookieTable && !this.$refs.cookieTable.validate()) {
return false;
}
return isValidate; return isValidate;
}, },
batchAdd() { batchAdd() {

View File

@ -16,10 +16,10 @@
:data="variables" :data="variables"
:total="items.length" :total="items.length"
:screen-height="'100px'" :screen-height="'100px'"
:batch-operators="batchButtons"
:remember-order="true" :remember-order="true"
:highlightCurrentRow="true" :highlightCurrentRow="true"
@refresh="onChange" @refresh="onChange"
:enable-selection="false"
ref="variableTable" ref="variableTable"
> >
<ms-table-column prop="cookie" label="cookie" min-width="160"> <ms-table-column prop="cookie" label="cookie" min-width="160">
@ -28,44 +28,44 @@
v-model="scope.row.cookie" v-model="scope.row.cookie"
size="mini" size="mini"
:placeholder="$t('cookie')" :placeholder="$t('cookie')"
@change="change" @change="change(scope.row)"
/> />
</template> </template>
</ms-table-column> </ms-table-column>
<ms-table-column <!-- <ms-table-column-->
prop="userName" <!-- prop="userName"-->
:label="$t('api_test.request.sql.username')" <!-- :label="$t('api_test.request.sql.username')"-->
min-width="200" <!-- min-width="200"-->
> <!-- >-->
<template slot-scope="scope"> <!-- <template slot-scope="scope">-->
<el-input <!-- <el-input-->
v-model="scope.row.userName" <!-- v-model="scope.row.userName"-->
size="mini" <!-- size="mini"-->
maxlength="200" <!-- maxlength="200"-->
:placeholder="$t('api_test.request.sql.username')" <!-- :placeholder="$t('api_test.request.sql.username')"-->
show-word-limit <!-- show-word-limit-->
@change="change" <!-- @change="change"-->
/> <!-- />-->
</template> <!-- </template>-->
</ms-table-column> <!-- </ms-table-column>-->
<ms-table-column <!-- <ms-table-column-->
prop="password" <!-- prop="password"-->
:label="$t('api_test.request.tcp.password')" <!-- :label="$t('api_test.request.tcp.password')"-->
min-width="140" <!-- min-width="140"-->
> <!-- >-->
<template slot-scope="scope"> <!-- <template slot-scope="scope">-->
<el-input <!-- <el-input-->
v-model="scope.row.password" <!-- v-model="scope.row.password"-->
size="mini" <!-- size="mini"-->
maxlength="200" <!-- maxlength="200"-->
show-password <!-- show-password-->
:placeholder="$t('api_test.request.tcp.password')" <!-- :placeholder="$t('api_test.request.tcp.password')"-->
@change="change" <!-- @change="change"-->
/> <!-- />-->
</template> <!-- </template>-->
</ms-table-column> <!-- </ms-table-column>-->
<ms-table-column <ms-table-column
prop="description" prop="description"
@ -74,7 +74,7 @@
:editContent="'aaa'" :editContent="'aaa'"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<mini-timing-item :expr="scope.row.expireTime"></mini-timing-item> <mini-timing-item :expr.sync="scope.row.expireTime" @chooseChange="change(scope.row)"></mini-timing-item>
</template> </template>
</ms-table-column> </ms-table-column>
@ -95,7 +95,8 @@
<el-switch v-model="scope.row.enable" size="mini"></el-switch> <el-switch v-model="scope.row.enable" size="mini"></el-switch>
<el-tooltip <el-tooltip
effect="dark" effect="dark"
:content="$t('关联登录场景/指令')" :content="$t('environment.relevance_ui')"
v-if="!existCookieConfig"
placement="top-start" placement="top-start"
> >
<el-button <el-button
@ -103,26 +104,26 @@
circle circle
size="mini" size="mini"
@click="openRelevance" @click="openRelevance"
v-if="!existCookieConfig" style="margin-left: 10px"
/>
</el-tooltip>
<el-dropdown @command="handleCommand" v-if="existCookieConfig">
<el-button
icon="el-icon-paperclip"
circle
size="mini"
style="margin-left: 10px" style="margin-left: 10px"
/> />
<el-dropdown @command="handleCommand" v-if="existCookieConfig"> <el-dropdown-menu slot="dropdown">
<el-button <el-dropdown-item command="view">{{ $t("environment.view_ui_relevane") }}</el-dropdown-item>
icon="el-icon-paperclip" <el-dropdown-item command="cancelRelevance">{{ $t("environment.cancel_ui_relevane") }}
circle </el-dropdown-item>
size="mini" <el-dropdown-item command="relevance">{{ $t("environment.re_ui_relevane") }}</el-dropdown-item>
style="margin-left: 10px" </el-dropdown-menu>
/> </el-dropdown>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="view">查看关联</el-dropdown-item>
<el-dropdown-item command="cancelRelevance">取消关联</el-dropdown-item>
<el-dropdown-item command="relevance">重新关联</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
</template> </template>
</ms-table-column> </ms-table-column>
</ms-table> </ms-table>
@ -158,6 +159,7 @@ import VariableImport from "metersphere-frontend/src/components/environment/Vari
import _ from "lodash"; import _ from "lodash";
import MiniTimingItem from "metersphere-frontend/src/components/environment/commons/MiniTimingItem"; import MiniTimingItem from "metersphere-frontend/src/components/environment/commons/MiniTimingItem";
import UiScenarioEditRelevance from "@/business/menu/environment/components/ui-related/UiScenarioEditRelevance"; import UiScenarioEditRelevance from "@/business/menu/environment/components/ui-related/UiScenarioEditRelevance";
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
export default { export default {
name: "MsUiScenarioCookieTable", name: "MsUiScenarioCookieTable",
@ -218,8 +220,8 @@ export default {
}, },
watch: { watch: {
items: { items: {
handler(v) { handler(val) {
this.variables = v; this.variables = val;
this.sortParameters(); this.sortParameters();
}, },
immediate: true, immediate: true,
@ -235,7 +237,7 @@ export default {
}, },
immediate: true, immediate: true,
deep: true, deep: true,
} },
}, },
methods: { methods: {
remove: function (index) { remove: function (index) {
@ -271,6 +273,7 @@ export default {
this.$t("load_test.param_is_duplicate") this.$t("load_test.param_is_duplicate")
); );
} }
this.variables[0].updateTime = new Date().getTime();
this.$emit("change", this.variables); this.$emit("change", this.variables);
}, },
changeType(data) { changeType(data) {
@ -314,23 +317,22 @@ export default {
}, },
sortParameters() { sortParameters() {
let index = 1; let index = 1;
this.variables.forEach((item) => { if (this.variables) {
item.num = index; this.variables.forEach((item) => {
if (!item.type || item.type === "text") { item.num = index;
item.type = "CONSTANT"; if (!item.type || item.type === "text") {
} item.type = "CONSTANT";
if (!item.id) { }
item.id = getUUID(); if (!item.id) {
} item.id = getUUID();
if (item.remark) { }
this.$set(item, "description", item.remark); if (item.remark) {
item.remark = undefined; this.$set(item, "description", item.remark);
} item.remark = undefined;
if (!item.scope) { }
this.$set(item, "scope", "api"); index++;
} });
index++; }
});
}, },
handleDeleteBatch() { handleDeleteBatch() {
operationConfirm( operationConfirm(
@ -509,17 +511,36 @@ export default {
handleCommand(c) { handleCommand(c) {
switch (c) { switch (c) {
case "view": case "view":
this.redirectPage(this.variables[0].relevanceId);
break; break;
case "cancelRelevance": case "cancelRelevance":
this.variables[0].relevanceId = null; this.variables[0].relevanceId = null;
this.$success(this.$t("organization.integration.successful_operation"));
break; break;
case "relevance": case "relevance":
this.openRelevance(); this.openRelevance("scenario", "scenario",);
break; break;
default: default:
break; break;
} }
}, },
redirectPage(resourceId) {
let uuid = getUUID().substring(1, 5);
let projectId = getCurrentProjectID();
let workspaceId = getCurrentWorkspaceId();
let prefix = '/#';
if (
this.$route &&
this.$route.path.startsWith('/#')
) {
prefix = '';
}
let path = `/ui/automation/?redirectID=${uuid}&dataType=scenario&projectId=${projectId}&workspaceId=${workspaceId}&resourceId=${resourceId}`;
let data = this.$router.resolve({
path: path,
});
window.open(data.href, '_blank');
},
openRelevance() { openRelevance() {
this.$refs.relevanceUiDialog.open(); this.$refs.relevanceUiDialog.open();
}, },
@ -527,19 +548,31 @@ export default {
this.variables[0].relevanceId = id.keys().next().value.id; this.variables[0].relevanceId = id.keys().next().value.id;
this.$refs.relevanceUiDialog.close(); this.$refs.relevanceUiDialog.close();
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
},
validate() {
if (!this.variables[0].enable) {
return true;
}
let cookieConfig = this.variables[0];
if (!cookieConfig) {
this.$warning(this.$t("配置错误"));
return false;
}
if (!cookieConfig.expireTime || cookieConfig.expireTime === "") {
this.$warning(this.$t("environment.need_expire_time"));
return false;
}
if (!cookieConfig.relevanceId) {
this.$warning(this.$t("environment.need_relevance_ui_scenario"));
return false;
}
return true;
} }
}, },
created() { created() {
if (this.items.length === 0) { if (!this.items || this.items.length === 0) {
this.items.push(new KeyValue({enable: true, expireTime: '1Y'})); this.items = [];
} else { this.items.push(new KeyValue({id: getUUID(), enable: true, expireTime: '1M'}));
// api
_.forEach(this.items, item => {
if (!item.scope) {
this.$set(item, "scope", "api");
}
})
this.variables = this.items;
} }
}, },
}; };

View File

@ -35,6 +35,15 @@ const message = {
}, },
project_version: { project_version: {
version_time: 'Version cycle', version_time: 'Version cycle',
},
environment: {
export_variable_tip : "Export interface test variables",
need_expire_time : "Please enter an expiration time",
need_relevance_ui_scenario : "Please associate the login scenario",
view_ui_relevane : "View Relevane",
cancel_ui_relevane : "Relevant",
re_ui_relevane : "Relevane",
relevance_ui : "Relevance login scene/command",
} }
} }

View File

@ -37,7 +37,13 @@ const message = {
version_time: '版本周期', version_time: '版本周期',
}, },
environment: { environment: {
export_variable_tip : "导出接口测试变量" export_variable_tip : "导出接口测试变量",
need_expire_time : "请输入过期时间",
need_relevance_ui_scenario : "请关联登录场景",
view_ui_relevane : "查看关联",
cancel_ui_relevane : "取消关联",
re_ui_relevane : "重新关联",
relevance_ui : "关联登录场景/指令",
} }
} }

View File

@ -35,6 +35,15 @@ const message = {
}, },
project_version: { project_version: {
version_time: '版本週期', version_time: '版本週期',
},
environment: {
export_variable_tip : "導出接口測試變量",
need_expire_time : "請輸入過期時間",
need_relevance_ui_scenario : "請關聯登錄場景",
view_ui_relevane : "查看關聯",
cancel_ui_relevane : "取消關聯",
re_ui_relevane : "重新關聯",
relevance_ui : "關聯登錄場景/指令",
} }
} }