feat: 接口测试用例保存tag

This commit is contained in:
Captain.B 2021-01-07 15:18:52 +08:00
parent 590e6c9a9c
commit 18340d16e5
11 changed files with 645 additions and 473 deletions

View File

@ -4,6 +4,7 @@ import io.metersphere.api.dto.definition.request.MsTestElement;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Setter
@ -35,4 +36,6 @@ public class SaveApiTestCaseRequest {
private Long updateTime;
private List<String> bodyUploadIds;
private List<String> tags = new ArrayList<>();
}

View File

@ -222,6 +222,7 @@ public class ApiTestCaseService {
test.setPriority(request.getPriority());
test.setUpdateTime(System.currentTimeMillis());
test.setDescription(request.getDescription());
test.setTags(JSON.toJSONString(new HashSet<>(request.getTags())));
apiTestCaseMapper.updateByPrimaryKeySelective(test);
return test;
}
@ -243,6 +244,7 @@ public class ApiTestCaseService {
test.setUpdateTime(System.currentTimeMillis());
test.setDescription(request.getDescription());
test.setNum(getNextNum(request.getApiDefinitionId()));
test.setTags(JSON.toJSONString(new HashSet<>(request.getTags())));
apiTestCaseMapper.insert(test);
return test;
}

View File

@ -1,8 +1,9 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import java.io.Serializable;
@Data
public class ApiTestCase implements Serializable {
private String id;
@ -25,5 +26,7 @@ public class ApiTestCase implements Serializable {
private Integer num;
private String tags;
private static final long serialVersionUID = 1L;
}

View File

@ -773,6 +773,76 @@ public class ApiTestCaseExample {
addCriterion("num not between", value1, value2, "num");
return (Criteria) this;
}
public Criteria andTagsIsNull() {
addCriterion("tags is null");
return (Criteria) this;
}
public Criteria andTagsIsNotNull() {
addCriterion("tags is not null");
return (Criteria) this;
}
public Criteria andTagsEqualTo(String value) {
addCriterion("tags =", value, "tags");
return (Criteria) this;
}
public Criteria andTagsNotEqualTo(String value) {
addCriterion("tags <>", value, "tags");
return (Criteria) this;
}
public Criteria andTagsGreaterThan(String value) {
addCriterion("tags >", value, "tags");
return (Criteria) this;
}
public Criteria andTagsGreaterThanOrEqualTo(String value) {
addCriterion("tags >=", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLessThan(String value) {
addCriterion("tags <", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLessThanOrEqualTo(String value) {
addCriterion("tags <=", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLike(String value) {
addCriterion("tags like", value, "tags");
return (Criteria) this;
}
public Criteria andTagsNotLike(String value) {
addCriterion("tags not like", value, "tags");
return (Criteria) this;
}
public Criteria andTagsIn(List<String> values) {
addCriterion("tags in", values, "tags");
return (Criteria) this;
}
public Criteria andTagsNotIn(List<String> values) {
addCriterion("tags not in", values, "tags");
return (Criteria) this;
}
public Criteria andTagsBetween(String value1, String value2) {
addCriterion("tags between", value1, value2, "tags");
return (Criteria) this;
}
public Criteria andTagsNotBetween(String value1, String value2) {
addCriterion("tags not between", value1, value2, "tags");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -12,6 +12,7 @@
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="num" jdbcType="INTEGER" property="num" />
<result column="tags" jdbcType="VARCHAR" property="tags" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiTestCaseWithBLOBs">
<result column="description" jdbcType="LONGVARCHAR" property="description" />
@ -78,7 +79,7 @@
</sql>
<sql id="Base_Column_List">
id, project_id, `name`, priority, api_definition_id, create_user_id, update_user_id,
create_time, update_time, num
create_time, update_time, num, tags
</sql>
<sql id="Blob_Column_List">
description, request, response
@ -135,13 +136,13 @@
insert into api_test_case (id, project_id, `name`,
priority, api_definition_id, create_user_id,
update_user_id, create_time, update_time,
num, description, request,
response)
num, tags, description,
request, response)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{priority,jdbcType=VARCHAR}, #{apiDefinitionId,jdbcType=VARCHAR}, #{createUserId,jdbcType=VARCHAR},
#{updateUserId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{num,jdbcType=INTEGER}, #{description,jdbcType=LONGVARCHAR}, #{request,jdbcType=LONGVARCHAR},
#{response,jdbcType=LONGVARCHAR})
#{num,jdbcType=INTEGER}, #{tags,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR},
#{request,jdbcType=LONGVARCHAR}, #{response,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiTestCaseWithBLOBs">
insert into api_test_case
@ -176,6 +177,9 @@
<if test="num != null">
num,
</if>
<if test="tags != null">
tags,
</if>
<if test="description != null">
description,
</if>
@ -217,6 +221,9 @@
<if test="num != null">
#{num,jdbcType=INTEGER},
</if>
<if test="tags != null">
#{tags,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=LONGVARCHAR},
</if>
@ -267,6 +274,9 @@
<if test="record.num != null">
num = #{record.num,jdbcType=INTEGER},
</if>
<if test="record.tags != null">
tags = #{record.tags,jdbcType=VARCHAR},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=LONGVARCHAR},
</if>
@ -293,6 +303,7 @@
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
num = #{record.num,jdbcType=INTEGER},
tags = #{record.tags,jdbcType=VARCHAR},
description = #{record.description,jdbcType=LONGVARCHAR},
request = #{record.request,jdbcType=LONGVARCHAR},
response = #{record.response,jdbcType=LONGVARCHAR}
@ -311,7 +322,8 @@
update_user_id = #{record.updateUserId,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
num = #{record.num,jdbcType=INTEGER}
num = #{record.num,jdbcType=INTEGER},
tags = #{record.tags,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -346,6 +358,9 @@
<if test="num != null">
num = #{num,jdbcType=INTEGER},
</if>
<if test="tags != null">
tags = #{tags,jdbcType=VARCHAR},
</if>
<if test="description != null">
description = #{description,jdbcType=LONGVARCHAR},
</if>
@ -369,6 +384,7 @@
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
num = #{num,jdbcType=INTEGER},
tags = #{tags,jdbcType=VARCHAR},
description = #{description,jdbcType=LONGVARCHAR},
request = #{request,jdbcType=LONGVARCHAR},
response = #{response,jdbcType=LONGVARCHAR}
@ -384,7 +400,8 @@
update_user_id = #{updateUserId,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
num = #{num,jdbcType=INTEGER}
num = #{num,jdbcType=INTEGER},
tags = #{tags,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -162,6 +162,7 @@
atc.update_user_id,
atc.update_time,
atc.num,
atc.tags,
ader.status execResult,
ader.create_time execTime
from

View File

@ -1,8 +1,8 @@
ALTER TABLE api_definition
ADD tag VARCHAR(1000) NULL;
ADD tags VARCHAR(1000) NULL;
ALTER TABLE api_test_case
ADD tag VARCHAR(1000) NULL;
ADD tags VARCHAR(1000) NULL;
ALTER TABLE test_case
ADD tag VARCHAR(1000) NULL;
ADD tags VARCHAR(1000) NULL;

View File

@ -1,309 +1,377 @@
<template>
<el-card style="margin-top: 5px" @click.native="selectTestCase(apiCase,$event)">
<el-row>
<el-col :span="6">
<div class="el-step__icon is-text ms-api-col">
<div class="el-step__icon-inner">{{index+1}}</div>
</div>
<el-card style="margin-top: 5px" @click.native="selectTestCase(apiCase,$event)">
<el-row>
<el-col :span="6">
<div class="el-step__icon is-text ms-api-col">
<div class="el-step__icon-inner">{{ index + 1 }}</div>
</div>
<label class="ms-api-label">{{$t('test_track.case.priority')}}</label>
<el-select size="small" v-model="apiCase.priority" class="ms-api-select" @change="changePriority(apiCase)">
<el-option v-for="grd in priorities" :key="grd.id" :label="grd.name" :value="grd.id"/>
</el-select>
</el-col>
<el-col :span="10">
<i class="icon el-icon-arrow-right" :class="{'is-active': apiCase.active}"
@click="active(apiCase)"/>
<el-input v-if="!apiCase.id || isShowInput" size="small" v-model="apiCase.name" :name="index" :key="index"
class="ms-api-header-select" style="width: 180px"
@blur="saveTestCase(apiCase)" placeholder="请输入用例名称"/>
<span v-else>
{{apiCase.id ? apiCase.name:''}}
<label class="ms-api-label">{{ $t('test_track.case.priority') }}</label>
<el-select size="small" v-model="apiCase.priority" class="ms-api-select" @change="changePriority(apiCase)">
<el-option v-for="grd in priorities" :key="grd.id" :label="grd.name" :value="grd.id"/>
</el-select>
</el-col>
<el-col :span="10">
<i class="icon el-icon-arrow-right" :class="{'is-active': apiCase.active}"
@click="active(apiCase)"/>
<el-input v-if="!apiCase.id || isShowInput" size="small" v-model="apiCase.name" :name="index" :key="index"
class="ms-api-header-select" style="width: 180px"
@blur="saveTestCase(apiCase)" placeholder="请输入用例名称"/>
<span v-else>
{{ apiCase.id ? apiCase.name : '' }}
<i class="el-icon-edit" style="cursor:pointer" @click="showInput(apiCase)" v-tester/>
</span>
<div v-if="apiCase.id" style="color: #999999;font-size: 12px">
</span>
<label class="ms-api-label" style="padding-left: 20px; padding-right: 20px;">{{ $t('commons.tag') }}</label>
<el-tag
:key="apiCase.id + '_' + index"
v-for="(tag, index) in apiCase.tags"
closable
size="mini"
:disable-transitions="false"
@close="handleClose(tag)">
{{ tag }}
</el-tag>
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="inputValue"
ref="saveTagInput"
size="mini"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="mini" @click="showTagInput">+</el-button>
<div v-if="apiCase.id" style="color: #999999;font-size: 12px">
<span>
{{apiCase.createTime | timestampFormatDate }}
{{apiCase.createUser}} {{$t('api_test.definition.request.create_info')}}
{{ apiCase.createTime | timestampFormatDate }}
{{ apiCase.createUser }} {{ $t('api_test.definition.request.create_info') }}
</span>
<span>
{{apiCase.updateTime | timestampFormatDate }}
{{apiCase.updateUser}} {{$t('api_test.definition.request.update_info')}}
<span>
{{ apiCase.updateTime | timestampFormatDate }}
{{ apiCase.updateUser }} {{ $t('api_test.definition.request.update_info') }}
</span>
</div>
</el-col>
</div>
</el-col>
<el-col :span="4">
<ms-tip-button @click="singleRun(apiCase)" :tip="$t('api_test.run')" icon="el-icon-video-play"
style="background-color: #409EFF;color: white" size="mini" :disabled="!apiCase.id" circle v-tester/>
<ms-tip-button @click="copyCase(apiCase)" :tip="$t('commons.copy')" icon="el-icon-document-copy"
size="mini" :disabled="!apiCase.id || isCaseEdit" circle v-tester/>
<ms-tip-button @click="deleteCase(index,apiCase)" :tip="$t('commons.delete')" icon="el-icon-delete"
size="mini" :disabled="!apiCase.id || isCaseEdit" circle v-tester/>
<ms-api-extend-btns :is-case-edit="isCaseEdit" :row="apiCase" v-tester/>
</el-col>
<el-col :span="4">
<ms-tip-button @click="singleRun(apiCase)" :tip="$t('api_test.run')" icon="el-icon-video-play"
style="background-color: #409EFF;color: white" size="mini" :disabled="!apiCase.id" circle v-tester/>
<ms-tip-button @click="copyCase(apiCase)" :tip="$t('commons.copy')" icon="el-icon-document-copy"
size="mini" :disabled="!apiCase.id || isCaseEdit" circle v-tester/>
<ms-tip-button @click="deleteCase(index,apiCase)" :tip="$t('commons.delete')" icon="el-icon-delete"
size="mini" :disabled="!apiCase.id || isCaseEdit" circle v-tester/>
<ms-api-extend-btns :is-case-edit="isCaseEdit" :row="apiCase" v-tester/>
</el-col>
<el-col :span="3">
<el-link type="danger" v-if="apiCase.execResult && apiCase.execResult==='error'" @click="showExecResult(apiCase)">{{getResult(apiCase.execResult)}}</el-link>
<el-link v-else-if="apiCase.execResult && apiCase.execResult==='success'" @click="showExecResult(apiCase)">{{getResult(apiCase.execResult)}}</el-link>
<div v-else> {{getResult(apiCase.execResult)}}</div>
<el-col :span="3">
<el-link type="danger" v-if="apiCase.execResult && apiCase.execResult==='error'" @click="showExecResult(apiCase)">
{{ getResult(apiCase.execResult) }}
</el-link>
<el-link v-else-if="apiCase.execResult && apiCase.execResult==='success'" @click="showExecResult(apiCase)">
{{ getResult(apiCase.execResult) }}
</el-link>
<div v-else> {{ getResult(apiCase.execResult) }}</div>
<div v-if="apiCase.id" style="color: #999999;font-size: 12px">
<span> {{apiCase.execTime | timestampFormatDate }}</span>
{{apiCase.updateUser}}
</div>
</el-col>
</el-row>
<!-- 请求参数-->
<el-collapse-transition>
<div v-if="apiCase.active">
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<div v-if="apiCase.id" style="color: #999999;font-size: 12px">
<span> {{ apiCase.execTime | timestampFormatDate }}</span>
{{ apiCase.updateUser }}
</div>
</el-col>
</el-row>
<!-- 请求参数-->
<el-collapse-transition>
<div v-if="apiCase.active">
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :request="apiCase.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :request="apiCase.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :request="apiCase.request" v-if="api.protocol==='DUBBO'"/>
<!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(apiCase)" v-tester>
{{$t('commons.save')}}
</el-button>
</div>
</el-collapse-transition>
</el-card>
<ms-api-request-form :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :request="apiCase.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :request="apiCase.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :request="apiCase.request" v-if="api.protocol==='DUBBO'"/>
<!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(apiCase)" v-tester>
{{ $t('commons.save') }}
</el-button>
</div>
</el-collapse-transition>
</el-card>
</template>
<script>
import {getCurrentProjectID, getUUID} from "../../../../../../common/js/utils";
import {PRIORITY, RESULT_MAP} from "../../model/JsonData";
import MsTag from "../../../../common/components/MsTag";
import MsTipButton from "../../../../common/components/MsTipButton";
import MsApiRequestForm from "../request/http/ApiRequestForm";
import ApiEnvironmentConfig from "../environment/ApiEnvironmentConfig";
import MsApiAssertions from "../assertion/ApiAssertions";
import MsSqlBasisParameters from "../request/database/BasisParameters";
import MsTcpBasisParameters from "../request/tcp/BasisParameters";
import MsDubboBasisParameters from "../request/dubbo/BasisParameters";
import MsApiExtendBtns from "../reference/ApiExtendBtns";
import {getCurrentProjectID, getUUID} from "../../../../../../common/js/utils";
import {PRIORITY, RESULT_MAP} from "../../model/JsonData";
import MsTag from "../../../../common/components/MsTag";
import MsTipButton from "../../../../common/components/MsTipButton";
import MsApiRequestForm from "../request/http/ApiRequestForm";
import ApiEnvironmentConfig from "../environment/ApiEnvironmentConfig";
import MsApiAssertions from "../assertion/ApiAssertions";
import MsSqlBasisParameters from "../request/database/BasisParameters";
import MsTcpBasisParameters from "../request/tcp/BasisParameters";
import MsDubboBasisParameters from "../request/dubbo/BasisParameters";
import MsApiExtendBtns from "../reference/ApiExtendBtns";
export default {
name: "ApiCaseItem",
components: {
MsTag,
MsTipButton,
MsApiRequestForm,
ApiEnvironmentConfig,
MsApiAssertions,
MsSqlBasisParameters,
MsTcpBasisParameters,
MsDubboBasisParameters,
MsApiExtendBtns
export default {
name: "ApiCaseItem",
components: {
MsTag,
MsTipButton,
MsApiRequestForm,
ApiEnvironmentConfig,
MsApiAssertions,
MsSqlBasisParameters,
MsTcpBasisParameters,
MsDubboBasisParameters,
MsApiExtendBtns
},
data() {
return {
result: {},
grades: [],
environment: {},
isReadOnly: false,
selectedEvent: Object,
priorities: PRIORITY,
runData: [],
reportId: "",
checkedCases: new Set(),
visible: false,
condition: {},
isShowInput: false,
inputVisible: false,
inputValue: ''
}
},
props: {
apiCase: {
type: Object,
default() {
return {}
}
},
data() {
return {
result: {},
grades: [],
environment: {},
isReadOnly: false,
selectedEvent: Object,
priorities: PRIORITY,
runData: [],
reportId: "",
checkedCases: new Set(),
visible: false,
condition: {},
isShowInput: false
index: {
type: Number,
default() {
return 0
}
},
api: {
type: Object,
default() {
return {}
}
},
isCaseEdit: Boolean,
},
watch: {},
methods: {
deleteCase(index, row) {
this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this.$get('/api/testcase/delete/' + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.$emit('refresh');
});
}
}
},
props: {
apiCase: {
type: Object,
default() {
return {}
}
},
index: {
type: Number,
default() {
return 0
}
},
api: {
type: Object,
default() {
return {}
}
},
isCaseEdit: Boolean,
},
watch: {
},
methods: {
});
deleteCase(index, row) {
this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this.$get('/api/testcase/delete/' + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.$emit('refresh');
});
}
}
});
},
singleRun(data) {
this.$emit('singleRun', data);
},
copyCase(data) {
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, request: data.request};
this.$emit('copyCase', obj);
},
},
singleRun(data) {
this.$emit('singleRun', data);
},
copyCase(data) {
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, request: data.request};
this.$emit('copyCase', obj);
},
selectTestCase(item, $event) {
if (!item.id || !this.loaded) {
return;
}
if ($event.currentTarget.className.indexOf('is-selected') > 0) {
$event.currentTarget.className = "el-card is-always-shadow";
this.$emit('selectTestCase', null);
} else {
if (this.selectedEvent.currentTarget != undefined) {
this.selectedEvent.currentTarget.className = "el-card is-always-shadow";
}
this.selectedEvent.currentTarget = $event.currentTarget;
$event.currentTarget.className = "el-card is-always-shadow is-selected";
this.$emit('selectTestCase', item);
}
selectTestCase(item, $event) {
if (!item.id || !this.loaded) {
return;
}
if ($event.currentTarget.className.indexOf('is-selected') > 0) {
$event.currentTarget.className = "el-card is-always-shadow";
this.$emit('selectTestCase', null);
} else {
if (this.selectedEvent.currentTarget != undefined) {
this.selectedEvent.currentTarget.className = "el-card is-always-shadow";
}
this.selectedEvent.currentTarget = $event.currentTarget;
$event.currentTarget.className = "el-card is-always-shadow is-selected";
this.$emit('selectTestCase', item);
}
},
changePriority(row) {
if (row.id) {
this.saveTestCase(row);
}
},
saveTestCase(row) {
this.isShowInput = false;
if (this.validate(row)) {
return;
}
let bodyFiles = this.getBodyUploadFiles(row);
row.projectId = getCurrentProjectID();
row.active = true;
row.request.path = this.api.path;
row.request.method = this.api.method;
row.apiDefinitionId = row.apiDefinitionId || this.api.id;
let url = "/api/testcase/create";
if (row.id) {
url = "/api/testcase/update";
}
this.$fileUpload(url, null, bodyFiles, row, () => {
this.$success(this.$t('commons.save_success'));
this.$emit('refresh');
});
},
showInput(row) {
// row.type = "create";
this.isShowInput = true;
row.active = true;
this.active(row);
},
active(item) {
item.active = !item.active;
},
getResult(data) {
if (RESULT_MAP.get(data)) {
return RESULT_MAP.get(data);
} else {
return RESULT_MAP.get("default");
}
},
validate(row) {
if (!row.name) {
this.$warning(this.$t('api_test.input_name'));
return true;
}
},
showExecResult(data) {
this.$emit('showExecResult', data);
},
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);
}
});
},
changePriority(row) {
if (row.id) {
this.saveTestCase(row);
}
},
saveTestCase(row) {
this.isShowInput = false;
if (this.validate(row)) {
return;
}
let bodyFiles = this.getBodyUploadFiles(row);
row.projectId = getCurrentProjectID();
row.active = true;
row.request.path = this.api.path;
row.request.method = this.api.method;
row.apiDefinitionId = row.apiDefinitionId || this.api.id;
let url = "/api/testcase/create";
if (row.id) {
url = "/api/testcase/update";
}
this.$fileUpload(url, null, bodyFiles, row, () => {
this.$success(this.$t('commons.save_success'));
this.$emit('refresh');
});
},
showInput(row) {
// row.type = "create";
this.isShowInput = true;
row.active = true;
this.active(row);
},
active(item) {
item.active = !item.active;
},
getResult(data) {
if (RESULT_MAP.get(data)) {
return RESULT_MAP.get(data);
} else {
return RESULT_MAP.get("default");
}
},
validate(row) {
if (!row.name) {
this.$warning(this.$t('api_test.input_name'));
return true;
}
},
showExecResult(data) {
this.$emit('showExecResult', data);
},
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);
}
});
}
});
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;
},
});
}
}
return bodyUploadFiles;
},
handleClose(tag) {
this.apiCase.tags.splice(this.apiCase.tags.indexOf(tag), 1);
this.saveTestCase(this.apiCase)
},
showTagInput() {
this.inputVisible = true;
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus();
});
},
handleInputConfirm() {
let inputValue = this.inputValue;
if (inputValue) {
this.apiCase.tags.push(inputValue);
this.saveTestCase(this.apiCase)
}
this.inputVisible = false;
this.inputValue = '';
}
}
}
</script>
<style scoped>
.ms-api-select {
margin-left: 20px;
width: 80px;
}
.ms-api-select {
margin-left: 20px;
width: 80px;
}
.ms-api-header-select {
margin-left: 20px;
min-width: 100px;
}
.ms-api-header-select {
margin-left: 20px;
min-width: 100px;
}
.ms-api-label {
color: #CCCCCC;
}
.ms-api-label {
color: #CCCCCC;
}
.ms-api-col {
background-color: #7C3985;
border-color: #7C3985;
margin-right: 10px;
color: white;
}
.ms-api-col {
background-color: #7C3985;
border-color: #7C3985;
margin-right: 10px;
color: white;
}
.icon.is-active {
transform: rotate(90deg);
}
.icon.is-active {
transform: rotate(90deg);
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
margin: 20px 0;
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
margin: 20px 0;
}
.is-selected {
background: #EFF7FF;
}
.is-selected {
background: #EFF7FF;
}
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 20px;
/*line-height: 30px;*/
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
</style>

