feat(接口自动化): 获取实时执行步骤结果

This commit is contained in:
fit2-zhao 2021-06-25 19:06:06 +08:00 committed by fit2-zhao
parent fe677b0b40
commit 6743dac777
11 changed files with 820 additions and 577 deletions

View File

@ -62,4 +62,9 @@ public class APIScenarioReportController {
return resultService.getResult(reportId);
}
@GetMapping("/remove/real/{reportId}")
public void removeRealReport(@PathVariable String reportId) {
resultService.delete(reportId);
}
}

View File

@ -39,7 +39,9 @@ public class MsResultService {
testResult = new TestResult();
}
if (result.getResponseCode().equals(MsResultCollector.TEST_END)) {
testResult.setEnd(true);
this.cache.put(key, testResult);
return;
}
testResult.setTestId(key);
testResult.setConsole(getJmeterLogger(key, false));
@ -50,7 +52,7 @@ public class MsResultService {
testResult.getScenarios().addAll(scenarios.values());
testResult.getScenarios().sort(Comparator.comparing(ScenarioResult::getId));
System.out.println(key + "=======" + result.getURL());
this.cache.put(key, testResult);
}

View File

@ -136,24 +136,21 @@
<el-col :span="3" class="ms-col-one ms-font">
<el-checkbox v-model="onSampleError">{{ $t('commons.failure_continues') }}</el-checkbox>
</el-col>
<el-col :span="4">
<el-col :span="8">
<div style=" float: right">
<env-popover :disabled="scenarioDefinition.length < 1" :env-map="projectEnvMap"
:project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap" :result="envResult"
:show-config-button-with-out-permission="showConfigButtonWithOutPermission"
:isReadOnly="scenarioDefinition.length < 1" @showPopover="showPopover"
:project-list="projectList" ref="envPopover"/>
</el-col>
<el-col :span="4">
<!-- <el-dropdown split-button type="primary" @click="runDebug" style="margin-right: 10px" size="mini" @command="handleCommand">-->
<!-- {{ $t('api_test.request.debug') }}-->
<!-- <el-dropdown-menu slot="dropdown">-->
<!-- <el-dropdown-item>{{ $t('api_test.run') }}</el-dropdown-item>-->
<!-- </el-dropdown-menu>-->
<!-- </el-dropdown>-->
<el-button :disabled="scenarioDefinition.length < 1" size="mini" type="primary" v-prevent-re-click
@click="runDebug">{{ $t('api_test.request.debug') }}
</el-button>
<el-tooltip class="item" effect="dark" :content="$t('commons.refresh')" placement="right-start">
:project-list="projectList" ref="envPopover" style="margin-right: 10px"/>
<el-dropdown split-button type="primary" @click="runDebug" style="margin-right: 10px" size="mini" @command="handleCommand" v-if="!debugLoading">
{{ $t('api_test.request.debug') }}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>{{ $t('test_track.case.steps') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button icon="el-icon-loading" size="mini" type="primary" :disabled="debug" v-else>执行中</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>
@ -161,6 +158,7 @@
placement="top-start">
<font-awesome-icon class="alt-ico" :icon="['fa', 'expand-alt']" size="lg" @click="fullScreen"/>
</el-tooltip>
</div>
</el-col>
</el-row>
</div>
@ -179,7 +177,7 @@
<font-awesome-icon class="ms-open-btn" :icon="['fas', 'toggle-on']" v-prevent-re-click @click="disableAll"/>
</el-tooltip>
<div class="ms-debug-result" v-if="debug">
354 ms 请求 10 成功 8 失败 2
{{ reqTotalTime }} ms 请求 {{ reqTotal }} 成功 {{ reqSuccess }} 失败 {{ reqError }}
</div>
<el-tree node-key="resourceId" :props="props" :data="scenarioDefinition" class="ms-tree"
:default-expanded-keys="expandedNode"
@ -256,15 +254,17 @@
:projectIds.sync="projectIds" :projectList="projectList"
:scenarioDefinition="scenarioDefinition" :enableCookieShare="enableCookieShare"
:onSampleError="onSampleError"
:execDebug="stopDebug"
:isFullUrl.sync="isFullUrl" @closePage="close" @unFullScreen="unFullScreen"
@showAllBtn="showAllBtn" @runDebug="runDebug" @setProjectEnvMap="setProjectEnvMap"
@showAllBtn="showAllBtn" @runDebug="runDebug" @handleCommand="handleCommand" @setProjectEnvMap="setProjectEnvMap"
@showScenarioParameters="showScenarioParameters"
@setCookieShare="setCookieShare" @setSampleError="setSampleError"
ref="maximizeHeader"/>
</template>
<maximize-scenario :scenario-definition="scenarioDefinition" :envMap="projectEnvMap" :moduleOptions="moduleOptions"
:currentScenario="currentScenario" :type="type" :stepReEnable="stepEnable" ref="maximizeScenario" @openScenario="openScenario"/>
:req-error="reqError" :req-success="reqSuccess" :req-total="reqTotal" :req-total-time="reqTotalTime"
:currentScenario="currentScenario" :type="type" :debug="debug" :reloadDebug="reloadDebug" :stepReEnable="stepEnable" ref="maximizeScenario" @openScenario="openScenario"/>
</ms-drawer>
<ms-change-history ref="changeHistory"/>
@ -274,16 +274,7 @@
<script>
import {API_STATUS, PRIORITY} from "../../definition/model/JsonData";
import {WORKSPACE_ID} from '@/common/js/constants';
import {
Assertions,
ConstantTimer,
Extract,
IfController,
JSR223Processor,
LoopController,
TransactionController
} from "../../definition/model/ApiTestModel";
import {buttons, setComponent} from './menu/Menu';
import {parseEnvironment} from "../../definition/model/EnvironmentModel";
import {ELEMENT_TYPE, ELEMENTS} from "./Setting";
import MsApiCustomize from "./ApiCustomize";
@ -402,12 +393,21 @@ export default {
loading: false
},
debug: false,
debugLoading: false,
reqTotal: 0,
reqSuccess: 0,
reqError: 0,
reqTotalTime: 0,
reloadDebug: "",
stopDebug: "",
}
},
created() {
if (!this.currentScenario.apiScenarioModuleId) {
this.currentScenario.apiScenarioModuleId = "";
}
this.debug = false;
this.debugLoading = false;
this.operatingElements = ELEMENTS.get("ALL");
this.getWsProjects();
this.getMaintainerOptions();
@ -417,147 +417,106 @@ export default {
},
directives: {OutsideClick},
computed: {
buttons() {
let buttons = [
{
title: this.$t('api_test.definition.request.extract_param'),
show: this.showButton("Extract"),
titleColor: "#015478",
titleBgColor: "#E6EEF2",
icon: "colorize",
click: () => {
this.addComponent('Extract')
}
},
{
title: this.$t('api_test.definition.request.post_script'),
show: this.showButton("JSR223PostProcessor"),
titleColor: "#783887",
titleBgColor: "#F2ECF3",
icon: "skip_next",
click: () => {
this.addComponent('JSR223PostProcessor')
}
},
{
title: this.$t('api_test.definition.request.pre_script'),
show: this.showButton("JSR223PreProcessor"),
titleColor: "#B8741A",
titleBgColor: "#F9F1EA",
icon: "skip_previous",
click: () => {
this.addComponent('JSR223PreProcessor')
}
},
{
title: this.$t('api_test.automation.customize_script'),
show: this.showButton("JSR223Processor"),
titleColor: "#7B4D12",
titleBgColor: "#F1EEE9",
icon: "code",
click: () => {
this.addComponent('JSR223Processor')
}
},
{
title: this.$t('api_test.automation.if_controller'),
show: this.showButton("IfController"),
titleColor: "#E6A23C",
titleBgColor: "#FCF6EE",
icon: "alt_route",
click: () => {
this.addComponent('IfController')
}
},
{
title: this.$t('api_test.automation.loop_controller'),
show: this.showButton("LoopController"),
titleColor: "#02A7F0",
titleBgColor: "#F4F4F5",
icon: "next_plan",
click: () => {
this.addComponent('LoopController')
}
},
{
title: this.$t('api_test.automation.transcation_controller'),
show: this.showButton("TransactionController"),
titleColor: "#6D317C",
titleBgColor: "#F4F4F5",
icon: "alt_route",
click: () => {
this.addComponent('TransactionController')
}
},
{
title: this.$t('api_test.automation.wait_controller'),
show: this.showButton("ConstantTimer"),
titleColor: "#67C23A",
titleBgColor: "#F2F9EE",
icon: "access_time",
click: () => {
this.addComponent('ConstantTimer')
}
},
{
title: this.$t('api_test.definition.request.assertions_rule'),
show: this.showButton("Assertions"),
titleColor: "#A30014",
titleBgColor: "#F7E6E9",
icon: "next_plan",
click: () => {
this.addComponent('Assertions')
}
},
{
title: this.$t('api_test.automation.customize_req'),
show: this.showButton("CustomizeReq"),
titleColor: "#008080",
titleBgColor: "#EBF2F2",
icon: "tune",
click: () => {
this.addComponent('CustomizeReq')
}
},
{
title: this.$t('api_test.automation.scenario_import'),
show: this.showButton("scenario"),
titleColor: "#606266",
titleBgColor: "#F4F4F5",
icon: "movie",
click: () => {
this.addComponent('scenario')
}
},
{
title: this.$t('api_test.automation.api_list_import'),
show: this.showButton("HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler"),
titleColor: "#F56C6C",
titleBgColor: "#FCF1F1",
icon: "api",
click: this.apiListImport
}
];
return buttons.filter(btn => btn.show);
},
buttons,
projectId() {
return getCurrentProjectID();
},
},
methods: {
clearDebug() {
this.reqError = 0;
this.reqTotalTime = 0;
this.reqTotal = 0;
this.reqSuccess = 0;
},
editParent(node, status) {
if (!status) {
node.data.code = "error";
}
node.data.debug = true;
if (node.parent && node.parent.data && node.parent.data.id) {
this.editParent(node.parent, status);
}
},
findNodeChild(arr, name, index, status) {
arr.forEach(item => {
if (item.data.name === name && item.data.index === index) {
this.editParent(item.parent, status);
}
if (item.childNodes && item.childNodes.length > 0) {
this.findNodeChild(item.childNodes, name, index, status);
}
})
},
findNode(name, index, status) {
if (this.$refs.stepTree && this.$refs.stepTree.root) {
this.$refs.stepTree.root.childNodes.forEach(item => {
if (item.childNodes && item.childNodes.length > 0) {
this.findNodeChild(item.childNodes, name, index, status);
}
})
}
},
getReport() {
if (this.debug) {
let url = "/api/scenario/report/get/real/" + this.reportId;
this.$get(url, response => {
// if (response.data && response.data.end) {
// console.log(response.data);
// } else {
// setTimeout(this.getReport, 2000)
// }
if (response.data) {
this.formatResult(response.data);
if (response.data.end) {
this.removeReport();
this.debugLoading = false;
this.stopDebug = "stop";
} else {
setTimeout(this.getReport, 2000)
}
} else {
setTimeout(this.getReport, 2000)
}
});
}
},
formatResult(res) {
let resMap = new Map;
let startTime = 99991611737506593;
let endTime = 0;
this.clearDebug();
if (res && res.scenarios) {
res.scenarios.forEach(item => {
this.reqTotal += item.requestResults.length;
if (item && item.requestResults) {
item.requestResults.forEach(req => {
req.responseResult.console = res.console;
let name = req.name.split('<->')[0];
resMap.set(req.id + name, req);
if (req.success) {
this.reqSuccess++;
} else {
this.reqError++;
}
if (req.startTime && Number(req.startTime) < startTime) {
startTime = req.startTime;
}
if (req.endTime && Number(req.endTime) > endTime) {
endTime = req.endTime;
}
})
}
})
}
if (startTime < endTime) {
this.reqTotalTime = endTime - startTime + 100;
}
this.debugResult = resMap;
this.sort();
this.reload();
this.reloadDebug = getUUID();
},
removeReport() {
let url = "/api/scenario/report/remove/real/" + this.reportId;
this.$get(url, response => {
});
},
handleCommand() {
this.debug = false;
/*触发执行操作*/
@ -591,7 +550,6 @@ export default {
}
})
},
openHis() {
this.$refs.changeHistory.open(this.currentScenario.id);
},
@ -658,59 +616,7 @@ export default {
}
},
addComponent(type) {
switch (type) {
case ELEMENT_TYPE.IfController:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new IfController()) :
this.scenarioDefinition.push(new IfController());
break;
case ELEMENT_TYPE.ConstantTimer:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new ConstantTimer()) :
this.scenarioDefinition.push(new ConstantTimer());
break;
case ELEMENT_TYPE.JSR223Processor:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new JSR223Processor()) :
this.scenarioDefinition.push(new JSR223Processor());
break;
case ELEMENT_TYPE.JSR223PreProcessor:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new JSR223Processor({type: "JSR223PreProcessor"})) :
this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PreProcessor"}));
break;
case ELEMENT_TYPE.JSR223PostProcessor:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new JSR223Processor({type: "JSR223PostProcessor"})) :
this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PostProcessor"}));
break;
case ELEMENT_TYPE.Assertions:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new Assertions()) :
this.scenarioDefinition.push(new Assertions());
break;
case ELEMENT_TYPE.Extract:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new Extract()) :
this.scenarioDefinition.push(new Extract());
break;
case ELEMENT_TYPE.CustomizeReq:
this.customizeRequest = {protocol: "HTTP", type: "API", hashTree: [], referenced: 'Created', active: false};
this.customizeVisible = true;
break;
case ELEMENT_TYPE.LoopController:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new LoopController()) :
this.scenarioDefinition.push(new LoopController());
break;
case ELEMENT_TYPE.TransactionController:
this.selectedTreeNode !== undefined ? this.selectedTreeNode.hashTree.push(new TransactionController()) :
this.scenarioDefinition.push(new TransactionController());
break;
case ELEMENT_TYPE.scenario:
this.isBtnHide = true;
this.$refs.scenarioRelevance.open();
break;
default:
this.$refs.apiImport.open();
break;
}
if (this.selectedNode) {
this.selectedNode.expanded = true;
}
this.sort();
setComponent(type, this);
},
nodeClick(data, node) {
if (data.referenced != 'REF' && data.referenced != 'Deleted' && !data.disabled) {
@ -763,6 +669,8 @@ export default {
// debug
if (this.debugResult && this.debugResult.get(arr[i].id + arr[i].name)) {
arr[i].requestResult = this.debugResult.get(arr[i].id + arr[i].name);
arr[i].debug = this.debug;
this.findNode(arr[i].name, arr[i].index, arr[i].requestResult.success);
}
}
},
@ -794,6 +702,7 @@ export default {
// debug
if (this.debugResult && this.debugResult.get(this.scenarioDefinition[i].id + this.scenarioDefinition[i].name)) {
this.scenarioDefinition[i].requestResult = this.debugResult.get(this.scenarioDefinition[i].id + this.scenarioDefinition[i].name);
this.scenarioDefinition[i].debug = this.debug;
}
}
},
@ -928,7 +837,10 @@ export default {
if (this.scenarioDefinition.length < 1) {
return;
}
// this.debug = true;
this.debug = true;
this.debugLoading = true;
this.stopDebug = "";
this.clearDebug();
/*触发执行操作*/
this.$refs['currentScenario'].validate((valid) => {
if (valid) {
@ -955,11 +867,7 @@ export default {
onSampleError: this.onSampleError,
};
this.reportId = getUUID().substring(0, 8);
// this.editScenario().then(() => {
//
// })
})
})
}
})
@ -1463,7 +1371,6 @@ export default {
.alt-ico:hover {
color: black;
cursor: pointer;
font-size: 18px;
}
.scenario-name {

View File

@ -8,6 +8,7 @@
<el-tag class="ms-left-btn" size="small" :style="{'color': color, 'background-color': backgroundColor}">{{title}}</el-tag>
<el-tag size="mini" v-if="data.method">{{getMethod()}}</el-tag>
</slot>
<slot name="behindHeaderLeft" v-if="!isMax"></slot>
<span>
<slot name="headerLeft">
@ -25,11 +26,11 @@
</el-tooltip>
</span>
</slot>
<slot name="behindHeaderLeft" v-if="!isMax"></slot>
</span>
<div class="header-right" @click.stop>
<slot name="message"></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" style="width: 30px"/>
</el-tooltip>
@ -202,7 +203,7 @@
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
width: 180px;
width: 140px;
}
.scenario-name {
@ -214,7 +215,7 @@
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
width: calc(100% - 30rem);
width: calc(100% - 35rem);
}
/deep/ .el-step__icon {
@ -240,4 +241,5 @@
white-space: nowrap;
width: 400px;
}
</style>

View File

@ -20,7 +20,13 @@
<el-tag size="mini" class="ms-tag" v-if="request.referenced ==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag>
<span class="ms-tag">{{ getProjectName(request.projectId) }}</span>
</template>
<template v-slot:debugStepCode>
<el-tooltip :content="request.requestResult.responseResult.responseCode" v-if="request.debug && request.requestResult && request.requestResult.responseResult">
<span class="ms-step-debug-code" :class="request.requestResult.success?'ms-req-success':'ms-req-error'">
{{ request.requestResult.responseResult.responseCode }}
</span>
</el-tooltip>
</template>
<template v-slot:button>
<el-tooltip :content="$t('api_test.run')" placement="top">
<el-button :disabled="!request.enable" @click="run" icon="el-icon-video-play" style="padding: 5px" class="ms-btn" size="mini" circle/>
@ -38,23 +44,22 @@
:headers="request.headers "
:is-read-only="isCompReadOnly"
:request="request"/>
<esb-definition v-if="showXpackCompnent&&request.esbDataStruct!=null"
v-xpack
:request="request"
:showScript="false"
:is-read-only="isCompReadOnly"
ref="esbDefinition"/>
<!-- <ms-tcp-basis-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "-->
<!-- :request="request"-->
<!-- :is-read-only="isCompReadOnly"-->
<!-- :showScript="false"/>-->
:is-read-only="isCompReadOnly" ref="esbDefinition"/>
<ms-tcp-format-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "
:is-read-only="isCompReadOnly"
:show-script="false" :request="request"/>
<ms-sql-basis-parameters v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
:request="request"
:is-read-only="isCompReadOnly"
:showScript="false"/>
<ms-dubbo-basis-parameters v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
:request="request"
:is-read-only="isCompReadOnly"
@ -94,7 +99,6 @@
<script>
import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters";
// import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters";
import MsTcpFormatParameters from "../../../definition/components/request/tcp/TcpFormatParameters";
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
@ -104,6 +108,7 @@ import {getUUID, getCurrentProjectID} from "@/common/js/utils";
import ApiBaseComponent from "../common/ApiBaseComponent";
import ApiResponseComponent from "./ApiResponseComponent";
import CustomizeReqInfo from "@/business/components/api/automation/scenario/common/CustomizeReqInfo";
import TemplateComponent from "@/business/components/track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const esbDefinition = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {};
@ -133,6 +138,7 @@ export default {
envMap: Map
},
components: {
TemplateComponent,
CustomizeReqInfo,
ApiBaseComponent, ApiResponseComponent,
MsSqlBasisParameters, MsTcpFormatParameters, MsDubboBasisParameters, MsApiRequestForm, MsRequestResultTail, MsRun,
@ -147,6 +153,7 @@ export default {
isShowInput: false,
showXpackCompnent: false,
environment: {},
result: {},
}
},
created() {
@ -462,6 +469,25 @@ export default {
}
.ms-tag {
margin-left: 20px;
margin-left: 10px;
}
.ms-step-debug-code {
display: inline-block;
margin: 0 5px;
overflow-x: hidden;
padding-bottom: 0;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
width: 100px;
}
.ms-req-error {
color: #F56C6C;
}
.ms-req-success {
color: #67C23A;
}
</style>

View File

@ -22,6 +22,13 @@
<span class="ms-tag">{{ getProjectName(scenario.projectId) }}</span>
</template>
<template v-slot:debugStepCode>
<el-tooltip :content="getCode()" v-if="node.data.debug">
<span class="ms-step-debug-code" :class="node.data.code ==='error'?'ms-req-error':'ms-req-success'">
{{ getCode() }}
</span>
</el-tooltip>
</template>
</api-base-component>
</template>
@ -107,6 +114,16 @@
},
},
methods: {
getCode() {
if (this.node && this.node.data.debug) {
if (this.node.data.code && this.node.data.code === 'error') {
return 'error';
} else {
return 'success';
}
}
return '';
},
remove() {
this.$emit('remove', this.scenario, this.node);
},
@ -179,6 +196,14 @@
}
.ms-tag {
margin-left: 20px;
margin-left: 0px;
}
.ms-req-error {
color: #F56C6C;
}
.ms-req-success {
color: #67C23A;
}
</style>

