This commit is contained in:
chenjianxing 2020-12-23 17:21:47 +08:00
commit 576b858977
4 changed files with 103 additions and 256 deletions

View File

@ -31,6 +31,7 @@ public class ApiAutomationController {
@PostMapping("/list/{goPage}/{pageSize}") @PostMapping("/list/{goPage}/{pageSize}")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
public Pager<List<ApiScenarioDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiScenarioRequest request) { public Pager<List<ApiScenarioDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiScenarioRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId()); request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());

View File

@ -226,6 +226,7 @@
}, },
reductionApi(row) { reductionApi(row) {
row.scenarioDefinition = null; row.scenarioDefinition = null;
row.tags = null;
let rows = [row]; let rows = [row];
this.$post("/api/automation/reduction", rows, response => { this.$post("/api/automation/reduction", rows, response => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));

View File

@ -224,7 +224,7 @@
</div> </div>
<!--接口列表--> <!--接口列表-->
<el-drawer :visible.sync="apiListVisible" :destroy-on-close="true" direction="ltr" :withHeader="true" :modal="false" size="90%"> <el-drawer :visible.sync="apiListVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :modal="false" size="90%">
<ms-api-definition :visible="visibleRef" :currentRow="currentRow"/> <ms-api-definition :visible="visibleRef" :currentRow="currentRow"/>
<el-button style="float: right;margin: 0px 20px 0px" type="primary" @click="pushApiOrCase('REF')">{{$t('api_test.scenario.reference')}}</el-button> <el-button style="float: right;margin: 0px 20px 0px" type="primary" @click="pushApiOrCase('REF')">{{$t('api_test.scenario.reference')}}</el-button>
<el-button style="float: right;" type="primary" @click="pushApiOrCase('Copy')">{{ $t('commons.copy') }}</el-button> <el-button style="float: right;" type="primary" @click="pushApiOrCase('Copy')">{{ $t('commons.copy') }}</el-button>
@ -839,7 +839,7 @@
} }
.ms-col-one { .ms-col-one {
margin-top: 6px; margin-top: 5px;
} }
.ms-right-buttion { .ms-right-buttion {

View File

@ -4,21 +4,24 @@
<el-header style="width: 100% ;padding: 0px"> <el-header style="width: 100% ;padding: 0px">
<el-card> <el-card>
<el-row> <el-row>
<el-col :span="api.protocol==='HTTP'? 3:5"> <el-col :span="2" class="ms-api-col">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
</el-col>
<el-col :span="api.protocol==='HTTP'? 3:6" class="ms-api-col">
<div class="variable-combine"> {{api.name}}</div> <div class="variable-combine"> {{api.name}}</div>
</el-col> </el-col>
<el-col :span="api.protocol==='HTTP'? 1:3"> <el-col :span="api.protocol==='HTTP'? 1:3" class="ms-api-col">
<el-tag size="mini" :style="{'background-color': getColor(true, api.method), border: getColor(true, api.method)}" class="api-el-tag"> <el-tag size="mini" :style="{'background-color': getColor(true, api.method), border: getColor(true, api.method)}" class="api-el-tag">
{{ api.method}} {{ api.method}}
</el-tag> </el-tag>
</el-col> </el-col>
<el-col :span="api.protocol==='HTTP'? 4:0"> <el-col :span="api.protocol==='HTTP'? 5:0" class="ms-api-col">
<div class="variable-combine" style="margin-left: 10px">{{api.path ===null ? " " : api.path}}</div> <div class="variable-combine" style="margin-left: 10px">{{api.path ===null ? " " : api.path}}</div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2" class="ms-api-col">
<div>{{$t('test_track.plan_view.case_count')}}{{apiCaseList.length}}</div> <div>{{$t('test_track.plan_view.case_count')}}{{apiCaseList.length}}</div>
</el-col> </el-col>
<el-col :span="3"> <el-col :span="4">
<div> <div>
<el-select size="small" :placeholder="$t('api_test.definition.request.grade_info')" v-model="priorityValue" <el-select size="small" :placeholder="$t('api_test.definition.request.grade_info')" v-model="priorityValue"
class="ms-api-header-select" @change="getApiTest"> class="ms-api-header-select" @change="getApiTest">
@ -26,28 +29,7 @@
</el-select> </el-select>
</div> </div>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="4">
<div>
<el-select :disabled="isReadOnly" v-model="environment" size="small" class="ms-api-header-select"
:placeholder="$t('api_test.definition.request.run_env')"
@change="environmentChange" clearable>
<el-option v-for="(environment, index) in environments" :key="index"
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')"
:value="environment.id"/>
<el-button class="environment-button" size="mini" type="primary" @click="openEnvironmentConfig">
{{ $t('api_test.environment.environment_config') }}
</el-button>
<template v-slot:empty>
<div class="empty-environment">
<el-button class="environment-button" size="mini" type="primary" @click="openEnvironmentConfig">
{{ $t('api_test.environment.environment_config') }}
</el-button>
</div>
</template>
</el-select>
</div>
</el-col>
<el-col :span="3">
<div class="ms-api-header-select"> <div class="ms-api-header-select">
<el-input size="small" :placeholder="$t('api_test.definition.request.select_case')" <el-input size="small" :placeholder="$t('api_test.definition.request.select_case')"
v-model="name" @blur="getApiTest"/> v-model="name" @blur="getApiTest"/>
@ -61,76 +43,67 @@
</el-row> </el-row>
</el-card> </el-card>
<!-- 环境 -->
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
</el-header> </el-header>
<!-- 用例部分 --> <!-- 用例部分 -->
<el-main v-loading="loading" style="overflow: auto"> <el-main v-loading="loading" style="overflow: auto;padding: 5px 10px 10px">
<div v-for="(item,index) in apiCaseList" :key="index"> <el-checkbox-group v-model="checkedIndex" @change="handleCheckedChange">
<el-card style="margin-top: 5px"> <div v-for="(item,index) in apiCaseList" :key="index">
<el-row> <el-card style="margin-top: 5px">
<el-col :span="1"> <el-row>
<el-checkbox v-model="item.checked" @change="caseChecked(item)"/> <el-col :span="1" class="ms-api-col">
</el-col> <el-checkbox :key="item.id" :label="index+1"/>
<el-col :span="5"> </el-col>
<div class="el-step__icon is-text ms-api-col"> <el-col :span="3">
<div class="el-step__icon-inner">{{index+1}}</div> <el-select size="small" v-model="item.priority" class="ms-api-select">
</div> <el-option v-for="grd in priority" :key="grd.id" :label="grd.name" :value="grd.id"/>
</el-select>
<label class="ms-api-label">{{$t('test_track.case.priority')}}</label> </el-col>
<el-select size="small" v-model="item.priority" class="ms-api-select"> <el-col :span="14">
<el-option v-for="grd in priority" :key="grd.id" :label="grd.name" :value="grd.id"/> <span v-if="item.type!='create'" style="color: #303132;font-size: 13px">
</el-select> <i class="icon el-icon-arrow-right" :class="{'is-active': item.active}"
</el-col> @click="active(item)"/>
<el-col :span="14"> {{item.name}}
<i class="icon el-icon-arrow-right" :class="{'is-active': item.active}"
@click="active(item)"/>
<el-input v-if="item.type==='create'" size="small" v-model="item.name" :name="index" :key="index"
class="ms-api-header-select" style="width: 180px"
@blur="saveTestCase(item)"/>
<span v-else>
{{item.type!= 'create' ? item.name:''}}
<i class="el-icon-edit" style="cursor:pointer" @click="showInput(item)"/>
</span>
<div v-if="item.type!='create'" style="color: #999999;font-size: 12px">
<span>
{{item.createTime | timestampFormatDate }}
{{item.createUser}} {{$t('api_test.definition.request.create_info')}}
</span> </span>
<span> <div v-if="item.type!='create'" style="color: #999999;font-size: 12px">
{{item.updateTime | timestampFormatDate }} <span>
{{item.updateUser}} {{$t('api_test.definition.request.update_info')}} {{item.createTime | timestampFormatDate }}
</span> {{item.createUser}} {{$t('api_test.definition.request.create_info')}}
</div> </span>
</el-col> <span>
{{item.updateTime | timestampFormatDate }}
{{item.updateUser}} {{$t('api_test.definition.request.update_info')}}
</span>
</div>
</el-col>
<el-col :span="3"> <el-col :span="6">
<div v-if="item.type!='create'">{{getResult(item.execResult)}}</div> <div v-if="item.type!='create'">{{getResult(item.execResult)}}</div>
<div v-if="item.type!='create'" style="color: #999999;font-size: 12px"> <div v-if="item.type!='create'" style="color: #999999;font-size: 12px">
<span> {{item.updateTime | timestampFormatDate }}</span> <span> {{item.updateTime | timestampFormatDate }}</span>
{{item.updateUser}} {{item.updateUser}}
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<!-- 请求参数--> <!-- 请求参数-->
<el-collapse-transition> <el-collapse-transition>
<div v-if="item.active"> <div v-if="item.active">
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p> <p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<ms-api-request-form :is-read-only="isReadOnly" :headers="item.request.headers " :request="item.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :request="item.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :request="item.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :request="item.request" v-if="api.protocol==='DUBBO'"/>
<!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)">
{{$t('commons.save')}}
</el-button>
</div>
</el-collapse-transition>
</el-card>
</div>
</el-checkbox-group>
<ms-api-request-form :is-read-only="isReadOnly" :headers="item.request.headers " :request="item.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :request="item.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :request="item.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :request="item.request" v-if="api.protocol==='DUBBO'"/>
<!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)">
{{$t('commons.save')}}
</el-button>
</div>
</el-collapse-transition>
</el-card>
</div>
</el-main> </el-main>
</el-container> </el-container>
@ -143,8 +116,6 @@
import MsTipButton from "../../../../common/components/MsTipButton"; import MsTipButton from "../../../../common/components/MsTipButton";
import MsApiRequestForm from "../../../definition/components/request/http/ApiRequestForm"; import MsApiRequestForm from "../../../definition/components/request/http/ApiRequestForm";
import {downloadFile, getUUID, getCurrentProjectID} from "@/common/js/utils"; import {downloadFile, getUUID, getCurrentProjectID} from "@/common/js/utils";
import {parseEnvironment} from "../../../definition/model/EnvironmentModel";
import ApiEnvironmentConfig from "../../../definition/components/environment/ApiEnvironmentConfig";
import {PRIORITY, RESULT_MAP} from "../../../definition/model/JsonData"; import {PRIORITY, RESULT_MAP} from "../../../definition/model/JsonData";
import MsApiAssertions from "../../../definition/components/assertion/ApiAssertions"; import MsApiAssertions from "../../../definition/components/assertion/ApiAssertions";
import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters"; import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters";
@ -159,7 +130,6 @@
MsTag, MsTag,
MsTipButton, MsTipButton,
MsApiRequestForm, MsApiRequestForm,
ApiEnvironmentConfig,
MsApiAssertions, MsApiAssertions,
MsSqlBasisParameters, MsSqlBasisParameters,
MsTcpBasisParameters, MsTcpBasisParameters,
@ -192,8 +162,12 @@
runData: [], runData: [],
reportId: "", reportId: "",
projectId: "", projectId: "",
checkedCases: new Set(),
methodColorMap: new Map(API_METHOD_COLOUR), methodColorMap: new Map(API_METHOD_COLOUR),
checkAll: false,
checkedIndex: [],
isIndeterminate: true
} }
}, },
watch: { watch: {
@ -207,7 +181,6 @@
}, },
created() { created() {
this.projectId = getCurrentProjectID(); this.projectId = getCurrentProjectID();
this.getEnvironments();
this.getApiTest(); this.getApiTest();
}, },
methods: { methods: {
@ -218,11 +191,6 @@
return RESULT_MAP.get("default"); return RESULT_MAP.get("default");
} }
}, },
handleCommand(e) {
if (e === "run") {
this.batchRun();
}
},
showInput(row) { showInput(row) {
row.type = "create"; row.type = "create";
row.active = true; row.active = true;
@ -232,112 +200,12 @@
this.apiCaseList = []; this.apiCaseList = [];
this.$emit('apiCaseClose'); this.$emit('apiCaseClose');
}, },
batchRun() {
if (!this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.loading = true;
if (this.apiCaseList.length > 0) {
this.apiCaseList.forEach(item => {
if (item.type != "create") {
item.request.name = item.id;
item.request.useEnvironment = this.environment.id;
this.runData.push(item.request);
}
})
this.loading = true;
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
} else {
this.$warning("没有可执行的用例!");
}
},
singleRun(row) {
if (!this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.runData = [];
this.loading = true;
row.request.name = row.id;
row.request.useEnvironment = this.environment.id;
this.runData.push(row.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
},
runRefresh(data) {
this.loading = false;
this.$success(this.$t('schedule.event_success'));
this.getApiTest();
this.$emit('refresh');
},
deleteCase(index, row) {
this.$get('/api/testcase/delete/' + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.apiCaseList.splice(index, 1);
this.$emit('refresh');
});
},
copyCase(data) {
let obj = {name: data.name, priority: data.priority, type: 'create', active: false, request: data.request};
this.apiCaseList.unshift(obj);
},
addCase() {
//
let request = {};
if (this.api.request instanceof Object) {
request = this.api.request;
} else {
request = JSON.parse(this.api.request);
}
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', type: 'create', active: false};
obj.request = request;
this.apiCaseList.unshift(obj);
},
active(item) { active(item) {
item.active = !item.active; item.active = !item.active;
}, },
getBodyUploadFiles(row) {
let bodyUploadFiles = [];
row.bodyUploadIds = [];
let request = row.request;
if (request.body && request.body.kvs) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
row.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
if (request.body.binary) {
request.body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
row.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
return bodyUploadFiles;
},
getApiTest() { getApiTest() {
if (this.api) { if (this.api) {
this.checkedCases = new Set();
this.loading = true; this.loading = true;
if (this.currentRow) { if (this.currentRow) {
this.currentRow.cases = []; this.currentRow.cases = [];
@ -364,61 +232,40 @@
return true; return true;
} }
}, },
getEnvironments() {
if (this.projectId) {
this.$get('/api/environment/list/' + this.projectId, response => {
this.environments = response.data;
this.environments.forEach(environment => {
parseEnvironment(environment);
});
let hasEnvironment = false;
for (let i in this.environments) {
if (this.api && this.environments[i].id === this.api.environmentId) {
hasEnvironment = true;
break;
}
}
if (!hasEnvironment) {
this.environment = undefined;
}
});
} else {
this.environment = undefined;
}
},
openEnvironmentConfig() {
if (!this.projectId) {
this.$error(this.$t('api_test.select_project'));
return;
}
this.$refs.environmentConfig.open(this.projectId);
},
environmentChange(value) {
for (let i in this.environments) {
if (this.environments[i].id === value) {
this.environment = this.environments[i];
break;
}
}
},
environmentConfigClose() {
this.getEnvironments();
},
getColor(enable, method) { getColor(enable, method) {
if (enable) { if (enable) {
return this.methodColorMap.get(method); return this.methodColorMap.get(method);
} }
}, },
caseChecked(row) { handleCheckAllChange(val) {
row.protocol = this.api.protocol; this.currentRow.cases = [];
row.hashTree = []; if (val) {
if (this.checkedCases.has(row)) { let index = 1;
this.checkedCases.delete(row); this.apiCaseList.forEach(item => {
this.checkedIndex.push(index);
item.protocol = this.api.protocol;
item.hashTree = [];
this.currentRow.cases.push(item)
index++;
})
} else { } else {
this.checkedCases.add(row) this.checkedIndex = [];
} }
let arr = Array.from(this.checkedCases); this.isIndeterminate = false;
this.currentRow.cases = arr; },
handleCheckedChange(value) {
let checkedCount = value.length;
this.checkAll = checkedCount === this.apiCaseList.length;
this.isIndeterminate = checkedCount > 0 && checkedCount < this.apiCaseList.length;
this.currentRow.cases = [];
value.forEach(i => {
let index = i - 1;
let item = this.apiCaseList[index];
item.protocol = this.api.protocol;
item.hashTree = [];
this.currentRow.cases.push(item);
})
} }
} }
} }
@ -449,14 +296,11 @@
} }
.ms-api-label { .ms-api-label {
color: #CCCCCC; /*color: #CCCCCC;*/
} }
.ms-api-col { .ms-api-col {
background-color: #7C3985; margin-top: 5px;
border-color: #7C3985;
margin-right: 10px;
color: white;
} }
.variable-combine { .variable-combine {
@ -486,6 +330,7 @@
.api-el-tag { .api-el-tag {
color: white; color: white;
} }
.is-selected { .is-selected {
background: #EFF7FF; background: #EFF7FF;
} }