View File

@ -42,216 +42,224 @@
</template>
<script>
import ApiCaseHeader from "./ApiCaseHeader";
import ApiCaseItem from "./ApiCaseItem";
import MsRun from "../Run";
import {downloadFile, getUUID, getCurrentProjectID} 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 {PRIORITY} from "../../model/JsonData";
export default {
name: 'ApiCaseList',
components: {
MsDrawer,
MsRun,
ApiCaseHeader,
ApiCaseItem,
export default {
name: 'ApiCaseList',
components: {
MsDrawer,
MsRun,
ApiCaseHeader,
ApiCaseItem,
},
props: {
createCase: String,
loaded: Boolean,
refreshSign: String,
currentApi: {
type: Object
},
props: {
createCase: String,
loaded: Boolean,
refreshSign: String,
currentApi: {
type: Object
},
},
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();
},
createCase() {
this.api = this.currentApi;
this.sysAddition();
}
},
created() {
},
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.projectId = getCurrentProjectID();
if (this.createCase) {
this.sysAddition();
} else {
this.getApiTest();
}
this.getApiTest();
},
computed: {
isCaseEdit() {
return this.testCaseId ? true : false;
}
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;
},
methods: {
open(api, testCaseId) {
this.api = api;
// testCaseId
this.testCaseId = testCaseId;
this.getApiTest();
this.visible = true;
},
setEnvironment(environment) {
this.environment = environment;
},
sysAddition() {
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();
});
},
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;
this.condition.apiDefinitionId = this.api.id;
this.$post("/api/testcase/list", this.condition, response => {
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 => {
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;
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;
if (this.apiCaseList.length == 0 && !this.loaded) {
this.addCase();
}
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();
}
});
}
},
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};
obj.request = request;
this.apiCaseList.unshift(obj);
}
},
copyCase(data) {
this.apiCaseList.unshift(data);
},
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);
},
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);
this.apiCaseList.forEach(apiCase => {
if (!apiCase.tags) {
apiCase.tags = [];
} else {
apiCase.tags = JSON.parse(apiCase.tags);
}
})
if (this.runData.length > 0) {
this.batchLoading = true;
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
} else {
this.$warning("没有可执行的用例!");
});
}
},
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);
},
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);
},
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("没有可执行的用例!");
}
} else {
this.$warning("没有可执行的用例!");
}
}
}
}
</script>
<style scoped>
.ms-drawer >>> .ms-drawer-body {
margin-top: 80px;
}
.ms-drawer >>> .ms-drawer-body {
margin-top: 80px;
}
</style>

View File

@ -55,8 +55,8 @@
<el-col :span="8">
<el-form-item :label="$t('commons.tag')" prop="tag">
<el-tag
:key="tag"
v-for="tag in basicForm.tags"
:key="basicForm + '_' + index"
v-for="(tag, index) in basicForm.tags"
closable
size="mini"
:disable-transitions="false"

View File

@ -78,8 +78,8 @@
<el-col :span="8">
<el-form-item :label="$t('commons.tag')" prop="tag">
<el-tag
:key="tag"
v-for="tag in httpForm.tags"
:key="httpForm + '_' + index"
v-for="(tag, index) in httpForm.tags"
closable
size="mini"
:disable-transitions="false"