style(接口测试): 统一场景步骤样式

--bug=1013424 --user=赵勇 【接口测试】场景断言步骤-开关和...显示按钮未居中且按钮间距和其它步骤不同-场景内所有步骤的操作按钮间距、居中显示、步骤高度均显示一致 https://www.tapd.cn/55049933/s/1169441
This commit is contained in:
fit2-zhao 2022-05-31 14:22:01 +08:00 committed by fit2-zhao
parent eabc1b9509
commit 515ed77aca
4 changed files with 277 additions and 266 deletions

View File

@ -1,12 +1,12 @@
<template>
<el-card :style="{'border-color':colorStyle}">
<div class="header" @click="active(data)">
<el-card :style="{'border-color':colorStyle}" class="ms-base-card">
<div class="ms-base-header" @click="active(data)">
<slot name="beforeHeaderLeft">
<div v-if="data.index" class="el-step__icon is-text enable-switch" :style="{'color': color, 'background-color': backgroundColor}">
<div v-if="data.index" class="el-step__icon is-text" :style="{'color': color, 'background-color': backgroundColor}">
<div class="el-step__icon-inner" :key="$store.state.forceRerenderIndex">{{ data.index }}</div>
</div>
<el-tag class="ms-left-btn" size="small" :style="{'color': color, 'background-color': backgroundColor}">{{ title }}</el-tag>
<slot name="behindHeaderLeft" v-if="!isMax"></slot>
<el-tag class="ms-left-btn" size="mini" :style="{'color': color, 'background-color': backgroundColor}">{{ title }}</el-tag>
</slot>
<span v-show="!isMax">
@ -28,7 +28,7 @@
</span>
<span v-show="isMax">
<slot name="headerLeft">
<span style="font-size: 12px" class="ms-step-name-width">{{ data.name }}</span>
<span class="ms-step-name-width">{{ data.name }}</span>
</slot>
</span>
@ -36,18 +36,19 @@
<slot name="message" v-show="!isMax"></slot>
<slot name="debugStepCode"></slot>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn">
<el-switch v-model="data.enable" class="enable-switch" size="mini" :disabled="(data.disabled && !data.root) || !showVersion" style="width: 30px"/>
</el-tooltip>
<slot name="button" v-if="showVersion"></slot>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn">
<el-switch v-model="data.enable" class="enable-switch" size="mini" :disabled="(data.disabled && !data.root) || !showVersion"/>
</el-tooltip>
<el-button v-if="showVersion && showCopy" size="mini" icon="el-icon-copy-document" circle @click="copyRow"
style="padding: 5px"
:disabled="(data.disabled && !data.root) || !showVersion "/>
<el-button v-show="isSingleButton" size="mini" icon="el-icon-delete" type="danger" style="padding: 5px" circle @click="remove"
:disabled="(data.disabled && !data.root) || !showVersion "/>
<step-extend-btns style="display: contents"
:data="data"
:environmentType="environmentType"
@ -63,7 +64,7 @@
</div>
<!--最大化不显示具体内容-->
<div class="header" v-if="!isMax">
<div v-if="!isMax">
<el-collapse-transition>
<!-- 这里的组件默认不展开时不加载 -->
<div v-if="data.active && showCollapse" :draggable="draggable">
@ -261,7 +262,7 @@ export default {
}
.el-icon-arrow-right {
margin-right: 5px;
margin-right: 3px;
}
.ms-left-btn {
@ -269,14 +270,19 @@ export default {
margin-left: 0px;
}
.ms-base-header{
min-height: 26px;
}
.header-right {
margin-top: 0px;
margin-top: 1px;
float: right;
z-index: 1;
}
.enable-switch {
margin-right: 10px;
margin: 0px 5px 0px;
padding-bottom: 2px;
width: 30px;
}
.scenario-version {
@ -321,7 +327,7 @@ export default {
.scenario-name {
display: inline-block;
font-size: 13px;
margin: 0 5px;
margin: 0 0px;
/*overflow-x: hidden;*/
overflow-x: auto;
overflow-y: hidden;
@ -364,7 +370,7 @@ export default {
.scenario-unscroll {
display: inline-block;
font-size: 13px;
margin: 0 5px;
margin: 0 0px;
overflow-x: hidden;
/*overflow-x: auto;*/
overflow-y: hidden;
@ -395,6 +401,7 @@ fieldset {
}
.ms-step-name-width {
font-size: 12px;
display: inline-block;
margin: 0 0px;
overflow-x: hidden;
@ -404,5 +411,10 @@ fieldset {
white-space: nowrap;
width: 60px;
}
.ms-base-card{
min-height: 36px;
}
.is-text{
margin-right: 5px;
}
</style>

View File

@ -30,11 +30,11 @@
</template>
<template v-slot:behindHeaderLeft>
<el-tag size="mini" class="ms-tag" v-if="request.referenced==='Deleted'" type="danger">
<el-tag size="small" class="ms-tag" v-if="request.referenced==='Deleted'" type="danger">
{{ $t('api_test.automation.reference_deleted') }}
</el-tag>
<el-tag size="mini" class="ms-tag" v-if="request.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
<el-tag size="mini" class="ms-tag" v-if="request.referenced ==='REF'">{{
<el-tag size="small" class="ms-tag" v-if="request.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
<el-tag size="small" class="ms-tag" v-if="request.referenced ==='REF'">{{
$t('api_test.scenario.reference')
}}
</el-tag>
@ -59,7 +59,7 @@
</template>
<template v-slot:button v-if="!ifFromVariableAdvance">
<el-tooltip :content="$t('api_test.run')" placement="top" v-if="!loading">
<el-button :disabled="!request.enable" @click="run" icon="el-icon-video-play" style="padding: 5px" class="ms-btn" size="mini" circle/>
<el-button :disabled="!request.enable" @click="run" icon="el-icon-video-play" class="ms-btn" size="mini" circle/>
</el-tooltip>
<el-tooltip :content="$t('report.stop_btn')" placement="top" :enterable="false" v-else>
<el-button @click.once="stop" size="mini" style="color:white;padding: 0 0.1px;width: 24px;height: 24px;"
@ -706,10 +706,6 @@ export default {
color: #409EFF;
}
/deep/ .el-card__body {
padding: 6px 10px;
}
.icon.is-active {
transform: rotate(90deg);
}
@ -720,17 +716,18 @@ export default {
}
.ms-btn {
padding: 5px;
background-color: #409EFF;
color: white;
}
.ms-btn-flot {
.ms-btn-float {
margin: 20px;
float: right;
}
.ms-step-name-api {
padding-left: 10px;
padding-left: 5px;
}
.ms-tag {

View File

@ -31,9 +31,9 @@
</template>
<template v-slot:behindHeaderLeft>
<el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='Deleted'" type="danger">{{ $t('api_test.automation.reference_deleted') }}</el-tag>
<el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
<el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag>
<el-tag size="small" class="ms-tag" v-if="scenario.referenced==='Deleted'" type="danger">{{ $t('api_test.automation.reference_deleted') }}</el-tag>
<el-tag size="small" class="ms-tag" v-if="scenario.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
<el-tag size="small" class="ms-tag" v-if="scenario.referenced==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag>
<span class="ms-tag ms-step-name-api">{{ getProjectName(scenario.projectId) }}</span>
</template>
<template v-slot:debugStepCode>
@ -339,7 +339,7 @@ export default {
}
.ms-step-name-api {
padding-left: 10px;
padding-left: 5px;
}
.ms-tag {

View File

@ -15,271 +15,273 @@
background-color="#F7E6E9"
:title="$t('api_test.definition.request.scenario_assertions')">
<el-card :draggable="true">
<el-row>
<span>{{ $t('api_test.request.assertions.description') }}</span>
<span style="float: right">
<el-row>
<span>{{ $t('api_test.request.assertions.description') }}</span>
<span style="float: right">
<api-json-path-suggest-button
:show-suggest-button="false"
:clear-tip="$t('api_test.request.assertions.json_path_clear')"
:isReadOnly="request.disabled"
@clear="clearJson"/>
</span>
</el-row>
<div class="assertion-add" :draggable="draggable">
<el-row :gutter="10">
<el-col :span="4">
<el-select :disabled="request.disabled" class="assertion-item" v-model="type"
:placeholder="$t('api_test.request.assertions.select_type')" size="small">
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT"/>
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX"/>
<el-option :label="'JSONPath'" :value="options.JSON_PATH"/>
<el-option :label="'XPath'" :value="options.XPATH2"/>
<el-option :label="$t('api_test.request.assertions.response_time')" :value="options.DURATION"/>
<el-option :label="$t('api_test.request.assertions.jsr223')" :value="options.JSR223"/>
<el-option :label="$t('api_test.definition.request.document_structure')" :value="options.DOCUMENT"/>
</el-select>
</el-col>
<el-col :span="20">
<ms-api-assertion-text
:is-read-only="request.disabled"
:list="assertions.regex"
:callback="after"
v-if="type === options.TEXT"
/>
<ms-api-assertion-regex
:is-read-only="request.disabled"
:list="assertions.regex"
:callback="after"
@callback="after"
v-if="type === options.REGEX"
/>
<ms-api-assertion-json-path
:is-read-only="request.disabled"
:list="assertions.jsonPath"
:callback="after"
v-if="type === options.JSON_PATH"
/>
<ms-api-assertion-x-path2
:is-read-only="request.disabled"
:list="assertions.xpath2"
:callback="after"
v-if="type === options.XPATH2"
/>
<ms-api-assertion-duration
v-model="time"
:is-read-only="request.disabled"
:duration="assertions.duration"
:callback="after"
v-if="type === options.DURATION"
/>
<ms-api-assertion-jsr223
:is-read-only="request.disabled"
:list="assertions.jsr223"
:callback="after"
v-if="type === options.JSR223"
/>
<ms-api-assertion-document
:is-read-only="request.disabled"
v-model="time"
:document="assertions.document"
:callback="after"
v-if="type === options.DOCUMENT"
/>
<el-button v-if="!type" :disabled="true" type="primary" size="mini">
{{ $t('api_test.request.assertions.add') }}
</el-button>
</el-col>
</el-row>
<div class="assertion-add" :draggable="draggable">
<el-row :gutter="10">
<el-col :span="4">
<el-select :disabled="request.disabled" class="assertion-item" v-model="type"
:placeholder="$t('api_test.request.assertions.select_type')" size="small">
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT"/>
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX"/>
<el-option :label="'JSONPath'" :value="options.JSON_PATH"/>
<el-option :label="'XPath'" :value="options.XPATH2"/>
<el-option :label="$t('api_test.request.assertions.response_time')" :value="options.DURATION"/>
<el-option :label="$t('api_test.request.assertions.jsr223')" :value="options.JSR223"/>
<el-option :label="$t('api_test.definition.request.document_structure')" :value="options.DOCUMENT"/>
</el-select>
</el-col>
<el-col :span="20">
<ms-api-assertion-text
:is-read-only="request.disabled"
:list="assertions.regex"
:callback="after"
v-if="type === options.TEXT"
/>
<ms-api-assertion-regex
:is-read-only="request.disabled"
:list="assertions.regex"
:callback="after"
@callback="after"
v-if="type === options.REGEX"
/>
<ms-api-assertion-json-path
:is-read-only="request.disabled"
:list="assertions.jsonPath"
:callback="after"
v-if="type === options.JSON_PATH"
/>
<ms-api-assertion-x-path2
:is-read-only="request.disabled"
:list="assertions.xpath2"
:callback="after"
v-if="type === options.XPATH2"
/>
<ms-api-assertion-duration
v-model="time"
:is-read-only="request.disabled"
:duration="assertions.duration"
:callback="after"
v-if="type === options.DURATION"
/>
<ms-api-assertion-jsr223
:is-read-only="request.disabled"
:list="assertions.jsr223"
:callback="after"
v-if="type === options.JSR223"
/>
<ms-api-assertion-document
:is-read-only="request.disabled"
v-model="time"
:document="assertions.document"
:callback="after"
v-if="type === options.DOCUMENT"
/>
<el-button v-if="!type" :disabled="true" type="primary" size="mini">
{{ $t('api_test.request.assertions.add') }}
</el-button>
</el-col>
</el-row>
</div>
</div>
<ms-api-assertions-edit
:is-read-only="request.disabled"
:assertions="assertions"
:apiId="apiId"
:reloadData="reloadData"
style="margin-bottom: 20px"/>
<ms-api-assertions-edit
:is-read-only="request.disabled"
:assertions="assertions"
:apiId="apiId"
:reloadData="reloadData"
style="margin-bottom: 20px"/>
<ms-api-jsonpath-suggest
:tip="$t('api_test.request.extract.suggest_tip')"
@addSuggest="addJsonPathSuggest"
ref="jsonpathSuggest"/>
<ms-api-jsonpath-suggest
:tip="$t('api_test.request.extract.suggest_tip')"
@addSuggest="addJsonPathSuggest"
ref="jsonpathSuggest"/>
</el-card>
</api-base-component>
</template>
<script>
import MsApiAssertionText from "./ApiAssertionText";
import MsApiAssertionRegex from "./ApiAssertionRegex";
import MsApiAssertionDuration from "./ApiAssertionDuration";
import {ASSERTION_TYPE, JSONPath} from "../../model/ApiTestModel";
import MsApiAssertionsEdit from "./ApiAssertionsEdit";
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
import MsApiJsonpathSuggestList from "./ApiJsonpathSuggestList";
import MsApiAssertionXPath2 from "./ApiAssertionXPath2";
import {getUUID} from "@/common/js/utils";
import ApiJsonPathSuggestButton from "./ApiJsonPathSuggestButton";
import MsApiJsonpathSuggest from "./ApiJsonpathSuggest";
import ApiBaseComponent from "../../../automation/scenario/common/ApiBaseComponent";
import MsApiAssertionDocument from "./document/DocumentHeader";
import MsApiAssertionText from "./ApiAssertionText";
import MsApiAssertionRegex from "./ApiAssertionRegex";
import MsApiAssertionDuration from "./ApiAssertionDuration";
import {ASSERTION_TYPE, JSONPath} from "../../model/ApiTestModel";
import MsApiAssertionsEdit from "./ApiAssertionsEdit";
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
import MsApiJsonpathSuggestList from "./ApiJsonpathSuggestList";
import MsApiAssertionXPath2 from "./ApiAssertionXPath2";
import {getUUID} from "@/common/js/utils";
import ApiJsonPathSuggestButton from "./ApiJsonPathSuggestButton";
import MsApiJsonpathSuggest from "./ApiJsonpathSuggest";
import ApiBaseComponent from "../../../automation/scenario/common/ApiBaseComponent";
import MsApiAssertionDocument from "./document/DocumentHeader";
export default {
name: "MsApiAssertions",
components: {
ApiBaseComponent,
MsApiJsonpathSuggest,
ApiJsonPathSuggestButton,
MsApiAssertionXPath2,
MsApiAssertionJsr223,
MsApiJsonpathSuggestList,
MsApiAssertionJsonPath,
MsApiAssertionsEdit,
MsApiAssertionDuration,
MsApiAssertionRegex,
MsApiAssertionText,
MsApiAssertionDocument,
},
props: {
draggable: {
type: Boolean,
default: false,
export default {
name: "MsApiAssertions",
components: {
ApiBaseComponent,
MsApiJsonpathSuggest,
ApiJsonPathSuggestButton,
MsApiAssertionXPath2,
MsApiAssertionJsr223,
MsApiJsonpathSuggestList,
MsApiAssertionJsonPath,
MsApiAssertionsEdit,
MsApiAssertionDuration,
MsApiAssertionRegex,
MsApiAssertionText,
MsApiAssertionDocument,
},
isMax: {
type: Boolean,
default: false,
},
innerStep: {
type: Boolean,
default: false,
},
showBtn: {
type: Boolean,
default: true,
},
showVersion: {
type: Boolean,
default: true,
},
assertions: {},
node: {},
request: {},
apiId: String,
response: {},
customizeStyle: {
type: String,
default: "margin-top: 10px"
},
isReadOnly: {
type: Boolean,
default: false
}
},
data() {
return {
options: ASSERTION_TYPE,
time: "",
type: "",
loading: false,
reloadData: "",
}
},
watch: {
assertions: {
handler(v) {
this.computeStep();
props: {
draggable: {
type: Boolean,
default: false,
},
deep: true
},
},
methods: {
computeStep() {
let ruleSize = 0;
ruleSize = (this.assertions.jsonPath.length + this.assertions.jsr223.length + this.assertions.regex.length + this.assertions.xpath2.length);
if (this.assertions && this.assertions.document.data && (this.assertions.document.data.json.length > 0 || this.assertions.document.data.xml.length > 0)) {
ruleSize++;
isMax: {
type: Boolean,
default: false,
},
innerStep: {
type: Boolean,
default: false,
},
showBtn: {
type: Boolean,
default: true,
},
showVersion: {
type: Boolean,
default: true,
},
assertions: {},
node: {},
request: {},
apiId: String,
response: {},
customizeStyle: {
type: String,
default: "margin-top: 10px"
},
isReadOnly: {
type: Boolean,
default: false
}
if (this.assertions.duration && this.assertions.duration.value > 0) {
ruleSize++;
},
data() {
return {
options: ASSERTION_TYPE,
time: "",
type: "",
loading: false,
reloadData: "",
}
ruleSize += this.assertions.text ? this.assertions.text.length : 0;
this.request.ruleSize = ruleSize;
this.$emit('reload');
},
after() {
this.type = "";
this.reloadData = getUUID().substring(0, 8);
this.reload();
watch: {
assertions: {
handler(v) {
this.computeStep();
},
deep: true
},
},
copyRow() {
this.$emit('copyRow', this.assertions, this.node);
},
suggestJsonOpen() {
this.$emit('suggestClick');
this.$nextTick(() => {
if (!this.response || !this.response.responseResult || !this.response.responseResult.body) {
this.$message(this.$t('api_test.request.assertions.debug_first'));
return;
methods: {
computeStep() {
let ruleSize = 0;
ruleSize = (this.assertions.jsonPath.length + this.assertions.jsr223.length + this.assertions.regex.length + this.assertions.xpath2.length);
if (this.assertions && this.assertions.document.data && (this.assertions.document.data.json.length > 0 || this.assertions.document.data.xml.length > 0)) {
ruleSize++;
}
this.$refs.jsonpathSuggest.open(this.response.responseResult.body);
})
},
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
})
},
active() {
this.assertions.active = !this.assertions.active;
this.reload();
},
remove() {
this.$emit('remove', this.assertions, this.node);
},
addJsonPathSuggest(data) {
let jsonItem = new JSONPath();
jsonItem.expression = data.path;
jsonItem.expect = data.value;
jsonItem.setJSONPathDescription();
let expect = jsonItem.expect;
if (expect) {
expect = expect.replaceAll('\\', "\\\\").replaceAll('(', "\\(").replaceAll(')', "\\)")
.replaceAll('+', "\\+").replaceAll('[', "\\[").replaceAll(']', "\\]")
.replaceAll('?', "\\?").replaceAll('/', "\\/").replaceAll('*', "\\*")
.replaceAll('^', "\\^").replaceAll('{', "\\{").replaceAll('}', "\\}").replaceAll('$', "\\$");
if (this.assertions.duration && this.assertions.duration.value > 0) {
ruleSize++;
}
ruleSize += this.assertions.text ? this.assertions.text.length : 0;
this.request.ruleSize = ruleSize;
this.$emit('reload');
},
after() {
this.type = "";
this.reloadData = getUUID().substring(0, 8);
this.reload();
},
copyRow() {
this.$emit('copyRow', this.assertions, this.node);
},
suggestJsonOpen() {
this.$emit('suggestClick');
this.$nextTick(() => {
if (!this.response || !this.response.responseResult || !this.response.responseResult.body) {
this.$message(this.$t('api_test.request.assertions.debug_first'));
return;
}
this.$refs.jsonpathSuggest.open(this.response.responseResult.body);
})
},
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
})
},
active() {
this.assertions.active = !this.assertions.active;
this.reload();
},
remove() {
this.$emit('remove', this.assertions, this.node);
},
addJsonPathSuggest(data) {
let jsonItem = new JSONPath();
jsonItem.expression = data.path;
jsonItem.expect = data.value;
jsonItem.setJSONPathDescription();
let expect = jsonItem.expect;
if (expect) {
expect = expect.replaceAll('\\', "\\\\").replaceAll('(', "\\(").replaceAll(')', "\\)")
.replaceAll('+', "\\+").replaceAll('[', "\\[").replaceAll(']', "\\]")
.replaceAll('?', "\\?").replaceAll('/', "\\/").replaceAll('*', "\\*")
.replaceAll('^', "\\^").replaceAll('{', "\\{").replaceAll('}', "\\}").replaceAll('$', "\\$");
}
jsonItem.expect = expect;
jsonItem.enable = true;
this.assertions.jsonPath.push(jsonItem);
},
clearJson() {
this.assertions.jsonPath = [];
}
jsonItem.expect = expect;
jsonItem.enable = true;
this.assertions.jsonPath.push(jsonItem);
},
clearJson() {
this.assertions.jsonPath = [];
}
}
}
</script>
<style scoped>
.assertion-item {
width: 100%;
}
.assertion-item {
width: 100%;
}
.assertion-add {
padding: 10px;
margin: 5px 0;
border-radius: 5px;
border: #DCDFE6 solid 1px;
}
.assertion-add {
padding: 10px;
margin: 5px 0;
border-radius: 5px;
border: #DCDFE6 solid 1px;
}
.icon.is-active {
transform: rotate(90deg);
}
/deep/ .el-card__body {
padding: 6px 10px;
}
.icon.is-active {
transform: rotate(90deg);
}
/deep/ .header-right{
margin-top: 4px;
}
/deep/.enable-switch{
margin: 0px 0px 0px;
padding-bottom: 3px;
width: 30px;
}
</style>