fix(接口测试): 修复文档结构断言,导入了一个比较长的json卡住的缺陷

--bug=1013770 --user=王孝刚 【接口测试】文档结构断言导入JSON文件页面卡住 https://www.tapd.cn/55049933/s/1180117
This commit is contained in:
wxg0103 2022-06-13 16:55:54 +08:00 committed by f2c-ci-robot[bot]
parent 77c4ba4cf1
commit 3427b91b3c
18 changed files with 537 additions and 354 deletions

View File

@ -402,7 +402,7 @@ import {
} from "@/business/components/api/automation/api-automation"; } from "@/business/components/api/automation/api-automation";
import MsComponentConfig from "./component/ComponentConfig"; import MsComponentConfig from "./component/ComponentConfig";
import {ENV_TYPE} from "@/common/js/constants"; import {ENV_TYPE} from "@/common/js/constants";
import {hisDataProcessing} from "@/business/components/api/definition/api-definition"; import {hisDataProcessing, mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/); const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const versionHistory = requireComponent.keys().length > 0 ? requireComponent("./version/VersionHistory.vue") : {}; const versionHistory = requireComponent.keys().length > 0 ? requireComponent("./version/VersionHistory.vue") : {};
@ -1019,6 +1019,7 @@ export default {
this.debug = false; this.debug = false;
this.saved = true; this.saved = true;
this.executeType = "Saved"; this.executeType = "Saved";
this.mergeScenario(this.scenarioDefinition);
this.validatePluginData(this.scenarioDefinition); this.validatePluginData(this.scenarioDefinition);
if (this.pluginDelStep) { if (this.pluginDelStep) {
this.$error("场景包含插件步骤,对应场景已经删除不能执行!"); this.$error("场景包含插件步骤,对应场景已经删除不能执行!");
@ -1436,7 +1437,16 @@ export default {
run() { run() {
this.reportId = this.debugReportId; this.reportId = this.debugReportId;
}, },
mergeScenario(data) {
data.forEach(item => {
mergeRequestDocumentData(item);
if (item.hashTree && item.hashTree > 0) {
this.mergeScenario(item.hashTree);
}
})
},
runDebug(runScenario) { runDebug(runScenario) {
this.mergeScenario(this.scenarioDefinition);
if (this.debugLoading) { if (this.debugLoading) {
return; return;
} }
@ -1457,6 +1467,7 @@ export default {
this.debugLoading = false; this.debugLoading = false;
return; return;
} }
this.stopDebug = ""; this.stopDebug = "";
this.clearDebug(); this.clearDebug();
this.validatePluginData(this.scenarioDefinition); this.validatePluginData(this.scenarioDefinition);
@ -1569,6 +1580,7 @@ export default {
} }
}, },
editScenario() { editScenario() {
this.mergeScenario(this.scenarioDefinition);
if (!document.getElementById("inputDelay")) { if (!document.getElementById("inputDelay")) {
return; return;
} }

View File

@ -125,7 +125,7 @@ export function hisDataProcessing(array, request) {
} }
} }
assertionsIndex.forEach(item => { assertionsIndex.forEach(item => {
const rmIndex = request.hashTree.findIndex((d) => d.id === item.id&&d.resourceId===item.resourceId); const rmIndex = request.hashTree.findIndex((d) => d.id === item.id && d.resourceId === item.resourceId);
request.hashTree.splice(rmIndex, 1); request.hashTree.splice(rmIndex, 1);
}) })
@ -157,3 +157,36 @@ export function stepCompute(array, request) {
request.ruleSize = ruleSize; request.ruleSize = ruleSize;
} }
export function mergeDocumentData(originalData, childMap) {
originalData.forEach(item => {
if (childMap && childMap.has(item.id)) {
let sourceData = JSON.parse(JSON.stringify(item.children));
item.children = JSON.parse(JSON.stringify(childMap.get(item.id)));
item.children.forEach(target => {
let index = sourceData.findIndex(source => source.id === target.id);
if (index !== -1) {
target.children = sourceData[index].children
}
})
if (item.children && item.children.length > 0) {
mergeDocumentData(item.children, childMap);
}
}
})
}
export function mergeRequestDocumentData(request) {
if (request && request.hashTree && request.hashTree.length > 0) {
let index = request.hashTree.findIndex(item => item.type === 'Assertions');
if (index !== -1) {
if (request.hashTree[index].document.originalData && request.hashTree[index].document.tableData.size && request.hashTree[index].document.tableData.size !== 0) {
mergeDocumentData(request.hashTree[index].document.originalData, request.hashTree[index].document.tableData);
request.hashTree[index].document.data.json = request.hashTree[index].document.originalData;
}
}
}
}

View File