View File

@ -23,6 +23,13 @@
<el-input draggable size="mini" v-model="controller.value" :placeholder="$t('api_test.value')" v-if="!hasEmptyOperator" class="ms-btn"/>
</template>
<template v-slot:debugStepCode>
<el-tooltip :content="getCode()" v-if="node.data.debug">
<span class="ms-step-debug-code" :class="node.data.code ==='error'?'ms-req-error':'ms-req-success'">
{{ getCode() }}
</span>
</el-tooltip>
</template>
</api-base-component>
</template>
@ -88,6 +95,16 @@
}
},
methods: {
getCode() {
if (this.node && this.node.data.debug) {
if (this.node.data.code && this.node.data.code === 'error') {
return 'error';
} else {
return 'success';
}
}
return '';
},
remove() {
this.$emit('remove', this.controller, this.node);
},
@ -118,4 +135,12 @@
width: 15%;
margin-left: 5px;
}
.ms-req-error {
color: #F56C6C;
}
.ms-req-success {
color: #67C23A;
}
</style>

View File

@ -69,6 +69,14 @@
<el-input-number size="small" v-model="controller.whileController.timeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="3000" :step="1000"/>
<span class="ms-span ms-radio">ms</span>
</div>
<template v-slot:debugStepCode>
<el-tooltip :content="getCode()" v-if="node.data.debug">
<span class="ms-step-debug-code" :class="node.data.code ==='error'?'ms-req-error':'ms-req-success'">
{{ getCode() }}
</span>
</el-tooltip>
</template>
</api-base-component>
</div>
@ -151,6 +159,16 @@
};
},
methods: {
getCode() {
if (this.node && this.node.data.debug) {
if (this.node.data.code && this.node.data.code === 'error') {
return 'error';
} else {
return 'success';
}
}
return '';
},
initResult() {
if (this.controller) {
switch (this.controller.loopType) {
@ -363,6 +381,13 @@
.icon.is-active {
transform: rotate(90deg);
}
.ms-req-error {
color: #F56C6C;
}
.ms-req-success {
color: #67C23A;
}
/deep/ .el-radio {
margin-right: 5px;

View File

@ -17,6 +17,10 @@
<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']" @click="disableAll"/>
</el-tooltip>
<span class="ms-debug-result" v-if="debug">
{{ reqTotalTime }} ms 请求 {{ reqTotal }} 成功 {{ reqSuccess }} 失败 {{ reqError }}
</span>
<el-tree node-key="resourceId"
:props="props"
:data="scenarioDefinition"
@ -175,9 +179,15 @@ export default {
moduleOptions: Array,
currentScenario: {},
type: String,
debug: Boolean,
reloadDebug: String,
stepReEnable: Boolean,
scenarioDefinition: Array,
envMap: Map,
reqTotal: Number,
reqSuccess: Number,
reqError: Number,
reqTotalTime: Number,
},
components: {
MsVariableList,
@ -242,6 +252,7 @@ export default {
debugResult: new Map,
expandedStatus: false,
stepEnable: true,
debugLoading: false,
}
},
created() {
@ -255,6 +266,9 @@ export default {
watch: {
envMap() {
this.projectEnvMap = this.envMap;
},
reloadDebug() {
this.reload();
}
},
directives: {OutsideClick},
@ -1198,4 +1212,10 @@ export default {
.ms-open-btn-left {
margin-left: 30px;
}
.ms-debug-result {
float: right;
margin-right: 30px;
margin-top: 3px;
}
</style>

View File

@ -25,10 +25,13 @@
@showPopover="showPopover" :project-list="projectList" ref="envPopover" class="ms-right"
:result="envResult"/>
<el-button :disabled="scenarioDefinition.length < 1" size="mini" type="primary" v-prevent-re-click
@click="runDebug">{{ $t('api_test.request.debug') }}
</el-button>
<el-dropdown split-button type="primary" @click="runDebug" style="margin-right: 10px" size="mini" @command="handleCommand" v-if="!debug">
{{ $t('api_test.request.debug') }}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>{{ $t('test_track.case.steps') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button icon="el-icon-loading" size="mini" type="primary" :disabled="debug" v-else>执行中</el-button>
<font-awesome-icon class="ms-alt-ico" :icon="['fa', 'compress-alt']" size="lg" @click="unFullScreen"/>
<!-- <i class="el-icon-close alt-ico-close" @click="close"/>-->
</div>
@ -48,7 +51,8 @@ import html2canvas from 'html2canvas';
projectEnvMap: Map,
projectIds: Set,
projectList: Array,
isFullUrl: Boolean
isFullUrl: Boolean,
execDebug: String,
},
data() {
return {
@ -59,12 +63,23 @@ import html2canvas from 'html2canvas';
sampleError: true,
envResult: {
loading: false
}
},
debugLoading: false,
reqTotal: 0,
reqSuccess: 0,
reqError: 0,
reqTotalTime: 0,
debug: false,
}
},
computed: {
projectId() {
return getCurrentProjectID();
},
},
watch:{
execDebug(){
this.debug = false;
}
},
mounted() {
@ -96,8 +111,15 @@ import html2canvas from 'html2canvas';
this.$emit('unFullScreen');
},
runDebug() {
this.debug = true;
this.debugLoading = true;
this.$emit('runDebug');
},
handleCommand() {
this.debug = false;
this.debugLoading = false;
this.$emit('handleCommand');
},
setCookieShare() {
this.$emit('setCookieShare', this.cookieShare);
},
@ -169,7 +191,7 @@ import html2canvas from 'html2canvas';
.ms-header-right {
float: right;
width: 500px;
width: 540px;
margin-top: 4px;
z-index: 1;
}
@ -209,6 +231,7 @@ import html2canvas from 'html2canvas';
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
font-size: 13px;
}
.ms-scenario-name {
display: inline-block;
margin: 0 5px;
@ -219,4 +242,5 @@ import html2canvas from 'html2canvas';
white-space: nowrap;
width: 200px;
}
</style>

View File

@ -0,0 +1,182 @@
import {ELEMENT_TYPE} from "@/business/components/api/automation/scenario/Setting";
import {Assertions, ConstantTimer, Extract, IfController, JSR223Processor, LoopController, TransactionController} from "@/business/components/api/definition/model/ApiTestModel";
export function buttons() {
let buttons = [
{
title: this.$t('api_test.definition.request.extract_param'),
show: this.showButton("Extract"),
titleColor: "#015478",
titleBgColor: "#E6EEF2",
icon: "colorize",
click: () => {
this.addComponent('Extract')
}
},
{
title: this.$t('api_test.definition.request.post_script'),
show: this.showButton("JSR223PostProcessor"),
titleColor: "#783887",
titleBgColor: "#F2ECF3",
icon: "skip_next",
click: () => {
this.addComponent('JSR223PostProcessor')
}
},
{
title: this.$t('api_test.definition.request.pre_script'),
show: this.showButton("JSR223PreProcessor"),
titleColor: "#B8741A",
titleBgColor: "#F9F1EA",
icon: "skip_previous",
click: () => {
this.addComponent('JSR223PreProcessor')
}
},
{
title: this.$t('api_test.automation.customize_script'),
show: this.showButton("JSR223Processor"),
titleColor: "#7B4D12",
titleBgColor: "#F1EEE9",
icon: "code",
click: () => {
this.addComponent('JSR223Processor')
}
},
{
title: this.$t('api_test.automation.if_controller'),
show: this.showButton("IfController"),
titleColor: "#E6A23C",
titleBgColor: "#FCF6EE",
icon: "alt_route",
click: () => {
this.addComponent('IfController')
}
},
{
title: this.$t('api_test.automation.loop_controller'),
show: this.showButton("LoopController"),
titleColor: "#02A7F0",
titleBgColor: "#F4F4F5",
icon: "next_plan",
click: () => {
this.addComponent('LoopController')
}
},
{
title: this.$t('api_test.automation.transcation_controller'),
show: this.showButton("TransactionController"),
titleColor: "#6D317C",
titleBgColor: "#F4F4F5",
icon: "alt_route",
click: () => {
this.addComponent('TransactionController')
}
},
{
title: this.$t('api_test.automation.wait_controller'),
show: this.showButton("ConstantTimer"),
titleColor: "#67C23A",
titleBgColor: "#F2F9EE",
icon: "access_time",
click: () => {
this.addComponent('ConstantTimer')
}
},
{
title: this.$t('api_test.definition.request.assertions_rule'),
show: this.showButton("Assertions"),
titleColor: "#A30014",
titleBgColor: "#F7E6E9",
icon: "next_plan",
click: () => {
this.addComponent('Assertions')
}
},
{
title: this.$t('api_test.automation.customize_req'),
show: this.showButton("CustomizeReq"),
titleColor: "#008080",
titleBgColor: "#EBF2F2",
icon: "tune",
click: () => {
this.addComponent('CustomizeReq')
}
},
{
title: this.$t('api_test.automation.scenario_import'),
show: this.showButton("scenario"),
titleColor: "#606266",
titleBgColor: "#F4F4F5",
icon: "movie",
click: () => {
this.addComponent('scenario')
}
},
{
title: this.$t('api_test.automation.api_list_import'),
show: this.showButton("HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler"),
titleColor: "#F56C6C",
titleBgColor: "#FCF1F1",
icon: "api",
click: this.apiListImport
}
];
return buttons.filter(btn => btn.show);
}
export function setComponent(type, _this) {
switch (type) {
case ELEMENT_TYPE.IfController:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new IfController()) :
_this.scenarioDefinition.push(new IfController());
break;
case ELEMENT_TYPE.ConstantTimer:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new ConstantTimer()) :
_this.scenarioDefinition.push(new ConstantTimer());
break;
case ELEMENT_TYPE.JSR223Processor:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new JSR223Processor()) :
_this.scenarioDefinition.push(new JSR223Processor());
break;
case ELEMENT_TYPE.JSR223PreProcessor:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new JSR223Processor({type: "JSR223PreProcessor"})) :
_this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PreProcessor"}));
break;
case ELEMENT_TYPE.JSR223PostProcessor:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new JSR223Processor({type: "JSR223PostProcessor"})) :
_this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PostProcessor"}));
break;
case ELEMENT_TYPE.Assertions:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new Assertions()) :
_this.scenarioDefinition.push(new Assertions());
break;
case ELEMENT_TYPE.Extract:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new Extract()) :
_this.scenarioDefinition.push(new Extract());
break;
case ELEMENT_TYPE.CustomizeReq:
_this.customizeRequest = {protocol: "HTTP", type: "API", hashTree: [], referenced: 'Created', active: false};
_this.customizeVisible = true;
break;
case ELEMENT_TYPE.LoopController:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new LoopController()) :
_this.scenarioDefinition.push(new LoopController());
break;
case ELEMENT_TYPE.TransactionController:
_this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new TransactionController()) :
_this.scenarioDefinition.push(new TransactionController());
break;
case ELEMENT_TYPE.scenario:
_this.isBtnHide = true;
_this.$refs.scenarioRelevance.open();
break;
default:
_this.$refs.apiImport.open();
break;
}
if (_this.selectedNode) {
_this.selectedNode.expanded = true;
}
_this.sort();
}