feat(接口定制): 基础保存功能完善

This commit is contained in:
fit2-zhao 2020-11-09 18:44:56 +08:00
parent 8404272115
commit 9bdb4f9625
26 changed files with 519 additions and 418 deletions

View File

@ -49,6 +49,11 @@ public class ApiDelimitController {
apiDelimitService.delete(id);
}
@PostMapping("/deleteBatch")
public void deleteBatch(@RequestBody List<String> ids) {
apiDelimitService.deleteBatch(ids);
}
@GetMapping("/get/{id}")
public ApiDelimit get(@PathVariable String id) {
return apiDelimitService.get(id);

View File

@ -6,6 +6,7 @@ import io.metersphere.api.dto.delimit.ApiDelimitRequest;
import io.metersphere.api.dto.delimit.ApiDelimitResult;
import io.metersphere.api.dto.delimit.SaveApiDelimitRequest;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDelimitExecResultMapper;
import io.metersphere.base.mapper.ApiDelimitMapper;
import io.metersphere.base.mapper.ApiTestFileMapper;
import io.metersphere.commons.constants.APITestStatus;
@ -43,6 +44,8 @@ public class ApiDelimitService {
private FileService fileService;
@Resource
private ApiTestCaseService apiTestCaseService;
@Resource
private ApiDelimitExecResultMapper apiDelimitExecResultMapper;
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
@ -134,11 +137,19 @@ public class ApiDelimitService {
public void delete(String apiId) {
apiTestCaseService.checkIsRelateTest(apiId);
deleteFileByTestId(apiId);
//apiReportService.deleteByTestId(apiId);
apiDelimitExecResultMapper.deleteByResourceId(apiId);
apiDelimitMapper.deleteByPrimaryKey(apiId);
deleteBodyFiles(apiId);
}
public void deleteBatch(List<String> apiIds) {
// 简单处理后续优化
apiIds.forEach(item -> {
delete(item);
});
}
public void deleteBodyFiles(String apiId) {
File file = new File(BODY_FILE_DIR + "/" + apiId);
FileUtil.deleteContents(file);
@ -149,9 +160,9 @@ public class ApiDelimitService {
private void checkNameExist(SaveApiDelimitRequest request) {
ApiDelimitExample example = new ApiDelimitExample();
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId());
example.createCriteria().andUrlEqualTo(request.getUrl()).andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId());
if (apiDelimitMapper.countByExample(example) > 0) {
MSException.throwException(Translator.get("load_test_already_exists"));
MSException.throwException(Translator.get("api_delimit_url_not_repeating"));
}
}

View File

@ -207,7 +207,7 @@ public class ApiModuleService {
if (level > 8) {
MSException.throwException(Translator.get("node_deep_limit"));
}
if (rootNode.getId().equals("rootID")) {
if (rootNode.getId().equals("root")) {
rootPath = "";
}
ApiModule apiDelimitNode = new ApiModule();

View File

@ -5,6 +5,7 @@ import io.metersphere.api.dto.delimit.ApiTestCaseRequest;
import io.metersphere.api.dto.delimit.ApiTestCaseResult;
import io.metersphere.api.dto.delimit.SaveApiTestCaseRequest;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDelimitExecResultMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.base.mapper.ApiTestFileMapper;
import io.metersphere.commons.exception.MSException;
@ -38,6 +39,8 @@ public class ApiTestCaseService {
private ApiTestFileMapper apiTestFileMapper;
@Resource
private FileService fileService;
@Resource
private ApiDelimitExecResultMapper apiDelimitExecResultMapper;
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
@ -110,7 +113,7 @@ public class ApiTestCaseService {
public void delete(String testId) {
deleteFileByTestId(testId);
//apiReportService.deleteByTestId(testId);
apiDelimitExecResultMapper.deleteByResourceId(testId);
apiTestCaseMapper.deleteByPrimaryKey(testId);
deleteBodyFiles(testId);
}

View File

@ -264,6 +264,11 @@ public class ApiDelimitExample {
return (Criteria) this;
}
public Criteria andUrlEqualTo(String value) {
addCriterion("url =", value, "url");
return (Criteria) this;
}
public Criteria andNameNotEqualTo(String value) {
addCriterion("name <>", value, "name");
return (Criteria) this;

View File

@ -0,0 +1,18 @@
package io.metersphere.base.domain;
import lombok.Data;
import java.io.Serializable;
@Data
public class ApiDelimitExecResult implements Serializable {
private String id;
private String resourceId;
private String name;
private String content;
private String status;
private String userId;
private String startTime;
private String endTime;
}

View File

@ -0,0 +1,10 @@
package io.metersphere.base.mapper;
import io.metersphere.base.domain.ApiDelimitExecResult;
public interface ApiDelimitExecResultMapper {
int deleteByResourceId(String id);
int insert(ApiDelimitExecResult record);
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.base.mapper.ApiDelimitExecResultMapper">
<delete id="deleteByResourceId" parameterType="java.lang.String">
delete from api_delimit_exec_result where resource_id = #{id,jdbcType=VARCHAR}
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.ApiDelimitExecResult">
insert into api_delimit_exec_result
(id, resource_id,name,content, status, user_id, start_time, end_time)
values
(#{id,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR}, #{status,jdbcType=VARCHAR},
#{startTime,jdbcType=BIGINT}, #{endTime,jdbcType=BIGINT})
</insert>
</mapper>

View File

@ -260,7 +260,7 @@
request = #{request,jdbcType=LONGVARCHAR},
</if>
<if test="response != null">
request = #{response,jdbcType=LONGVARCHAR},
response = #{response,jdbcType=LONGVARCHAR},
</if>
</set>

View File

@ -1,13 +0,0 @@
CREATE TABLE IF NOT EXISTS `api_module` (
`id` varchar(50) NOT NULL COMMENT 'Test case node ID',
`project_id` varchar(50) NOT NULL COMMENT 'Project ID this node belongs to',
`name` varchar(64) NOT NULL COMMENT 'Node name',
`protocol` varchar(64) NOT NULL COMMENT 'Node protocol',
`parent_id` varchar(50) DEFAULT NULL COMMENT 'Parent node ID',
`level` int(10) DEFAULT 1 COMMENT 'Node level',
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
PRIMARY KEY (`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;

View File

@ -169,6 +169,7 @@ test_plan_notification=Test plan notification
task_defect_notification=Task defect notification
task_notification=Jenkins Task notification
task_notification_=Timing task result notification
api_delimit_url_not_repeating=The interface request address already exists

View File

@ -169,4 +169,5 @@ upload_content_is_null=导入内容为空
test_plan_notification=测试计划通知
task_defect_notification=缺陷任务通知
task_notification=jenkins任务通知
task_notification_=定时任务结果通知
task_notification_=定时任务结果通知
api_delimit_url_not_repeating=接口请求地址已经存在

View File

@ -171,4 +171,4 @@ test_plan_notification=測試計畫通知
task_defect_notification=缺陷任務通知
task_notification=jenkins任務通知
task_notification_=定時任務通知
api_delimit_url_not_repeating=接口請求地址已經存在

View File

@ -2,8 +2,8 @@
<ms-container>
<ms-aside-container>
<ms-node-tree @selectModule="selectModule" @getApiModuleTree="initTree"
@changeProject="changeProject"></ms-node-tree>
<ms-node-tree @selectModule="selectModule" @getApiModuleTree="initTree" @changeProject="changeProject"
@refresh="refresh"/>
</ms-aside-container>
<ms-main-container>
@ -16,12 +16,11 @@
<el-dropdown-item command="closeAll">{{$t('api_test.delimit.request.close_all_label')}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-tabs v-model="editableTabsValue" @edit="handleTabsEdit">
<!-- 主框架列表 -->
<el-tabs v-model="apiDefaultTab" @edit="handleTabsEdit">
<el-tab-pane
:key="item.name"
v-for="(item) in editableTabs"
v-for="(item) in apiTabs"
:label="item.title"
:closable="item.closable"
:name="item.name">
@ -32,20 +31,23 @@
:current-module="currentModule"
@editApi="editApi"
@handleCase="handleCase"
ref="apiList">
</ms-api-list>
ref="apiList"/>
<!-- 添加测试窗口-->
<div v-else-if="item.type=== 'add'">
<ms-api-config @runTest="runTest" @saveApi="saveApi" :current-api="currentApi"
:currentProject="currentProject"
:moduleOptions="moduleOptions" ref="apiConfig"></ms-api-config>
:moduleOptions="moduleOptions" ref="apiConfig"/>
</div>
<!-- 快捷调试 -->
<div v-else-if="item.type=== 'debug'">
<ms-debug-http-page @saveAs="saveAs"></ms-debug-http-page>
<ms-debug-http-page @saveAs="editApi"/>
</div>
<!-- 测试-->
<div v-else-if="item.type=== 'test'">
<!-- 测试-->
<ms-run-test-http-page></ms-run-test-http-page>
<ms-run-test-http-page :api-data="runTestData" @saveAsApi="editApi"/>
</div>
</el-tab-pane>
@ -83,21 +85,16 @@
comments: {},
data() {
return {
projectId: null,
isHide: true,
editableTabsValue: '1',
tabIndex: 1,
result: {},
currentPage: 1,
pageSize: 5,
total: 0,
apiDefaultTab: 'default',
currentProject: null,
currentModule: null,
currentApi: {},
moduleOptions: {},
editableTabs: [{
runTestData: {},
apiTabs: [{
title: this.$t('api_test.delimit.api_title'),
name: '1',
name: 'default',
type: "list",
closable: false
}],
@ -106,21 +103,17 @@
methods: {
handleCommand(e) {
if (e === "add") {
this.currentApi = {
status: "Underway",
path: "GET",
userId: getCurrentUser().id,
};
this.currentApi = {status: "Underway", path: "GET", userId: getCurrentUser().id};
this.handleTabsEdit(this.$t('api_test.delimit.request.title'), e);
}
else if (e === "test") {
this.handleTabsEdit(this.$t("commons.api"), e);
}
else if (e === "closeAll") {
let tabs = this.editableTabs[0];
this.editableTabs = [];
this.editableTabsValue = tabs.name;
this.editableTabs.push(tabs);
let tabs = this.apiTabs[0];
this.apiTabs = [];
this.apiDefaultTab = tabs.name;
this.apiTabs.push(tabs);
}
else {
this.handleTabsEdit(this.$t('api_test.delimit.request.fast_debug'), "debug");
@ -128,8 +121,8 @@
},
handleTabsEdit(targetName, action) {
if (action === 'remove') {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
let tabs = this.apiTabs;
let activeName = this.apiDefaultTab;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
@ -140,23 +133,22 @@
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
this.apiDefaultTab = activeName;
this.apiTabs = tabs.filter(tab => tab.name !== targetName);
} else {
if (targetName === undefined || targetName === null) {
targetName = this.$t('api_test.delimit.request.title');
}
let newTabName = getUUID().substring(0, 8);
this.editableTabs.push({
this.apiTabs.push({
title: targetName,
name: newTabName,
closable: true,
type: action
});
this.editableTabsValue = newTabName;
this.apiDefaultTab = newTabName;
}
},
editApi(row) {
this.currentApi = row;
this.handleTabsEdit(row.name, "add");
@ -172,24 +164,25 @@
this.currentModule = data;
},
refresh(data) {
this.$refs.apiList[0].initTableData(data);
this.$refs.apiList[0].initApiTable(data);
},
saveAs(data) {
this.handleCommand("add");
},
runTest(data) {
this.handleCommand("test");
},
saveApi(data) {
for (let index in this.editableTabs) {
let tab = this.editableTabs[index];
if (tab.name === this.editableTabsValue) {
setTabTitle(data) {
for (let index in this.apiTabs) {
let tab = this.apiTabs[index];
if (tab.name === this.apiDefaultTab) {
tab.title = data.name;
break;
}
}
this.runTestData = data;
},
runTest(data) {
this.setTabTitle(data);
this.handleCommand("test");
},
saveApi(data) {
this.setTabTitle(data);
this.$refs.apiList[0].initTableData(data);
},
initTree(data) {
this.moduleOptions = data;

View File

@ -27,7 +27,7 @@
</el-col>
<el-col :span="4">
<div>
<el-select size="small" :placeholder="$t('api_test.delimit.request.grade_info')" v-model="grdValue"
<el-select size="small" :placeholder="$t('api_test.delimit.request.grade_info')" v-model="priorityValue"
class="ms-api-header-select" @change="getApiTest">
<el-option v-for="grd in priority" :key="grd.id" :label="grd.name" :value="grd.id"/>
</el-select>
@ -72,16 +72,15 @@
</el-row>
</el-card>
<!-- 环境 -->
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
</el-header>
<!-- 用例部分 -->
<el-main>
<div v-for="(item,index) in apiCaseList" :key="index">
<el-card style="margin-top: 10px">
<el-card style="margin-top: 10px" @click.native="selectTestCase(item,$event)">
<el-row>
<el-col :span="5">
@ -100,8 +99,7 @@
@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"/>
{{item.type!= 'create'? item.name : ''}}
{{item.type!= 'create' ? item.name:''}}
<div v-if="item.type!='create'" style="color: #999999;font-size: 12px">
<span> {{item.createTime | timestampFormatDate }}</span> {{item.createUser}} 创建
<span> {{item.updateTime | timestampFormatDate }}</span> {{item.updateUser}} 更新
@ -128,8 +126,7 @@
<!-- 请求参数-->
<el-collapse-transition>
<div v-if="item.active">
<ms-api-request-form :is-read-only="isReadOnly" :debug-report-id="debugReportId" @runDebug="runDebug"
:request="item.test.request"/>
<ms-api-request-form :is-read-only="isReadOnly" :request="item.test.request"/>
<!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)">
{{$t('commons.save')}}
@ -153,6 +150,7 @@
import {downloadFile, getUUID} from "@/common/js/utils";
import {parseEnvironment} from "../model/EnvironmentModel";
import ApiEnvironmentConfig from "../../test/components/ApiEnvironmentConfig";
import {PRIORITY} from "../model/JsonData";
export default {
name: 'ApiCaseList',
@ -173,18 +171,12 @@
grades: [],
environments: [],
envValue: {},
grdValue: "",
value: "",
isReadOnly: false,
name: "",
priority: [
{name: 'P0', id: 'P0'},
{name: 'P1', id: 'P1'},
{name: 'P2', id: 'P2'},
{name: 'P3', id: 'P3'}
],
priorityValue: "",
isReadOnly: false,
selectedEvent: Object,
priority: PRIORITY,
apiCaseList: [],
debugReportId: ''
}
},
@ -197,16 +189,10 @@
this.getEnvironments();
}
},
created() {
this.getApiTest();
},
methods: {
getRequest(request) {
if (request === undefined || request === null) {
this.test = new Test();
this.test.request.environment = this.envValue;
return this.test.request;
} else {
return new RequestFactory(JSON.parse(request));
}
},
getResult(data) {
if (data === 'PASS') {
return '执行结果:通过';
@ -249,9 +235,6 @@
test: test,
};
this.apiCaseList.push(obj);
},
runDebug() {
},
active(item) {
item.active = !item.active;
@ -281,9 +264,9 @@
let condition = {};
condition.projectId = this.api.projectId;
condition.apiDelimitId = this.api.id;
condition.priority = this.grdValue;
condition.priority = this.priorityValue;
condition.name = this.name;
this.result = this.$post("/api/testcase/list", condition, response => {
this.$post("/api/testcase/list", condition, response => {
for (let index in response.data) {
let test = response.data[index];
test.test = new Test({request: new RequestFactory(JSON.parse(test.request))});
@ -308,7 +291,6 @@
row.projectId = this.api.projectId;
row.apiDelimitId = this.api.id;
row.request = row.test.request;
let jmx = row.test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
@ -323,7 +305,7 @@
},
getEnvironments() {
if (this.currentProject) {
this.result = this.$get('/api/environment/list/' + this.currentProject.id, response => {
this.$get('/api/environment/list/' + this.currentProject.id, response => {
this.environments = response.data;
this.environments.forEach(environment => {
parseEnvironment(environment);
@ -363,6 +345,23 @@
},
environmentConfigClose() {
this.getEnvironments();
},
selectTestCase(item, $event) {
if (item.type === "create") {
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);
}
}
}
}
@ -413,4 +412,8 @@
.icon.is-active {
transform: rotate(90deg);
}
.is-selected {
background: #EFF7FF;
}
</style>

View File

@ -1,6 +1,7 @@
<template>
<div class="card-container">
<!-- HTTP 请求参数 -->
<ms-add-complete-http-api @runTest="runTest" @saveApi="saveApi" :httpData="currentApi" :test="test"
:moduleOptions="moduleOptions" :currentProject="currentProject"
v-if="reqType === 'HTTP'"></ms-add-complete-http-api>
@ -10,7 +11,7 @@
<script>
import MsAddCompleteHttpApi from "./complete/AddCompleteHttpApi";
import {RequestFactory, Test} from "../model/ScenarioModel";
import {downloadFile, getUUID} from "@/common/js/utils";
import {getUUID} from "@/common/js/utils";
export default {
name: "ApiConfig",
@ -18,8 +19,8 @@
data() {
return {
reqType: RequestFactory.TYPES.HTTP,
reqUrl: "",
test: new Test(),
postUrl: "",
}
},
props: {
@ -28,30 +29,44 @@
currentProject: {},
},
created() {
this.test = new Test({
request: this.currentApi.request != null ? new RequestFactory(JSON.parse(this.currentApi.request)) : null
});
if (this.currentApi != null && this.currentApi.id != null) {
let item = this.currentApi;
this.test = new Test({
id: item.id,
projectId: item.projectId,
name: item.name,
status: item.status,
path: item.path,
request: new RequestFactory(JSON.parse(item.request)),
});
this.postUrl = "/api/delimit/update";
this.reqUrl = "/api/delimit/update";
} else {
this.test = new Test();
this.postUrl = "/api/delimit/create";
this.reqUrl = "/api/delimit/create";
this.currentApi.id = getUUID().substring(0, 8);
}
},
methods: {
runTest(data) {
this.$emit('runTest', data);
if (this.editApi(data) === true) {
this.$emit('runTest', data);
}
},
getBodyUploadFiles() {
saveApi(data) {
if (this.editApi(data) === true) {
this.$emit('saveApi', data);
}
},
editApi(data) {
data.projectId = this.currentProject.id;
data.request = data.test.request;
let bodyFiles = this.getBodyUploadFiles(data);
let jmx = data.test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
this.$fileUpload(this.reqUrl, file, bodyFiles, data, () => {
this.$success(this.$t('commons.save_success'));
this.reqUrl = "/api/delimit/update";
return true;
});
},
getBodyUploadFiles(data) {
let bodyUploadFiles = [];
this.test.bodyUploadIds = [];
let request = this.test.request;
data.bodyUploadIds = [];
let request = data.request;
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
@ -60,7 +75,7 @@
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
this.test.bodyUploadIds.push(fileId);
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
@ -69,18 +84,6 @@
}
return bodyUploadFiles;
},
saveApi(data) {
this.test = data;
let bodyFiles = this.getBodyUploadFiles();
let jmx = this.test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
this.$fileUpload(this.postUrl, file, bodyFiles, this.test, () => {
this.$success(this.$t('commons.save_success'));
this.$emit('saveApi', this.test);
this.postUrl = "/api/delimit/update";
});
}
}
}
</script>

View File

@ -1,42 +1,34 @@
<template>
<div class="card-container">
<el-card class="card-content" v-loading="result.loading">
<el-card class="card-content">
<template v-slot:header>
<ms-table-header :showCreate="false" :condition.sync="condition"
@search="search"
<ms-table-header :showCreate="false" :condition.sync="condition" @search="search"
:title="$t('api_test.delimit.api_title')"/>
</template>
<el-table
border
:data="tableData"
row-key="id"
class="test-content adjust-table">
<el-table-column
prop="name"
:label="$t('api_test.delimit.api_name')"
show-overflow-tooltip/>
<el-table border :data="tableData" row-key="id" class="test-content adjust-table"
@select-all="handleSelectAll"
@select="handleSelect">
<el-table-column type="selection"/>
<el-table-column width="40" :resizable="false" align="center">
<template v-slot:default="scope">
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectRows.size"/>
</template>
</el-table-column>
<el-table-column prop="name" :label="$t('api_test.delimit.api_name')" show-overflow-tooltip/>
<el-table-column
prop="status"
column-key="api_status"
:label="$t('api_test.delimit.api_status')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span class="el-dropdown-link">
<template>
<div>
<ms-tag v-if="scope.row.status == 'Prepare'" type="info"
:content="$t('test_track.plan.plan_status_prepare')"/>
<ms-tag v-if="scope.row.status == 'Underway'" type="primary"
:content="$t('test_track.plan.plan_status_running')"/>
<ms-tag v-if="scope.row.status == 'Completed'" type="success"
:content="$t('test_track.plan.plan_status_completed')"/>
</div>
</template>
</span>
<ms-tag v-if="scope.row.status == 'Prepare'" type="info"
:content="$t('test_track.plan.plan_status_prepare')"/>
<ms-tag v-if="scope.row.status == 'Underway'" type="primary"
:content="$t('test_track.plan.plan_status_running')"/>
<ms-tag v-if="scope.row.status == 'Completed'" type="success"
:content="$t('test_track.plan.plan_status_completed')"/>
</template>
</el-table-column>
@ -44,17 +36,12 @@
prop="path"
:label="$t('api_test.delimit.api_type')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span class="el-dropdown-link">
<template>
<div class="request-method">
<el-tag size="mini"
:style="{'background-color': getColor(true, scope.row.path)}" class="api-el-tag"> {{ scope.row.path }}</el-tag>
</div>
<template v-slot:default="scope" class="request-method">
<el-tag size="mini"
:style="{'background-color': getColor(true, scope.row.path)}" class="api-el-tag"> {{ scope.row.path
}}
</el-tag>
</template>
</span>
</template>
</el-table-column>
<el-table-column
@ -99,7 +86,7 @@
</el-table-column>
</el-table>
<ms-table-pagination :change="initTableData" :current-page.sync="currentPage" :page-size.sync="pageSize"
<ms-table-pagination :change="initApiTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
:total="total"/>
</el-card>
@ -123,7 +110,8 @@
import MsApiCaseList from "./ApiCaseList";
import MsContainer from "../../../common/components/MsContainer";
import MsBottomContainer from "./BottomContainer";
import {Message} from "element-ui";
import ShowMoreBtn from "../../../../components/track/case/components/ShowMoreBtn";
import {API_METHOD_COLOUR} from "../model/JsonData";
export default {
name: "ApiList",
@ -136,22 +124,19 @@
MsTag,
MsApiCaseList,
MsContainer,
MsBottomContainer
MsBottomContainer,
ShowMoreBtn
},
data() {
return {
result: {},
condition: {},
isHide: true,
selectApi: {},
moduleId: "",
deletePath: "/test/case/delete",
methodColorMap: new Map([
['GET', "#61AFFE"], ['POST', '#49CC90'], ['PUT', '#fca130'],
['PATCH', '#E2EE11'], ['DELETE', '#f93e3d'], ['OPTIONS', '#0EF5DA'],
['HEAD', '#8E58E7'], ['CONNECT', '#90AFAE'],
['DUBBO', '#C36EEF'], ['SQL', '#0AEAD4'], ['TCP', '#0A52DF'],
]),
selectRows: new Set(),
buttons: [{name: this.$t('api_test.delimit.request.batch_delete'), handleClick: this.handleDeleteBatch}],
methodColorMap: new Map(API_METHOD_COLOUR),
tableData: [],
currentPage: 1,
pageSize: 10,
@ -159,26 +144,24 @@
}
},
props: {
currentProject: {
type: Object
},
currentProject: Object,
currentModule: Object
},
created: function () {
this.initTableData();
this.initApiTable();
},
watch: {
currentProject() {
this.initTableData();
this.initApiTable();
},
currentModule() {
this.initTableData();
this.initApiTable();
}
},
methods: {
initTableData() {
initApiTable() {
if (this.currentModule != null) {
if (this.currentModule.id == "rootID") {
if (this.currentModule.id == "root") {
this.condition.moduleIds = [];
} else {
this.condition.moduleIds = this.currentModule.ids;
@ -192,8 +175,45 @@
this.tableData = response.data.listObject;
});
},
handleSelect(selection, row) {
if (this.selectRows.has(row)) {
this.$set(row, "showMore", false);
this.selectRows.delete(row);
} else {
this.$set(row, "showMore", true);
this.selectRows.add(row);
}
let arr = Array.from(this.selectRows);
// 1
if (this.selectRows.size === 1) {
this.$set(arr[0], "showMore", false);
} else if (this.selectRows.size === 2) {
arr.forEach(row => {
this.$set(row, "showMore", true);
})
}
},
handleSelectAll(selection) {
if (selection.length > 0) {
if (selection.length === 1) {
this.selectRows.add(selection[0]);
} else {
this.tableData.forEach(item => {
this.$set(item, "showMore", true);
this.selectRows.add(item);
});
}
} else {
this.selectRows.clear();
this.tableData.forEach(row => {
this.$set(row, "showMore", false);
})
}
},
search() {
this.initTableData();
this.initApiTable();
},
buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize;
@ -202,14 +222,29 @@
editApi(row) {
this.$emit('editApi', row);
},
handleDeleteBatch() {
this.$alert(this.$t('api_test.delimit.request.delete_confirm') + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
let ids = Array.from(this.selectRows).map(row => row.id);
this.$post('/api/delimit/deleteBatch/', ids, () => {
this.selectRows.clear();
this.initApiTable();
this.$success(this.$t('commons.delete_success'));
});
}
}
});
},
handleTestCase(testCase) {
this.selectApi = testCase;
this.isHide = false;
},
handleDelete(testCase) {
this.$get('/api/delimit/delete/' + testCase.id, () => {
Message.success(this.$t('commons.delete_success'));
this.initTableData();
this.$success(this.$t('commons.delete_success'));
this.initApiTable();
});
},
apiCaseClose() {
@ -238,5 +273,4 @@
.api-el-tag {
color: white;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div v-loading="result.loading">
<div>
<select-menu
:data="projects"
:current-data="currentProject"
@ -49,7 +49,7 @@
<span class="node-operate child">
<el-tooltip
v-if="data.id!='rootID'"
v-if="data.id!='root'"
class="item"
effect="dark"
:open-delay="200"
@ -68,7 +68,7 @@
</el-tooltip>
<el-tooltip
v-if="data.id!='rootID'"
v-if="data.id!='root'"
class="item"
effect="dark"
:open-delay="200"
@ -89,6 +89,7 @@
<script>
import MsAddBasisHttpApi from "./basis/AddBasisHttpApi";
import SelectMenu from "../../../track/common/SelectMenu";
import {OPTIONS, DEFAULT_DATA} from "../model/JsonData";
export default {
name: 'MsApiModule',
@ -98,35 +99,15 @@
},
data() {
return {
options: [{
value: 'HTTP',
name: 'HTTP'
}, {
value: 'DUBBO',
name: 'DUBBO'
}, {
value: 'TCP',
name: 'TCP'
}, {
value: 'SQL',
name: 'SQL'
}],
value: 'HTTP',
options: OPTIONS,
value: OPTIONS[0].value,
httpVisible: false,
expandedNode: [],
result: {},
filterText: "",
nextFlag: true,
currentProject: {},
projects: [],
data: [
{
"id": "rootID",
"name": "默认模块",
"level": 0,
"children": [],
}
],
data: DEFAULT_DATA,
currentModule: {},
newLabel: ""
}
@ -146,7 +127,7 @@
methods: {
getApiModuleTree() {
if (this.currentProject) {
this.result = this.$get("/api/module/list/" + this.currentProject.id + "/" + this.value, response => {
this.$get("/api/module/list/" + this.currentProject.id + "/" + this.value, response => {
if (response.data != undefined && response.data != null) {
this.data[0].children = response.data;
let moduleOptions = [];
@ -220,7 +201,7 @@
param.nodeIds = nodeIds;
return param;
},
getNodeTree(nodes, id, list) {
getTreeNode(nodes, id, list) {
if (!nodes) {
return;
}
@ -232,21 +213,21 @@
return;
}
if (nodes[i].children) {
this.getNodeTree(nodes[i].children, id, list);
this.getTreeNode(nodes[i].children, id, list);
}
}
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
if (dropNode.data.id === "rootID" || dropType === "none" || dropType === undefined) {
if (dropNode.data.id === "root" || dropType === "none" || dropType === undefined) {
return;
}
let param = this.buildParam(draggingNode, dropNode, dropType);
this.list = [];
if (param.parentId === "rootID") {
if (param.parentId === "root") {
param.parentId = null;
}
this.getNodeTree(this.data, draggingNode.data.id, this.list);
this.getTreeNode(this.data, draggingNode.data.id, this.list);
this.$post("/api/module/drag", param, () => {
this.getApiGroupData();
@ -256,7 +237,7 @@
},
allowDrop(draggingNode, dropNode, type) {
if (dropNode.data.id === "rootID") {
if (dropNode.data.id === "root") {
return false
} else {
return true
@ -264,13 +245,12 @@
},
allowDrag(draggingNode) {
//
if (draggingNode.data.id === "rootID") {
if (draggingNode.data.id === "root") {
return false
} else {
return true
}
},
append(node, data) {
if (this.nextFlag === true) {
const newChild = {
@ -311,7 +291,6 @@
this.$set(data, 'isEdit', 1)
this.newLabel = data.name
this.$nextTick(() => {
//this.$refs.input.focus();
})
},
@ -355,7 +334,7 @@
if (data.id === "newId") {
url = '/api/module/add';
data.level = 1;
if (node.parent && node.parent.key != "rootID") {
if (node.parent && node.parent.key != "root") {
data.parentId = node.parent.key;
data.level = node.parent.level;
}
@ -377,7 +356,7 @@
},
selectModule(data) {
if (data.id != "rootID") {
if (data.id != "root") {
if (data.path != undefined && !data.path.startsWith("/")) {
data.path = "/" + data.path;
}

View File

@ -10,7 +10,7 @@
<el-form-item :label="$t('api_report.request')" prop="url">
<el-input :placeholder="$t('api_test.delimit.request.path_info')" v-model="httpForm.url"
class="ms-http-input" size="small">
<el-select v-model="value" slot="prepend" style="width: 100px" size="small">
<el-select v-model="httpForm.path" slot="prepend" style="width: 100px" size="small">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-input>
@ -47,8 +47,10 @@
<script>
import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import {TokenKey, WORKSPACE_ID} from '../../../../../../common/js/constants';
import {Scenario, KeyValue, Test} from "../../model/ScenarioModel"
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {Test} from "../../model/ScenarioModel"
import {REQ_METHOD} from "../../model/JsonData";
import {getCurrentUser} from "../../../../../../common/js/utils";
export default {
name: "MsAddBasisHttpApi",
@ -61,7 +63,6 @@
currentModule: {},
projectId: "",
maintainerOptions: [],
test: new Test(),
rule: {
name: [
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
@ -70,18 +71,9 @@
url: [{required: true, message: this.$t('api_test.delimit.request.path_info'), trigger: 'blur'}],
userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
},
value: "GET",
options: [{
id: 'GET',
label: 'GET'
}, {
id: 'POST',
label: 'POST'
}],
value: REQ_METHOD[0].id,
options: REQ_METHOD,
}
},
created() {
},
methods: {
saveApi() {
@ -89,26 +81,22 @@
if (valid) {
let bodyFiles = [];
let url = "/api/delimit/create";
this.test.name = this.httpForm.name;
this.test.path = this.value;
this.test.url = this.httpForm.url;
this.test.userId = this.httpForm.userId;
this.test.description = this.httpForm.description;
this.test.request.url = this.httpForm.url;
this.test.request.path = this.value;
this.test.bodyUploadIds = [];
this.test.projectId = this.projectId;
let test = new Test();
this.httpForm.bodyUploadIds = [];
this.httpForm.request = test.request;
this.httpForm.request.url = this.httpForm.url;
this.httpForm.request.path = this.httpForm.path;
this.httpForm.projectId = this.projectId;
this.httpForm.id = test.id;
if (this.currentModule != null) {
this.test.modulePath = this.currentModule.path != undefined ? this.currentModule.path : null;
this.test.moduleId = this.currentModule.id;
this.httpForm.modulePath = this.currentModule.path != undefined ? this.currentModule.path : null;
this.httpForm.moduleId = this.currentModule.id;
}
let jmx = this.test.toJMX();
let jmx = test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
this.result = this.$fileUpload(url, file, bodyFiles, this.test, () => {
this.result = this.$fileUpload(url, file, bodyFiles, this.httpForm, () => {
this.httpVisible = false;
this.$parent.refresh(this.currentModule);
});
@ -117,36 +105,6 @@
}
})
},
urlChange() {
if (!this.httpForm.url) return;
let url = this.getURL(this.addProtocol(this.httpForm.url));
if (url) {
this.httpForm.url = decodeURIComponent(url.origin + url.pathname);
}
}
,
getURL(urlStr) {
try {
let url = new URL(urlStr);
url.searchParams.forEach((value, key) => {
if (key && value) {
this.request.parameters.splice(0, 0, new KeyValue({name: key, value: value}));
}
});
return url;
} catch (e) {
this.$error(this.$t('api_test.request.url_invalid'), 2000);
}
}
,
addProtocol(url) {
if (url) {
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
return "https://" + url;
}
}
return url;
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
@ -155,8 +113,7 @@
}
,
open(currentModule, projectId) {
this.httpForm = {};
this.test = new Test();
this.httpForm = {path: REQ_METHOD[0].id, userId: getCurrentUser().id};
this.currentModule = currentModule;
this.projectId = projectId;
this.getMaintainerOptions();

View File

@ -6,7 +6,7 @@
<el-form :model="httpForm" :rules="rule" ref="httpForm" :inline="true" label-position="right">
<div style="float: right;margin-right: 20px">
<el-button type="primary" size="small" @click="saveApi">{{$t('commons.save')}}</el-button>
<el-button type="primary" size="small" @click="runTest(httpForm)">{{$t('commons.test')}}</el-button>
<el-button type="primary" size="small" @click="runTest">{{$t('commons.test')}}</el-button>
</div>
<br/>
<div style="font-size: 16px;color: #333333">{{$t('test_track.plan_view.base_info')}}</div>
@ -60,13 +60,13 @@
</el-form-item>
<div style="font-size: 16px;color: #333333;padding-top: 30px">请求参数</div>
<div style="font-size: 16px;color: #333333;padding-top: 30px">{{$t('api_test.delimit.request.req_param')}}</div>
<br/>
<!-- HTTP 请求参数 -->
<ms-api-request-form :debug-report-id="debugReportId" :request="this.test.request"/>
<ms-api-request-form :request="test.request"/>
</el-form>
<div style="font-size: 16px;color: #333333 ;padding-top: 30px">响应模版</div>
<div style="font-size: 16px;color: #333333 ;padding-top: 30px">{{$t('api_test.delimit.request.res_param')}}</div>
<br/>
<ms-response-text :response="responseData"></ms-response-text>
</el-card>
@ -77,7 +77,7 @@
import MsApiRequestForm from "../request/ApiRequestForm";
import MsResponseText from "../../../report/components/ResponseText";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {Scenario, KeyValue, Test} from "../../model/ScenarioModel"
import {REQ_METHOD, API_STATUS} from "../../model/JsonData";
export default {
name: "MsAddCompleteHttpApi",
@ -95,37 +95,28 @@
status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
},
httpForm: {},
reqValue: '',
debugReportId: '',
maintainerOptions: [],
responseData: {},
currentScenario: new Scenario(),
currentModule: {},
postUrl: "",
reqOptions: [{
id: 'GET',
label: 'GET'
}, {
id: 'POST',
label: 'POST'
}],
options: [{
id: 'Prepare',
label: '未开始'
}, {
id: 'Underway',
label: '进行中'
}, {
id: 'Completed',
label: '已完成'
}],
reqOptions: REQ_METHOD,
options: API_STATUS
}
},
props: {httpData: {}, moduleOptions: {}, currentProject: {}, test: {}},
methods: {
runTest(data) {
this.$emit('runTest', data);
runTest() {
if (this.currentProject === null) {
this.$error(this.$t('api_test.select_project'));
return;
}
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('runTest', this.httpForm);
} else {
return false;
}
})
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
@ -133,35 +124,26 @@
this.maintainerOptions = response.data;
});
},
setParameter() {
this.httpForm.test = this.test;
this.httpForm.test.request.url = this.httpForm.url;
this.httpForm.test.request.path = this.httpForm.path;
this.httpForm.modulePath = this.getPath(this.httpForm.moduleId);
},
saveApi() {
if (this.currentProject === null) {
this.$error(this.$t('api_test.select_project'), 2000);
return;
}
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.test.name = this.httpForm.name;
this.test.path = this.httpForm.path;
this.test.url = this.httpForm.url;
this.test.userId = this.httpForm.userId;
this.test.description = this.httpForm.description;
this.test.status = this.httpForm.status;
this.test.moduleId = this.httpForm.moduleId;
this.test.projectId = this.currentProject.id;
this.test.modulePath = this.getPath(this.httpForm.moduleId);
this.test.bodyUploadIds = [];
this.test.request.url = this.httpForm.url;
this.test.request.path = this.httpForm.path;
console.log(this.httpForm)
this.$emit('saveApi', this.test);
}
else {
return false;
}
if (valid) {
this.setParameter();
this.$emit('saveApi', this.httpForm);
}
)
else {
return false;
}
})
},
getPath(id) {
if (id === null) {

View File

@ -1,22 +1,20 @@
<template>
<div class="card-container">
<el-card class="card-content" v-loading="result.loading">
<el-form :model="httpForm" :rules="rule" ref="httpForm" :inline="true" :label-position="labelPosition">
<el-card class="card-content">
<el-form :model="httpForm" :rules="rules" ref="httpForm" :inline="true" label-position="right">
<div style="font-size: 16px;color: #333333">{{$t('test_track.plan_view.base_info')}}</div>
<br/>
<el-form-item :label="$t('api_report.request')" prop="responsible">
<el-input :placeholder="$t('api_test.delimit.request.path_info')" v-model="httpForm.request"
<el-input :placeholder="$t('api_test.delimit.request.path_info')" v-model="httpForm.url"
class="ms-http-input" size="small">
<el-select v-model="reqValue" slot="prepend" style="width: 100px" size="small">
<el-select v-model="httpForm.path" slot="prepend" style="width: 100px" size="small">
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-input>
</el-form-item>
<el-form-item>
<el-dropdown split-button type="primary" class="ms-api-buttion" @click="handleCommand"
@command="handleCommand" size="small">
@ -27,13 +25,13 @@
</el-dropdown>
</el-form-item>
<div style="font-size: 16px;color: #333333;padding-top: 30px">请求参数</div>
<div style="font-size: 16px;color: #333333;padding-top: 30px">{{$t('api_test.delimit.request.req_param')}}</div>
<br/>
<!-- HTTP 请求参数 -->
<ms-api-request-form :debug-report-id="debugReportId" :request="selected" :scenario="currentScenario"/>
<ms-api-request-form :request="test.request"/>
</el-form>
<div style="font-size: 16px;color: #333333 ;padding-top: 30px">响应内容</div>
<div style="font-size: 16px;color: #333333 ;padding-top: 30px">{{$t('api_test.delimit.request.res_param')}}</div>
<br/>
<ms-response-text :response="responseData"></ms-response-text>
</el-card>
@ -42,35 +40,26 @@
<script>
import MsApiRequestForm from "../request/ApiRequestForm";
import {Request, Scenario} from "../../model/ScenarioModel";
import {Test} from "../../model/ScenarioModel";
import MsResponseText from "../../../report/components/ResponseText";
import {REQ_METHOD} from "../../model/JsonData";
export default {
name: "ApiConfig",
components: {MsResponseText, MsApiRequestForm},
data() {
return {
result: {},
rule: {},
labelPosition: 'right',
httpForm: {},
rules: {
path: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
url: [{required: true, message: this.$t('api_test.delimit.request.path_info'), trigger: 'blur'}],
},
httpForm: {path: REQ_METHOD[0].id},
options: [],
reqValue: '',
debugReportId: '',
responseData: {},
currentScenario: Scenario,
selected: [Scenario, Request],
reqOptions: [{
id: 'GET',
label: 'GET'
}, {
id: 'POST',
label: 'POST'
}],
moduleValue: '',
test: new Test(),
reqOptions: REQ_METHOD,
}
},
props: {httpData: {},},
methods: {
handleCommand(e) {
if (e === "save_as") {
@ -78,12 +67,15 @@
}
},
saveAs() {
this.$emit('saveAs', this.httpForm);
}
},
watch: {
httpData(v) {
this.httpForm = v;
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.httpForm.request = JSON.stringify(this.test.request);
this.$emit('saveAs', this.httpForm);
}
else {
return false;
}
})
}
}
}
@ -92,6 +84,6 @@
<style scoped>
.ms-http-input {
width: 500px;
margin-top:5px;
margin-top: 5px;
}
</style>

View File

@ -1,17 +1,17 @@
<template>
<div class="card-container">
<el-card class="card-content" v-loading="result.loading">
<el-card class="card-content">
<el-form :model="httpForm" :rules="rule" ref="httpForm" :inline="true" :label-position="labelPosition">
<el-form :model="apiData" ref="apiData" :inline="true" label-position="right">
<div style="font-size: 16px;color: #333333">{{$t('test_track.plan_view.base_info')}}</div>
<br/>
<el-form-item :label="$t('api_report.request')" prop="responsible">
<el-input :placeholder="$t('api_test.delimit.request.path_info')" v-model="httpForm.request"
class="ms-http-input" size="small">
<el-select v-model="reqValue" slot="prepend" style="width: 100px">
<el-input :placeholder="$t('api_test.delimit.request.path_info')" v-model="url"
class="ms-http-input" size="small" :disabled="false">
<el-select v-model="path" slot="prepend" style="width: 100px">
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
</el-select>
</el-input>
@ -33,13 +33,13 @@
</el-form-item>
<div style="font-size: 16px;color: #333333;padding-top: 30px">请求参数</div>
<div style="font-size: 16px;color: #333333;padding-top: 30px">{{$t('api_test.delimit.request.req_param')}}</div>
<br/>
<!-- HTTP 请求参数 -->
<ms-api-request-form :debug-report-id="debugReportId" :request="selected" :scenario="currentScenario"/>
<ms-api-request-form :request="apiData.request"/>
</el-form>
<div style="font-size: 16px;color: #333333 ;padding-top: 30px">响应内容</div>
<div style="font-size: 16px;color: #333333 ;padding-top: 30px">{{$t('api_test.delimit.request.res_param')}}</div>
<br/>
<ms-response-text :response="responseData"></ms-response-text>
@ -47,7 +47,7 @@
<!-- 加载用例 -->
<ms-bottom-container v-bind:enableAsideHidden="isHide">
<ms-api-case-list @apiCaseClose="apiCaseClose" :api="httpForm"></ms-api-case-list>
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="apiData" ref="caseList"/>
</ms-bottom-container>
</div>
@ -55,69 +55,121 @@
<script>
import MsApiRequestForm from "../request/ApiRequestForm";
import {Request, Scenario} from "../../model/ScenarioModel";
import {downloadFile, getUUID} from "@/common/js/utils";
import MsResponseText from "../../../report/components/ResponseText";
import MsApiCaseList from "../ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer";
import MsBottomContainer from "../BottomContainer";
import {RequestFactory, Test} from "../../model/ScenarioModel";
import {REQ_METHOD} from "../../model/JsonData";
export default {
name: "ApiConfig",
components: {MsResponseText, MsApiRequestForm, MsApiCaseList, MsContainer, MsBottomContainer},
data() {
return {
result: {},
rule: {},
isHide: true,
labelPosition: 'right',
httpForm: {},
options: [],
reqValue: '',
debugReportId: '',
url: '',
path: '',
currentRequest: {},
responseData: {},
currentScenario: Scenario,
selected: [Scenario, Request],
reqOptions: [{
id: 'GET',
label: 'GET'
}, {
id: 'POST',
label: 'POST'
}],
moduleValue: '',
reqOptions: REQ_METHOD,
}
},
props: {httpData: {},},
props: {apiData: {}},
methods: {
handleCommand(e) {
switch (e) {
case "load_case":
return this.loadCase();
case "save_as_case":
return "";
return this.saveAsCase();
case "update_api":
return "update_api";
return this.updateApi();
case "save_as_api":
return "save_as_api";
return this.saveAsApi();
default:
return [];
}
},
saveAs() {
this.$emit('saveAs', this.httpForm);
this.$emit('saveAs', this.apiData);
},
loadCase() {
console.log(this.httpForm)
this.isHide = false;
},
apiCaseClose() {
this.isHide = true;
},
getBodyUploadFiles() {
let bodyUploadFiles = [];
this.apiData.bodyUploadIds = [];
let request = this.apiData.request;
if (request.body) {
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;
this.apiData.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
return bodyUploadFiles;
},
saveAsCase() {
let testCase = {};
let test = new Test();
test.request = this.apiData.request;
testCase.test = test;
testCase.request = this.apiData.request;
testCase.name = this.apiData.name;
testCase.priority = "P0";
this.$refs.caseList.saveTestCase(testCase);
},
saveAsApi() {
let data = {};
data.request = JSON.stringify(this.apiData.request);
data.path = this.apiData.path;
data.url = this.apiData.url;
data.status = this.apiData.status;
data.userId = this.apiData.userId;
data.description = this.apiData.description;
this.$emit('saveAsApi', data);
},
editApi(url) {
this.apiData.url = this.url;
this.apiData.path = this.path;
let bodyFiles = this.getBodyUploadFiles();
let jmx = this.apiData.test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
this.$fileUpload(url, file, bodyFiles, this.apiData, () => {
this.$success(this.$t('commons.save_success'));
this.$emit('saveApi', this.apiData);
});
},
updateApi() {
let url = "/api/delimit/update";
this.editApi(url);
},
selectTestCase(item) {
if (item != null) {
this.apiData.request = new RequestFactory(JSON.parse(item.request));
} else {
this.apiData.request = this.currentRequest;
}
}
},
watch: {
httpData(v) {
this.httpForm = v;
}
created() {
this.currentRequest = this.apiData.request;
this.url = this.apiData.url;
this.path = this.apiData.path;
}
}
</script>

View File

@ -0,0 +1,39 @@
/* 用例等级 */
export const PRIORITY = [
{name: 'P0', id: 'P0'},
{name: 'P1', id: 'P1'},
{name: 'P2', id: 'P2'},
{name: 'P3', id: 'P3'}
]
export const OPTIONS = [
{value: 'HTTP', name: 'HTTP'},
{value: 'DUBBO', name: 'DUBBO'},
{value: 'TCP', name: 'TCP'},
{value: 'SQL', name: 'SQL'}
]
export const DEFAULT_DATA = [{
"id": "root",
"name": "默认模块",
"level": 0,
"children": [],
}]
export const REQ_METHOD = [
{id: 'GET', label: 'GET'},
{id: 'POST', label: 'POST'}
]
export const API_STATUS = [
{id: 'Prepare', label: '未开始'},
{id: 'Underway', label: '进行中'},
{id: 'Completed', label: '已完成'}
]
export const API_METHOD_COLOUR = [
['GET', "#61AFFE"], ['POST', '#49CC90'], ['PUT', '#fca130'],
['PATCH', '#E2EE11'], ['DELETE', '#f93e3d'], ['OPTIONS', '#0EF5DA'],
['HEAD', '#8E58E7'], ['CONNECT', '#90AFAE'],
['DUBBO', '#C36EEF'], ['SQL', '#0AEAD4'], ['TCP', '#0A52DF'],
]

View File

@ -498,6 +498,10 @@ export default {
verification_method: "Verification method",
verified: "verified",
encryption: "encryption",
req_param: "Request parameter",
res_param: "Response template",
batch_delete: "Batch deletion",
delete_confirm: "confirm deletion",
}
},
environment: {

View File

@ -499,7 +499,10 @@ export default {
verification_method: "认证方式",
verified: "认证",
encryption: "加密",
req_param: "请求参数",
res_param: "响应模版",
batch_delete: "批量删除",
delete_confirm: "确认删除接口",
}
},
environment: {

View File

@ -499,8 +499,11 @@ export default {
verification_method: "認證方式",
verified: "認證",
encryption: "加密",
req_param: "請求參數",
res_param: "響應模版",
batch_delete: "批量删除",
delete_confirm: "確認刪除接口",
}
},
environment: {
name: "環境名稱",