feat(接口测试): 场景步骤重构优化

This commit is contained in:
fit2-zhao 2022-03-04 18:33:52 +08:00 committed by fit2-zhao
parent a1f3cc8701
commit 777e62dbb8
14 changed files with 715 additions and 534 deletions

View File

@ -19,7 +19,6 @@
"@fortawesome/vue-fontawesome": "^0.1.9",
"axios": "^0.21.3",
"core-js": "^3.4.3",
"default-passive-events": "^2.0.0",
"diffable-html": "^4.0.0",
"echarts": "^5.0.2",
"el-table-infinite-scroll": "^1.0.10",

View File

@ -1,6 +1,6 @@
<template>
<ms-container v-if="renderComponent" v-loading="loading">
<ms-aside-container>
<ms-aside-container v-show="isAsideHidden">
<ms-api-scenario-module
:show-operator="true"
@nodeSelectEvent="nodeChange"
@ -162,7 +162,8 @@ export default {
//API
initApiTableOpretion: 'init',
isLeave: false,
isSave: false
isSave: false,
isAsideHidden: true,
};
},
created() {
@ -201,6 +202,7 @@ export default {
this.activeName = "default";
},
activeName() {
this.isAsideHidden = this.activeName === 'default';
}
},
methods: {
@ -502,7 +504,9 @@ export default {
this.$refs.nodeTree.list();
},
refreshTree() {
if (this.$refs.nodeTree) {
this.$refs.nodeTree.list();
}
},
refreshAll() {
this.$refs.nodeTree.list();

View File

@ -1,54 +1,26 @@
<template>
<el-card>
<div class="card-content">
<div class="ms-main-div" @click="showAll" v-if="type!=='detail'">
<!--操作按钮-->
<div class="ms-opt-btn">
<el-tooltip :content="$t('commons.follow')" placement="bottom" effect="dark" v-if="!showFollow">
<i class="el-icon-star-off" style="color: #783987; font-size: 25px; margin-right: 5px;cursor: pointer;position: relative; top: 5px; " @click="saveFollow"/>
</el-tooltip>
<el-tooltip :content="$t('commons.cancel')" placement="bottom" effect="dark" v-if="showFollow">
<i class="el-icon-star-on" style="color: #783987; font-size: 28px; margin-right: 5px;cursor: pointer;position: relative; top: 5px; " @click="saveFollow"/>
</el-tooltip>
<el-link type="primary" style="margin-right: 5px" @click="openHis" v-if="path === '/api/automation/update'">{{ $t('operating_log.change_history') }}</el-link>
<!-- 版本历史 -->
<ms-version-history v-xpack
ref="versionHistory"
:version-data="versionData"
:current-id="currentScenario.id"
@compare="compare" @checkout="checkout" @create="create" @del="del"/>
<el-button id="inputDelay" type="primary" size="small" v-prevent-re-click @click="editScenario"
title="ctrl + s" v-permission="['PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+COPY']">
{{ $t('commons.save') }}
</el-button>
</div>
<ms-container>
<ms-aside-container>
<div @click="showAll">
<div class="tip">{{ $t('test_track.plan_view.base_info') }}</div>
<el-form :model="currentScenario" label-position="right" label-width="80px" size="small" :rules="rules"
ref="currentScenario" style="margin-right: 20px">
ref="currentScenario">
<!-- 基础信息 -->
<el-row>
<el-col :span="7">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input class="ms-scenario-input" size="small" v-model="currentScenario.name"/>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :label="$t('test_track.module.module')" prop="apiScenarioModuleId">
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="currentScenario.apiScenarioModuleId" @getValue="setModule" :obj="moduleObj" clearable checkStrictly/>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :label="$t('commons.status')" prop="status">
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.status">
<el-option v-for="item in options" :key="item.id" :label="$t(item.label)" :value="item.id"/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="principal">
<el-select v-model="currentScenario.principal"
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
@ -61,22 +33,17 @@
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :label="$t('test_track.case.priority')" prop="level">
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.level">
<el-option v-for="item in levels" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :label="$t('api_test.automation.tag')" prop="tags">
<ms-input-tag :currentScenario="currentScenario" ref="tag"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<el-form-item :label="$t('commons.description')" prop="description">
<el-input class="ms-http-textarea"
v-model="currentScenario.description"
@ -84,50 +51,37 @@
:autosize="{ minRows: 1, maxRows: 10}"
:rows="1" size="small"/>
</el-form-item>
</el-col>
<el-col :span="7" v-if="customNum">
<el-form-item label="ID" prop="customNum">
<el-form-item label="ID" prop="customNum" v-if="customNum">
<el-input v-model.trim="currentScenario.customNum" size="small"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<!-- 场景步骤-->
<div v-loading="loading">
<div @click="showAll">
<p class="tip">{{ $t('api_test.automation.scenario_step') }} </p>
</div>
<el-row>
<el-col :span="21">
<!-- 调试部分 -->
<div class="ms-debug-div" @click="showAll" :class="{'is-top' : isTop}" ref="debugHeader">
</ms-aside-container>
<!-- 右侧部分 -->
<ms-main-container style="overflow: hidden" class="ms-scenario-main-container">
<!-- header 调试部分 -->
<div class="ms-debug-div" @click="showAll" ref="debugHeader">
<el-row style="margin: 5px">
<el-col :span="4" class="ms-col-one ms-font">
<el-tooltip placement="top" effect="light">
<template v-slot:content>
<div>{{
currentScenario.name === undefined || '' ? $t('api_test.scenario.name') : currentScenario.name
}}
</div>
</template>
<span class="scenario-name">
{{
currentScenario.name === undefined || '' ? $t('api_test.scenario.name') : currentScenario.name
}}
</span>
<el-col :span="1" class="ms-col-one ms-font" v-show="scenarioDefinition.length > 1">
<el-tooltip :content="$t('test_track.case.batch_operate')" placement="top" effect="light" v-show="!isBatchProcess">
<font-awesome-icon class="ms-batch-btn" :icon="['fa', 'bars']" v-prevent-re-click @click="batchProcessing"/>
</el-tooltip>
<el-checkbox v-show="isBatchProcess" v-model="isCheckedAll" @change="checkedAll"/>
<el-tooltip :content="$t('commons.cancel')" placement="top" effect="light" v-show="isBatchProcess">
<font-awesome-icon class="ms-batch-btn" :icon="['fa', 'times']" v-prevent-re-click @click="cancelBatchProcessing"/>
</el-tooltip>
</el-col>
<el-col :span="3" class="ms-col-one ms-font">
<el-col :span="2" class="ms-col-one ms-font">
{{ $t('api_test.automation.step_total') }}{{ scenarioDefinition.length }}
</el-col>
<el-col :span="3" class="ms-col-one ms-font">
<el-col :span="2" class="ms-col-one ms-font">
<el-link class="head" @click="showScenarioParameters">{{ $t('api_test.automation.scenario_total') }}
</el-link>
{{ getVariableSize() }}
</el-col>
<el-col :span="3" class="ms-col-one ms-font">
<el-col :span="2" class="ms-col-one ms-font">
<el-checkbox v-model="enableCookieShare"><span style="font-size: 13px;">{{ $t('api_test.scenario.share_cookie') }}</span></el-checkbox>
</el-col>
<el-col :span="3" class="ms-col-one ms-font">
@ -135,7 +89,7 @@
</el-col>
<el-col :span="7">
<div style="float: right;width: 300px">
<div style="float: right;width: 330px">
<env-popover :disabled="scenarioDefinition.length < 1" :env-map="projectEnvMap"
:project-ids="projectIds" :result="envResult"
:environment-type.sync="environmentType" :isReadOnly="scenarioDefinition.length < 1"
@ -153,56 +107,83 @@
</el-dropdown>
</el-tooltip>
<el-button size="mini" type="primary" v-else @click="stop">{{ $t('report.stop_btn') }}</el-button>
<el-button id="inputDelay" type="primary" size="mini" v-prevent-re-click @click="editScenario"
title="ctrl + s" v-permission="['PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+COPY']">
{{ $t('commons.save') }}
</el-button>
<el-tooltip class="item" effect="dark" :content="$t('commons.refresh')" placement="top-start">
<el-button :disabled="scenarioDefinition.length < 1" size="mini" icon="el-icon-refresh"
v-prevent-re-click @click="getApiScenario"></el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="$t('commons.full_screen_editing')"
placement="top-start">
<font-awesome-icon class="alt-ico" :icon="['fa', 'expand-alt']" size="lg" @click="fullScreen"/>
</el-tooltip>
</div>
</el-col>
<!--操作按钮-->
<el-link type="primary" @click.stop @click="showHistory" style="margin-right: 10px">
{{ $t("commons.debug_history") }}
</el-link>
<el-tooltip :content="$t('commons.follow')" placement="bottom" effect="dark" v-show="!showFollow">
<i class="el-icon-star-off" style="color: #783987; font-size: 25px; margin-right: 5px;cursor: pointer;position: relative; top: 5px; " @click="saveFollow"/>
</el-tooltip>
<el-tooltip :content="$t('commons.cancel')" placement="bottom" effect="dark" v-show="showFollow">
<i class="el-icon-star-on" style="color: #783987; font-size: 28px; margin-right: 5px;cursor: pointer;position: relative; top: 5px; " @click="saveFollow"/>
</el-tooltip>
<el-link type="primary" style="margin-right: 5px" @click="openHis" v-show="path === '/api/automation/update'">{{ $t('operating_log.change_history') }}</el-link>
<!-- 版本历史 -->
<ms-version-history v-xpack
ref="versionHistory"
:version-data="versionData"
:current-id="currentScenario.id"
@compare="compare" @checkout="checkout" @create="create" @del="del"/>
<el-tooltip effect="dark" :content="$t('commons.full_screen_editing')"
placement="top-start" style="margin-top: 6px">
<font-awesome-icon class="alt-ico" :icon="['fa', 'expand-alt']" size="lg" @click="fullScreen"/>
</el-tooltip>
</el-row>
</div>
<!-- 场景步骤内容 -->
<div ref="stepInfo">
<el-tooltip :content="$t('api_test.automation.open_expansion')" placement="top" effect="light">
<i class="el-icon-circle-plus-outline ms-open-btn ms-open-btn-left" v-prevent-re-click @click="openExpansion"/>
</el-tooltip>
<el-tooltip :content="$t('api_test.automation.close_expansion')" placement="top" effect="light">
<i class="el-icon-remove-outline ms-open-btn" size="mini" v-prevent-re-click @click="closeExpansion"/>
</el-tooltip>
<el-tooltip :content="$t('api_test.scenario.disable')" placement="top" effect="light" v-if="!stepEnable">
<font-awesome-icon class="ms-open-btn" :icon="['fas', 'toggle-off']" v-prevent-re-click @click="enableAll"/>
</el-tooltip>
<el-tooltip :content="$t('api_test.scenario.enable')" placement="top" effect="light" v-else>
<font-awesome-icon class="ms-open-btn" :icon="['fas', 'toggle-on']" v-prevent-re-click @click="disableAll"/>
</el-tooltip>
<el-link style="float:right;margin-right: 20px;margin-top: 3px" type="primary" @click.stop @click="showHistory">
{{ $t("commons.debug_history") }}
</el-link>
<div class="ms-debug-result" v-if="debug">
<div class="card-content">
<!-- 场景步骤-->
<div v-loading="loading">
<el-row>
<el-col :span="21">
<div class="ms-debug-result" v-show="debug">
<span class="ms-message-right"> {{ reqTotalTime }} ms </span>
<span class="ms-message-right">{{ $t('api_test.automation.request_total') }} {{ reqTotal }}</span>
<span class="ms-message-right">{{ $t('api_test.automation.request_success') }} {{ reqSuccess }}</span>
<span class="ms-message-right"> {{ $t('api_test.automation.request_error') }} {{ reqError }}</span>
</div>
</el-col>
<el-col></el-col>
</el-row>
<el-row>
<el-col :span="21">
<!-- 场景步骤内容 -->
<div ref="stepInfo">
<el-tree node-key="resourceId" :props="props" :data="scenarioDefinition" class="ms-tree"
:default-expanded-keys="expandedNode"
:expand-on-click-node="false"
:allow-drop="allowDrop"
:empty-text="$t('api_test.scenario.step_info')"
highlight-current
:show-checkbox="isBatchProcess"
@check-change="chooseHeadsUp"
@node-expand="nodeExpand"
@node-collapse="nodeCollapse"
:allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" draggable ref="stepTree" v-if="showHideTree">
@node-drag-end="allowDrag" @node-click="nodeClick" draggable ref="stepTree">
<el-row class="custom-tree-node" :gutter="18" type="flex" align="middle" slot-scope="{node, data}" style="width: 100%">
<el-col class="custom-tree-node-col" style="padding-left:0px;padding-right:0px" v-if="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf">
<span v-if="!node.expanded" class="el-icon-circle-plus-outline custom-node_e" @click="openOrClose(node)"/>
<span v-else class="el-icon-remove-outline custom-node_e" @click="openOrClose(node)"/>
<el-col class="custom-tree-node-col" style="padding-left:0px;padding-right:0px" v-show="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf">
<span v-show="!node.expanded" class="el-icon-circle-plus-outline custom-node_e" @click="openOrClose(node)"/>
<span v-show="node.expanded" class="el-icon-remove-outline custom-node_e" @click="openOrClose(node)"/>
</el-col>
<el-col class="custom-tree-node-col" style="padding-left:0px;padding-right:0px" v-else>
<!-- 批量操作 -->
<el-col :class="data.checkBox? 'custom-tree-node-hide' : 'custom-tree-node-col'" style="padding-left: 0px; padding-right: 0px;"
v-show="(data.hashTree && data.hashTree.length === 0 )|| data.isLeaf">
<show-more-btn :is-show="node.checked" :buttons="batchOperators" :size="selectDataCounts" v-show="data.checkBox" style="margin-right: 3px"/>
</el-col>
<el-col>
<!-- 步骤组件-->
@ -351,17 +332,17 @@
ref="maximizeScenario"/>
</ms-drawer>
<ms-change-history ref="changeHistory"/>
<el-backtop target=".card-content" :visibility-height="100" :right="50"></el-backtop>
<el-backtop target=".card-content" :visibility-height="100" :right="20"></el-backtop>
</div>
<ms-task-center ref="taskCenter" :show-menu="false"/>
<!--版本对比-->
<el-dialog
:fullscreen="true"
:visible.sync="dialogVisible"
:destroy-on-close="true"
@close="closeDiff"
width="100%"
>
width="100%">
<scenario-diff
v-if="dialogVisible"
:old-data="oldData"
@ -377,11 +358,11 @@
:old-on-sample-error="onSampleError"
:new-on-sample-error="newOnSampleError"
:project-list="projectList"
:type="type"
></scenario-diff>
:type="type"/>
</el-dialog>
</el-card>
</ms-main-container>
</ms-container>
</template>
<script>
@ -446,6 +427,10 @@ export default {
MsChangeHistory: () => import("../../../history/ChangeHistory"),
MsTaskCenter: () => import("../../../task/TaskCenter"),
MsApiVariableAdvance: () => import("./../../definition/components/ApiVariableAdvance"),
MsMainContainer: () => import("@/business/components/common/components/MsMainContainer"),
MsAsideContainer: () => import("@/business/components/common/components/MsAsideContainer"),
MsContainer: () => import("@/business/components/common/components/MsContainer"),
ShowMoreBtn: () => import( "@/business/components/track/case/components/ShowMoreBtn"),
},
data() {
return {
@ -455,7 +440,8 @@ export default {
props: {
label: "label",
isLeaf: "isLeaf",
children: "hashTree"
children: "hashTree",
disabled: false
},
moduleObj: {
id: 'id',
@ -483,7 +469,7 @@ export default {
levels: PRIORITY,
scenario: {},
loading: false,
showHideTree: true,
renderComponent: true,
apiListVisible: false,
customizeVisible: false,
isBtnHide: false,
@ -547,7 +533,37 @@ export default {
newScenarioDefinition: [],
oldScenarioDefinition: [],
currentItem: {},
pluginDelStep: false
pluginDelStep: false,
isBatchProcess: false,
isCheckedAll: false,
selectDataCounts: 0,
batchOperators: [
{
name: this.$t('api_test.automation.bulk_activation_steps'),
handleClick: this.enableAll,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.automation.batch_disable_steps'),
handleClick: this.disableAll,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.automation.open_expansion'),
handleClick: this.openExpansion,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.automation.close_expansion'),
handleClick: this.closeExpansion,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.definition.request.batch_delete') + "步骤",
handleClick: this.handleDeleteBatch,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
],
}
},
watch: {
@ -583,7 +599,7 @@ export default {
this.$nextTick(() => {
this.addListener();
});
if (!this.currentScenario.name) {
if (!this.currentScenario.name && this.$refs.refFab) {
this.$refs.refFab.openMenu();
}
},
@ -597,6 +613,52 @@ export default {
}
},
methods: {
chooseHeadsUp() {
if (this.$refs.stepTree) {
this.selectDataCounts = this.$refs.stepTree.getCheckedNodes().length;
}
},
checkedAll(v) {
if (this.$refs.stepTree && this.$refs.stepTree.root && this.$refs.stepTree.root.childNodes) {
this.stepCheckedAll(v, this.$refs.stepTree.root.childNodes);
}
},
stepCheckedAll(v, array) {
if (array) {
array.forEach(item => {
if (item.childNodes && item.childNodes.length > 0) {
this.stepCheckedAll(v, item.childNodes);
}
item.checked = v;
})
}
},
batchProcessing() {
this.isBatchProcess = true;
this.expandedNode = [];
this.hideAllTreeNode(this.scenarioDefinition);
this.$refs.stepTree.root.expanded = true;
this.reloadTreeStatus();
},
cancelBatchProcessing() {
this.isBatchProcess = false;
this.isCheckedAll = false;
if (this.$refs.stepTree && this.$refs.stepTree.root && this.$refs.stepTree.root.childNodes) {
this.stepCheckedAll(false, this.$refs.stepTree.root.childNodes);
}
this.selectDataCounts = 0;
this.commandTreeNode();
this.reloadTreeStatus();
},
reloadTreeStatus() {
this.$nextTick(() => {
let row = {resourceId: "ms-reload-test"};
if (this.$refs.stepTree && this.$refs.stepTree.root.data) {
this.$refs.stepTree.root.data.push(row);
this.$refs.stepTree.root.data.splice(this.$refs.stepTree.root.data.length - 1, 1);
}
});
},
openOrClose(node) {
node.expanded = !node.expanded;
if (node.expanded) {
@ -609,17 +671,35 @@ export default {
node.isLeaf = true;
node.visible = false;
},
hideTreeNode(node, array) {
hideAllTreeNode(array) {
array.forEach(item => {
if (item.hashTree && item.hashTree.length > 0) {
this.hideAllTreeNode(item.hashTree);
}
item.isLeaf = this.isBatchProcess;
item.isBatchProcess = this.isBatchProcess;
item.checkBox = this.isBatchProcess;
})
},
commandTreeNode(node, array) {
if (!array) {
array = this.scenarioDefinition;
}
let isLeaf = true;
array.forEach(item => {
if (this.stepFilter.get('ALlSamplerStep').indexOf(item.type) === -1) {
item.checkBox = false;
if (isLeaf && this.stepFilter.get('ALlSamplerStep').indexOf(item.type) === -1) {
isLeaf = false;
}
if (item.hashTree && item.hashTree.length > 0) {
this.hideTreeNode(item, item.hashTree);
this.commandTreeNode(item, item.hashTree);
}
})
if (node) {
node.isBatchProcess = this.isBatchProcess;
node.checkBox = false;
node.isLeaf = isLeaf;
}
},
currentUser: () => {
return getCurrentUser();
@ -652,7 +732,8 @@ export default {
let data = JSON.parse(res.data);
if (data.hashTree) {
this.sort(data.hashTree);
this.scenarioDefinition = data.hashTree;
Object.assign(this.scenarioDefinition, data.hashTree)
this.cancelBatchProcessing();
if (this.$store.state.currentApiCase) {
this.$store.state.currentApiCase.resetDataSource = getUUID();
} else {
@ -718,7 +799,7 @@ export default {
this.clearNodeStatus(this.$refs.stepTree.root.childNodes);
this.clearDebug();
this.$success(this.$t('report.test_stop_success'));
this.showHide();
this.forceRerender();
} catch (e) {
this.debugLoading = false;
}
@ -980,14 +1061,10 @@ export default {
addListener() {
document.addEventListener("keydown", this.createCtrlSHandle);
document.addEventListener("keydown", this.createCtrlRHandle);
document.addEventListener("scroll", this.handleScroll, true);
window.addEventListener("resize", this.handleScroll);
},
removeListener() {
document.removeEventListener("keydown", this.createCtrlSHandle);
document.removeEventListener("keydown", this.createCtrlRHandle);
document.removeEventListener("scroll", this.handleScroll, true);
window.removeEventListener("onresize", this.handleScroll);
},
createCtrlSHandle(event) {
handleCtrlSEvent(event, this.editScenario);
@ -1101,7 +1178,6 @@ export default {
// debug
stepArray[i].parentIndex = fullPath ? fullPath + "_" + stepArray[i].index : stepArray[i].index;
if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) {
this.hideTreeNode(stepArray[i], stepArray[i].hashTree);
this.stepSize += stepArray[i].hashTree.length;
this.sort(stepArray[i].hashTree, stepArray[i].projectId, stepArray[i].parentIndex);
}
@ -1214,7 +1290,7 @@ export default {
const index = hashTree.findIndex(d => d.resourceId !== undefined && row.resourceId !== undefined && d.resourceId === row.resourceId)
hashTree.splice(index, 1);
this.sort();
this.showHide();
this.forceRerender();
}
}
});
@ -1253,10 +1329,9 @@ export default {
this.loading = false
});
},
showHide() {
this.showHideTree = false
forceRerender() {
this.$nextTick(() => {
this.showHideTree = true
this.$store.state.forceRerenderIndex = getUUID();
});
},
runDebug(runScenario) {
@ -1376,7 +1451,7 @@ export default {
allowDrag(draggingNode, dropNode, dropType) {
if (dropNode && draggingNode && dropType) {
this.sort();
this.showHide();
this.forceRerender();
}
},
nodeExpand(data, node) {
@ -1420,7 +1495,6 @@ export default {
if (this.currentScenario.tags instanceof String) {
this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
}
this.$emit('refresh', this.currentScenario);
this.pluginDelStep = false;
resolve();
});
@ -1442,7 +1516,10 @@ export default {
},
getApiScenario() {
this.loading = true;
this.isBatchProcess = false;
this.stepEnable = true;
this.isCheckedAll = false;
this.selectDataCounts = 0;
if (this.currentScenario.tags !== undefined && this.currentScenario.tags) {
if (!(this.currentScenario.tags instanceof Array)) {
this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
@ -1501,7 +1578,6 @@ export default {
}
this.dataProcessing(obj.hashTree);
this.scenarioDefinition = obj.hashTree;
this.scenarioDefinitionOrg = obj.hashTree;
let v1 = {
apiScenarioModuleId: this.currentScenario.apiScenarioModuleId,
name: this.currentScenario.name,
@ -1510,7 +1586,7 @@ export default {
level: this.currentScenario.level,
tags: this.currentScenario.tags,
description: this.currentScenario.description,
scenarioDefinition: this.scenarioDefinitionOrg
scenarioDefinition: this.scenarioDefinition
};
this.currentScenario.scenarioDefinitionOrg = v1
this.oldScenarioDefinition = obj.hashTree;
@ -1532,6 +1608,7 @@ export default {
this.loading = false;
this.setDomain();
this.sort();
this.commandTreeNode();
// resourceId
if (this.scenarioDefinition) {
this.resetResourceId(this.scenarioDefinition);
@ -1695,9 +1772,10 @@ export default {
this.envResult.loading = false;
})
},
changeNodeStatus(nodes) {
changeNodeStatus(resourceIds, nodes) {
for (let i in nodes) {
if (nodes[i]) {
if (resourceIds.indexOf(nodes[i].resourceId) !== -1) {
if (this.expandedStatus) {
this.expandedNode.push(nodes[i].resourceId);
}
@ -1705,27 +1783,42 @@ export default {
if (this.stepSize > 35 && this.expandedStatus) {
nodes[i].active = false;
}
}
if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
this.changeNodeStatus(nodes[i].hashTree);
}
}
}
},
getAllResourceIds() {
let selectValueArr = [];
if (this.$refs.stepTree) {
let checkNodes = this.$refs.stepTree.getCheckedNodes();
for (let node of checkNodes) {
selectValueArr.push(node.resourceId);
}
}
return selectValueArr;
},
openExpansion() {
this.expandedNode = [];
this.expandedStatus = true;
this.changeNodeStatus(this.scenarioDefinition);
let resourceIds = this.getAllResourceIds();
this.changeNodeStatus(resourceIds, this.scenarioDefinition);
},
closeExpansion() {
this.expandedStatus = false;
this.expandedNode = [];
this.changeNodeStatus(this.scenarioDefinition);
this.showHide();
let resourceIds = this.getAllResourceIds();
this.changeNodeStatus(resourceIds, this.scenarioDefinition);
this.forceRerender();
},
stepStatus(nodes) {
stepStatus(resourceIds, nodes) {
for (let i in nodes) {
if (nodes[i]) {
if (resourceIds.indexOf(nodes[i].resourceId) !== -1) {
nodes[i].enable = this.stepEnable;
}
if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
this.stepStatus(nodes[i].hashTree);
}
@ -1734,24 +1827,31 @@ export default {
},
enableAll() {
this.stepEnable = true;
this.stepStatus(this.scenarioDefinition);
let resourceIds = this.getAllResourceIds();
this.stepStatus(resourceIds, this.scenarioDefinition);
},
disableAll() {
this.stepEnable = false;
this.stepStatus(this.scenarioDefinition);
let resourceIds = this.getAllResourceIds();
this.stepStatus(resourceIds, this.scenarioDefinition);
},
handleScroll() {
let stepInfo = this.$refs.stepInfo;
let debugHeader = this.$refs.debugHeader;
if (debugHeader) {
let originWidth = debugHeader.parentElement.clientWidth;
if (stepInfo.getBoundingClientRect().top <= 178) {
this.isTop = true;
if (originWidth > 0) {
debugHeader.style.width = originWidth + 'px';
}
handleDeleteBatch() {
this.getAllResourceIds().forEach(item => {
this.recursionDelete(item, this.scenarioDefinition);
});
this.sort();
this.forceRerender();
},
recursionDelete(resourceId, nodes) {
for (let i in nodes) {
if (nodes[i]) {
if (resourceId === nodes[i].resourceId) {
nodes.splice(i, 1);
} else {
this.isTop = false;
if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
this.recursionDelete(resourceId, nodes[i].hashTree);
}
}
}
}
},
@ -1903,7 +2003,7 @@ export default {
<style scoped>
.card-content {
height: calc(100vh - 156px);
height: calc(100vh - 200px);
overflow-y: auto;
}
@ -1918,7 +2018,7 @@ export default {
.ms-debug-div {
border: 1px #DCDFE6 solid;
border-radius: 4px;
margin-right: 20px;
margin-right: 0px;
}
.ms-scenario-button {
@ -1944,7 +2044,7 @@ export default {
}
#fab {
right: 90px;
right: 60px;
bottom: 120px;
z-index: 5;
}
@ -2004,6 +2104,10 @@ export default {
transform: rotate(0deg);
}
.ms-tree >>> .el-tree-node__content > .el-tree-node__expand-icon {
padding: 3px;
}
.ms-tree >>> .el-icon-caret-right:before {
/*content: '\e723';*/
padding: 0;
@ -2041,6 +2145,11 @@ export default {
cursor: pointer;
}
.el-icon-more:hover {
color: #7C3985;
cursor: pointer;
}
.scenario-name {
display: inline-block;
margin: 0 5px;
@ -2064,10 +2173,19 @@ export default {
color: #67C23A;
}
.ms-batch-btn {
margin-left: 5px;
}
.ms-batch-btn:hover {
cursor: pointer;
color: #6D317C;
}
.ms-debug-result {
float: right;
margin-right: 30px;
margin-top: 3px;
height: 20px;
float: right;
}
.ms-open-btn-left {
@ -2094,5 +2212,23 @@ export default {
.custom-tree-node-col {
width: 20px;
padding: 0px;
margin-left: 5px;
vertical-align: center;
}
.custom-tree-node-hide {
width: 2px;
padding: 0px;
vertical-align: center;
}
/deep/ .show-more-btn {
width: 0px;
height: 17px;
line-height: 10px;
}
/deep/ .ms-main-container {
padding: 5px 5px 5px 10px;
}
</style>

View File

@ -25,7 +25,7 @@ export function STEP() {
['GenericController', getAll()],
['AllSamplerProxy', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'Sampler', 'AbstractSampler', 'JSR223Processor', 'API']],
['DEFINITION', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler']],
['ALlSamplerStep', ['JSR223Processor', 'JSR223PreProcessor', 'JSR223PostProcessor', 'JDBCPreProcessor', 'JDBCPostProcessor', 'Assertions', 'Extract','ConstantTimer']],
['ALlSamplerStep', ['JSR223PreProcessor', 'JSR223PostProcessor', 'JDBCPreProcessor', 'JDBCPostProcessor', 'Assertions', 'Extract', 'ConstantTimer']],
['AllCanExecType', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'JSR223Processor', 'AbstractSampler']]]);
return map
}

View File

@ -3,7 +3,7 @@
<div class="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 class="el-step__icon-inner">{{ data.index }}</div>
<div class="el-step__icon-inner" :key="$store.state.forceRerenderIndex">{{ data.index }}</div>
</div>
<slot name="behindHeaderLeft" v-if="!isMax"></slot>
<el-tag class="ms-left-btn" size="small" :style="{'color': color, 'background-color': backgroundColor}">{{ title }}</el-tag>
@ -18,10 +18,8 @@
<span :class="showVersion?'scenario-unscroll':'scenario-version'" id="moveout" @mouseenter="enter($event)" @mouseleave="leave($event)" v-else>
<i class="el-icon-edit" style="cursor:pointer;" @click="editName"
v-if="data.referenced!='REF' && !data.disabled"/>
<el-tooltip placement="top" :content="data.name">
v-show="data.referenced!='REF' && !data.disabled"/>
<span>{{ data.name }}</span>
</el-tooltip>
<el-tag size="mini" v-if="data.method && !data.pluginId" style="margin-left: 1rem">{{ getMethod() }}</el-tag>
<slot name="afterTitle"/>
</span>
@ -38,7 +36,7 @@
<el-button v-if="showVersion" size="mini" icon="el-icon-copy-document" circle @click="copyRow" style="padding: 5px"
:disabled="(data.disabled && !data.root) || !showVersion "/>
<el-button v-if="showVersion && stepFilter.get('ALlSamplerStep').indexOf(data.type) !==-1" size="mini" icon="el-icon-delete" type="danger" style="padding: 5px" circle @click="remove"/>
<el-button v-show="isSingleButton" size="mini" icon="el-icon-delete" type="danger" style="padding: 5px" circle @click="remove"/>
<step-extend-btns style="display: contents"
:data="data"
:environmentType="environmentType"
@ -47,7 +45,7 @@
@copy="copyRow"
@remove="remove"
@openScenario="openScenario"
v-if="showBtn && (!data.disabled || data.root) && showVersion && stepFilter.get('ALlSamplerStep').indexOf(data.type) ===-1"/>
v-show="isMoreButton"/>
</div>
</div>
@ -87,6 +85,10 @@ export default {
},
props: {
draggable: Boolean,
innerStep: {
type: Boolean,
default: false,
},
isMax: {
type: Boolean,
default: false,
@ -145,7 +147,7 @@ export default {
} else {
this.colorStyle = "";
}
}
},
},
created() {
if (!this.data.name) {
@ -162,6 +164,20 @@ export default {
}
}
},
computed: {
isSingleButton() {
if (this.data.type === 'ConstantTimer') {
return (this.innerStep && this.showVersion && this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) !== -1)
}
return (this.showVersion && this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) !== -1);
},
isMoreButton() {
if (this.data.type === 'ConstantTimer') {
return (!this.innerStep || this.showBtn && (!this.data.disabled || this.data.root) && this.showVersion && this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) === -1);
}
return (this.showBtn && (!this.data.disabled || this.data.root) && this.showVersion && this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) === -1);
},
},
methods: {
active() {
this.$emit('active');
@ -204,8 +220,6 @@ export default {
$event.currentTarget.className = "scenario-version"
}
}
}
}

View File

@ -20,7 +20,7 @@
:envMap="envMap"
:title="$t('commons.scenario')">
<template v-slot:afterTitle >
<template v-slot:afterTitle>
<span v-if="isShowNum" @click="clickResource(scenario)">{{ " ID: " + scenario.num + "" }}</span>
<span v-else>
<el-tooltip class="ms-num" effect="dark" :content="$t('api_test.automation.scenario.num_none')" placement="top">
@ -110,11 +110,13 @@ export default {
}
this.reload();
},
'node.data.isBatchProcess'() {
if (this.node.data && this.node.data.isBatchProcess && this.node.data.referenced === 'REF') {
this.node.expanded = false;
}
}
},
created() {
/*if (!this.scenario.projectId) {
this.scenario.projectId = getCurrentProjectID();
}*/
if (this.scenario.num) {
this.isShowNum = true;
this.getWorkspaceId(this.scenario.projectId);
@ -132,7 +134,7 @@ export default {
isShowInput: false,
isShowNum: false,
stepFilter: new STEP,
dataWorkspaceId:'',
dataWorkspaceId: '',
}
},
computed: {
@ -146,7 +148,7 @@ export default {
},
methods: {
run() {
if(!this.scenario.enable){
if (!this.scenario.enable) {
this.$warning(this.$t('api_test.automation.debug_message'));
return;
}
@ -202,8 +204,12 @@ export default {
},
active() {
if (this.node) {
if (this.node.data && this.node.data.isBatchProcess && this.node.data.referenced === 'REF') {
this.node.expanded = false;
} else {
this.node.expanded = !this.node.expanded;
}
}
this.reload();
},
copyRow() {
@ -257,7 +263,7 @@ export default {
clickResource(resource) {
let automationData = this.$router.resolve({
name: 'ApiAutomation',
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + resource.id, projectId: resource.projectId,workspaceId:this.dataWorkspaceId }
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + resource.id, projectId: resource.projectId, workspaceId: this.dataWorkspaceId}
});
window.open(automationData.href, '_blank');
},

View File

@ -6,6 +6,7 @@
:draggable="draggable"
:show-collapse="false"
:is-max="isMax"
:inner-step="innerStep"
color="#67C23A"
background-color="#F2F9EE"
:title="$t('api_test.automation.wait_controller')">
@ -26,6 +27,10 @@ export default {
components: {ApiBaseComponent},
props: {
timer: {},
innerStep: {
type: Boolean,
default: false,
},
node: {},
isMax: {
type: Boolean,

View File

@ -123,7 +123,7 @@
:draggable="false"
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick"
@refReload="refReload" @openScenario="openScenario"
v-if="selectedTreeNode && selectedNode && stepFilter.get('ALlSamplerStep').indexOf(item.type) ===-1"/>
v-show="selectedTreeNode && selectedNode && stepFilter.get('ALlSamplerStep').indexOf(item.type) ===-1"/>
</div>
</div>
</div>

View File

@ -53,7 +53,7 @@
color="#B8741A"
background-color="#F9F1EA"/>
<ms-constant-timer :timer="data" :node="node" v-if="data.type ==='ConstantTimer'" @remove="remove"/>
<ms-constant-timer :inner-step="true" :timer="data" :node="node" v-if="data.type ==='ConstantTimer'" @remove="remove"/>
</div>
<div v-if="tabType ==='post'">
@ -225,7 +225,7 @@ export default {
this.$emit('reload');
},
add() {
this.request.active = false;
this.request.active = true;
if (this.tabType === 'pre') {
if (this.preOperate === 'script') {
this.addPre();
@ -340,6 +340,7 @@ export default {
this.request.hashTree.splice(index, 1);
this.sort();
this.reload();
this.forceRerender();
},
copyRow(row) {
let obj = JSON.parse(JSON.stringify(row));
@ -352,6 +353,7 @@ export default {
}
this.sort();
this.reload();
this.forceRerender();
},
allowDrop(draggingNode, dropNode, dropType) {
//
@ -364,8 +366,14 @@ export default {
if (dropNode && draggingNode && dropType) {
this.reload();
this.filter();
this.forceRerender();
}
},
forceRerender() {
this.$nextTick(() => {
this.$store.state.forceRerenderIndex = getUUID();
});
},
reload() {
this.isReloadData = true
this.$nextTick(() => {

View File

@ -29,7 +29,6 @@ import formCreate from "@form-create/element-ui"
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
import 'element-ui/lib/theme-chalk/display.css';
import 'default-passive-events'
Vue.use(mavonEditor)
Vue.use(vueMinderEditor)

View File

@ -1316,8 +1316,10 @@ export default {
case_reduction_error_text: "Please restore first"
},
automation: {
open_expansion: "One-click expansion",
close_expansion: "One-click storage",
open_expansion: "Batch Folding Steps",
close_expansion: "Bulk Expand Steps",
bulk_activation_steps: "Bulk activation steps",
batch_disable_steps: "Batch disable steps",
all: "all",
constant: "constant",
counter: "counter",
@ -1463,6 +1465,7 @@ export default {
scenario_error: "Cannot reference or copy itself",
integrated: "Integrated",
independent: "Independent",
step_info: "Add a scene step on the right",
},
request: {
debug: "Debug",

View File

@ -1321,8 +1321,10 @@ export default {
case_reduction_error_text: "请先恢复"
},
automation: {
open_expansion: "一键展开",
close_expansion: "一键收起",
open_expansion: "批量展开步骤",
close_expansion: "批量折叠步骤",
bulk_activation_steps: "批量启用步骤",
batch_disable_steps: "批量禁用步骤",
all: "全部",
constant: "常量",
counter: "计数器",
@ -1467,6 +1469,7 @@ export default {
scenario_error: "不能引用或复制自身!",
integrated: "集合",
independent: "独立",
step_info: "在右侧添加场景步骤",
},
request: {
debug: "调试",

View File

@ -1321,8 +1321,10 @@ export default {
case_reduction_error_text: "請先恢復"
},
automation: {
open_expansion: "一鍵展開",
close_expansion: "一鍵收起",
open_expansion: "批量展開步驟",
close_expansion: "批量折疊步驟",
bulk_activation_steps: "批量啟用步驟",
batch_disable_steps: "批量禁用步驟",
all: "全部",
constant: "常量",
counter: "計數器",
@ -1467,6 +1469,7 @@ export default {
scenario_error: "不能引用或復製自身!",
integrated: "集合",
independent: "獨立",
step_info: "在右側添加場景步驟",
},
request: {
debug: "調試",

View File

@ -34,7 +34,8 @@ const state = {
apiStatus: new Map(),
testCaseMap: new Map(),
curTabId: null,
testCaseDefaultValue: {}
testCaseDefaultValue: {},
forceRerenderIndex: "",
}
const store = new Vuex.Store({