@ -81,13 +81,13 @@
</div> </div>
<div v-if="showMock && (currentProtocol === 'HTTP' || currentProtocol === 'TCP')"> <div v-if="showMock && (currentProtocol === 'HTTP' || currentProtocol === 'TCP')">
<mock-tab :base-mock-config-data="baseMockConfigData" @redirectToTest="redirectToTest" :version-name="currentApi.versionName" <mock-tab :base-mock-config-data="baseMockConfigData" @redirectToTest="redirectToTest"
:version-name="currentApi.versionName"
:is-tcp="currentProtocol === 'TCP'"/> :is-tcp="currentProtocol === 'TCP'"/>
</div> </div>
<div v-if="showTestCaseList"> <div v-if="showTestCaseList">
<!--测试用例列表--> <!--测试用例列表-->
<api-case-simple-list <api-case-simple-list
class="api-case-simple-list"
:apiDefinitionId="currentApi.id" :apiDefinitionId="currentApi.id"
:apiDefinition="currentApi" :apiDefinition="currentApi"
:current-version="currentApi.versionId" :current-version="currentApi.versionId"
@ -283,7 +283,7 @@ export default {
this.beforeChangeTab(); this.beforeChangeTab();
this.refreshButtonActiveClass(tabType); this.refreshButtonActiveClass(tabType);
}, },
beforeChangeTab(){ beforeChangeTab() {
// //
this.$refs.caseList.close(); this.$refs.caseList.close();
}, },
@ -295,9 +295,9 @@ export default {
if (param.params) { if (param.params) {
requestParam = param.params; requestParam = param.params;
} }
this.$refs.httpTestPage.setRequestParam(requestParam,true); this.$refs.httpTestPage.setRequestParam(requestParam, true);
} else if (this.currentProtocol === "TCP" && this.$refs.tcpTestPage) { } else if (this.currentProtocol === "TCP" && this.$refs.tcpTestPage) {
this.$refs.tcpTestPage.setRequestParam(param,true); this.$refs.tcpTestPage.setRequestParam(param, true);
} }
}); });
}, },
@ -405,11 +405,6 @@ export default {
border: solid 1px var(--primary_color); border: solid 1px var(--primary_color);
} }
.api-case-simple-list >>> .el-table {
height: calc(100vh - 262px) !important;
}
/deep/ .ms-opt-btn { /deep/ .ms-opt-btn {
position: fixed; position: fixed;
right: 50px; right: 50px;

View File

@ -5,10 +5,10 @@
{{ assertion.desc }} {{ assertion.desc }}
</div> </div>
<div class="assertion-item btn"> <div class="assertion-item btn">
<el-button :disabled="isReadOnly" type="success" size="small" @click="detail"> <el-button :disabled="isReadOnly" type="success" size="mini" @click="detail">
{{ $t('commons.edit') }} {{ $t('commons.edit') }}
</el-button> </el-button>
<el-button :disabled="isReadOnly" type="primary" size="small" @click="add"> <el-button :disabled="isReadOnly" type="primary" size="mini" @click="add">
{{ $t('api_test.request.assertions.add') }} {{ $t('api_test.request.assertions.add') }}
</el-button> </el-button>
</div> </div>
@ -21,7 +21,8 @@
<i class="el-icon-view el-button el-button--primary el-button--mini is-circle" circle @click="showPage"/> <i class="el-icon-view el-button el-button--primary el-button--mini is-circle" circle @click="showPage"/>
<el-button :disabled="isReadOnly" type="success" size="mini" icon="el-icon-edit" circle @click="detail"/> <el-button :disabled="isReadOnly" type="success" size="mini" icon="el-icon-edit" circle @click="detail"/>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top"> <el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top">
<el-switch v-model="assertion.enable" class="enable-switch" size="mini" :disabled="isReadOnly" style="width: 30px;margin:0px 10px 0px 10px"/> <el-switch v-model="assertion.enable" class="enable-switch" size="mini" :disabled="isReadOnly"
style="width: 30px;margin:0px 10px 0px 10px"/>
</el-tooltip> </el-tooltip>
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove"/> <el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove"/>
</div> </div>
@ -61,279 +62,279 @@
</template> </template>
<script> <script>
import {AssertionJSR223} from "../../model/ApiTestModel"; import {AssertionJSR223} from "../../model/ApiTestModel";
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter"; import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
import MsJsr233Processor from "../../../automation/scenario/common/Jsr233ProcessorContent"; import MsJsr233Processor from "../../../automation/scenario/common/Jsr233ProcessorContent";
export default { export default {
name: "MsApiAssertionJsr223", name: "MsApiAssertionJsr223",
components: {MsJsr233Processor, MsDialogFooter}, components: {MsJsr233Processor, MsDialogFooter},
props: { props: {
assertion: { assertion: {
default: () => { default: () => {
return new AssertionJSR223(); return new AssertionJSR223();
}
},
edit: {
type: Boolean,
default: false
},
index: Number,
list: Array,
callback: Function,
isReadOnly: {
type: Boolean,
default: false
} }
}, },
edit: {
type: Boolean,
default: false
},
index: Number,
list: Array,
callback: Function,
isReadOnly: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
visible: false, visible: false,
disabled: false, disabled: false,
operators: { operators: {
EQ: { EQ: {
label: "commons.adv_search.operators.equals", label: "commons.adv_search.operators.equals",
value: "==" value: "=="
},
NE: {
label: "commons.adv_search.operators.not_equals",
value: "!="
},
CONTAINS: {
label: "commons.adv_search.operators.like",
value: "contains"
},
NOT_CONTAINS: {
label: "commons.adv_search.operators.not_like",
value: "not contains"
},
GT: {
label: "commons.adv_search.operators.gt",
value: ">"
},
LT: {
label: "commons.adv_search.operators.lt",
value: "<"
},
IS_EMPTY: {
label: "commons.adv_search.operators.is_empty",
value: "is empty"
},
IS_NOT_EMPTY: {
label: "commons.adv_search.operators.is_not_empty",
value: "is not empty"
}
}, },
templates: [ NE: {
{ label: "commons.adv_search.operators.not_equals",
title: this.$t('api_test.request.assertions.set_failure_status'), value: "!="
value: 'AssertionResult.setFailure(true)', },
}, CONTAINS: {
{ label: "commons.adv_search.operators.like",
title: this.$t('api_test.request.assertions.set_failure_msg'), value: "contains"
value: 'AssertionResult.setFailureMessage("msg")', },
} NOT_CONTAINS: {
], label: "commons.adv_search.operators.not_like",
value: "not contains"
},
GT: {
label: "commons.adv_search.operators.gt",
value: ">"
},
LT: {
label: "commons.adv_search.operators.lt",
value: "<"
},
IS_EMPTY: {
label: "commons.adv_search.operators.is_empty",
value: "is empty"
},
IS_NOT_EMPTY: {
label: "commons.adv_search.operators.is_not_empty",
value: "is not empty"
}
},
templates: [
{
title: this.$t('api_test.request.assertions.set_failure_status'),
value: 'AssertionResult.setFailure(true)',
},
{
title: this.$t('api_test.request.assertions.set_failure_msg'),
value: 'AssertionResult.setFailureMessage("msg")',
}
],
}
},
methods: {
add() {
this.list.push(new AssertionJSR223(this.assertion));
this.callback();
},
remove() {
this.list.splice(this.index, 1);
},
changeOperator(value) {
if (value.indexOf("empty") > 0 && !!this.assertion.value) {
this.assertion.value = "";
}
this.quickScript();
},
beanShellOrGroovyScript() {
if (this.assertion.variable && this.assertion.operator) {
let variable = this.assertion.variable;
let operator = this.assertion.operator;
let value = this.assertion.value || "";
let desc = "${" + variable + "} " + operator + " '" + value + "'";
let msgScript = "\" + value + \" " + operator + " '" + value + "'";
let script = "value = vars.get(\"" + variable + "\");\n"
switch (this.assertion.operator) {
case "==":
script += "result = \"" + value + "\".equals(value);\n";
break;
case "!=":
script += "result = !\"" + value + "\".equals(value);\n";
break;
case "contains":
script += "result = value.contains(\"" + value + "\");\n";
break;
case "not contains":
script += "result = !value.contains(\"" + value + "\");\n";
break;
case ">":
desc = "${" + variable + "} " + operator + " " + value;
msgScript = "\" + value + \" " + operator + " " + value;
script += "number = Integer.parseInt(value);\n" +
"result = number > " + value + ";\n";
break;
case "<":
desc = "${" + variable + "} " + operator + " " + value;
msgScript = "\" + value + \" " + operator + " " + value;
script += "number = Integer.parseInt(value);\n" +
"result = number < " + value + ";\n";
break;
case "is empty":
desc = "${" + variable + "} " + operator;
msgScript = "\" + value + \" " + operator;
script += "result = value == void || value.length() == 0;\n";
break;
case "is not empty":
desc = "${" + variable + "} " + operator;
msgScript = "\" + value + \" " + operator;
script += "result = value != void && value.length() > 0;\n";
break;
}
let msg = (operator !== "is empty" && operator !== "is not empty") ? "assertion [" + msgScript + "]: false;" : "value " + operator
script += "if (!result){\n" +
"\tmsg = \"" + msg + "\";\n" +
"\tAssertionResult.setFailureMessage(msg);\n" +
"\tAssertionResult.setFailure(true);\n" +
"}";
this.assertion.desc = desc;
this.assertion.script = script;
this.$refs.jsr233.reload();
}
},
pythonScript() {
if (this.assertion.variable && this.assertion.operator) {
let variable = this.assertion.variable;
let operator = this.assertion.operator;
let value = this.assertion.value || "";
let desc = "${" + variable + "} " + operator + " '" + value + "'";
let msg = "";
let script = "value = vars.get(\"" + variable + "\");\n"
switch (this.assertion.operator) {
case "==":
script += "if value != \"" + value + "\" :\n";
break;
case "!=":
script += "if value == \"" + value + "\" :\n";
break;
case "contains":
script += "if value.find(\"" + value + "\") == -1:\n";
msg = "value " + operator + " " + value + ": false;";
break;
case "not contains":
script += "if value.find(\"" + value + "\") != -1:\n";
msg = "value " + operator + " " + ": false;";
break;
case ">":
desc = "${" + variable + "} " + operator + " " + value;
script += "if value is None or int(value) < " + value + ":\n";
msg = "value " + operator + " " + value + ": false;";
break;
case "<":
desc = "${" + variable + "} " + operator + " " + value;
script += "if value is None or int(value) > " + value + ":\n";
msg = "value " + operator + " " + value + ": false;";
break;
case "is empty":
desc = "${" + variable + "} " + operator
script += "if value is not None:\n";
msg = "value " + operator + ": false;";
break;
case "is not empty":
desc = "${" + variable + "} " + operator
script += "if value is None:\n";
msg = "value " + operator + ": false;";
break;
}
script +=
"\tmsg = \" " + msg + "\"\n" +
"\tAssertionResult.setFailureMessage(msg)" + "\n" +
"\tAssertionResult.setFailure(True)";
this.assertion.desc = desc;
this.assertion.script = script;
this.$refs.jsr233.reload();
}
},
quickScript() {
if (this.assertion.scriptLanguage == 'beanshell' || this.assertion.scriptLanguage == 'groovy' || this.assertion.scriptLanguage == 'javascript') {
this.beanShellOrGroovyScript();
} else {
this.pythonScript();
} }
}, },
detail() {
methods: { this.disabled = false;
add() { this.visible = true;
this.list.push(new AssertionJSR223(this.assertion));
this.callback();
},
remove() {
this.list.splice(this.index, 1);
},
changeOperator(value) {
if (value.indexOf("empty") > 0 && !!this.assertion.value) {
this.assertion.value = "";
}
this.quickScript();
},
beanShellOrGroovyScript() {
if (this.assertion.variable && this.assertion.operator) {
let variable = this.assertion.variable;
let operator = this.assertion.operator;
let value = this.assertion.value || "";
let desc = "${" + variable + "} " + operator + " '" + value + "'";
let msgScript = "\" + value + \" " + operator + " '" + value + "'";
let script = "value = vars.get(\"" + variable + "\");\n"
switch (this.assertion.operator) {
case "==":
script += "result = \"" + value + "\".equals(value);\n";
break;
case "!=":
script += "result = !\"" + value + "\".equals(value);\n";
break;
case "contains":
script += "result = value.contains(\"" + value + "\");\n";
break;
case "not contains":
script += "result = !value.contains(\"" + value + "\");\n";
break;
case ">":
desc = "${" + variable + "} " + operator + " " + value;
msgScript = "\" + value + \" " + operator + " " + value;
script += "number = Integer.parseInt(value);\n" +
"result = number > " + value + ";\n";
break;
case "<":
desc = "${" + variable + "} " + operator + " " + value;
msgScript = "\" + value + \" " + operator + " " + value;
script += "number = Integer.parseInt(value);\n" +
"result = number < " + value + ";\n";
break;
case "is empty":
desc = "${" + variable + "} " + operator;
msgScript = "\" + value + \" " + operator;
script += "result = value == void || value.length() == 0;\n";
break;
case "is not empty":
desc = "${" + variable + "} " + operator;
msgScript = "\" + value + \" " + operator;
script += "result = value != void && value.length() > 0;\n";
break;
}
let msg = (operator !== "is empty" && operator !== "is not empty") ? "assertion [" + msgScript + "]: false;" : "value " + operator
script += "if (!result){\n" +
"\tmsg = \"" + msg + "\";\n" +
"\tAssertionResult.setFailureMessage(msg);\n" +
"\tAssertionResult.setFailure(true);\n" +
"}";
this.assertion.desc = desc;
this.assertion.script = script;
this.$refs.jsr233.reload();
}
},
pythonScript() {
if (this.assertion.variable && this.assertion.operator) {
let variable = this.assertion.variable;
let operator = this.assertion.operator;
let value = this.assertion.value || "";
let desc = "${" + variable + "} " + operator + " '" + value + "'";
let msg = "";
let script = "value = vars.get(\"" + variable + "\");\n"
switch (this.assertion.operator) {
case "==":
script += "if value != \"" + value + "\" :\n";
break;
case "!=":
script += "if value == \"" + value + "\" :\n";
break;
case "contains":
script += "if value.find(\"" + value + "\") == -1:\n";
msg = "value " + operator + " " + value + ": false;";
break;
case "not contains":
script += "if value.find(\"" + value + "\") != -1:\n";
msg = "value " + operator + " " + ": false;";
break;
case ">":
desc = "${" + variable + "} " + operator + " " + value;
script += "if value is None or int(value) < " + value + ":\n";
msg = "value " + operator + " " + value + ": false;";
break;
case "<":
desc = "${" + variable + "} " + operator + " " + value;
script += "if value is None or int(value) > " + value + ":\n";
msg = "value " + operator + " " + value + ": false;";
break;
case "is empty":
desc = "${" + variable + "} " + operator
script += "if value is not None:\n";
msg = "value " + operator + ": false;";
break;
case "is not empty":
desc = "${" + variable + "} " + operator
script += "if value is None:\n";
msg = "value " + operator + ": false;";
break;
}
script +=
"\tmsg = \" " + msg + "\"\n" +
"\tAssertionResult.setFailureMessage(msg)" +"\n"+
"\tAssertionResult.setFailure(True)";
this.assertion.desc = desc;
this.assertion.script = script;
this.$refs.jsr233.reload();
}
},
quickScript() {
if (this.assertion.scriptLanguage == 'beanshell' || this.assertion.scriptLanguage == 'groovy' || this.assertion.scriptLanguage == 'javascript') {
this.beanShellOrGroovyScript();
} else {
this.pythonScript();
}
},
detail() {
this.disabled = false;
this.visible = true;
},
showPage() {
this.disabled = true;
this.visible = true;
},
close() {
this.visible = false;
},
confirm() {
if (!this.edit) {
this.add();
}
if (!this.assertion.desc) {
this.assertion.desc = this.assertion.script;
}
this.close();
}
}, },
showPage() {
computed: { this.disabled = true;
hasEmptyOperator() { this.visible = true;
return !!this.assertion.operator && this.assertion.operator.indexOf("empty") > 0; },
close() {
this.visible = false;
},
confirm() {
if (!this.edit) {
this.add();
} }
if (!this.assertion.desc) {
this.assertion.desc = this.assertion.script;
}
this.close();
}
},
computed: {
hasEmptyOperator() {
return !!this.assertion.operator && this.assertion.operator.indexOf("empty") > 0;
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.assertion-item { .assertion-item {
display: inline-block; display: inline-block;
} }
.assertion-item + .assertion-item { .assertion-item + .assertion-item {
margin-left: 10px; margin-left: 10px;
} }
.assertion-item.input { .assertion-item.input {
width: 100%; width: 100%;
} }
.assertion-item.select { .assertion-item.select {
min-width: 150px; min-width: 150px;
} }
.assertion-item.label { .assertion-item.label {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.assertion-item.btn { .assertion-item.btn {
min-width: 130px; min-width: 130px;
} }
.assertion-item.btn.circle { .assertion-item.btn.circle {
text-align: right; text-align: right;
min-width: 80px; min-width: 80px;
} }
.quick-script-block { .quick-script-block {
margin-bottom: 10px; margin-bottom: 10px;
} }
</style> </style>

View File

@ -129,7 +129,11 @@ export default {
}, },
methods: { methods: {
remove() { remove() {
this.assertions.document = {type: "JSON", data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}}; this.assertions.document = {
type: "JSON",
data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []},
enable: true
};
}, },
reload() { reload() {
this.loading = true this.loading = true

View File

@ -21,13 +21,18 @@
@cell-mouse-leave="editLeave" @cell-mouse-leave="editLeave"
row-key="id" row-key="id"
border border
default-expand-all lazy
:load="loadChild"
:height="300" :height="300"
v-loading="loading"> v-loading="loading"
ref="table">
<el-table-column prop="name" :label="$t('api_test.definition.request.esb_table.name')" width="230"> <el-table-column prop="name" :label="$t('api_test.definition.request.esb_table.name')" width="230">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-if="(scope.row.status && scope.column.fixed && scope.row.id!=='root') || (scope.row.type !=='object' && !scope.row.name)" v-model="scope.row.name" style="width: 140px" size="mini" :placeholder="$t('api_test.definition.request.esb_table.name')"/> <el-input
v-if="(scope.row.status && scope.column.fixed && scope.row.id!=='root') || (scope.row.type !=='object' && !scope.row.name)"
v-model="scope.row.name" style="width: 140px" size="mini"
:placeholder="$t('api_test.definition.request.esb_table.name')"/>
<span v-else>{{ scope.row.name }}</span> <span v-else>{{ scope.row.name }}</span>
</template> </template>
</el-table-column> </el-table-column>
@ -35,7 +40,8 @@
<el-table-column prop="include" width="78" :label="$t('api_test.request.assertions.must_contain')" <el-table-column prop="include" width="78" :label="$t('api_test.request.assertions.must_contain')"
:scoped-slot="renderHeader"> :scoped-slot="renderHeader">
<template slot-scope="scope"> <template slot-scope="scope">
<el-checkbox v-model="scope.row.include" @change="handleCheckOneChange" :disabled="checked || scope.row.type==='array'"/> <el-checkbox v-model="scope.row.include" @change="handleCheckOneChange"
:disabled="checked || scope.row.type==='array'"/>
</template> </template>
</el-table-column> </el-table-column>
@ -48,7 +54,8 @@
<el-table-column prop="type" :label="$t('api_test.definition.request.esb_table.type')" width="120"> <el-table-column prop="type" :label="$t('api_test.definition.request.esb_table.type')" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.type" :placeholder="$t('commons.please_select')" size="mini" @change="changeType(scope.row)" :disabled="checked"> <el-select v-model="scope.row.type" :placeholder="$t('commons.please_select')" size="mini"
@change="changeType(scope.row)" :disabled="checked">
<el-option v-for="item in typeSelectOptions " :key="item.value" :label="item.label" :value="item.value"/> <el-option v-for="item in typeSelectOptions " :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</template> </template>
@ -93,7 +100,8 @@
:disabled="(scope.row.type !=='object' && scope.row.type !=='array') || checked"/> :disabled="(scope.row.type !=='object' && scope.row.type !=='array') || checked"/>
</el-tooltip> </el-tooltip>
<el-tooltip effect="dark" :content="$t('commons.remove')" placement="top-start"> <el-tooltip effect="dark" :content="$t('commons.remove')" placement="top-start">
<el-button icon="el-icon-delete" type="primary" circle size="mini" style="margin-left: 10px" @click="remove(scope.row)" :disabled="checked || scope.row.id==='root'"/> <el-button icon="el-icon-delete" type="primary" circle size="mini" style="margin-left: 10px"
@click="remove(scope.row)" :disabled="checked || scope.row.id==='root'"/>
</el-tooltip> </el-tooltip>
</span> </span>
</template> </template>
@ -149,8 +157,11 @@ export default {
], ],
checked: false, checked: false,
tableData: Array, tableData: Array,
originalData: Array,
mapData: new Map(),
} }
}, },
created() { created() {
if (this.document.type === "JSON") { if (this.document.type === "JSON") {
this.checked = this.document.data.jsonFollowAPI && this.document.data.jsonFollowAPI !== "false" ? true : false; this.checked = this.document.data.jsonFollowAPI && this.document.data.jsonFollowAPI !== "false" ? true : false;
@ -167,7 +178,7 @@ export default {
this.checked = this.document.data.xmlFollowAPI && this.document.data.xmlFollowAPI !== "false" ? true : false; this.checked = this.document.data.xmlFollowAPI && this.document.data.xmlFollowAPI !== "false" ? true : false;
} }
this.changeData(); this.changeData();
} },
}, },
methods: { methods: {
removeDoc() { removeDoc() {
@ -177,13 +188,60 @@ export default {
this.checked = false; this.checked = false;
this.document.data.jsonFollowAPI = ""; this.document.data.jsonFollowAPI = "";
this.document.data.xmlFollowAPI = ""; this.document.data.xmlFollowAPI = "";
this.tableData = data; //childrennull
this.tableDataList(data);
if (this.document.type === "JSON") { if (this.document.type === "JSON") {
this.document.data.json = this.tableData; this.document.data.json = this.originalData;
} else if (this.document.type === "XML") { } else if (this.document.type === "XML") {
this.document.data.xml = this.tableData; this.document.data.xml = this.tableData;
} }
}, },
tableDataList(data) {
this.$set(this.document, 'originalData', data);
this.$set(this.document, 'tableData', this.mapData);
this.originalData = data;
this.tableData = JSON.parse(JSON.stringify(data)).map(item => {
// hasChildren
item.hasChildren = item.children && item.children.length > 0
item.idList = [item.id];
item.children = [];
return item;
});
},
loadChild(tree, treeNode, resolve) {
//
const idCopy = JSON.parse(JSON.stringify(tree.idList))
//
let resolveArr;
if (tree.children.length === 0) {
resolveArr = this.originalData;
//children
const tarItem = resolveArr.find(item => item.id === tree.idList.shift())
tarItem.loadedChildren = true
resolveArr = tarItem.children
} else {
resolveArr = tree;
resolveArr = tree.children;
}
//
resolveArr = JSON.parse(JSON.stringify(resolveArr))
resolveArr.forEach(item => {
item.hasChildren = item.children && item.children.length > 0
item.children = [];
// itemidList
item.idList = JSON.parse(JSON.stringify(idCopy));
item.parentId = item.idList[item.idList.length - 1];
item.idList.push(item.id);
})
//
tree.loadedChildren = true
//
resolve(resolveArr);
this.mapData.set(tree.id, resolveArr);
},
checkedAPI() { checkedAPI() {
this.document.data.jsonFollowAPI = ""; this.document.data.jsonFollowAPI = "";
this.document.data.xmlFollowAPI = ""; this.document.data.xmlFollowAPI = "";
@ -212,7 +270,7 @@ export default {
let url = "/api/definition/getDocument/" + (id ? id : this.apiId) + "/" + this.document.type; let url = "/api/definition/getDocument/" + (id ? id : this.apiId) + "/" + this.document.type;
this.$get(url, response => { this.$get(url, response => {
if (response.data) { if (response.data) {
this.tableData = response.data; this.tableDataList(response.data);
} }
}); });
}, },
@ -239,8 +297,9 @@ export default {
if (this.document.data.jsonFollowAPI) { if (this.document.data.jsonFollowAPI) {
this.getDocument(); this.getDocument();
} else { } else {
this.tableData = this.document.data.json; this.tableDataList(this.document.data.json);
} }
} else if (this.document.type === "XML") { } else if (this.document.type === "XML") {
this.document.data.xmlFollowAPI = this.checked ? this.apiId : ""; this.document.data.xmlFollowAPI = this.checked ? this.apiId : "";
if (this.document.data.xmlFollowAPI) { if (this.document.data.xmlFollowAPI) {
@ -251,13 +310,6 @@ export default {
} }
this.reload(); this.reload();
} }
if (this.tableData && this.tableData.length > 0) {
this.tableData.forEach(row => {
if (row.name == null || row.name === "") {
this.remove(row);
}
})
}
}, },
objectSpanMethod({row, column, rowIndex, columnIndex}) { objectSpanMethod({row, column, rowIndex, columnIndex}) {
if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2 || columnIndex === 3) { if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2 || columnIndex === 3) {
@ -268,7 +320,30 @@ export default {
} }
}, },
changeType(row) { changeType(row) {
row.children = []; if (this.mapData && this.mapData.has(row.id)) {
this.clearChild(this.mapData.get(row.id))
row.hasChildren = false;
row.idList = [row.parentId, row.id];
}
this.changeChild(this.originalData, row);
},
clearChild(data) {
data.forEach(item => {
this.remove(item)
})
if (data && data.length > 0) {
this.clearChild(data);
}
},
changeChild(data, row) {
data.forEach(item => {
if (item.id === row.id) {
item.children = [];
row.hasChildren = false;
} else {
this.changeChild(item.children, row)
}
})
}, },
getValue(key) { getValue(key) {
let value = ""; let value = "";
@ -308,6 +383,7 @@ export default {
) )
}, },
renderHeaderArray(h, {column}) { renderHeaderArray(h, {column}) {
return h( return h(
'span', [ 'span', [
h('el-checkbox', { h('el-checkbox', {
@ -358,19 +434,21 @@ export default {
if (this.checked) { if (this.checked) {
return; return;
} }
this.tableData.forEach(item => { this.originalData.forEach(item => {
item.typeVerification = val; item.typeVerification = val;
this.childrenChecked(item.children, 2, val); this.childrenChecked(item.children, 2, val);
}) })
this.tableDataList(this.originalData)
}, },
handleArray(val) { handleArray(val) {
if (this.checked) { if (this.checked) {
return; return;
} }
this.tableData.forEach(item => { this.originalData.forEach(item => {
item.arrayVerification = val; item.arrayVerification = val;
this.childrenChecked(item.children, 3, val); this.childrenChecked(item.children, 3, val);
}) })
this.tableDataList(this.originalData)
}, },
handleCheckOneChange(val) { handleCheckOneChange(val) {
}, },
@ -381,15 +459,44 @@ export default {
this.removeTableRow(row); this.removeTableRow(row);
}, },
addRow(row) { addRow(row) {
if (!row.idList && row.idList.length === 0) {
row.idList.push(row.id);
}
// //
if (row.type !== "array") { if (row.type !== "array") {
row.type = "object"; row.type = "object";
} }
let newRow = this.getNewRow(); let newRow = this.getNewRow();
row.children.push(newRow); newRow.idList = [row.id, newRow.id];
newRow.parentId = row.id;
if (this.mapData.has(row.id) && this.mapData.get(row.id).length > 0) {
this.mapData.get(row.id).push(newRow);
} else {
this.getChild(this.originalData, row);
row.children.push(newRow);
row.hasChildren = true;
if (row.parentId) {
let brotherRow = this.getNewRow();
brotherRow.idList = [row.parentId, brotherRow.id];
brotherRow.parentId = row.parentId;
this.mapData.get(row.parentId).push(brotherRow);
this.remove(brotherRow)
}
}
}, },
getChild(data, row) {
data.forEach(item => {
if (item.id === row.id) {
row.children = item.children
} else {
this.getChild(item.children, row)
}
})
},
verSet(arr, row) { verSet(arr, row) {
// //
arr = this.mapData.get(row.idList[row.idList.length - 2]);
if (row.groupId) { if (row.groupId) {
const index = arr.findIndex(d => d.id === row.groupId); const index = arr.findIndex(d => d.id === row.groupId);
if (index !== -1) { if (index !== -1) {
@ -398,7 +505,7 @@ export default {
} else if (row.rowspan > 0) { } else if (row.rowspan > 0) {
const index = arr.findIndex(d => d.id === row.id); const index = arr.findIndex(d => d.id === row.id);
if (index !== -1) { if (index !== -1) {
arr[index].rowspan = arr[index].rowspan + 1; arr[index].rowspan = arr[index].rowspan + 1;//
} }
} else { } else {
row.rowspan = 2; row.rowspan = 2;
@ -410,6 +517,7 @@ export default {
newRow.id = getUUID(); newRow.id = getUUID();
newRow.groupId = !row.groupId ? row.id : row.groupId; newRow.groupId = !row.groupId ? row.id : row.groupId;
newRow.rowspan = 0; newRow.rowspan = 0;
newRow.idList.splice(row.idList.length - 1, 0, newRow.id);
if (row.type !== "object" || row.type !== "array") { if (row.type !== "object" || row.type !== "array") {
newRow.children = []; newRow.children = [];
} }
@ -420,9 +528,6 @@ export default {
arr.push(newRow); arr.push(newRow);
} }
} }
if (item.children && item.children.length > 0) {
this.verSet(item.children, row);
}
}) })
}, },
addVerification(row) { addVerification(row) {
@ -508,15 +613,11 @@ export default {
} else { } else {
row.rowspan = 1; row.rowspan = 1;
} }
arr.forEach(item => {
if (item.children && item.children.length > 0) {
this.removeVerSet(item.children, row);
}
})
}, },
removeTableRow(row) { removeTableRow(row) {
this.removeVerSet(this.tableData, row); this.removeVerSet(this.mapData.get(row.parentId), row);
this.removeFromDataStruct(this.tableData, row); this.removeFromDataStruct(this.mapData.get(row.parentId), row);
}, },
removeFromDataStruct(dataStruct, row) { removeFromDataStruct(dataStruct, row) {
if (dataStruct == null || dataStruct.length === 0) { if (dataStruct == null || dataStruct.length === 0) {
@ -525,12 +626,6 @@ export default {
let rowIndex = dataStruct.indexOf(row); let rowIndex = dataStruct.indexOf(row);
if (rowIndex >= 0) { if (rowIndex >= 0) {
dataStruct.splice(rowIndex, 1); dataStruct.splice(rowIndex, 1);
} else {
dataStruct.forEach(itemData => {
if (itemData.children != null && itemData.children.length > 0) {
this.removeFromDataStruct(itemData.children, row);
}
});
} }
}, },
} }

View File

@ -8,7 +8,7 @@
</el-select> </el-select>
</el-col> </el-col>
<el-col class="assertion-btn"> <el-col class="assertion-btn">
<el-button :disabled="isReadOnly" type="primary" size="small" @click="add"> <el-button :disabled="isReadOnly" type="primary" size="mini" @click="add">
{{ $t('api_test.request.assertions.add') }} {{ $t('api_test.request.assertions.add') }}
</el-button> </el-button>
</el-col> </el-col>

View File

@ -182,8 +182,8 @@
</template> </template>
<script> <script>
import {_getBodyUploadFiles, getCurrentProjectID, getCurrentUser, getUUID} from "@/common/js/utils"; import {_getBodyUploadFiles, getCurrentProjectID, getCurrentUser, getUUID, hasPermission} from "@/common/js/utils";
import {API_STATUS, PRIORITY} from "../../model/JsonData"; import {API_METHOD_COLOUR, API_STATUS, PRIORITY} from "../../model/JsonData";
import MsTag from "../../../../common/components/MsTag"; import MsTag from "../../../../common/components/MsTag";
import MsTipButton from "../../../../common/components/MsTipButton"; import MsTipButton from "../../../../common/components/MsTipButton";
import MsApiRequestForm from "../request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
@ -197,15 +197,14 @@ import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag
import MsRequestResultTail from "../response/RequestResultTail"; import MsRequestResultTail from "../response/RequestResultTail";
import ApiResponseComponent from "../../../automation/scenario/component/ApiResponseComponent"; import ApiResponseComponent from "../../../automation/scenario/component/ApiResponseComponent";
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn"; import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
import MsChangeHistory from "../../../../history/ChangeHistory";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import ApiCaseHeader from "./ApiCaseHeader";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/); const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const esbDefinition = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {}; const esbDefinition = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {};
const esbDefinitionResponse = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinitionResponse.vue") : {}; const esbDefinitionResponse = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinitionResponse.vue") : {};
import {API_METHOD_COLOUR} from "../../model/JsonData";
import MsChangeHistory from "../../../../history/ChangeHistory";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {hasPermission} from '@/common/js/utils';
import ApiCaseHeader from "./ApiCaseHeader";
export default { export default {
name: "ApiCaseItem", name: "ApiCaseItem",
@ -312,12 +311,11 @@ export default {
this.isXpack = true; this.isXpack = true;
} }
if (this.apiCase.request && this.apiCase.request.hashTree && this.apiCase.request.hashTree.length > 0) { if (this.apiCase.request && this.apiCase.request.hashTree && this.apiCase.request.hashTree.length > 0) {
this.apiCase.request.hashTree.forEach(item => { let index = this.apiCase.request.hashTree.findIndex(item => item.type === 'Assertions');
if (item.type === 'Assertions') { if (index !== -1) {
item.document.nodeType = 'Case'; this.apiCase.request.hashTree[index].document.nodeType = 'Case';
item.document.apiDefinitionId = this.apiCase.apiDefinitionId; this.apiCase.request.hashTree[index].document.apiDefinitionId = this.apiCase.apiDefinitionId;
} }
})
} }
this.readonly = !hasPermission('PROJECT_API_DEFINITION:READ+EDIT_CASE'); this.readonly = !hasPermission('PROJECT_API_DEFINITION:READ+EDIT_CASE');
if (this.apiCase && this.apiCase.id) { if (this.apiCase && this.apiCase.id) {
@ -431,11 +429,12 @@ export default {
}); });
}, },
singleRun(data) { singleRun(data) {
let methods =["SQL","DUBBO","dubbo://","TCP" ]; let methods = ["SQL", "DUBBO", "dubbo://", "TCP"];
if (data.apiMethod && methods.indexOf(data.apiMethod) === -1 && !this.environment) { if (data.apiMethod && methods.indexOf(data.apiMethod) === -1 && !this.environment) {
this.$warning(this.$t('api_test.environment.select_environment')); this.$warning(this.$t('api_test.environment.select_environment'));
return; return;
} }
mergeRequestDocumentData(data.request);
if (data.apiMethod !== "SQL" && data.apiMethod !== "DUBBO" && data.apiMethod !== "dubbo://" && data.apiMethod !== "TCP") { if (data.apiMethod !== "SQL" && data.apiMethod !== "DUBBO" && data.apiMethod !== "dubbo://" && data.apiMethod !== "TCP") {
data.request.useEnvironment = this.environment; data.request.useEnvironment = this.environment;
} else { } else {
@ -614,6 +613,7 @@ export default {
if (this.validate(row)) { if (this.validate(row)) {
return; return;
} }
mergeRequestDocumentData(this.apiCase.request);
this.compare = []; this.compare = [];
if (this.compare.indexOf(row.id) === -1) { if (this.compare.indexOf(row.id) === -1) {
this.compare.push(row.id); this.compare.push(row.id);

View File

@ -2,7 +2,8 @@
<div class="card-container"> <div class="card-container">
<el-card class="card-content"> <el-card class="card-content">
<el-button size="small" type="primary" class="ms-api-button" style="float: right;margin-right: 20px" @click="stop" v-if="isStop"> <el-button size="small" type="primary" class="ms-api-button" style="float: right;margin-right: 20px" @click="stop"
v-if="isStop">
{{ $t('report.stop_btn') }} {{ $t('report.stop_btn') }}
</el-button> </el-button>
<div v-else> <div v-else>
@ -23,13 +24,17 @@
<ms-basis-parameters :request="request" ref="requestForm"/> <ms-basis-parameters :request="request" ref="requestForm"/>
<!-- 请求返回数据 --> <!-- 请求返回数据 -->
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<ms-request-result-tail v-if="!loading" :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/> <ms-request-result-tail v-if="!loading" :response="responseData" :currentProtocol="currentProtocol"
ref="debugResult"/>
</div> </div>
<!-- 执行组件 --> <!-- 执行组件 -->
<ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh" ref="runTest"/> <ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh"
ref="runTest"/>
</el-card> </el-card>
<div v-if="scenario"> <div v-if="scenario">
<el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')"> {{ $t('commons.save') }}</el-button> <el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')">
{{ $t('commons.save') }}
</el-button>
</div> </div>
<!-- 加载用例 --> <!-- 加载用例 -->
<ms-api-case-list @refreshModule="refreshModule" :loaded="false" ref="caseList"/> <ms-api-case-list @refreshModule="refreshModule" :loaded="false" ref="caseList"/>
@ -49,6 +54,7 @@ import MsRequestResultTail from "../response/RequestResultTail";
import MsBasisParameters from "../request/dubbo/BasisParameters"; import MsBasisParameters from "../request/dubbo/BasisParameters";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "ApiConfig", name: "ApiConfig",
@ -117,6 +123,7 @@ export default {
}, },
methods: { methods: {
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.request);
if (e === "save_as") { if (e === "save_as") {
this.saveAs(); this.saveAs();
} else if (e === 'save_as_api') { } else if (e === 'save_as_api') {

View File

@ -23,7 +23,10 @@
@command="handleCommand" size="small" v-if="testCase===undefined && !scenario"> @command="handleCommand" size="small" v-if="testCase===undefined && !scenario">
{{ $t('commons.test') }} {{ $t('commons.test') }}
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="save_as">{{ $t('api_test.definition.request.save_as_case') }}</el-dropdown-item> <el-dropdown-item command="save_as">{{
$t('api_test.definition.request.save_as_case')
}}
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<el-button v-if="scenario" size="small" type="primary" @click="handleCommand"> <el-button v-if="scenario" size="small" type="primary" @click="handleCommand">
@ -41,18 +44,22 @@
<div v-loading="loading"> <div v-loading="loading">
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<!-- HTTP 请求参数 --> <!-- HTTP 请求参数 -->
<ms-api-request-form :isShowEnable="true" :definition-test="true" :headers="request.headers" :request="request" :response="responseData" ref="apiRequestForm"/> <ms-api-request-form :isShowEnable="true" :definition-test="true" :headers="request.headers" :request="request"
:response="responseData" ref="apiRequestForm"/>
<!-- HTTP 请求返回数据 --> <!-- HTTP 请求返回数据 -->
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<ms-request-result-tail v-if="!loading" :response="responseData" ref="debugResult"/> <ms-request-result-tail v-if="!loading" :response="responseData" ref="debugResult"/>
<!-- 执行组件 --> <!-- 执行组件 -->
<ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh" ref="runTest"/> <ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh"
ref="runTest"/>
</div> </div>
</el-card> </el-card>
<div v-if="scenario"> <div v-if="scenario">
<el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')"> {{ $t('commons.save') }}</el-button> <el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')">
{{ $t('commons.save') }}
</el-button>
</div> </div>
<!-- 加载用例 --> <!-- 加载用例 -->
<ms-api-case-list :currentApi="debugForm" @refreshModule="refreshModule" :loaded="false" ref="caseList"/> <ms-api-case-list :currentApi="debugForm" @refreshModule="refreshModule" :loaded="false" ref="caseList"/>
@ -72,6 +79,7 @@ import MsRequestResultTail from "../response/RequestResultTail";
import {KeyValue} from "../../model/ApiTestModel"; import {KeyValue} from "../../model/ApiTestModel";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "ApiConfig", name: "ApiConfig",
@ -157,6 +165,7 @@ export default {
this.$refs.apiRequestForm.generate(); this.$refs.apiRequestForm.generate();
}, },
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.request);
if (e === "save_as") { if (e === "save_as") {
this.saveAs(); this.saveAs();
} else if (e === 'save_as_api') { } else if (e === 'save_as_api') {
@ -198,7 +207,7 @@ export default {
this.responseData = data; this.responseData = data;
this.loading = false; this.loading = false;
this.isStop = false; this.isStop = false;
if(this.$refs.debugResult) { if (this.$refs.debugResult) {
this.$refs.debugResult.reload(); this.$refs.debugResult.reload();
} }
}, },

View File

@ -2,7 +2,8 @@
<div class="card-container"> <div class="card-container">
<el-card class="card-content"> <el-card class="card-content">
<el-button size="small" type="primary" class="ms-api-button" style="float: right;margin-right: 20px" @click="stop" v-if="isStop"> <el-button size="small" type="primary" class="ms-api-button" style="float: right;margin-right: 20px" @click="stop"
v-if="isStop">
{{ $t('report.stop_btn') }} {{ $t('report.stop_btn') }}
</el-button> </el-button>
<div v-else> <div v-else>
@ -23,14 +24,18 @@
<ms-basis-parameters :request="request" @callback="runDebug" ref="requestForm"/> <ms-basis-parameters :request="request" @callback="runDebug" ref="requestForm"/>
<!-- JDBC 请求返回数据 --> <!-- JDBC 请求返回数据 -->
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<ms-request-result-tail v-if="!loading" :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/> <ms-request-result-tail v-if="!loading" :response="responseData" :currentProtocol="currentProtocol"
ref="debugResult"/>
</div> </div>
<!-- 执行组件 --> <!-- 执行组件 -->
<ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh" ref="runTest"/> <ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh"
ref="runTest"/>
</el-card> </el-card>
<div v-if="scenario"> <div v-if="scenario">
<el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')"> {{ $t('commons.save') }}</el-button> <el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')">
{{ $t('commons.save') }}
</el-button>
</div> </div>
<!-- 加载用例 --> <!-- 加载用例 -->
<ms-api-case-list @refreshModule="refreshModule" :loaded="false" ref="caseList"/> <ms-api-case-list @refreshModule="refreshModule" :loaded="false" ref="caseList"/>
@ -51,6 +56,7 @@ import MsRequestResultTail from "../response/RequestResultTail";
import MsBasisParameters from "../request/database/BasisParameters"; import MsBasisParameters from "../request/database/BasisParameters";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "ApiConfig", name: "ApiConfig",
@ -111,8 +117,8 @@ export default {
} else { } else {
this.request = createComponent("JDBCSampler"); this.request = createComponent("JDBCSampler");
} }
if(!this.request.environmentId){ if (!this.request.environmentId) {
this.request.environmentId = this.$store.state.useEnvironment; this.request.environmentId = this.$store.state.useEnvironment;
} }
}, },
watch: { watch: {
@ -122,6 +128,7 @@ export default {
}, },
methods: { methods: {
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.request);
if (e === "save_as") { if (e === "save_as") {
this.saveAs(); this.saveAs();
} else if (e === 'save_as_api') { } else if (e === 'save_as_api') {

View File

@ -8,7 +8,7 @@
<el-input v-model="request.server" maxlength="300" show-word-limit size="small"/> <el-input v-model="request.server" maxlength="300" show-word-limit size="small"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('api_test.request.tcp.port')" prop="port" label-width="60px"> <el-form-item :label="$t('api_test.request.tcp.port')" prop="port" label-width="60px">
<el-input v-model="request.port" size="small"/> <el-input v-model="request.port" size="small"/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button size="small" type="primary" @click="stop" v-if="isStop"> <el-button size="small" type="primary" @click="stop" v-if="isStop">
@ -35,13 +35,17 @@
<ms-tcp-format-parameters :request="request" @callback="runDebug" ref="requestForm"/> <ms-tcp-format-parameters :request="request" @callback="runDebug" ref="requestForm"/>
<!-- TCP 请求返回数据 --> <!-- TCP 请求返回数据 -->
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<ms-request-result-tail v-if="!loading" :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/> <ms-request-result-tail v-if="!loading" :response="responseData" :currentProtocol="currentProtocol"
ref="debugResult"/>
</div> </div>
<!-- 执行组件 --> <!-- 执行组件 -->
<ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh" ref="runTest"/> <ms-run :debug="true" :reportId="reportId" :isStop="isStop" :run-data="runData" @runRefresh="runRefresh"
ref="runTest"/>
</el-card> </el-card>
<div v-if="scenario"> <div v-if="scenario">
<el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')"> {{ $t('commons.save') }}</el-button> <el-button style="float: right;margin: 20px" type="primary" @click="handleCommand('save_as_api')">
{{ $t('commons.save') }}
</el-button>
</div> </div>
<!-- 加载用例 --> <!-- 加载用例 -->
<ms-api-case-list @refreshModule="refreshModule" :loaded="false" ref="caseList"/> <ms-api-case-list @refreshModule="refreshModule" :loaded="false" ref="caseList"/>
@ -63,6 +67,7 @@ import MsRequestResultTail from "../response/RequestResultTail";
import MsTcpFormatParameters from "@/business/components/api/definition/components/request/tcp/TcpFormatParameters"; import MsTcpFormatParameters from "@/business/components/api/definition/components/request/tcp/TcpFormatParameters";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "ApiConfig", name: "ApiConfig",
@ -126,6 +131,7 @@ export default {
}, },
methods: { methods: {
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.request);
if (e === "save_as") { if (e === "save_as") {
this.saveAs(); this.saveAs();
} else if (e === 'save_as_api') { } else if (e === 'save_as_api') {

View File

@ -33,6 +33,7 @@
operator-width="190px" operator-width="190px"
@refresh="initTable" @refresh="initTable"
ref="caseTable" ref="caseTable"
class="api-case-simple-list"
> >
<ms-table-column <ms-table-column
prop="deleteTime" prop="deleteTime"
@ -1351,4 +1352,9 @@ export default {
.ms-unexecute { .ms-unexecute {
} }
.api-case-simple-list >>> .el-table {
height: calc(100vh - 262px) !important;
}
</style> </style>

View File

@ -61,6 +61,7 @@ import MsRun from "../Run";
import MsBasisParameters from "../request/dubbo/BasisParameters"; import MsBasisParameters from "../request/dubbo/BasisParameters";
import {REQ_METHOD} from "../../model/JsonData"; import {REQ_METHOD} from "../../model/JsonData";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "RunTestDubboPage", name: "RunTestDubboPage",
@ -100,6 +101,7 @@ export default {
props: {apiData: {}, currentProtocol: String, syncTabs: Array, projectId: String}, props: {apiData: {}, currentProtocol: String, syncTabs: Array, projectId: String},
methods: { methods: {
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.request);
switch (e) { switch (e) {
case "load_case": case "load_case":
return this.loadCase(); return this.loadCase();

View File

@ -61,7 +61,8 @@
<div v-loading="loading"> <div v-loading="loading">
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<!-- HTTP 请求参数 --> <!-- HTTP 请求参数 -->
<ms-api-request-form :isShowEnable="true" :definition-test="true" :headers="api.request.headers" :response="responseData" <ms-api-request-form :isShowEnable="true" :definition-test="true" :headers="api.request.headers"
:response="responseData"
v-if="loadRequest" v-if="loadRequest"
:request="api.request" ref="apiRequestForm"/> :request="api.request" ref="apiRequestForm"/>
<!--返回结果--> <!--返回结果-->
@ -98,6 +99,7 @@ import MsRun from "../Run";
import {REQ_METHOD} from "../../model/JsonData"; import {REQ_METHOD} from "../../model/JsonData";
import EnvironmentSelect from "../environment/EnvironmentSelect"; import EnvironmentSelect from "../environment/EnvironmentSelect";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "RunTestHTTPPage", name: "RunTestHTTPPage",
@ -119,7 +121,7 @@ export default {
createCase: "", createCase: "",
currentRequest: {}, currentRequest: {},
refreshSign: "", refreshSign: "",
loadCaseConfirmButton:this.$t("commons.confirm"), loadCaseConfirmButton: this.$t("commons.confirm"),
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []}, responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
reqOptions: REQ_METHOD, reqOptions: REQ_METHOD,
rules: { rules: {
@ -201,6 +203,7 @@ export default {
}) })
}, },
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.api.request);
switch (e) { switch (e) {
case "load_case": case "load_case":
return this.loadCase(); return this.loadCase();

View File

@ -61,6 +61,7 @@ import MsRun from "../Run";
import MsBasisParameters from "../request/database/BasisParameters"; import MsBasisParameters from "../request/database/BasisParameters";
import {REQ_METHOD} from "../../model/JsonData"; import {REQ_METHOD} from "../../model/JsonData";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
export default { export default {
name: "RunTestSQLPage", name: "RunTestSQLPage",
@ -100,6 +101,7 @@ export default {
props: {apiData: {}, currentProtocol: String, syncTabs: Array, projectId: String}, props: {apiData: {}, currentProtocol: String, syncTabs: Array, projectId: String},
methods: { methods: {
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.api.request);
switch (e) { switch (e) {
case "load_case": case "load_case":
return this.loadCase(); return this.loadCase();
@ -290,13 +292,13 @@ export default {
created() { created() {
// //
this.api = JSON.parse(JSON.stringify(this.apiData)); this.api = JSON.parse(JSON.stringify(this.apiData));
if(!this.api.environmentId){ if (!this.api.environmentId) {
this.api.environmentId = this.$store.state.useEnvironment; this.api.environmentId = this.$store.state.useEnvironment;
} }
this.api.protocol = this.currentProtocol; this.api.protocol = this.currentProtocol;
this.currentRequest = this.api.request; this.currentRequest = this.api.request;
if(!this.currentRequest.environmentId){ if (!this.currentRequest.environmentId) {
this.currentRequest.environmentId = this.$store.state.useEnvironment; this.currentRequest.environmentId = this.$store.state.useEnvironment;
} }
this.runLoading = false; this.runLoading = false;
this.getEnvironments(); this.getEnvironments();

View File

@ -84,6 +84,7 @@ import MsTcpFormatParameters from "@/business/components/api/definition/componen
import {REQ_METHOD} from "../../model/JsonData"; import {REQ_METHOD} from "../../model/JsonData";
import EnvironmentSelect from "../environment/EnvironmentSelect"; import EnvironmentSelect from "../environment/EnvironmentSelect";
import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/); const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const esbDefinition = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {}; const esbDefinition = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {};
@ -128,7 +129,7 @@ export default {
props: {apiData: {}, currentProtocol: String, syncTabs: Array, projectId: String}, props: {apiData: {}, currentProtocol: String, syncTabs: Array, projectId: String},
watch: { watch: {
'$store.state.useEnvironment': function () { '$store.state.useEnvironment': function () {
if(this.api && this.api.request) { if (this.api && this.api.request) {
this.api.request.useEnvironment = this.$store.state.useEnvironment; this.api.request.useEnvironment = this.$store.state.useEnvironment;
} }
this.api.environmentId = this.$store.state.useEnvironment; this.api.environmentId = this.$store.state.useEnvironment;
@ -168,6 +169,7 @@ export default {
} }
}, },
handleCommand(e) { handleCommand(e) {
mergeRequestDocumentData(this.api.request);
switch (e) { switch (e) {
case "load_case": case "load_case":
return this.loadCase(); return this.loadCase();
@ -339,7 +341,7 @@ export default {
if (requireComponent != null && JSON.stringify(esbDefinition) !== '{}') { if (requireComponent != null && JSON.stringify(esbDefinition) !== '{}') {
this.showXpackCompnent = true; this.showXpackCompnent = true;
} }
if(this.api.environmentId) { if (this.api.environmentId) {
this.api.request.useEnvironment = this.api.environmentId; this.api.request.useEnvironment = this.api.environmentId;
} }
this.checkVersionEnable(); this.checkVersionEnable();

View File

@ -12,7 +12,6 @@ import {
HTTPsamplerFiles, HTTPsamplerFiles,
HTTPSamplerProxy, HTTPSamplerProxy,
IfController as JMXIfController, IfController as JMXIfController,
TransactionController as JMXTransactionController,
JDBCDataSource, JDBCDataSource,
JDBCSampler, JDBCSampler,
JSONPathAssertion, JSONPathAssertion,
@ -782,7 +781,7 @@ export class Assertions extends BaseConfig {
this.xpath2 = []; this.xpath2 = [];
this.duration = undefined; this.duration = undefined;
this.enable = true; this.enable = true;
this.document = {type: "JSON", data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}}; this.document = {type: "JSON", data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}, enable: true};
this.set(options); this.set(options);
this.sets({text: Text, regex: Regex, jsonPath: JSONPath, jsr223: AssertionJSR223, xpath2: XPath2}, options); this.sets({text: Text, regex: Regex, jsonPath: JSONPath, jsr223: AssertionJSR223, xpath2: XPath2}, options);
} }
@ -1131,7 +1130,7 @@ export class TransactionController extends Controller {
this.type = "TransactionController"; this.type = "TransactionController";
this.name; this.name;
this.hashTree = []; this.hashTree = [];
this.generateParentSample =true; this.generateParentSample = true;
this.includeTimers = true; this.includeTimers = true;
this.set(options); this.set(options);