提交 2564c813 编写于 作者: C Captain.B

Merge remote-tracking branch 'origin/master'

......@@ -24,6 +24,7 @@ public class ApiTestCaseRequest {
private List<String> moduleIds;
private List<OrderRequest> orders;
private Map<String, List<String>> filters;
private Map<String, Object> combine;
private boolean isSelectThisWeedData;
private long createTime = 0;
}
......@@ -147,6 +147,25 @@
<property name="object" value="${condition}.creator"/>
</include>
</if>
<if test="${condition}.path != null">
and api_definition.path
<include refid="condition">
<property name="object" value="${condition}.path"/>
</include>
</if>
<if test="${condition}.method != null">
and api_definition.method
<include refid="condition">
<property name="object" value="${condition}.method"/>
</include>
</if>
<if test="${condition}.tags != null">
and api_definition.tags
<include refid="condition">
<property name="object" value="${condition}.tags"/>
</include>
</if>
</sql>
<sql id="condition">
......
......@@ -144,7 +144,51 @@
</otherwise>
</choose>
</sql>
<sql id="combine">
<if test='${condition}.name != null and (${name} == null or ${name} == "")'>
and atc.name
<include refid="condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test="${condition}.updateTime != null">
and atc.update_time
<include refid="condition">
<property name="object" value="${condition}.updateTime"/>
</include>
</if>
<if test="${condition}.createTime != null">
and atc.create_time
<include refid="condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.priority != null">
and atc.priority
<include refid="condition">
<property name="object" value="${condition}.priority"/>
</include>
</if>
<if test="${condition}.creator != null">
and atc.user_id
<include refid="condition">
<property name="object" value="${condition}.creator"/>
</include>
</if>
<if test="${condition}.tags != null">
and atc.tags
<include refid="condition">
<property name="object" value="${condition}.tags"/>
</include>
</if>
<if test="${condition}.status != null">
and ader.status
<include refid="condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
</sql>
<select id="list" resultType="io.metersphere.api.dto.definition.ApiTestCaseResult">
select
atc.id,
......@@ -180,6 +224,13 @@
resource_id) as ader
on atc.id = ader.resource_id
<where>
<if test="request.combine != null">
<include refid="combine">
<property name="condition" value="request.combine"/>
<property name="name" value="request.name"/>
</include>
</if>
<if test="request.name != null and request.name!=''">
and atc.name like CONCAT('%', #{request.name},'%')
</if>
......@@ -196,6 +247,14 @@
AND atc.api_definition_id = #{request.apiDefinitionId}
</if>
</where>
<if test="request.orders != null and request.orders.size() > 0">
order by
<foreach collection="request.orders" separator="," item="order">
atc.${order.name} ${order.type}
</foreach>
</if>
</select>
<select id="listSimple" resultType="io.metersphere.api.dto.definition.ApiTestCaseDTO">
......
......@@ -18,19 +18,26 @@
</el-col>
<el-col :span="3">
<div>
<el-select size="small" :placeholder="$t('api_test.definition.request.grade_info')" v-model="condition.priority"
<el-select size="small" :placeholder="$t('api_test.definition.request.grade_order_asc')" v-model="condition.order"
:disabled="isCaseEdit"
class="ms-api-header-select" @change="getApiTest" clearable>
<el-option v-for="grd in priorities" :key="grd.id" :label="grd.name" :value="grd.id"/>
class="ms-api-header-select" @change="search" clearable>
<el-option v-for="grd in priorities" :key="grd.id" :label="$t(grd.label)" :value="grd.id"/>
</el-select>
</div>
</el-col>
<el-col :span="3">
<el-col :span="4">
<div class="ms-api-header-select" style="margin-right: 20px">
<el-input size="small" :placeholder="$t('api_test.definition.request.select_case')"
:disabled="isCaseEdit"
v-model="condition.name" @blur="getApiTest" @keyup.enter.native="getApiTest" />
<el-row>
<el-col :span="12">
<el-input size="small" :placeholder="$t('api_test.definition.request.select_case')"
:disabled="isCaseEdit"
v-model="condition.name" @blur="search" @keyup.enter.native="search"/>
</el-col>
<el-col :span="12">
<el-link type="primary" style="margin-left: 5px" @click="open">{{$t('commons.adv_search.title')}}</el-link>
</el-col>
</el-row>
</div>
</el-col>
......@@ -43,7 +50,7 @@
</div>
</el-col>
<el-col :span="2" v-if="!(isReadOnly || isCaseEdit)">
<el-col :span="1" v-if="!(isReadOnly || isCaseEdit)">
<el-dropdown size="small" split-button type="primary" class="ms-api-header-select" @click="addCase"
@command="handleCommand" v-tester>
+{{$t('api_test.definition.request.case')}}
......@@ -54,6 +61,10 @@
</el-col>
</el-row>
</el-card>
<!--高级搜索-->
<ms-table-adv-search-bar :condition.sync="condition" :showLink="false" ref="searchBar" @search="search"/>
</el-header>
</template>
......@@ -64,10 +75,11 @@
import MsTag from "../../../../common/components/MsTag";
import MsEnvironmentSelect from "./MsEnvironmentSelect";
import {API_METHOD_COLOUR} from "../../model/JsonData";
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
export default {
name: "ApiCaseHeader",
components: {MsEnvironmentSelect, MsTag, ApiEnvironmentConfig},
components: {MsEnvironmentSelect, MsTag, ApiEnvironmentConfig, MsTableAdvSearchBar},
data() {
return {
environments: [],
......@@ -86,7 +98,7 @@
type: Object,
default() {
return {}
}
},
}
},
created() {
......@@ -132,9 +144,19 @@
setEnvironment(data) {
this.$emit('setEnvironment', data);
},
getApiTest() {
search() {
if (this.priorities && this.condition.order) {
for (let index in this.priorities) {
if (this.priorities[index].id === this.condition.order) {
this.condition.orders = [this.priorities[index]];
}
}
}
this.$emit('getApiTest');
},
open() {
this.$refs.searchBar.open();
},
addCase() {
this.$emit('addCase');
},
......
......@@ -24,7 +24,7 @@
<label class="ms-api-label" style="padding-left: 20px; padding-right: 20px;">{{ $t('commons.tag') }}</label>
<ms-input-tag :currentScenario="apiCase" ref="tag" style="float: right;margin-right: 215px;margin-top: -3px;"/>
<ms-input-tag :currentScenario="apiCase" ref="tag" style="float: right;margin-right: 215px;margin-top: -3px;" @keyup.enter.native="saveTestCase(apiCase)"/>
<div v-if="apiCase.id" style="color: #999999;font-size: 12px">
<span>
......
......@@ -43,222 +43,225 @@
</template>
<script>
import ApiCaseHeader from "./ApiCaseHeader";
import ApiCaseItem from "./ApiCaseItem";
import MsRun from "../Run";
import {getCurrentProjectID, getUUID} from "@/common/js/utils";
import MsDrawer from "../../../../common/components/MsDrawer";
import {PRIORITY} from "../../model/JsonData";
import ApiCaseHeader from "./ApiCaseHeader";
import ApiCaseItem from "./ApiCaseItem";
import MsRun from "../Run";
import {getCurrentProjectID, getUUID} from "@/common/js/utils";
import MsDrawer from "../../../../common/components/MsDrawer";
import {CASE_ORDER} from "../../model/JsonData";
import {API_CASE_CONFIGS} from "@/business/components/common/components/search/search-components";
export default {
name: 'ApiCaseList',
components: {
MsDrawer,
MsRun,
ApiCaseHeader,
ApiCaseItem,
},
props: {
createCase: String,
loaded: Boolean,
refreshSign: String,
currentApi: {
type: Object
export default {
name: 'ApiCaseList',
components: {
MsDrawer,
MsRun,
ApiCaseHeader,
ApiCaseItem,
},
},
data() {
return {
result: {},
grades: [],
environment: {},
isReadOnly: false,
selectedEvent: Object,
priorities: PRIORITY,
apiCaseList: [],
batchLoading: false,
singleLoading: false,
singleRunId: "",
runData: [],
reportId: "",
projectId: "",
testCaseId: "",
checkedCases: new Set(),
visible: false,
condition: {},
api: {}
}
},
watch: {
refreshSign() {
this.api = this.currentApi;
this.getApiTest();
props: {
createCase: String,
loaded: Boolean,
refreshSign: String,
currentApi: {
type: Object
},
},
createCase() {
this.api = this.currentApi;
this.sysAddition();
}
},
created() {
this.api = this.currentApi;
this.projectId = getCurrentProjectID();
if (this.createCase) {
this.sysAddition();
} else {
this.getApiTest();
}
},
computed: {
isCaseEdit() {
return this.testCaseId ? true : false;
}
},
methods: {
open(api, testCaseId) {
this.api = api;
// testCaseId 不为空则为用例编辑页面
this.testCaseId = testCaseId;
this.getApiTest();
this.visible = true;
},
setEnvironment(environment) {
this.environment = environment;
},
sysAddition() {
this.condition.projectId = this.projectId;
this.condition.apiDefinitionId = this.api.id;
this.$post("/api/testcase/list", this.condition, response => {
for (let index in response.data) {
let test = response.data[index];
test.request = JSON.parse(test.request);
}
this.apiCaseList = response.data;
this.addCase();
});
data() {
return {
result: {},
grades: [],
environment: {},
isReadOnly: false,
selectedEvent: Object,
priorities: CASE_ORDER,
apiCaseList: [],
batchLoading: false,
singleLoading: false,
singleRunId: "",
runData: [],
reportId: "",
projectId: "",
testCaseId: "",
checkedCases: new Set(),
visible: false,
condition: {
components: API_CASE_CONFIGS
},
api: {}
}
},
apiCaseClose() {
this.apiCaseList = [];
this.visible = false;
watch: {
refreshSign() {
this.api = this.currentApi;
this.getApiTest();
},
createCase() {
this.api = this.currentApi;
this.sysAddition();
}
},
runRefresh(data) {
this.batchLoading = false;
this.singleLoading = false;
this.singleRunId = "";
this.$success(this.$t('schedule.event_success'));
this.getApiTest();
this.$emit('refresh');
created() {
this.api = this.currentApi;
this.projectId = getCurrentProjectID();
if (this.createCase) {
this.sysAddition();
} else {
this.getApiTest();
}
},
refresh(data) {
this.getApiTest();
this.$emit('refresh');
computed: {
isCaseEdit() {
return this.testCaseId ? true : false;
}
},
getApiTest() {
if (this.api) {
methods: {
open(api, testCaseId) {
this.api = api;
// testCaseId 不为空则为用例编辑页面
this.testCaseId = testCaseId;
this.condition = {components: API_CASE_CONFIGS};
this.getApiTest();
this.visible = true;
},
setEnvironment(environment) {
this.environment = environment;
},
sysAddition() {
this.condition.projectId = this.projectId;
if (this.isCaseEdit) {
this.condition.id = this.testCaseId;
} else {
this.condition.apiDefinitionId = this.api.id;
}
this.result = this.$post("/api/testcase/list", this.condition, response => {
this.condition.apiDefinitionId = this.api.id;
this.$post("/api/testcase/list", this.condition, response => {
for (let index in response.data) {
let test = response.data[index];
test.request = JSON.parse(test.request);
if (!test.request.hashTree) {
test.request.hashTree = [];
}
}
this.apiCaseList = response.data;
if (this.apiCaseList.length == 0 && !this.loaded) {
this.addCase();
this.addCase();
});
},
apiCaseClose() {
this.apiCaseList = [];
this.visible = false;
},
runRefresh(data) {
this.batchLoading = false;
this.singleLoading = false;
this.singleRunId = "";
this.$success(this.$t('schedule.event_success'));
this.getApiTest();
this.$emit('refresh');
},
refresh(data) {
this.getApiTest();
this.$emit('refresh');
},
getApiTest() {
if (this.api) {
this.condition.projectId = this.projectId;
if (this.isCaseEdit) {
this.condition.id = this.testCaseId;
} else {
this.condition.apiDefinitionId = this.api.id;
}
this.apiCaseList.forEach(apiCase => {
if (apiCase.tags && apiCase.tags.length > 0) {
apiCase.tags = JSON.parse(apiCase.tags);
this.result = this.$post("/api/testcase/list", this.condition, response => {
for (let index in response.data) {
let test = response.data[index];
test.request = JSON.parse(test.request);
if (!test.request.hashTree) {
test.request.hashTree = [];
}
}
})
this.apiCaseList = response.data;
// if (this.apiCaseList.length == 0 && !this.loaded) {
// this.addCase();
// }
this.apiCaseList.forEach(apiCase => {
if (apiCase.tags && apiCase.tags.length > 0) {
apiCase.tags = JSON.parse(apiCase.tags);
}
})
});
}
},
addCase() {
if (this.api.request) {
// 初始化对象
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', active: true, tags: []};
obj.request = request;
this.apiCaseList.unshift(obj);
}
},
},
addCase() {
if (this.api.request) {
// 初始化对象
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', active: true, tags: []};
obj.request = request;
this.apiCaseList.unshift(obj);
}
},
copyCase(data) {
this.apiCaseList.unshift(data);
},
copyCase(data) {
this.apiCaseList.unshift(data);
},
handleClose() {
this.visible = false;
},
showExecResult(row) {
this.visible = false;
this.$emit('showExecResult', row);
},
handleClose() {
this.visible = false;
},
showExecResult(row) {
this.visible = false;
this.$emit('showExecResult', row);
},
singleRun(row) {
if (!this.environment || !this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.runData = [];
this.singleLoading = true;
this.singleRunId = row.id;
row.request.name = row.id;
row.request.useEnvironment = this.environment.id;
this.runData.push(row.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
},
singleRun(row) {
if (!this.environment || !this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.runData = [];
this.singleLoading = true;
this.singleRunId = row.id;
row.request.name = row.id;
row.request.useEnvironment = this.environment.id;
this.runData.push(row.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
},
batchRun() {
if (!this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
if (this.apiCaseList.length > 0) {
this.apiCaseList.forEach(item => {
if (item.id) {
item.request.name = item.id;
item.request.useEnvironment = this.environment.id;
this.runData.push(item.request);
batchRun() {
if (!this.environment) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
if (this.apiCaseList.length > 0) {
this.apiCaseList.forEach(item => {
if (item.id) {
item.request.name = item.id;
item.request.useEnvironment = this.environment.id;
this.runData.push(item.request);
}
})
if (this.runData.length > 0) {
this.batchLoading = true;
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
} else {
this.$warning("没有可执行的用例!");
}
})
if (this.runData.length > 0) {
this.batchLoading = true;
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
} else {
this.$warning("没有可执行的用例!");
}
} else {
this.$warning("没有可执行的用例!");
}
},
}
}
}
</script>
<style scoped>
.ms-drawer >>> .ms-drawer-body {
margin-top: 80px;
}
.ms-drawer >>> .ms-drawer-body {
margin-top: 80px;
}
</style>
......@@ -6,6 +6,15 @@ export const PRIORITY = [
{name: 'P3', id: 'P3'}
]
export const CASE_ORDER = [
{label: 'api_test.definition.request.grade_order_asc', name: 'priority', type: 'desc', id: 'grade_order_asc'},
{label: 'api_test.definition.request.grade_order_desc', name: 'priority', type: 'asc', id: 'grade_order_desc'},
{label: 'api_test.definition.request.create_time_order_asc', name: 'create_time', type: 'asc', id: 'create_time_order_asc'},
{label: 'api_test.definition.request.create_time_order_desc', name: 'create_time', type: 'desc', id: 'create_time_order_desc'},
{label: 'api_test.definition.request.update_time_order_asc', name: 'update_time', type: 'asc', id: 'update_time_order_asc'},
{label: 'api_test.definition.request.update_time_order_desc', name: 'update_time', type: 'desc', id: 'update_time_order_desc'}
]
export const OPTIONS = [
{value: 'HTTP', name: 'HTTP'},
{value: 'TCP', name: 'TCP'},
......
<template>
<span class="adv-search-bar">
<el-link type="primary" @click="open">{{$t('commons.adv_search.title')}}</el-link>
<el-link type="primary" @click="open" v-if="showLink">{{$t('commons.adv_search.title')}}</el-link>
<el-dialog :title="$t('commons.adv_search.combine')" :visible.sync="visible" custom-class="adv-dialog"
:append-to-body="true">
<div>
......@@ -28,6 +28,10 @@
name: "MsTableAdvSearchBar",
props: {
condition: Object,
showLink: {
type: Boolean,
default: true,
}
},
data() {
return {
......
......@@ -115,6 +115,101 @@ export const STATUS = {
}
}
export const API_STATUS = {
key: "status",
name: 'MsTableSearchSelect',
label: 'commons.status',
operator: {
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: [
{value: 'Prepare', label: '未开始'},
{value: 'Underway', label: '进行中'},
{value: 'Completed', label: '已完成'}
],
props: { // 尾部控件的props,一般为element ui控件的props
multiple: true
}
}
export const API_CASE_PRIORITY = {
key: "priority",
name: 'MsTableSearchSelect',
label: 'test_track.case.priority',
operator: {
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: [
{value: 'P0', label: 'P0'},
{value: 'P1', label: 'P1'},
{value: 'P2', label: 'P2'},
{value: 'P3', label: 'P3'}
],
props: { // 尾部控件的props,一般为element ui控件的props
multiple: true
}
}
export const API_CASE_RESULT = {
key: "status",
name: 'MsTableSearchSelect',
label: 'test_track.plan_view.execute_result',
operator: {
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: [
{value: 'success', label: 'api_test.automation.success'},
{value: 'error', label: 'api_test.automation.fail'}
],
props: { // 尾部控件的props,一般为element ui控件的props
multiple: true
}
}
export const API_METHOD = {
key: "method",
name: 'MsTableSearchSelect',
label: 'api_test.definition.api_type',
operator: {
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: [
{value: 'GET', label: 'GET'},
{value: 'POST', label: 'POST'},
{value: 'PUT', label: 'PUT'},
{value: 'PATCH', label: 'PATCH'},
{value: 'DELETE', label: 'DELETE'},
{value: 'OPTIONS', label: 'OPTIONS'},
{value: 'HEAD', label: 'HEAD'},
{value: 'CONNECT', label: 'CONNECT'},
{value: 'DUBBO', label: 'DUBBO'},
{value: 'dubbo://', label: 'dubbo://'},
{value: 'SQL', label: 'SQL'},
{value: 'TCP', label: 'TCP'}
],
props: { // 尾部控件的props,一般为element ui控件的props
multiple: true
}
}
export const API_PATH = {
key: "path", // 返回结果Map的key
name: 'MsTableSearchInput', // Vue控件名称
label: 'api_test.definition.api_path', // 显示名称
operator: { // 运算符设置
value: OPERATORS.LIKE.value, // 如果未设置value初始值,则value初始值为options[0]
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE] // 运算符候选项
},
}
export const API_TAGS = {
key: "tags", // 返回结果Map的key
name: 'MsTableSearchInput', // Vue控件名称
label: 'commons.tag', // 显示名称
operator: { // 运算符设置
value: OPERATORS.LIKE.value, // 如果未设置value初始值,则value初始值为options[0]
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE] // 运算符候选项
},
}
export const CREATOR = {
key: "creator",
name: 'MsTableSearchSelect',
......@@ -311,10 +406,14 @@ export const TEST_PLAN_STATUS = {
}
};
export const TEST_CONFIGS = [NAME, UPDATE_TIME, PROJECT_NAME, CREATE_TIME, STATUS, CREATOR];
export const TEST_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, STATUS, CREATOR];
export const REPORT_CONFIGS = [NAME, TEST_NAME, PROJECT_NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE];
export const REPORT_CONFIGS = [NAME, TEST_NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE];
export const TEST_CASE_CONFIGS = [NAME, MODULE, PRIORITY, CREATE_TIME, TYPE, UPDATE_TIME, METHOD, CREATOR, EXECUTOR];
export const TEST_PLAN_CONFIGS = [NAME, UPDATE_TIME, PROJECT_NAME, CREATE_TIME, PRINCIPAL, TEST_PLAN_STATUS, STAGE];
export const TEST_PLAN_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, PRINCIPAL, TEST_PLAN_STATUS, STAGE];
export const API_DEFINITION_CONFIGS = [NAME, API_METHOD, API_PATH, API_STATUS, API_TAGS, UPDATE_TIME, CREATE_TIME, CREATOR];
export const API_CASE_CONFIGS = [NAME, API_CASE_PRIORITY, API_TAGS,API_CASE_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR];
......@@ -517,6 +517,12 @@ export default {
},
request: {
grade_info: "Filter by rank",
grade_order_asc: "from high to low by use case level",
grade_order_desc: "from high to low by use case level,",
create_time_order_asc: "by creation time from front to back",
create_time_order_desc: "from back to front by creation time,",
update_time_order_asc: "by update time from front to back",
update_time_order_desc: "from back to front by update time,",
run_env: "Operating environment",
select_case: "Search use cases",
case: "Case",
......
......@@ -515,6 +515,12 @@ export default {
},
request: {
grade_info: "按等级筛选",
grade_order_asc: "按用例等级从高到低",
grade_order_desc: "按用例等级从高到低",
create_time_order_asc: "按创建时间从前到后",
create_time_order_desc: "按创建时间从后到前",
update_time_order_asc: "按更新时间从前到后",
update_time_order_desc: "按更新时间从后到前",
run_env: "运行环境",
select_case: "搜索用例",
case: "用例",
......
......@@ -515,6 +515,12 @@ export default {
},
request: {
grade_info: "按等級篩選",
grade_order_asc: "按用例等級從高到低",
grade_order_desc: "按用例等級從高到低",
create_time_order_asc: "按創建時間從前到後",
create_time_order_desc: "按創建時間從後到前",
update_time_order_asc: "按更新時間從前到後",
update_time_order_desc: "按更新時間從後到前",
run_env: "運行環境",
select_case: "搜索用例",
case: "用例",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册