style(接口测试): 使用Prettier统一按照标准格式化
This commit is contained in:
parent
c1705b48c9
commit
db47ab5f5b
|
@ -1,3 +1,3 @@
|
|||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"]
|
||||
presets: ['@vue/cli-plugin-babel/preset'],
|
||||
};
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong
|
||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||
properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong
|
||||
>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
const BASE_URL = '/environment/';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import {fileUpload} from "@/api/base-network";
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
import { fileUpload } from '@/api/base-network';
|
||||
|
||||
export function getMockApiParams(id) {
|
||||
return get('/mock/config/get-api-params/' + id);
|
||||
|
@ -33,7 +33,7 @@ export function getMockTestData(mockParam) {
|
|||
return post('/mock/config/test-data', mockParam);
|
||||
}
|
||||
|
||||
export function updateMockExpectConfig(mockParam, file, files,) {
|
||||
export function updateMockExpectConfig(mockParam, file, files) {
|
||||
return fileUpload('/mock/config/update/form', file, files, mockParam);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {get} from 'metersphere-frontend/src/plugins/request'
|
||||
import { get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getApiTemplate(projectId) {
|
||||
return new Promise((resolve) => {
|
||||
|
@ -7,7 +7,7 @@ export function getApiTemplate(projectId) {
|
|||
get(baseUrl + projectId).then((response) => {
|
||||
template = response.data;
|
||||
if (template.customFields) {
|
||||
template.customFields.forEach(item => {
|
||||
template.customFields.forEach((item) => {
|
||||
if (item.options) {
|
||||
item.options = JSON.parse(item.options);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {fileUpload} from "@/api/base-network";
|
||||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { fileUpload } from '@/api/base-network';
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function editApiTestCaseOrder(request) {
|
||||
return post('/api/testcase/sort', request);
|
||||
|
@ -83,9 +83,9 @@ export function editApiCase(url, file, files, params) {
|
|||
}
|
||||
|
||||
export function apiTestCaseCount(param) {
|
||||
return post('/api/testcase/case-count',param);
|
||||
return post('/api/testcase/case-count', param);
|
||||
}
|
||||
|
||||
export function getApiCaseEnvironments(param) {
|
||||
return post('/api/testcase/get/env',param);
|
||||
return post('/api/testcase/get/env', param);
|
||||
}
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
import {request, socket} from "metersphere-frontend/src/plugins/request"
|
||||
import jsFileDownload from 'js-file-download'
|
||||
import {$error} from "metersphere-frontend/src/plugins/message"
|
||||
import { request, socket } from 'metersphere-frontend/src/plugins/request';
|
||||
import jsFileDownload from 'js-file-download';
|
||||
import { $error } from 'metersphere-frontend/src/plugins/message';
|
||||
|
||||
export function getUploadConfig(url, formData) {
|
||||
return {
|
||||
method: 'POST', url: url, data: formData, headers: {
|
||||
'Content-Type': undefined
|
||||
}
|
||||
method: 'POST',
|
||||
url: url,
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function fileUpload(url, file, files, param) {
|
||||
let formData = new FormData();
|
||||
if (file) {
|
||||
formData.append("file", file);
|
||||
formData.append('file', file);
|
||||
}
|
||||
if (files) {
|
||||
files.forEach(f => {
|
||||
formData.append("files", f);
|
||||
files.forEach((f) => {
|
||||
formData.append('files', f);
|
||||
});
|
||||
}
|
||||
formData.append('request', new Blob([JSON.stringify(param)], {type: "application/json"}));
|
||||
formData.append(
|
||||
'request',
|
||||
new Blob([JSON.stringify(param)], { type: 'application/json' })
|
||||
);
|
||||
let config = getUploadConfig(url, formData);
|
||||
return request(config);
|
||||
}
|
||||
|
@ -35,15 +41,18 @@ export function downloadFile(method, url, data, fileName) {
|
|||
method: method,
|
||||
data: data,
|
||||
responseType: 'blob',
|
||||
headers: {"Content-Type": "application/json; charset=utf-8"}
|
||||
headers: { 'Content-Type': 'application/json; charset=utf-8' },
|
||||
};
|
||||
request(config)
|
||||
.then((res) => {
|
||||
fileName = fileName ? fileName : window.decodeURI(res.headers['content-disposition'].split('=')[1]);
|
||||
fileName = fileName
|
||||
? fileName
|
||||
: window.decodeURI(res.headers['content-disposition'].split('=')[1]);
|
||||
jsFileDownload(res.data, fileName);
|
||||
}).catch((e) => {
|
||||
$error(e.message);
|
||||
})
|
||||
})
|
||||
.catch((e) => {
|
||||
$error(e.message);
|
||||
});
|
||||
}
|
||||
|
||||
export function baseSocket(url) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {get, post} from 'metersphere-frontend/src/plugins/request'
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getFuncById(id) {
|
||||
return get('/custom/func/get/' + id);
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getApiModules(projectId, protocol, currentVersion) {
|
||||
let url = '/api/module/list/' + projectId + '/' + protocol + (currentVersion ? '/' + currentVersion : '');
|
||||
let url =
|
||||
'/api/module/list/' +
|
||||
projectId +
|
||||
'/' +
|
||||
protocol +
|
||||
(currentVersion ? '/' + currentVersion : '');
|
||||
return get(url);
|
||||
}
|
||||
|
||||
|
@ -11,7 +16,13 @@ export function getApiModuleByProjectIdAndProtocol(projectId, protocol) {
|
|||
}
|
||||
|
||||
export function getApiModuleByTrash(projectId, protocol, currentVersion) {
|
||||
let url = '/api/module/trash/list/' + projectId + '/' + protocol + '/' + (currentVersion ? '/' + currentVersion : '');
|
||||
let url =
|
||||
'/api/module/trash/list/' +
|
||||
projectId +
|
||||
'/' +
|
||||
protocol +
|
||||
'/' +
|
||||
(currentVersion ? '/' + currentVersion : '');
|
||||
return get(url);
|
||||
}
|
||||
|
||||
|
@ -44,5 +55,3 @@ export function dragModule(param) {
|
|||
export function posModule(param) {
|
||||
return post('/api/module/pos', param);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {post, get} from 'metersphere-frontend/src/plugins/request'
|
||||
import { post, get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getApiReportPage(currentPage, pageSize, condition) {
|
||||
let url = '/api/testcase/list-execute-res/' + currentPage + '/' + pageSize;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {fileDownload, fileUpload} from "@/api/base-network";
|
||||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { fileDownload, fileUpload } from '@/api/base-network';
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getRelationshipCountApi(id) {
|
||||
return get('/api/definition/relationship/count/' + id);
|
||||
|
@ -62,11 +62,16 @@ export function apiListBatch(params) {
|
|||
}
|
||||
|
||||
export function definitionWeekList(projectId, page, pageSize) {
|
||||
return post('/api/definition/list/week/' + projectId + '/' + page + '/' + pageSize);
|
||||
return post(
|
||||
'/api/definition/list/week/' + projectId + '/' + page + '/' + pageSize
|
||||
);
|
||||
}
|
||||
|
||||
export function getRelevanceDefinitionPage(page, pageSize, params) {
|
||||
return post('/api/definition/list/relevance/' + page + '/' + pageSize, params);
|
||||
return post(
|
||||
'/api/definition/list/relevance/' + page + '/' + pageSize,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
export function getDefinitionPage(page, pageSize, params) {
|
||||
|
@ -110,7 +115,10 @@ export function definitionReduction(params) {
|
|||
}
|
||||
|
||||
export function definitionRelationship(currentPage, pageSize, params) {
|
||||
return post('/api/definition/relationship/relate/' + currentPage + '/' + pageSize, params);
|
||||
return post(
|
||||
'/api/definition/relationship/relate/' + currentPage + '/' + pageSize,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
export function addRelationship(params) {
|
||||
|
@ -122,11 +130,17 @@ export function jsonGenerator(params) {
|
|||
}
|
||||
|
||||
export function getDefinitionReference(currentPage, pageSize, params) {
|
||||
return post('/api/definition/get-reference/' + currentPage + '/' + pageSize, params);
|
||||
return post(
|
||||
'/api/definition/get-reference/' + currentPage + '/' + pageSize,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
export function getPlanReference(currentPage, pageSize, params) {
|
||||
return post('/test/plan/api/case/get-reference/' + currentPage + '/' + pageSize, params);
|
||||
return post(
|
||||
'/test/plan/api/case/get-reference/' + currentPage + '/' + pageSize,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
export function deleteBatchByParams(params) {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getRelationshipGraph(id, type) {
|
||||
return get('/graph/relationship/graph/' + id + '/' + type);
|
||||
}
|
||||
|
||||
|
||||
export function getGraphByCondition(relationshipType, param) {
|
||||
return post('/graph/relationship/graph/condition/' + relationshipType, param);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {fileUpload} from "@/api/base-network";
|
||||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { fileUpload } from '@/api/base-network';
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function apiCountByProjectId(projectId) {
|
||||
return get('/home/api/count/' + projectId);
|
||||
|
@ -17,7 +17,6 @@ export function scheduleTaskCountByProjectId(projectId) {
|
|||
return get('/home/schedule/task/count/' + projectId);
|
||||
}
|
||||
|
||||
|
||||
export function dubboProviders(params) {
|
||||
return post('/home/api/dubbo/providers', params);
|
||||
}
|
||||
|
@ -32,11 +31,20 @@ export function genPerformanceTestXml(file, files, params) {
|
|||
}
|
||||
|
||||
export function getRunningTask(selectProjectId, currentPage, pageSize, param) {
|
||||
return post("/task/center/runningTask/" + selectProjectId + "/" + currentPage + "/" + pageSize, param);
|
||||
return post(
|
||||
'/task/center/runningTask/' +
|
||||
selectProjectId +
|
||||
'/' +
|
||||
currentPage +
|
||||
'/' +
|
||||
pageSize,
|
||||
param
|
||||
);
|
||||
}
|
||||
|
||||
export function formatNumber(param) {
|
||||
let num = (param || 0).toString(), result = '';
|
||||
let num = (param || 0).toString(),
|
||||
result = '';
|
||||
while (num.length > 3) {
|
||||
result = ',' + num.slice(-3) + result;
|
||||
num = num.slice(0, num.length - 3);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function uploadMarkDownImg(file) {
|
||||
|
||||
}
|
||||
export function uploadMarkDownImg(file) {}
|
||||
|
||||
export function deleteMarkDownImg(file) {
|
||||
if (file) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {post, get} from 'metersphere-frontend/src/plugins/request'
|
||||
import { post, get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getMessageById(id) {
|
||||
let url = '/notice/search/message/' + id;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getPlugin(id) {
|
||||
return get('/plugin/get/' + id);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {get, post} from 'metersphere-frontend/src/plugins/request'
|
||||
import {getCurrentWorkspaceId} from 'metersphere-frontend/src/utils/token'
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
import { getCurrentWorkspaceId } from 'metersphere-frontend/src/utils/token';
|
||||
|
||||
export function getProject(projectId) {
|
||||
let url = '/project/get/' + projectId;
|
||||
|
@ -11,7 +11,8 @@ export function getOwnerProjectIds() {
|
|||
return get(url);
|
||||
}
|
||||
|
||||
export function getMaintainer() {getAll
|
||||
export function getMaintainer() {
|
||||
getAll;
|
||||
let url = '/user/project/member/list';
|
||||
return get(url);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {post, get} from 'metersphere-frontend/src/plugins/request'
|
||||
import { post, get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getModuleByProjectId(projectId) {
|
||||
let url = '/api/automation/module/list/' + projectId;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {post, get} from 'metersphere-frontend/src/plugins/request'
|
||||
import { post, get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getReportPage(currentPage, pageSize, condition) {
|
||||
let url = '/api/scenario/report/list/' + currentPage + '/' + pageSize;
|
||||
|
@ -12,7 +12,7 @@ export function getReportPageDetail(currentPage, pageSize, condition) {
|
|||
|
||||
export function delReport(id) {
|
||||
let url = '/api/scenario/report/delete';
|
||||
return post(url, {id: id});
|
||||
return post(url, { id: id });
|
||||
}
|
||||
|
||||
export function delBatchReport(condition) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {fileUpload} from "@/api/base-network";
|
||||
import {get, post, request} from 'metersphere-frontend/src/plugins/request'
|
||||
import { fileUpload } from '@/api/base-network';
|
||||
import { get, post, request } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getScenarioById(scenarioId) {
|
||||
return get('/api/automation/get/' + scenarioId);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {post, get} from 'metersphere-frontend/src/plugins/request'
|
||||
import { post, get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getScheduleByIdAndType(scheduleResourceID, taskType) {
|
||||
let url = '/api/schedule/get/' + scheduleResourceID + '/' + taskType;
|
||||
|
|
|
@ -1,24 +1,30 @@
|
|||
import {post, generateShareUrl, get} from "metersphere-frontend/src/plugins/request"
|
||||
import {
|
||||
post,
|
||||
generateShareUrl,
|
||||
get,
|
||||
} from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function generateApiDocumentShareInfo(param) {
|
||||
return post("/share/generate/api/document", param);
|
||||
return post('/share/generate/api/document', param);
|
||||
}
|
||||
|
||||
export function selectApiInfoByParam(param, currentPage, pageSize) {
|
||||
return post("/share/list/" + currentPage + "/" + pageSize, param);
|
||||
return post('/share/list/' + currentPage + '/' + pageSize, param);
|
||||
}
|
||||
|
||||
export function generateShareInfoWithExpired(param) {
|
||||
return post("/share/generate/expired", param);
|
||||
return post('/share/generate/expired', param);
|
||||
}
|
||||
|
||||
export function getShareContent(shareId, stepId) {
|
||||
let url = "/share/" + shareId + "/scenario/report/detail/" + stepId;
|
||||
let url = '/share/' + shareId + '/scenario/report/detail/' + stepId;
|
||||
return get(url);
|
||||
}
|
||||
|
||||
export function getShareApiReport(shareId, testId) {
|
||||
return get('/share/api/definition/report/getReport/' + shareId + '/' + testId);
|
||||
return get(
|
||||
'/share/api/definition/report/getReport/' + shareId + '/' + testId
|
||||
);
|
||||
}
|
||||
|
||||
export function getShareInfo(id) {
|
||||
|
@ -36,18 +42,18 @@ export function getShareId() {
|
|||
});
|
||||
return shareId;
|
||||
} else {
|
||||
if (hrefUrl.indexOf("?") > 0) {
|
||||
let paramArr = hrefUrl.split("?");
|
||||
if (hrefUrl.indexOf('?') > 0) {
|
||||
let paramArr = hrefUrl.split('?');
|
||||
if (paramArr.length > 1) {
|
||||
let shareId = paramArr[1];
|
||||
if (shareId.indexOf("#") > 0) {
|
||||
shareId = shareId.split("#")[0];
|
||||
if (shareId.indexOf('#') > 0) {
|
||||
shareId = shareId.split('#')[0];
|
||||
}
|
||||
return shareId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getShareRedirectUrl(data) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import { get, post } from 'metersphere-frontend/src/plugins/request';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
|
||||
export function getPlanStageOption() {
|
||||
let projectID = getCurrentProjectID();
|
||||
|
@ -7,7 +7,7 @@ export function getPlanStageOption() {
|
|||
}
|
||||
|
||||
export function planPage(page, pageSize, params) {
|
||||
return post('/test/plan/list/all/'+ page + '/' + pageSize, params);
|
||||
return post('/test/plan/list/all/' + page + '/' + pageSize, params);
|
||||
}
|
||||
|
||||
export function testPlanGetPrincipal(id) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {get} from "metersphere-frontend/src/plugins/request"
|
||||
import { get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getTestResourcePools() {
|
||||
let url = '/testresourcepool/list/quota/valid';
|
||||
return get(url);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {get} from "metersphere-frontend/src/plugins/request"
|
||||
import { get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function getCurrentByResourceId(id) {
|
||||
return get('/api/current/user/' + id, () => {
|
||||
});
|
||||
return get('/api/current/user/' + id, () => {});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {post, get} from "metersphere-frontend/src/plugins/request"
|
||||
import { post, get } from 'metersphere-frontend/src/plugins/request';
|
||||
|
||||
export function apiTestReRun(condition) {
|
||||
return post('/api/test/exec/rerun', condition);
|
||||
|
@ -26,4 +26,4 @@ export function getProjectVersions(projectId) {
|
|||
|
||||
export function versionEnableByProjectId(projectId) {
|
||||
return get('/project/version/enable/' + projectId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,27 @@
|
|||
<template>
|
||||
<el-col>
|
||||
<ms-api-header-menus/>
|
||||
<ms-api-header-menus />
|
||||
<div>
|
||||
<transition>
|
||||
<keep-alive>
|
||||
<router-view :baseUrl="baseUrl"/>
|
||||
<router-view :baseUrl="baseUrl" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</div>
|
||||
</el-col>
|
||||
</template>
|
||||
<script>
|
||||
import MsApiHeaderMenus from './head/ApiHeaderMenus';
|
||||
|
||||
import MsApiHeaderMenus from "./head/ApiHeaderMenus";
|
||||
|
||||
export default {
|
||||
name: "MsApiTest",
|
||||
components: {MsApiHeaderMenus},
|
||||
data() {
|
||||
return {
|
||||
baseUrl: "api"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'MsApiTest',
|
||||
components: { MsApiHeaderMenus },
|
||||
data() {
|
||||
return {
|
||||
baseUrl: 'api',
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -15,14 +15,22 @@
|
|||
page-source="scenario"
|
||||
:is-trash-data="trashEnable"
|
||||
:type="'edit'"
|
||||
:total='total'
|
||||
ref="nodeTree"/>
|
||||
:total="total"
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</ms-aside-container>
|
||||
<ms-main-container>
|
||||
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="closeConfirm">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
@tab-click="addTab"
|
||||
@tab-remove="closeConfirm"
|
||||
>
|
||||
<el-tab-pane
|
||||
name="trash" :closable="true"
|
||||
:label="$t('commons.trash')" v-if="trashEnable">
|
||||
name="trash"
|
||||
:closable="true"
|
||||
:label="$t('commons.trash')"
|
||||
v-if="trashEnable"
|
||||
>
|
||||
<ms-api-scenario-list
|
||||
@getTrashCase="getTrashCase"
|
||||
@refreshTree="refreshTree"
|
||||
|
@ -39,13 +47,21 @@
|
|||
:custom-num="customNum"
|
||||
:init-api-table-opretion="initApiTableOpretion"
|
||||
@updateInitApiTableOpretion="updateInitApiTableOpretion"
|
||||
ref="apiTrashScenarioList">
|
||||
ref="apiTrashScenarioList"
|
||||
>
|
||||
<template v-slot:version>
|
||||
<mx-version-select v-xpack :project-id="projectId" @changeVersion="changeVersion"/>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion"
|
||||
/>
|
||||
</template>
|
||||
</ms-api-scenario-list>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="default" :label="$t('api_test.automation.scenario_list')">
|
||||
<el-tab-pane
|
||||
name="default"
|
||||
:label="$t('api_test.automation.scenario_list')"
|
||||
>
|
||||
<ms-api-scenario-list
|
||||
v-if="!trashEnable"
|
||||
@getTrashCase="getTrashCase"
|
||||
|
@ -63,41 +79,63 @@
|
|||
:custom-num="customNum"
|
||||
:init-api-table-opretion="initApiTableOpretion"
|
||||
@updateInitApiTableOpretion="updateInitApiTableOpretion"
|
||||
ref="apiScenarioList">
|
||||
ref="apiScenarioList"
|
||||
>
|
||||
<template v-slot:version>
|
||||
<mx-version-select v-xpack :project-id="projectId" @changeVersion="changeVersion"/>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion"
|
||||
/>
|
||||
</template>
|
||||
</ms-api-scenario-list>
|
||||
</el-tab-pane>
|
||||
|
||||
|
||||
<el-tab-pane
|
||||
:key="item.name"
|
||||
v-for="(item) in tabs"
|
||||
v-for="item in tabs"
|
||||
:label="item.label"
|
||||
:name="item.name"
|
||||
closable>
|
||||
<el-tooltip slot="label" effect="dark" :content="item.label" placement="bottom-start"
|
||||
class="ms-tab-name-width">
|
||||
closable
|
||||
>
|
||||
<el-tooltip
|
||||
slot="label"
|
||||
effect="dark"
|
||||
:content="item.label"
|
||||
placement="bottom-start"
|
||||
class="ms-tab-name-width"
|
||||
>
|
||||
<span>{{ item.label }}</span>
|
||||
</el-tooltip>
|
||||
<div class="ms-api-scenario-div">
|
||||
<ms-edit-api-scenario @refresh="refresh" @openScenario="editScenario" @closePage="closePage"
|
||||
:currentScenario="item.currentScenario"
|
||||
:custom-num="customNum" :moduleOptions="moduleOptions" ref="autoScenarioConfig"/>
|
||||
<ms-edit-api-scenario
|
||||
@refresh="refresh"
|
||||
@openScenario="editScenario"
|
||||
@closePage="closePage"
|
||||
:currentScenario="item.currentScenario"
|
||||
:custom-num="customNum"
|
||||
:moduleOptions="moduleOptions"
|
||||
ref="autoScenarioConfig"
|
||||
/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane name="add" v-if="hasPermission('PROJECT_API_SCENARIO:READ+CREATE')">
|
||||
<el-tab-pane
|
||||
name="add"
|
||||
v-if="hasPermission('PROJECT_API_SCENARIO:READ+CREATE')"
|
||||
>
|
||||
<template v-slot:label>
|
||||
<el-dropdown @command="handleCommand">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini"/>
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="ADD"
|
||||
v-permission="['PROJECT_API_SCENARIO:READ+CREATE']">
|
||||
<el-dropdown-item
|
||||
command="ADD"
|
||||
v-permission="['PROJECT_API_SCENARIO:READ+CREATE']"
|
||||
>
|
||||
{{ $t('api_test.automation.add_scenario') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="CLOSE_ALL">{{ $t('api_test.definition.request.close_all_label') }}
|
||||
<el-dropdown-item command="CLOSE_ALL"
|
||||
>{{ $t('api_test.definition.request.close_all_label') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
@ -109,29 +147,45 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {getCurrentProjectID, getCurrentUser, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import {hasPermission} from "metersphere-frontend/src/utils/permission";
|
||||
import {PROJECT_ID, WORKSPACE_ID} from "metersphere-frontend/src/utils/constants";
|
||||
import {buildTree} from "metersphere-frontend/src/model/NodeTree";
|
||||
import {getScenarioById, getScenarioByTrash} from "@/api/scenario";
|
||||
import {getOwnerProjectIds, getProject, getProjectConfig} from "@/api/project";
|
||||
import {getModuleByProjectId} from "@/api/scenario-module";
|
||||
import {useApiStore} from "@/store";
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentUser,
|
||||
getCurrentWorkspaceId,
|
||||
} from 'metersphere-frontend/src/utils/token';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { hasPermission } from 'metersphere-frontend/src/utils/permission';
|
||||
import {
|
||||
PROJECT_ID,
|
||||
WORKSPACE_ID,
|
||||
} from 'metersphere-frontend/src/utils/constants';
|
||||
import { buildTree } from 'metersphere-frontend/src/model/NodeTree';
|
||||
import { getScenarioById, getScenarioByTrash } from '@/api/scenario';
|
||||
import {
|
||||
getOwnerProjectIds,
|
||||
getProject,
|
||||
getProjectConfig,
|
||||
} from '@/api/project';
|
||||
import { getModuleByProjectId } from '@/api/scenario-module';
|
||||
import { useApiStore } from '@/store';
|
||||
|
||||
const store = useApiStore();
|
||||
const jsondiffpatch = require('jsondiffpatch');
|
||||
export default {
|
||||
name: "ApiAutomation",
|
||||
name: 'ApiAutomation',
|
||||
components: {
|
||||
MxVersionSelect: () => import("metersphere-frontend/src/components/version/MxVersionSelect"),
|
||||
MsApiScenarioModule: () => import("@/business/automation/scenario/ApiScenarioModule"),
|
||||
MsApiScenarioList: () => import("@/business/automation/scenario/ApiScenarioList"),
|
||||
MsMainContainer: () => import("metersphere-frontend/src/components/MsMainContainer"),
|
||||
MsAsideContainer: () => import("metersphere-frontend/src/components/MsAsideContainer"),
|
||||
MsContainer: () => import("metersphere-frontend/src/components/MsContainer"),
|
||||
MsEditApiScenario: () => import("./scenario/EditApiScenario")
|
||||
MxVersionSelect: () =>
|
||||
import('metersphere-frontend/src/components/version/MxVersionSelect'),
|
||||
MsApiScenarioModule: () =>
|
||||
import('@/business/automation/scenario/ApiScenarioModule'),
|
||||
MsApiScenarioList: () =>
|
||||
import('@/business/automation/scenario/ApiScenarioList'),
|
||||
MsMainContainer: () =>
|
||||
import('metersphere-frontend/src/components/MsMainContainer'),
|
||||
MsAsideContainer: () =>
|
||||
import('metersphere-frontend/src/components/MsAsideContainer'),
|
||||
MsContainer: () =>
|
||||
import('metersphere-frontend/src/components/MsContainer'),
|
||||
MsEditApiScenario: () => import('./scenario/EditApiScenario'),
|
||||
},
|
||||
comments: {},
|
||||
computed: {
|
||||
|
@ -167,7 +221,7 @@ export default {
|
|||
trashEnable: false,
|
||||
selectNodeIds: [],
|
||||
nodeTree: [],
|
||||
currentModulePath: "",
|
||||
currentModulePath: '',
|
||||
customNum: false,
|
||||
//影响API表格刷新的操作。 为了防止高频率刷新模块列表用。如果是模块更新而造成的表格刷新,则不回调模块刷新方法
|
||||
initApiTableOpretion: 'init',
|
||||
|
@ -204,10 +258,11 @@ export default {
|
|||
this.renderComponent = true;
|
||||
});
|
||||
},
|
||||
'$route'(to, from) { // 路由改变时,把接口定义界面中的 ctrl s 保存快捷键监听移除
|
||||
$route(to, from) {
|
||||
// 路由改变时,把接口定义界面中的 ctrl s 保存快捷键监听移除
|
||||
if (to.path.indexOf('/api/automation') == -1) {
|
||||
if (this.$refs && this.$refs.autoScenarioConfig) {
|
||||
this.$refs.autoScenarioConfig.forEach(item => {
|
||||
this.$refs.autoScenarioConfig.forEach((item) => {
|
||||
item.removeListener();
|
||||
});
|
||||
}
|
||||
|
@ -215,12 +270,13 @@ export default {
|
|||
},
|
||||
selectNodeIds() {
|
||||
if (!this.trashEnable) {
|
||||
this.activeName = "default";
|
||||
this.activeName = 'default';
|
||||
}
|
||||
},
|
||||
activeName() {
|
||||
this.isAsideHidden = (this.activeName === 'default' || this.activeName === 'trash');
|
||||
}
|
||||
this.isAsideHidden =
|
||||
this.activeName === 'default' || this.activeName === 'trash';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission,
|
||||
|
@ -234,20 +290,28 @@ export default {
|
|||
if (!params) {
|
||||
return;
|
||||
}
|
||||
if (typeof params === "string") {
|
||||
let paramArr = params.split("edit:");
|
||||
if (typeof params === 'string') {
|
||||
let paramArr = params.split('edit:');
|
||||
if (paramArr.length !== 2) {
|
||||
return;
|
||||
}
|
||||
let scenarioId = paramArr[1];
|
||||
//查找单条数据,跳转修改页面
|
||||
getScenarioById(scenarioId).then(response => {
|
||||
getScenarioById(scenarioId).then((response) => {
|
||||
let data = response.data;
|
||||
if (data) {
|
||||
let row = data;
|
||||
let checks = ["array", "object"];
|
||||
if (row && row.tags && (checks.indexOf(Object.prototype.toString.call(row.tags)
|
||||
.match(/\[object (\w+)\]/)[1].toLowerCase()) !== -1)) {
|
||||
let checks = ['array', 'object'];
|
||||
if (
|
||||
row &&
|
||||
row.tags &&
|
||||
checks.indexOf(
|
||||
Object.prototype.toString
|
||||
.call(row.tags)
|
||||
.match(/\[object (\w+)\]/)[1]
|
||||
.toLowerCase()
|
||||
) !== -1
|
||||
) {
|
||||
row.tags = JSON.parse(row.tags);
|
||||
}
|
||||
//如果树未加载
|
||||
|
@ -262,11 +326,14 @@ export default {
|
|||
}
|
||||
},
|
||||
initModules(row, projectId) {
|
||||
getModuleByProjectId(projectId).then(response => {
|
||||
getModuleByProjectId(projectId).then((response) => {
|
||||
if (response.data) {
|
||||
response.data.forEach(node => {
|
||||
node.name = node.name === '未规划场景' ? this.$t('api_test.automation.unplanned_scenario') : node.name
|
||||
buildTree(node, {path: ''});
|
||||
response.data.forEach((node) => {
|
||||
node.name =
|
||||
node.name === '未规划场景'
|
||||
? this.$t('api_test.automation.unplanned_scenario')
|
||||
: node.name;
|
||||
buildTree(node, { path: '' });
|
||||
});
|
||||
this.moduleOptions = response.data;
|
||||
}
|
||||
|
@ -276,13 +343,13 @@ export default {
|
|||
changeRedirectParam(redirectIDParam) {
|
||||
this.redirectID = redirectIDParam;
|
||||
if (redirectIDParam != null) {
|
||||
if (this.redirectFlag == "none") {
|
||||
this.activeName = "default";
|
||||
if (this.redirectFlag == 'none') {
|
||||
this.activeName = 'default';
|
||||
this.addListener();
|
||||
this.redirectFlag = "redirected";
|
||||
this.redirectFlag = 'redirected';
|
||||
}
|
||||
} else {
|
||||
this.redirectFlag = "none";
|
||||
this.redirectFlag = 'none';
|
||||
}
|
||||
},
|
||||
getPath(id, arr) {
|
||||
|
@ -290,7 +357,7 @@ export default {
|
|||
return null;
|
||||
}
|
||||
if (arr) {
|
||||
arr.forEach(item => {
|
||||
arr.forEach((item) => {
|
||||
if (item.id === id) {
|
||||
this.currentModulePath = item.path;
|
||||
}
|
||||
|
@ -311,16 +378,19 @@ export default {
|
|||
this.$warning(this.$t('commons.check_project_tip'));
|
||||
return;
|
||||
}
|
||||
this.currentModulePath = "";
|
||||
this.currentModulePath = '';
|
||||
if (tab.name === 'add') {
|
||||
let label = this.$t('api_test.automation.add_scenario');
|
||||
let name = getUUID().substring(0, 8);
|
||||
this.activeName = name;
|
||||
let currentScenario = {
|
||||
status: "Underway", principal: getCurrentUser().id,
|
||||
apiScenarioModuleId: "default-module", id: getUUID(),
|
||||
modulePath: "/" + this.$t("commons.module_title"),
|
||||
level: "P0", type: "add"
|
||||
status: 'Underway',
|
||||
principal: getCurrentUser().id,
|
||||
apiScenarioModuleId: 'default-module',
|
||||
id: getUUID(),
|
||||
modulePath: '/' + this.$t('commons.module_title'),
|
||||
level: 'P0',
|
||||
type: 'add',
|
||||
};
|
||||
if (this.nodeTree && this.nodeTree.length > 0) {
|
||||
currentScenario.apiScenarioModuleId = this.nodeTree[0].id;
|
||||
|
@ -332,7 +402,11 @@ export default {
|
|||
this.getPath(this.selectNodeIds[0], this.moduleOptions);
|
||||
currentScenario.modulePath = this.currentModulePath;
|
||||
}
|
||||
this.tabs.push({label: label, name: name, currentScenario: currentScenario});
|
||||
this.tabs.push({
|
||||
label: label,
|
||||
name: name,
|
||||
currentScenario: currentScenario,
|
||||
});
|
||||
}
|
||||
if (tab.name === 'edit') {
|
||||
let label = this.$t('api_test.automation.add_scenario');
|
||||
|
@ -340,55 +414,68 @@ export default {
|
|||
this.activeName = name;
|
||||
label = tab.currentScenario.name;
|
||||
if (!tab.currentScenario.level) {
|
||||
tab.currentScenario.level = "P0";
|
||||
tab.currentScenario.level = 'P0';
|
||||
}
|
||||
this.tabs.push({label: label, name: name, currentScenario: tab.currentScenario});
|
||||
this.tabs.push({
|
||||
label: label,
|
||||
name: name,
|
||||
currentScenario: tab.currentScenario,
|
||||
});
|
||||
}
|
||||
if (this.$refs && this.$refs.autoScenarioConfig) {
|
||||
this.$refs.autoScenarioConfig.forEach(item => {
|
||||
this.$refs.autoScenarioConfig.forEach((item) => {
|
||||
item.removeListener();
|
||||
}); // 删除所有tab的 ctrl + s 监听
|
||||
}); // 删除所有tab的 ctrl + s 监听
|
||||
this.addListener();
|
||||
}
|
||||
},
|
||||
addListener() {
|
||||
let index = this.tabs.findIndex(item => item.name === this.activeName); // 找到当前选中tab的index
|
||||
if (index != -1) { // 为当前选中的tab添加监听
|
||||
let index = this.tabs.findIndex((item) => item.name === this.activeName); // 找到当前选中tab的index
|
||||
if (index != -1) {
|
||||
// 为当前选中的tab添加监听
|
||||
this.$nextTick(() => {
|
||||
this.$refs.autoScenarioConfig[index].addListener();
|
||||
});
|
||||
}
|
||||
},
|
||||
handleTabClose() {
|
||||
let message = "";
|
||||
this.tabs.forEach(t => {
|
||||
let message = '';
|
||||
this.tabs.forEach((t) => {
|
||||
this.diff(t);
|
||||
if (t && this.isSave) {
|
||||
message += t.currentScenario.name + ",";
|
||||
message += t.currentScenario.name + ',';
|
||||
this.isSave = false;
|
||||
}
|
||||
});
|
||||
if (message !== "") {
|
||||
this.$alert(this.$t('commons.scenario') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this.tabs = [];
|
||||
this.trashEnable = false;
|
||||
this.activeName = "default";
|
||||
this.isSave = false;
|
||||
// 清除vuex中缓存的环境
|
||||
store.scenarioEnvMap = new Map();
|
||||
} else {
|
||||
this.isSave = false;
|
||||
}
|
||||
if (message !== '') {
|
||||
this.$alert(
|
||||
this.$t('commons.scenario') +
|
||||
' [ ' +
|
||||
message.substr(0, message.length - 1) +
|
||||
' ] ' +
|
||||
this.$t('commons.confirm_info'),
|
||||
'',
|
||||
{
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this.tabs = [];
|
||||
this.trashEnable = false;
|
||||
this.activeName = 'default';
|
||||
this.isSave = false;
|
||||
// 清除vuex中缓存的环境
|
||||
store.scenarioEnvMap = new Map();
|
||||
} else {
|
||||
this.isSave = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
);
|
||||
} else {
|
||||
this.tabs = [];
|
||||
this.trashEnable = false;
|
||||
this.activeName = "default";
|
||||
this.activeName = 'default';
|
||||
this.refresh();
|
||||
this.isSave = false;
|
||||
}
|
||||
|
@ -398,28 +485,28 @@ export default {
|
|||
},
|
||||
handleCommand(e) {
|
||||
switch (e) {
|
||||
case "ADD":
|
||||
this.addTab({name: 'add'});
|
||||
case 'ADD':
|
||||
this.addTab({ name: 'add' });
|
||||
break;
|
||||
case "CLOSE_ALL":
|
||||
case 'CLOSE_ALL':
|
||||
this.handleTabClose();
|
||||
break;
|
||||
default:
|
||||
this.addTab({name: 'add'});
|
||||
this.addTab({ name: 'add' });
|
||||
break;
|
||||
}
|
||||
},
|
||||
closePage(targetName) {
|
||||
this.tabs = this.tabs.filter(tab => tab.label !== targetName);
|
||||
this.tabs = this.tabs.filter((tab) => tab.label !== targetName);
|
||||
if (this.tabs.length > 0) {
|
||||
this.activeName = this.tabs[this.tabs.length - 1].name;
|
||||
this.addListener(); // 自动切换当前标签时,也添加监听
|
||||
} else {
|
||||
this.activeName = "default";
|
||||
this.activeName = 'default';
|
||||
}
|
||||
},
|
||||
diff(t) {
|
||||
if (t.currentScenario.type !== "add") {
|
||||
if (t.currentScenario.type !== 'add') {
|
||||
let v1 = t.currentScenario.scenarioDefinitionOrg;
|
||||
let v2 = {
|
||||
apiScenarioModuleId: t.currentScenario.apiScenarioModuleId,
|
||||
|
@ -429,7 +516,7 @@ export default {
|
|||
level: t.currentScenario.level,
|
||||
tags: t.currentScenario.tags,
|
||||
description: t.currentScenario.description,
|
||||
scenarioDefinition: t.currentScenario.scenarioDefinition
|
||||
scenarioDefinition: t.currentScenario.scenarioDefinition,
|
||||
};
|
||||
let v3 = JSON.parse(JSON.stringify(v2));
|
||||
if (v1.scenarioDefinition) {
|
||||
|
@ -438,7 +525,10 @@ export default {
|
|||
if (v3.scenarioDefinition) {
|
||||
this.deleteResourceIds(v3.scenarioDefinition);
|
||||
}
|
||||
let delta = jsondiffpatch.diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v3)));
|
||||
let delta = jsondiffpatch.diff(
|
||||
JSON.parse(JSON.stringify(v1)),
|
||||
JSON.parse(JSON.stringify(v3))
|
||||
);
|
||||
if (delta) {
|
||||
this.isSave = true;
|
||||
}
|
||||
|
@ -452,7 +542,7 @@ export default {
|
|||
},
|
||||
deleteResourceIds(array) {
|
||||
if (array instanceof Array && array.length > 0) {
|
||||
array.forEach(item => {
|
||||
array.forEach((item) => {
|
||||
if (item.currentScenarioId && item.currentScenarioId.length > 0) {
|
||||
delete item.currentScenarioId;
|
||||
}
|
||||
|
@ -490,7 +580,7 @@ export default {
|
|||
delete item.maxThreads;
|
||||
}
|
||||
if (item.parentIndex) {
|
||||
delete item.parentIndex
|
||||
delete item.parentIndex;
|
||||
}
|
||||
if (item.connectTimeout) {
|
||||
delete item.connectTimeout;
|
||||
|
@ -520,20 +610,24 @@ export default {
|
|||
item.delay = Number(item.delay);
|
||||
}
|
||||
if (item.body && item.body.kvs) {
|
||||
item.body.kvs.forEach(v => {
|
||||
item.body.kvs.forEach((v) => {
|
||||
if (v.files) {
|
||||
delete v.files;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
if (item.body && ((item.body.binary && item.body.binary.length === 0) || (item.body.kvs && item.body.kvs.length === 0))) {
|
||||
if (
|
||||
item.body &&
|
||||
((item.body.binary && item.body.binary.length === 0) ||
|
||||
(item.body.kvs && item.body.kvs.length === 0))
|
||||
) {
|
||||
delete item.body;
|
||||
}
|
||||
delete item.projectId;
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
this.deleteResourceIds(item.hashTree);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
closeConfirm(targetName) {
|
||||
|
@ -541,28 +635,38 @@ export default {
|
|||
this.selectNodeIds = [];
|
||||
this.trashEnable = false;
|
||||
} else {
|
||||
let message = "";
|
||||
this.tabs.forEach(tab => {
|
||||
let message = '';
|
||||
this.tabs.forEach((tab) => {
|
||||
if (tab.name === targetName) {
|
||||
this.diff(tab);
|
||||
if (tab && this.isSave) {
|
||||
message += tab.currentScenario.name ? tab.currentScenario.name : this.$t('api_test.automation.add_scenario');
|
||||
message += tab.currentScenario.name
|
||||
? tab.currentScenario.name
|
||||
: this.$t('api_test.automation.add_scenario');
|
||||
}
|
||||
}
|
||||
})
|
||||
if (message !== "") {
|
||||
this.$alert(this.$t('commons.scenario') + " [ " + message + " ] " + this.$t('commons.confirm_info'), '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this.removeTab(targetName);
|
||||
this.isSave = false;
|
||||
} else {
|
||||
this.isSave = false;
|
||||
}
|
||||
});
|
||||
if (message !== '') {
|
||||
this.$alert(
|
||||
this.$t('commons.scenario') +
|
||||
' [ ' +
|
||||
message +
|
||||
' ] ' +
|
||||
this.$t('commons.confirm_info'),
|
||||
'',
|
||||
{
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this.removeTab(targetName);
|
||||
this.isSave = false;
|
||||
} else {
|
||||
this.isSave = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
);
|
||||
} else {
|
||||
this.isSave = false;
|
||||
this.removeTab(targetName);
|
||||
|
@ -573,28 +677,33 @@ export default {
|
|||
}
|
||||
},
|
||||
removeTab(targetName) {
|
||||
let index = this.tabs.findIndex(item => item.name === targetName);
|
||||
let index = this.tabs.findIndex((item) => item.name === targetName);
|
||||
if (index !== -1) {
|
||||
// 清除vuex中缓存的环境
|
||||
let tab = this.tabs[index];
|
||||
if (tab && tab.currentScenario && store.scenarioEnvMap && store.scenarioEnvMap instanceof Map) {
|
||||
if (
|
||||
tab &&
|
||||
tab.currentScenario &&
|
||||
store.scenarioEnvMap &&
|
||||
store.scenarioEnvMap instanceof Map
|
||||
) {
|
||||
store.scenarioEnvMap.forEach((v, k) => {
|
||||
if (k.indexOf(tab.currentScenario.id) !== -1) {
|
||||
store.scenarioEnvMap.delete(k);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
this.tabs.splice(index, 1);
|
||||
if (tab) {
|
||||
tab = undefined;
|
||||
}
|
||||
}
|
||||
this.tabs = this.tabs.filter(tab => tab.name !== targetName);
|
||||
this.tabs = this.tabs.filter((tab) => tab.name !== targetName);
|
||||
if (this.tabs.length > 0) {
|
||||
this.activeName = this.tabs[this.tabs.length - 1].name;
|
||||
this.addListener(); // 自动切换当前标签时,也添加监听
|
||||
} else {
|
||||
this.activeName = "default";
|
||||
this.activeName = 'default';
|
||||
}
|
||||
},
|
||||
setTabLabel(data) {
|
||||
|
@ -655,15 +764,18 @@ export default {
|
|||
this.$error(this.$t('api_test.scenario_jump_message'));
|
||||
return;
|
||||
}
|
||||
const index = this.tabs.find(p => p.currentScenario.id === row.id && p.currentScenario.copy === row.copy);
|
||||
const index = this.tabs.find(
|
||||
(p) =>
|
||||
p.currentScenario.id === row.id && p.currentScenario.copy === row.copy
|
||||
);
|
||||
if (!index) {
|
||||
this.addTab({name: 'edit', currentScenario: row});
|
||||
this.addTab({ name: 'edit', currentScenario: row });
|
||||
} else {
|
||||
this.activeName = index.name;
|
||||
}
|
||||
},
|
||||
nodeChange(node, nodeIds, pNodes) {
|
||||
this.initApiTableOpretion = "nodeChange";
|
||||
this.initApiTableOpretion = 'nodeChange';
|
||||
this.selectNodeIds = nodeIds;
|
||||
},
|
||||
setModuleOptions(data) {
|
||||
|
@ -676,29 +788,31 @@ export default {
|
|||
this.$route.params.dataSelectRange = 'all';
|
||||
},
|
||||
enableTrash(data) {
|
||||
this.activeName = "default";
|
||||
this.initApiTableOpretion = "enableTrash";
|
||||
this.activeName = 'default';
|
||||
this.initApiTableOpretion = 'enableTrash';
|
||||
this.trashEnable = data;
|
||||
if (data) {
|
||||
this.activeName = "trash";
|
||||
this.activeName = 'trash';
|
||||
} else {
|
||||
this.activeName = "default";
|
||||
this.activeName = 'default';
|
||||
}
|
||||
this.getTrashCase();
|
||||
},
|
||||
getTrashCase() {
|
||||
let param = {};
|
||||
param.projectId = this.projectId;
|
||||
getScenarioByTrash(param).then(response => {
|
||||
getScenarioByTrash(param).then((response) => {
|
||||
this.total = response.data;
|
||||
});
|
||||
},
|
||||
getProject() {
|
||||
getProjectConfig(this.projectId, '/SCENARIO_CUSTOM_NUM').then(result => {
|
||||
if (result.data) {
|
||||
this.customNum = result.data.scenarioCustomNum;
|
||||
getProjectConfig(this.projectId, '/SCENARIO_CUSTOM_NUM').then(
|
||||
(result) => {
|
||||
if (result.data) {
|
||||
this.customNum = result.data.scenarioCustomNum;
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
},
|
||||
updateInitApiTableOpretion(param) {
|
||||
this.initApiTableOpretion = param;
|
||||
|
@ -708,16 +822,17 @@ export default {
|
|||
this.$refs.apiScenarioList.condition.versionId = currentVersion || null;
|
||||
}
|
||||
if (this.$refs.apiTrashScenarioList) {
|
||||
this.$refs.apiTrashScenarioList.condition.versionId = currentVersion || null;
|
||||
this.$refs.apiTrashScenarioList.condition.versionId =
|
||||
currentVersion || null;
|
||||
}
|
||||
this.refreshAll();
|
||||
},
|
||||
clickResource(resource) {
|
||||
let workspaceId = getCurrentWorkspaceId();
|
||||
let isTurnSpace = true
|
||||
let isTurnSpace = true;
|
||||
if (resource.projectId !== getCurrentProjectID()) {
|
||||
isTurnSpace = false;
|
||||
getProject(resource.projectId).then(response => {
|
||||
getProject(resource.projectId).then((response) => {
|
||||
if (response.data) {
|
||||
workspaceId = response.data.workspaceId;
|
||||
isTurnSpace = true;
|
||||
|
@ -733,27 +848,27 @@ export default {
|
|||
name: 'ApiAutomationWithQuery',
|
||||
params: {
|
||||
redirectID: getUUID(),
|
||||
dataType: "scenario",
|
||||
dataType: 'scenario',
|
||||
dataSelectRange: 'edit:' + resource.id,
|
||||
projectId: resource.projectId,
|
||||
workspaceId: workspaceId
|
||||
}
|
||||
workspaceId: workspaceId,
|
||||
},
|
||||
});
|
||||
if (isTurnSpace) {
|
||||
window.open(automationData.href, '_blank');
|
||||
}
|
||||
},
|
||||
checkPermission(resource, workspaceId, isTurnSpace) {
|
||||
getOwnerProjectIds().then(res => {
|
||||
const project = res.data.find(p => p === resource.projectId);
|
||||
getOwnerProjectIds().then((res) => {
|
||||
const project = res.data.find((p) => p === resource.projectId);
|
||||
if (!project) {
|
||||
this.$warning(this.$t('commons.no_permission'));
|
||||
} else {
|
||||
this.gotoTurn(resource, workspaceId, isTurnSpace)
|
||||
this.gotoTurn(resource, workspaceId, isTurnSpace);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import {editScenario} from "@/api/scenario";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import {ELEMENT_TYPE} from "@/business/automation/scenario/Setting";
|
||||
import {baseSocket, getUploadConfig} from "@/api/base-network";
|
||||
import {useApiStore} from "@/store";
|
||||
import { editScenario } from '@/api/scenario';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { ELEMENT_TYPE } from '@/business/automation/scenario/Setting';
|
||||
import { baseSocket, getUploadConfig } from '@/api/base-network';
|
||||
import { useApiStore } from '@/store';
|
||||
|
||||
const store = useApiStore();
|
||||
|
||||
function buildBodyFile(item, bodyUploadFiles, obj, bodyParam) {
|
||||
if (bodyParam) {
|
||||
bodyParam.forEach(param => {
|
||||
bodyParam.forEach((param) => {
|
||||
if (param.files) {
|
||||
param.files.forEach(fileItem => {
|
||||
param.files.forEach((fileItem) => {
|
||||
if (fileItem.file) {
|
||||
fileItem.name = fileItem.file.name;
|
||||
obj.bodyFileRequestIds.push(item.id);
|
||||
|
@ -31,9 +31,9 @@ function setFiles(item, bodyUploadFiles, obj) {
|
|||
|
||||
function recursiveFile(arr, bodyUploadFiles, obj) {
|
||||
if (arr) {
|
||||
arr.forEach(item => {
|
||||
arr.forEach((item) => {
|
||||
setFiles(item, bodyUploadFiles, obj);
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
recursiveFile(item.hashTree, bodyUploadFiles, obj);
|
||||
}
|
||||
});
|
||||
|
@ -43,12 +43,12 @@ function recursiveFile(arr, bodyUploadFiles, obj) {
|
|||
export function getBodyUploadFiles(obj, scenarioDefinition) {
|
||||
let bodyUploadFiles = [];
|
||||
obj.bodyFileRequestIds = [];
|
||||
scenarioDefinition.forEach(item => {
|
||||
scenarioDefinition.forEach((item) => {
|
||||
setFiles(item, bodyUploadFiles, obj);
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
recursiveFile(item.hashTree, bodyUploadFiles, obj);
|
||||
}
|
||||
})
|
||||
});
|
||||
return bodyUploadFiles;
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,9 @@ function getScenarioFiles(obj) {
|
|||
obj.scenarioFileIds = [];
|
||||
// 场景变量csv 文件
|
||||
if (obj.variables) {
|
||||
obj.variables.forEach(param => {
|
||||
obj.variables.forEach((param) => {
|
||||
if (param.type === 'CSV' && param.files) {
|
||||
param.files.forEach(item => {
|
||||
param.files.forEach((item) => {
|
||||
if (item.file) {
|
||||
if (!item.id) {
|
||||
let fileId = getUUID().substring(0, 12);
|
||||
|
@ -69,17 +69,23 @@ function getScenarioFiles(obj) {
|
|||
obj.scenarioFileIds.push(item.id);
|
||||
scenarioFiles.push(item.file);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return scenarioFiles;
|
||||
}
|
||||
|
||||
export function saveScenario(url, scenario, scenarioDefinition, _this, success) {
|
||||
export function saveScenario(
|
||||
url,
|
||||
scenario,
|
||||
scenarioDefinition,
|
||||
_this,
|
||||
success
|
||||
) {
|
||||
let bodyFiles = getBodyUploadFiles(scenario, scenarioDefinition);
|
||||
if (store.pluginFiles && store.pluginFiles.length > 0) {
|
||||
store.pluginFiles.forEach(fileItem => {
|
||||
store.pluginFiles.forEach((fileItem) => {
|
||||
if (fileItem.file) {
|
||||
scenario.bodyFileRequestIds.push(fileItem.file.uid);
|
||||
bodyFiles.push(fileItem.file);
|
||||
|
@ -89,25 +95,31 @@ export function saveScenario(url, scenario, scenarioDefinition, _this, success)
|
|||
let scenarioFiles = getScenarioFiles(scenario);
|
||||
let formData = new FormData();
|
||||
if (bodyFiles) {
|
||||
bodyFiles.forEach(f => {
|
||||
formData.append("bodyFiles", f);
|
||||
})
|
||||
bodyFiles.forEach((f) => {
|
||||
formData.append('bodyFiles', f);
|
||||
});
|
||||
}
|
||||
if (scenarioFiles) {
|
||||
scenarioFiles.forEach(f => {
|
||||
formData.append("scenarioFiles", f);
|
||||
})
|
||||
scenarioFiles.forEach((f) => {
|
||||
formData.append('scenarioFiles', f);
|
||||
});
|
||||
}
|
||||
formData.append('request', new Blob([JSON.stringify(scenario)], {type: "application/json"}));
|
||||
formData.append(
|
||||
'request',
|
||||
new Blob([JSON.stringify(scenario)], { type: 'application/json' })
|
||||
);
|
||||
let config = getUploadConfig(url, formData);
|
||||
editScenario(config).then((response) => {
|
||||
if (success) {
|
||||
success(response.data);
|
||||
editScenario(config).then(
|
||||
(response) => {
|
||||
if (success) {
|
||||
success(response.data);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
_this.isPreventReClick = false;
|
||||
_this.errorRefresh();
|
||||
}
|
||||
}, error => {
|
||||
_this.isPreventReClick = false;
|
||||
_this.errorRefresh();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export function savePreciseEnvProjectIds(projectIds, envMap) {
|
||||
|
@ -120,19 +132,22 @@ export function savePreciseEnvProjectIds(projectIds, envMap) {
|
|||
}
|
||||
for (let id of projectIds) {
|
||||
if (!envMap.get(id)) {
|
||||
envMap.set(id, "");
|
||||
envMap.set(id, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function scenarioSort(_this) {
|
||||
for (let i in _this.scenarioDefinition) {
|
||||
// 排序
|
||||
_this.$set(_this.scenarioDefinition[i], 'index', Number(i) + 1);
|
||||
// 设置循环控制
|
||||
if (_this.scenarioDefinition[i].type === ELEMENT_TYPE.LoopController && _this.scenarioDefinition[i].hashTree && _this.scenarioDefinition[i].hashTree.length > 1) {
|
||||
if (
|
||||
_this.scenarioDefinition[i].type === ELEMENT_TYPE.LoopController &&
|
||||
_this.scenarioDefinition[i].hashTree &&
|
||||
_this.scenarioDefinition[i].hashTree.length > 1
|
||||
) {
|
||||
_this.scenarioDefinition[i].countController.proceed = true;
|
||||
}
|
||||
// 设置项目ID
|
||||
|
@ -140,15 +155,32 @@ export function scenarioSort(_this) {
|
|||
_this.scenarioDefinition[i].projectId = _this.projectId;
|
||||
}
|
||||
|
||||
if (_this.scenarioDefinition[i].hashTree != undefined && _this.scenarioDefinition[i].hashTree.length > 0) {
|
||||
if (
|
||||
_this.scenarioDefinition[i].hashTree != undefined &&
|
||||
_this.scenarioDefinition[i].hashTree.length > 0
|
||||
) {
|
||||
if (_this.hideTreeNode) {
|
||||
_this.hideTreeNode(_this.scenarioDefinition[i], _this.scenarioDefinition[i].hashTree);
|
||||
_this.hideTreeNode(
|
||||
_this.scenarioDefinition[i],
|
||||
_this.scenarioDefinition[i].hashTree
|
||||
);
|
||||
}
|
||||
recursiveSorting(_this, _this.scenarioDefinition[i].hashTree, _this.scenarioDefinition[i].projectId);
|
||||
recursiveSorting(
|
||||
_this,
|
||||
_this.scenarioDefinition[i].hashTree,
|
||||
_this.scenarioDefinition[i].projectId
|
||||
);
|
||||
}
|
||||
// 添加debug结果
|
||||
if (_this.debugResult && _this.debugResult.get(_this.scenarioDefinition[i].id + _this.scenarioDefinition[i].name)) {
|
||||
_this.scenarioDefinition[i].requestResult = _this.debugResult.get(_this.scenarioDefinition[i].id + _this.scenarioDefinition[i].name);
|
||||
if (
|
||||
_this.debugResult &&
|
||||
_this.debugResult.get(
|
||||
_this.scenarioDefinition[i].id + _this.scenarioDefinition[i].name
|
||||
)
|
||||
) {
|
||||
_this.scenarioDefinition[i].requestResult = _this.debugResult.get(
|
||||
_this.scenarioDefinition[i].id + _this.scenarioDefinition[i].name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,11 +188,18 @@ export function scenarioSort(_this) {
|
|||
export function recursiveSorting(_this, arr, scenarioProjectId) {
|
||||
for (let i in arr) {
|
||||
arr[i].index = Number(i) + 1;
|
||||
if (arr[i].type === ELEMENT_TYPE.LoopController && arr[i].loopType === "LOOP_COUNT" && arr[i].hashTree && arr[i].hashTree.length > 1) {
|
||||
if (
|
||||
arr[i].type === ELEMENT_TYPE.LoopController &&
|
||||
arr[i].loopType === 'LOOP_COUNT' &&
|
||||
arr[i].hashTree &&
|
||||
arr[i].hashTree.length > 1
|
||||
) {
|
||||
arr[i].countController.proceed = true;
|
||||
}
|
||||
if (!arr[i].projectId) {
|
||||
arr[i].projectId = scenarioProjectId ? scenarioProjectId : _this.projectId;
|
||||
arr[i].projectId = scenarioProjectId
|
||||
? scenarioProjectId
|
||||
: _this.projectId;
|
||||
}
|
||||
if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) {
|
||||
if (_this.hideTreeNode) {
|
||||
|
@ -175,12 +214,11 @@ export function recursiveSorting(_this, arr, scenarioProjectId) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export function copyScenarioRow(row, node) {
|
||||
if (!row || !node) {
|
||||
return;
|
||||
}
|
||||
const parent = node.parent
|
||||
const parent = node.parent;
|
||||
const hashTree = parent.data.hashTree || parent.data;
|
||||
// 深度复制
|
||||
let obj = JSON.parse(JSON.stringify(row));
|
||||
|
@ -191,7 +229,7 @@ export function copyScenarioRow(row, node) {
|
|||
if (obj.name) {
|
||||
obj.name = obj.name + '_copy';
|
||||
}
|
||||
const index = hashTree.findIndex(d => d.resourceId === row.resourceId);
|
||||
const index = hashTree.findIndex((d) => d.resourceId === row.resourceId);
|
||||
if (index != -1) {
|
||||
hashTree.splice(index + 1, 0, obj);
|
||||
} else {
|
||||
|
@ -201,12 +239,12 @@ export function copyScenarioRow(row, node) {
|
|||
}
|
||||
|
||||
export function resetResourceId(hashTree) {
|
||||
hashTree.forEach(item => {
|
||||
hashTree.forEach((item) => {
|
||||
item.resourceId = getUUID();
|
||||
if (item.hashTree && item.hashTree.length > 0) {
|
||||
resetResourceId(item.hashTree);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export function getReportMessageSocket(reportId) {
|
||||
|
|
|
@ -14,14 +14,23 @@
|
|||
:report="report"
|
||||
:project-env-map="projectEnvMap"
|
||||
@reportExport="handleExport"
|
||||
@reportSave="handleSave"/>
|
||||
@reportSave="handleSave"
|
||||
/>
|
||||
|
||||
<!-- content -->
|
||||
<main v-if="isNotRunning">
|
||||
<!-- content header chart -->
|
||||
<ms-metric-chart :content="content" :totalTime="totalTime" :report="report"/>
|
||||
<ms-metric-chart
|
||||
:content="content"
|
||||
:totalTime="totalTime"
|
||||
:report="report"
|
||||
/>
|
||||
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick" style="min-width: 1200px">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
@tab-click="handleClick"
|
||||
style="min-width: 1200px"
|
||||
>
|
||||
<!-- all step-->
|
||||
<el-tab-pane label="All" name="total">
|
||||
<ms-scenario-results
|
||||
|
@ -31,28 +40,27 @@
|
|||
:is-share="isShare"
|
||||
:share-id="shareId"
|
||||
v-on:requestResult="requestResult"
|
||||
ref="resultsTree"/>
|
||||
ref="resultsTree"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- fail step -->
|
||||
<el-tab-pane name="fail">
|
||||
<template slot="label">
|
||||
Error
|
||||
</template>
|
||||
<template slot="label"> Error </template>
|
||||
<ms-scenario-results
|
||||
v-on:requestResult="requestResult"
|
||||
:console="content.console"
|
||||
:report="report"
|
||||
:is-share="isShare"
|
||||
:share-id="shareId"
|
||||
:treeData="fullTreeNodes" ref="failsTree"
|
||||
:errorReport="content.error"/>
|
||||
:treeData="fullTreeNodes"
|
||||
ref="failsTree"
|
||||
:errorReport="content.error"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!--error step -->
|
||||
<el-tab-pane name="errorReport" v-if="content.errorCode > 0">
|
||||
<template slot="label">
|
||||
<span class="fail" style="color: #F6972A">
|
||||
FakeError
|
||||
</span>
|
||||
<span class="fail" style="color: #f6972a"> FakeError </span>
|
||||
</template>
|
||||
<ms-scenario-results
|
||||
v-on:requestResult="requestResult"
|
||||
|
@ -60,15 +68,14 @@
|
|||
:is-share="isShare"
|
||||
:share-id="shareId"
|
||||
:console="content.console"
|
||||
:treeData="fullTreeNodes" ref="errorReportTree"/>
|
||||
:treeData="fullTreeNodes"
|
||||
ref="errorReportTree"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- Not performed step -->
|
||||
<el-tab-pane name="unExecute" v-if="content.unExecute > 0">
|
||||
<template slot="label">
|
||||
<span class="fail"
|
||||
style="color: #9C9B9A">
|
||||
Pending
|
||||
</span>
|
||||
<span class="fail" style="color: #9c9b9a"> Pending </span>
|
||||
</template>
|
||||
<ms-scenario-results
|
||||
v-on:requestResult="requestResult"
|
||||
|
@ -76,7 +83,9 @@
|
|||
:is-share="isShare"
|
||||
:share-id="shareId"
|
||||
:console="content.console"
|
||||
:treeData="fullTreeNodes" ref="unExecuteTree"/>
|
||||
:treeData="fullTreeNodes"
|
||||
ref="unExecuteTree"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- console -->
|
||||
<el-tab-pane name="console">
|
||||
|
@ -87,14 +96,14 @@
|
|||
:mode="'text'"
|
||||
:read-only="true"
|
||||
:data.sync="content.console"
|
||||
height="calc(100vh - 500px)"/>
|
||||
height="calc(100vh - 500px)"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</main>
|
||||
</section>
|
||||
</el-card>
|
||||
</ms-main-container>
|
||||
|
||||
</ms-container>
|
||||
|
||||
<!--export report-->
|
||||
|
@ -105,36 +114,36 @@
|
|||
:title="report.name"
|
||||
:content="content"
|
||||
:report="report"
|
||||
:total-time="totalTime"/>
|
||||
:total-time="totalTime"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsRequestResult from "./components/RequestResult";
|
||||
import MsRequestResultTail from "./components/RequestResultTail";
|
||||
import MsScenarioResult from "./components/ScenarioResult";
|
||||
import MsMetricChart from "./components/MetricChart";
|
||||
import MsScenarioResults from "./components/ScenarioResults";
|
||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||
import MsApiReportExport from "./ApiReportExport";
|
||||
import MsApiReportViewHeader from "./ApiReportViewHeader";
|
||||
import {RequestFactory} from "../../definition/model/ApiTestModel";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {downloadPDF, getUUID} from "metersphere-frontend/src/utils";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import MsRequestResult from './components/RequestResult';
|
||||
import MsRequestResultTail from './components/RequestResultTail';
|
||||
import MsScenarioResult from './components/ScenarioResult';
|
||||
import MsMetricChart from './components/MetricChart';
|
||||
import MsScenarioResults from './components/ScenarioResults';
|
||||
import MsContainer from 'metersphere-frontend/src/components/MsContainer';
|
||||
import MsMainContainer from 'metersphere-frontend/src/components/MsMainContainer';
|
||||
import MsApiReportExport from './ApiReportExport';
|
||||
import MsApiReportViewHeader from './ApiReportViewHeader';
|
||||
import { RequestFactory } from '../../definition/model/ApiTestModel';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { downloadPDF, getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
import {
|
||||
getScenarioReport,
|
||||
getScenarioReportDetail,
|
||||
getShareScenarioReport,
|
||||
reportReName
|
||||
} from "../../../api/scenario-report";
|
||||
import {STEP} from "../../automation/scenario/Setting";
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
reportReName,
|
||||
} from '../../../api/scenario-report';
|
||||
import { STEP } from '../../automation/scenario/Setting';
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
|
||||
export default {
|
||||
name: "MsApiReport",
|
||||
name: 'MsApiReport',
|
||||
components: {
|
||||
MsApiReportViewHeader,
|
||||
MsApiReportExport,
|
||||
|
@ -145,11 +154,11 @@ export default {
|
|||
MsRequestResultTail,
|
||||
MsMetricChart,
|
||||
MsScenarioResult,
|
||||
MsRequestResult
|
||||
MsRequestResult,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: "total",
|
||||
activeName: 'total',
|
||||
content: {},
|
||||
report: {},
|
||||
loading: true,
|
||||
|
@ -164,12 +173,12 @@ export default {
|
|||
requestType: undefined,
|
||||
fullTreeNodes: [],
|
||||
showRerunButton: false,
|
||||
stepFilter: new STEP,
|
||||
stepFilter: new STEP(),
|
||||
exportReportIsOk: false,
|
||||
tempResult: [],
|
||||
projectEnvMap: {},
|
||||
showCancel: false
|
||||
}
|
||||
showCancel: false,
|
||||
};
|
||||
},
|
||||
activated() {
|
||||
this.isRequestResult = false;
|
||||
|
@ -186,8 +195,8 @@ export default {
|
|||
isPlan: Boolean,
|
||||
showCancelButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
reportId() {
|
||||
|
@ -199,16 +208,16 @@ export default {
|
|||
if (this.isTemplate) {
|
||||
this.getReport();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
filter(index) {
|
||||
if (index === "1") {
|
||||
if (index === '1') {
|
||||
this.$refs.failsTree.filter(index);
|
||||
} else if (this.activeName === "errorReport") {
|
||||
this.$refs.errorReportTree.filter("FAKE_ERROR");
|
||||
} else if (this.activeName === "unExecute") {
|
||||
this.$refs.unExecuteTree.filter("PENDING");
|
||||
} else if (this.activeName === 'errorReport') {
|
||||
this.$refs.errorReportTree.filter('FAKE_ERROR');
|
||||
} else if (this.activeName === 'unExecute') {
|
||||
this.$refs.unExecuteTree.filter('PENDING');
|
||||
}
|
||||
},
|
||||
init() {
|
||||
|
@ -220,30 +229,46 @@ export default {
|
|||
this.fullTreeNodes = [];
|
||||
this.failsTreeNodes = [];
|
||||
this.isRequestResult = false;
|
||||
this.activeName = "total";
|
||||
this.activeName = 'total';
|
||||
this.showRerunButton = false;
|
||||
if (this.$route && this.$route.path.startsWith('/api/automation/report')
|
||||
&& this.$route.query && this.$route.query.list) {
|
||||
if (
|
||||
this.$route &&
|
||||
this.$route.path.startsWith('/api/automation/report') &&
|
||||
this.$route.query &&
|
||||
this.$route.query.list
|
||||
) {
|
||||
this.$nextTick(() => {
|
||||
this.showCancel = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
rerunVerify() {
|
||||
if (hasLicense() && this.fullTreeNodes && this.fullTreeNodes.length > 0 && !this.isShare) {
|
||||
this.fullTreeNodes.forEach(item => {
|
||||
item.redirect = true;
|
||||
if (item.totalStatus === 'FAIL' || item.totalStatus === 'ERROR' || item.unExecuteTotal > 0
|
||||
|| (item.type === "API" && item.totalStatus === 'PENDING')) {
|
||||
this.showRerunButton = true;
|
||||
}
|
||||
if (
|
||||
hasLicense() &&
|
||||
this.fullTreeNodes &&
|
||||
this.fullTreeNodes.length > 0 &&
|
||||
!this.isShare
|
||||
) {
|
||||
this.fullTreeNodes.forEach((item) => {
|
||||
item.redirect = true;
|
||||
if (
|
||||
item.totalStatus === 'FAIL' ||
|
||||
item.totalStatus === 'ERROR' ||
|
||||
item.unExecuteTotal > 0 ||
|
||||
(item.type === 'API' && item.totalStatus === 'PENDING')
|
||||
) {
|
||||
this.showRerunButton = true;
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
this.isRequestResult = false;
|
||||
if (this.report && this.report.reportVersion && this.report.reportVersion > 1) {
|
||||
if (
|
||||
this.report &&
|
||||
this.report.reportVersion &&
|
||||
this.report.reportVersion > 1
|
||||
) {
|
||||
this.filter(tab.index);
|
||||
}
|
||||
},
|
||||
|
@ -251,19 +276,19 @@ export default {
|
|||
this.isActive = !this.isActive;
|
||||
},
|
||||
formatResult(res) {
|
||||
let resMap = new Map;
|
||||
let resMap = new Map();
|
||||
let array = [];
|
||||
if (res && res.scenarios) {
|
||||
res.scenarios.forEach(item => {
|
||||
res.scenarios.forEach((item) => {
|
||||
if (item && item.requestResults) {
|
||||
item.requestResults.forEach(req => {
|
||||
item.requestResults.forEach((req) => {
|
||||
req.responseResult.console = res.console;
|
||||
resMap.set(req.id + req.name, req);
|
||||
req.name = item.name + "^@~@^" + req.name + "UUID=" + getUUID();
|
||||
req.name = item.name + '^@~@^' + req.name + 'UUID=' + getUUID();
|
||||
array.push(req);
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
this.formatTree(array, this.fullTreeNodes);
|
||||
this.sort(this.fullTreeNodes);
|
||||
|
@ -276,12 +301,12 @@ export default {
|
|||
let children = tree;
|
||||
//运行场景中如果连续将1个场景引入多次,会出现运行结果合并的情况。
|
||||
//为了解决这种问题,在转hashTree的时候给场景放了个新ID,前台加载解析的时候也要做处理
|
||||
let scenarioId = "";
|
||||
let scenarioName = "";
|
||||
let scenarioId = '';
|
||||
let scenarioName = '';
|
||||
if (item.scenario) {
|
||||
let scenarioArr = JSON.parse(item.scenario);
|
||||
if (scenarioArr.length > 1) {
|
||||
let scenarioIdArr = scenarioArr[0].split("_");
|
||||
let scenarioIdArr = scenarioArr[0].split('_');
|
||||
scenarioId = scenarioIdArr[0];
|
||||
scenarioName = scenarioIdArr[1];
|
||||
}
|
||||
|
@ -295,14 +320,16 @@ export default {
|
|||
label: nodeArray[i],
|
||||
value: item,
|
||||
};
|
||||
if (i !== (nodeArray.length - 1)) {
|
||||
if (i !== nodeArray.length - 1) {
|
||||
node.children = [];
|
||||
} else {
|
||||
if (item.subRequestResults && item.subRequestResults.length > 0) {
|
||||
let itemChildren = this.deepFormatTreeNode(item.subRequestResults);
|
||||
let itemChildren = this.deepFormatTreeNode(
|
||||
item.subRequestResults
|
||||
);
|
||||
node.children = itemChildren;
|
||||
if (node.label.indexOf("UUID=")) {
|
||||
node.label = node.label.split("UUID=")[0];
|
||||
if (node.label.indexOf('UUID=')) {
|
||||
node.label = node.label.split('UUID=')[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,25 +340,24 @@ export default {
|
|||
let isExist = false;
|
||||
for (let j in children) {
|
||||
if (children[j].label === node.label) {
|
||||
|
||||
let idIsPath = true;
|
||||
//判断ID是否匹配 目前发现问题的只有重复场景,而重复场景是在第二个节点开始合并的。所以这里暂时只判断第二个场景问题。
|
||||
//如果出现了其他问题,则需要检查其他问题的数据结构。暂时采用具体问题具体分析的策略
|
||||
if (i === nodeArray.length - 2) {
|
||||
idIsPath = false;
|
||||
let childId = "";
|
||||
let childName = "";
|
||||
let childId = '';
|
||||
let childName = '';
|
||||
if (children[j].value && children[j].value.scenario) {
|
||||
let scenarioArr = JSON.parse(children[j].value.scenario);
|
||||
if (scenarioArr.length > 1) {
|
||||
let childArr = scenarioArr[0].split("_");
|
||||
let childArr = scenarioArr[0].split('_');
|
||||
childId = childArr[0];
|
||||
if (childArr.length > 1) {
|
||||
childName = childArr[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scenarioId === "") {
|
||||
if (scenarioId === '') {
|
||||
idIsPath = true;
|
||||
} else if (scenarioId === childId) {
|
||||
idIsPath = true;
|
||||
|
@ -344,7 +370,8 @@ export default {
|
|||
if (i !== nodeArray.length - 1 && !children[j].children) {
|
||||
children[j].children = [];
|
||||
}
|
||||
children = (i === nodeArray.length - 1 ? children : children[j].children);
|
||||
children =
|
||||
i === nodeArray.length - 1 ? children : children[j].children;
|
||||
isExist = true;
|
||||
break;
|
||||
}
|
||||
|
@ -352,13 +379,19 @@ export default {
|
|||
}
|
||||
if (!isExist) {
|
||||
children.push(node);
|
||||
if (i !== nodeArray.length - 1 && !children[children.length - 1].children) {
|
||||
if (
|
||||
i !== nodeArray.length - 1 &&
|
||||
!children[children.length - 1].children
|
||||
) {
|
||||
children[children.length - 1].children = [];
|
||||
}
|
||||
children = (i === nodeArray.length - 1 ? children : children[children.length - 1].children);
|
||||
children =
|
||||
i === nodeArray.length - 1
|
||||
? children
|
||||
: children[children.length - 1].children;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
deepFormatTreeNode(array) {
|
||||
|
@ -369,12 +402,12 @@ export default {
|
|||
let nodeArray = key.split('<->');
|
||||
//运行场景中如果连续将1个场景引入多次,会出现运行结果合并的情况。
|
||||
//为了解决这种问题,在转hashTree的时候给场景放了个新ID,前台加载解析的时候也要做处理
|
||||
let scenarioId = "";
|
||||
let scenarioName = "";
|
||||
let scenarioId = '';
|
||||
let scenarioName = '';
|
||||
if (item.scenario) {
|
||||
let scenarioArr = JSON.parse(item.scenario);
|
||||
if (scenarioArr.length > 1) {
|
||||
let scenarioIdArr = scenarioArr[0].split("_");
|
||||
let scenarioIdArr = scenarioArr[0].split('_');
|
||||
scenarioId = scenarioIdArr[0];
|
||||
scenarioName = scenarioIdArr[1];
|
||||
}
|
||||
|
@ -383,17 +416,16 @@ export default {
|
|||
let node = {
|
||||
label: nodeArray[0],
|
||||
value: item,
|
||||
children: []
|
||||
children: [],
|
||||
};
|
||||
if (item.subRequestResults && item.subRequestResults.length > 0) {
|
||||
let itemChildren = this.deepFormatTreeNode(item.subRequestResults);
|
||||
node.children = itemChildren;
|
||||
}
|
||||
children.push(node);
|
||||
children.forEach(itemNode => {
|
||||
children.forEach((itemNode) => {
|
||||
returnChildren.push(itemNode);
|
||||
});
|
||||
|
||||
});
|
||||
return returnChildren;
|
||||
},
|
||||
|
@ -412,7 +444,10 @@ export default {
|
|||
// 排序
|
||||
if (scenarioDefinition[i]) {
|
||||
scenarioDefinition[i].index = Number(i) + 1;
|
||||
if (scenarioDefinition[i].children && scenarioDefinition[i].children.length > 0) {
|
||||
if (
|
||||
scenarioDefinition[i].children &&
|
||||
scenarioDefinition[i].children.length > 0
|
||||
) {
|
||||
this.recursiveSorting(scenarioDefinition[i].children);
|
||||
}
|
||||
}
|
||||
|
@ -433,12 +468,13 @@ export default {
|
|||
this.fullTreeNodes = report.steps;
|
||||
this.content.console = report.console;
|
||||
this.content.error = report.error;
|
||||
let successCount = (report.total - report.error - report.errorCode - report.unExecute);
|
||||
let successCount =
|
||||
report.total - report.error - report.errorCode - report.unExecute;
|
||||
this.content.success = successCount;
|
||||
this.totalTime = report.totalTime;
|
||||
}
|
||||
this.exportReportIsOk = true;
|
||||
setTimeout(this.startExport, 500)
|
||||
setTimeout(this.startExport, 500);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -454,7 +490,7 @@ export default {
|
|||
}
|
||||
} else if (this.isShare) {
|
||||
if (this.reportId) {
|
||||
getShareScenarioReport(this.shareId, this.reportId).then(res => {
|
||||
getShareScenarioReport(this.shareId, this.reportId).then((res) => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.checkReport(data);
|
||||
|
@ -463,7 +499,7 @@ export default {
|
|||
});
|
||||
}
|
||||
} else if (this.reportId) {
|
||||
getScenarioReport(this.reportId).then(res => {
|
||||
getScenarioReport(this.reportId).then((res) => {
|
||||
let data = res.data;
|
||||
this.checkReport(data);
|
||||
this.handleGetScenarioReport(data);
|
||||
|
@ -482,7 +518,7 @@ export default {
|
|||
if (this.report.reportVersion && this.report.reportVersion > 1) {
|
||||
this.report.status = data.status;
|
||||
if (!this.isNotRunning) {
|
||||
setTimeout(this.getReport, 2000)
|
||||
setTimeout(this.getReport, 2000);
|
||||
} else {
|
||||
if (data.content) {
|
||||
let report = JSON.parse(data.content);
|
||||
|
@ -493,12 +529,20 @@ export default {
|
|||
this.fullTreeNodes = report.steps;
|
||||
this.content.console = report.console;
|
||||
this.content.error = report.error;
|
||||
let successCount = (report.total - report.error - report.errorCode - report.unExecute);
|
||||
let successCount =
|
||||
report.total -
|
||||
report.error -
|
||||
report.errorCode -
|
||||
report.unExecute;
|
||||
this.content.success = successCount;
|
||||
this.totalTime = report.totalTime;
|
||||
}
|
||||
// 增加失败重跑校验
|
||||
if (this.report && this.report.reportType === 'SCENARIO_INTEGRATED' || this.report.reportType === 'API_INTEGRATED') {
|
||||
if (
|
||||
(this.report &&
|
||||
this.report.reportType === 'SCENARIO_INTEGRATED') ||
|
||||
this.report.reportType === 'API_INTEGRATED'
|
||||
) {
|
||||
this.rerunVerify();
|
||||
}
|
||||
this.loading = false;
|
||||
|
@ -517,39 +561,45 @@ export default {
|
|||
}
|
||||
if (Array.isArray(origin)) {
|
||||
this.sortChildren(origin);
|
||||
origin.forEach(v => {
|
||||
origin.forEach((v) => {
|
||||
if (v.children) {
|
||||
this.checkOrder(v.children)
|
||||
this.checkOrder(v.children);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
sortChildren(source) {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
source.forEach(item => {
|
||||
source.forEach((item) => {
|
||||
let children = item.children;
|
||||
if (children && children.length > 0) {
|
||||
let tempArr = new Array(children.length);
|
||||
let tempMap = new Map();
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
if (!children[i].value || !children[i].value.startTime || children[i].value.startTime === 0) {
|
||||
if (
|
||||
!children[i].value ||
|
||||
!children[i].value.startTime ||
|
||||
children[i].value.startTime === 0
|
||||
) {
|
||||
//若没有value或未执行的,则step留在当前位置
|
||||
tempArr[i] = children[i];
|
||||
//进行标识
|
||||
tempMap.set(children[i].stepId, children[i])
|
||||
tempMap.set(children[i].stepId, children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//过滤出还没有指定好位置的step
|
||||
let arr = children.filter(m => {
|
||||
return !tempMap.get(m.stepId);
|
||||
}).sort((m, n) => {
|
||||
//按时间排序
|
||||
return m.value.startTime - n.value.startTime;
|
||||
});
|
||||
let arr = children
|
||||
.filter((m) => {
|
||||
return !tempMap.get(m.stepId);
|
||||
})
|
||||
.sort((m, n) => {
|
||||
//按时间排序
|
||||
return m.value.startTime - n.value.startTime;
|
||||
});
|
||||
|
||||
//找出arr(已经有序,从头取即可)中时间最小的插入 tempArr 可用位置
|
||||
for (let j = 0, i = 0; j < tempArr.length; j++) {
|
||||
|
@ -565,21 +615,21 @@ export default {
|
|||
//赋值
|
||||
item.children = tempArr;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
buildReport() {
|
||||
if (this.report) {
|
||||
if (this.isNotRunning) {
|
||||
this.content = JSON.parse(this.report.content);
|
||||
if (!this.content) {
|
||||
this.content = {scenarios: []};
|
||||
this.content = { scenarios: [] };
|
||||
}
|
||||
this.formatResult(this.content);
|
||||
this.getFails();
|
||||
this.computeTotalTime();
|
||||
this.loading = false;
|
||||
} else {
|
||||
setTimeout(this.getReport, 2000)
|
||||
setTimeout(this.getReport, 2000);
|
||||
}
|
||||
} else {
|
||||
this.loading = false;
|
||||
|
@ -590,10 +640,10 @@ export default {
|
|||
if (this.isNotRunning) {
|
||||
this.fails = [];
|
||||
let array = [];
|
||||
this.totalTime = 0
|
||||
this.totalTime = 0;
|
||||
if (this.content.scenarios) {
|
||||
this.content.scenarios.forEach((scenario) => {
|
||||
this.totalTime = this.totalTime + Number(scenario.responseTime)
|
||||
this.totalTime = this.totalTime + Number(scenario.responseTime);
|
||||
let failScenario = Object.assign({}, scenario);
|
||||
if (scenario.error > 0) {
|
||||
this.fails.push(failScenario);
|
||||
|
@ -604,9 +654,9 @@ export default {
|
|||
failScenario.requestResults.push(failRequest);
|
||||
array.push(request);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
this.formatTree(array, this.failsTreeNodes);
|
||||
this.sort(this.failsTreeNodes);
|
||||
|
@ -627,14 +677,14 @@ export default {
|
|||
}
|
||||
let resTime;
|
||||
if (startTime === 0 || endTime === 0) {
|
||||
resTime = 0
|
||||
resTime = 0;
|
||||
} else {
|
||||
resTime = endTime - startTime
|
||||
resTime = endTime - startTime;
|
||||
}
|
||||
requestTime = requestTime + resTime;
|
||||
})
|
||||
})
|
||||
this.totalTime = requestTime
|
||||
});
|
||||
});
|
||||
this.totalTime = requestTime;
|
||||
}
|
||||
},
|
||||
requestResult(requestResult) {
|
||||
|
@ -651,8 +701,11 @@ export default {
|
|||
});
|
||||
},
|
||||
formatExportApi(array, scenario) {
|
||||
array.forEach(item => {
|
||||
if (this.stepFilter && this.stepFilter.get("AllSamplerProxy").indexOf(item.type) !== -1) {
|
||||
array.forEach((item) => {
|
||||
if (
|
||||
this.stepFilter &&
|
||||
this.stepFilter.get('AllSamplerProxy').indexOf(item.type) !== -1
|
||||
) {
|
||||
if (item.errorCode) {
|
||||
item.value.errorCode = item.errorCode;
|
||||
}
|
||||
|
@ -661,30 +714,36 @@ export default {
|
|||
if (item.children && item.children.length > 0) {
|
||||
this.formatExportApi(item.children, scenario);
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
handleExport() {
|
||||
this.getReportByExport();
|
||||
},
|
||||
startExport() {
|
||||
if (this.report.reportVersion && this.report.reportVersion > 1) {
|
||||
if (this.report.reportType === 'API_INTEGRATED' || this.report.reportType === 'UI_INTEGRATED') {
|
||||
let scenario = {name: "", requestResults: []};
|
||||
if (
|
||||
this.report.reportType === 'API_INTEGRATED' ||
|
||||
this.report.reportType === 'UI_INTEGRATED'
|
||||
) {
|
||||
let scenario = { name: '', requestResults: [] };
|
||||
this.content.scenarios = [scenario];
|
||||
this.formatExportApi(this.fullTreeNodes, scenario);
|
||||
} else {
|
||||
if (this.fullTreeNodes) {
|
||||
this.fullTreeNodes.forEach(item => {
|
||||
if (item.type === "scenario") {
|
||||
let scenario = {name: item.label, requestResults: []};
|
||||
if (this.content.scenarios && this.content.scenarios.length > 0) {
|
||||
this.fullTreeNodes.forEach((item) => {
|
||||
if (item.type === 'scenario') {
|
||||
let scenario = { name: item.label, requestResults: [] };
|
||||
if (
|
||||
this.content.scenarios &&
|
||||
this.content.scenarios.length > 0
|
||||
) {
|
||||
this.content.scenarios.push(scenario);
|
||||
} else {
|
||||
this.content.scenarios = [scenario];
|
||||
}
|
||||
this.formatExportApi(item.children, scenario);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -693,7 +752,10 @@ export default {
|
|||
let name = this.report.name;
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
downloadPDF(document.getElementById("apiTestReport"), name || "scenario-report");
|
||||
downloadPDF(
|
||||
document.getElementById('apiTestReport'),
|
||||
name || 'scenario-report'
|
||||
);
|
||||
reset();
|
||||
}, 5000);
|
||||
});
|
||||
|
@ -707,14 +769,17 @@ export default {
|
|||
reportReName({
|
||||
id: this.report.id,
|
||||
name: this.report.name,
|
||||
reportType: this.report.reportType
|
||||
}).then(response => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.loading = false;
|
||||
this.$emit('refresh');
|
||||
}, error => {
|
||||
this.loading = false;
|
||||
});
|
||||
reportType: this.report.reportType,
|
||||
}).then(
|
||||
(response) => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.loading = false;
|
||||
this.$emit('refresh');
|
||||
},
|
||||
(error) => {
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
exportReportReset() {
|
||||
this.reportExportVisible = false;
|
||||
|
@ -739,16 +804,16 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
path() {
|
||||
return "/api/test/edit?id=" + this.report.testId;
|
||||
return '/api/test/edit?id=' + this.report.testId;
|
||||
},
|
||||
isNotRunning() {
|
||||
return "RUNNING" !== this.report.status;
|
||||
return 'RUNNING' !== this.report.status;
|
||||
},
|
||||
projectId() {
|
||||
return getCurrentProjectID();
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.report-container .el-tabs__header {
|
||||
|
@ -757,7 +822,6 @@ export default {
|
|||
</style>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.report-container {
|
||||
height: calc(100vh - 70px);
|
||||
min-height: 600px;
|
||||
|
@ -778,7 +842,7 @@ export default {
|
|||
}
|
||||
|
||||
.report-container .fail {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.report-container .is-active .fail {
|
||||
|
@ -803,6 +867,6 @@ export default {
|
|||
}
|
||||
|
||||
.target-node-item {
|
||||
background: #FFFFFF;
|
||||
background: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,14 +1,32 @@
|
|||
<template>
|
||||
<ms-report-export-template :title="title" :report="report" :project-env-map="projectEnvMap"
|
||||
:type="$t('report.api_test_report')">
|
||||
<ms-metric-chart :content="content" :is-export="true" :totalTime="totalTime" :report="report"/>
|
||||
<div class="scenario-result" v-for="(scenario, index) in content.scenarios" :key="index" :scenario="scenario">
|
||||
<ms-report-export-template
|
||||
:title="title"
|
||||
:report="report"
|
||||
:project-env-map="projectEnvMap"
|
||||
:type="$t('report.api_test_report')"
|
||||
>
|
||||
<ms-metric-chart
|
||||
:content="content"
|
||||
:is-export="true"
|
||||
:totalTime="totalTime"
|
||||
:report="report"
|
||||
/>
|
||||
<div
|
||||
class="scenario-result"
|
||||
v-for="(scenario, index) in content.scenarios"
|
||||
:key="index"
|
||||
:scenario="scenario"
|
||||
>
|
||||
<el-card>
|
||||
<template v-slot:header>
|
||||
{{ $t('api_report.scenario_name') }}:{{ scenario.name }}
|
||||
</template>
|
||||
<div class="ms-border clearfix" v-for="(request, index) in scenario.requestResults" :key="index"
|
||||
:request="request">
|
||||
<div
|
||||
class="ms-border clearfix"
|
||||
v-for="(request, index) in scenario.requestResults"
|
||||
:key="index"
|
||||
:request="request"
|
||||
>
|
||||
<div class="request-top">
|
||||
<div>
|
||||
{{ getName(request.name) }}
|
||||
|
@ -17,13 +35,17 @@
|
|||
{{ request.url }}
|
||||
</div>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<el-divider />
|
||||
<div class="request-middle">
|
||||
<api-report-request-header-item :title="$t('api_test.request.method')">
|
||||
<api-report-request-header-item
|
||||
:title="$t('api_test.request.method')"
|
||||
>
|
||||
<span class="method"> {{ request.method }}</span>
|
||||
</api-report-request-header-item>
|
||||
|
||||
<api-report-request-header-item :title="$t('api_report.response_time')">
|
||||
<api-report-request-header-item
|
||||
:title="$t('api_report.response_time')"
|
||||
>
|
||||
{{ request.responseResult.responseTime }} ms
|
||||
</api-report-request-header-item>
|
||||
|
||||
|
@ -31,11 +53,15 @@
|
|||
{{ request.responseResult.latency }} ms
|
||||
</api-report-request-header-item>
|
||||
|
||||
<api-report-request-header-item :title="$t('api_report.request_size')">
|
||||
<api-report-request-header-item
|
||||
:title="$t('api_report.request_size')"
|
||||
>
|
||||
{{ request.requestSize }} bytes
|
||||
</api-report-request-header-item>
|
||||
|
||||
<api-report-request-header-item :title="$t('api_report.response_size')">
|
||||
<api-report-request-header-item
|
||||
:title="$t('api_report.response_size')"
|
||||
>
|
||||
{{ request.responseResult.responseSize }} bytes
|
||||
</api-report-request-header-item>
|
||||
|
||||
|
@ -43,22 +69,29 @@
|
|||
{{ request.error }}
|
||||
</api-report-request-header-item>
|
||||
|
||||
<api-report-request-header-item :title="$t('api_report.assertions')">
|
||||
{{ request.passAssertions + " / " + request.totalAssertions }}
|
||||
<api-report-request-header-item
|
||||
:title="$t('api_report.assertions')"
|
||||
>
|
||||
{{ request.passAssertions + ' / ' + request.totalAssertions }}
|
||||
</api-report-request-header-item>
|
||||
|
||||
<api-report-request-header-item :title="$t('api_report.response_code')">
|
||||
<api-report-request-header-item
|
||||
:title="$t('api_report.response_code')"
|
||||
>
|
||||
{{ request.responseResult.responseCode }}
|
||||
</api-report-request-header-item>
|
||||
|
||||
<api-report-request-header-item :title="$t('api_report.result')">
|
||||
<el-tag v-if="request.unexecute">{{
|
||||
$t('api_test.home_page.detail_card.unexecute')
|
||||
}}
|
||||
<el-tag v-if="request.unexecute"
|
||||
>{{ $t('api_test.home_page.detail_card.unexecute') }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="!request.success && request.status && request.status==='PENDING'">{{
|
||||
$t('api_test.home_page.detail_card.unexecute')
|
||||
}}
|
||||
<el-tag
|
||||
v-else-if="
|
||||
!request.success &&
|
||||
request.status &&
|
||||
request.status === 'PENDING'
|
||||
"
|
||||
>{{ $t('api_test.home_page.detail_card.unexecute') }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="request.errorCode" class="ms-test-error_code">
|
||||
{{ $t('error_report_library.option.name') }}
|
||||
|
@ -66,9 +99,7 @@
|
|||
<el-tag size="mini" type="success" v-else-if="request.success">
|
||||
Success
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" v-else>
|
||||
Error
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" v-else> Error </el-tag>
|
||||
</api-report-request-header-item>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -78,47 +109,51 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsScenarioResult from "./components/ScenarioResult";
|
||||
import MsRequestResultTail from "./components/RequestResultTail";
|
||||
import ApiReportRequestHeaderItem from "./ApiReportRequestHeaderItem";
|
||||
import MsMetricChart from "./components/MetricChart";
|
||||
import MsReportTitle from "metersphere-frontend/src/components/report/MsReportTitle";
|
||||
import MsReportExportTemplate from "metersphere-frontend/src/components/report/MsReportExportTemplate";
|
||||
import MsAssertionResults from "../../../business/automation/report/components/AssertionResults"
|
||||
import MsScenarioResult from './components/ScenarioResult';
|
||||
import MsRequestResultTail from './components/RequestResultTail';
|
||||
import ApiReportRequestHeaderItem from './ApiReportRequestHeaderItem';
|
||||
import MsMetricChart from './components/MetricChart';
|
||||
import MsReportTitle from 'metersphere-frontend/src/components/report/MsReportTitle';
|
||||
import MsReportExportTemplate from 'metersphere-frontend/src/components/report/MsReportExportTemplate';
|
||||
import MsAssertionResults from '../../../business/automation/report/components/AssertionResults';
|
||||
|
||||
export default {
|
||||
name: "MsApiReportExport",
|
||||
name: 'MsApiReportExport',
|
||||
components: {
|
||||
MsReportExportTemplate,
|
||||
MsReportTitle, MsMetricChart, ApiReportRequestHeaderItem, MsRequestResultTail, MsScenarioResult, MsAssertionResults
|
||||
MsReportTitle,
|
||||
MsMetricChart,
|
||||
ApiReportRequestHeaderItem,
|
||||
MsRequestResultTail,
|
||||
MsScenarioResult,
|
||||
MsAssertionResults,
|
||||
},
|
||||
props: {
|
||||
report: Object,
|
||||
content: Object,
|
||||
totalTime: Number,
|
||||
projectEnvMap: {},
|
||||
title: String
|
||||
title: String,
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
getName(name) {
|
||||
if (name && name.indexOf("^@~@^") !== -1) {
|
||||
let arr = name.split("^@~@^");
|
||||
if (arr[arr.length - 1].indexOf("UUID=")) {
|
||||
return arr[arr.length - 1].split("UUID=")[0];
|
||||
if (name && name.indexOf('^@~@^') !== -1) {
|
||||
let arr = name.split('^@~@^');
|
||||
if (arr[arr.length - 1].indexOf('UUID=')) {
|
||||
return arr[arr.length - 1].split('UUID=')[0];
|
||||
}
|
||||
return arr[arr.length - 1];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.scenario-result {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
@ -126,17 +161,19 @@ export default {
|
|||
}
|
||||
|
||||
.method {
|
||||
color: #1E90FF;
|
||||
color: #1e90ff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.request-top, .request-bottom, .request-middle {
|
||||
.request-top,
|
||||
.request-bottom,
|
||||
.request-middle {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.url {
|
||||
color: #409EFF;
|
||||
color: #409eff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
|
@ -152,9 +189,8 @@ export default {
|
|||
}
|
||||
|
||||
.ms-test-error_code {
|
||||
color: #F6972A;
|
||||
background-color: #FDF5EA;
|
||||
border-color: #FDF5EA;
|
||||
color: #f6972a;
|
||||
background-color: #fdf5ea;
|
||||
border-color: #fdf5ea;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -3,51 +3,91 @@
|
|||
<ms-main-container>
|
||||
<el-card class="table-card" v-loading="result">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :condition.sync="condition" v-if="loadIsOver" @search="search" :show-create="false">
|
||||
<ms-table-header
|
||||
:condition.sync="condition"
|
||||
v-if="loadIsOver"
|
||||
@search="search"
|
||||
:show-create="false"
|
||||
>
|
||||
<template v-slot:button>
|
||||
<el-button-group>
|
||||
|
||||
<el-tooltip class="item" effect="dark" content="left" :disabled="true" placement="left">
|
||||
<el-button plain :class="{active: leftActive}" @click="changeTab('left')">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
content="left"
|
||||
:disabled="true"
|
||||
placement="left"
|
||||
>
|
||||
<el-button
|
||||
plain
|
||||
:class="{ active: leftActive }"
|
||||
@click="changeTab('left')"
|
||||
>
|
||||
{{ $t('commons.scenario') }}
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip class="item" effect="dark" content="right" :disabled="true" placement="right">
|
||||
<el-button plain :class="{active: rightActive}" @click="changeTab('right')">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
content="right"
|
||||
:disabled="true"
|
||||
placement="right"
|
||||
>
|
||||
<el-button
|
||||
plain
|
||||
:class="{ active: rightActive }"
|
||||
@click="changeTab('right')"
|
||||
>
|
||||
{{ $t('api_test.definition.request.case') }}
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
</el-button-group>
|
||||
</template>
|
||||
</ms-table-header>
|
||||
</template>
|
||||
|
||||
|
||||
<el-table ref="reportListTable" border :data="tableData" class="adjust-table table-content" @sort-change="sort"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelect"
|
||||
:height="screenHeight"
|
||||
@filter-change="filter" @row-click="handleView" v-if="loadIsOver">
|
||||
<el-table-column
|
||||
type="selection"/>
|
||||
<el-table
|
||||
ref="reportListTable"
|
||||
border
|
||||
:data="tableData"
|
||||
class="adjust-table table-content"
|
||||
@sort-change="sort"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelect"
|
||||
:height="screenHeight"
|
||||
@filter-change="filter"
|
||||
@row-click="handleView"
|
||||
v-if="loadIsOver"
|
||||
>
|
||||
<el-table-column type="selection" />
|
||||
<el-table-column width="40" :resizable="false" align="center">
|
||||
<el-dropdown slot="header" style="width: 14px">
|
||||
<span class="el-dropdown-link" style="width: 14px">
|
||||
<i class="el-icon-arrow-down el-icon--right" style="margin-left: 0px"></i>
|
||||
<i
|
||||
class="el-icon-arrow-down el-icon--right"
|
||||
style="margin-left: 0px"
|
||||
></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native.stop="isSelectDataAll(true)">
|
||||
{{ $t('api_test.batch_menus.select_all_data', [total]) }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native.stop="isSelectDataAll(false)">
|
||||
{{ $t('api_test.batch_menus.select_show_data', [tableData.length]) }}
|
||||
{{
|
||||
$t('api_test.batch_menus.select_show_data', [
|
||||
tableData.length,
|
||||
])
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<template v-slot:default="scope">
|
||||
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
|
||||
<show-more-btn
|
||||
:is-show="scope.row.showMore"
|
||||
:buttons="buttons"
|
||||
:size="selectDataCounts"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
@ -59,12 +99,17 @@
|
|||
:editable="true"
|
||||
:edit-content="$t('report.rename_report')"
|
||||
@editColumn="openReNameDialog"
|
||||
min-width="200px">
|
||||
min-width="200px"
|
||||
>
|
||||
</ms-table-column>
|
||||
|
||||
<el-table-column prop="reportType" :label="$t('load_test.report_type')" width="150"
|
||||
column-key="reportType"
|
||||
:filters="reportTypeFilters">
|
||||
<el-table-column
|
||||
prop="reportType"
|
||||
:label="$t('load_test.report_type')"
|
||||
width="150"
|
||||
column-key="reportType"
|
||||
:filters="reportTypeFilters"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<div v-if="scope.row.reportType === 'SCENARIO_INTEGRATED'">
|
||||
<el-tag size="mini" type="primary">
|
||||
|
@ -92,14 +137,29 @@
|
|||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<ms-table-column prop="userName" :label="$t('api_test.creator')" width="150" show-overflow-tooltip
|
||||
:filters="userFilters"/>
|
||||
<el-table-column prop="createTime" min-width="120" :label="$t('commons.create_time')" sortable>
|
||||
<ms-table-column
|
||||
prop="userName"
|
||||
:label="$t('api_test.creator')"
|
||||
width="150"
|
||||
show-overflow-tooltip
|
||||
:filters="userFilters"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
min-width="120"
|
||||
:label="$t('commons.create_time')"
|
||||
sortable
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="endTime" min-width="120" :label="$t('report.test_end_time')" sortable>
|
||||
<el-table-column
|
||||
prop="endTime"
|
||||
min-width="120"
|
||||
:label="$t('report.test_end_time')"
|
||||
sortable
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span v-if="scope.row.endTime && scope.row.endTime > 0">
|
||||
{{ scope.row.endTime | datetimeFormat }}
|
||||
|
@ -109,86 +169,132 @@
|
|||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="triggerMode" width="150" :label="$t('commons.trigger_mode.name')"
|
||||
column-key="triggerMode" :filters="triggerFilters">
|
||||
<el-table-column
|
||||
prop="triggerMode"
|
||||
width="150"
|
||||
:label="$t('commons.trigger_mode.name')"
|
||||
column-key="triggerMode"
|
||||
:filters="triggerFilters"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<report-trigger-mode-item :trigger-mode="scope.row.triggerMode"/>
|
||||
<report-trigger-mode-item :trigger-mode="scope.row.triggerMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('commons.status')"
|
||||
:filters="statusFilters"
|
||||
column-key="status"
|
||||
prop="status">
|
||||
<template v-slot:default="{row}">
|
||||
<ms-api-report-status :status="row.status"/>
|
||||
prop="status"
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<ms-api-report-status :status="row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="150" :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<div>
|
||||
<ms-table-operator-button
|
||||
:tip="$t('api_report.detail')" icon="el-icon-s-data"
|
||||
@exec="handleView(scope.row)" type="primary"/>
|
||||
:tip="$t('api_report.detail')"
|
||||
icon="el-icon-s-data"
|
||||
@exec="handleView(scope.row)"
|
||||
type="primary"
|
||||
/>
|
||||
<ms-table-operator-button
|
||||
:tip="$t('api_report.delete')"
|
||||
v-permission="['PROJECT_API_REPORT:READ+DELETE']"
|
||||
icon="el-icon-delete" @exec="handleDelete(scope.row)" type="danger"/>
|
||||
icon="el-icon-delete"
|
||||
@exec="handleDelete(scope.row)"
|
||||
type="danger"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
<ms-table-pagination
|
||||
:change="search"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:total="total"
|
||||
/>
|
||||
</el-card>
|
||||
<ms-rename-report-dialog ref="renameDialog" @submit="rename($event)"></ms-rename-report-dialog>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('test_track.plan_view.test_result')" width="60%"
|
||||
:visible.sync="resVisible" class="api-import" destroy-on-close @close="resVisible=false">
|
||||
<ms-request-result-tail :report-id="reportId" :response="response" ref="debugResult"/>
|
||||
<ms-rename-report-dialog
|
||||
ref="renameDialog"
|
||||
@submit="rename($event)"
|
||||
></ms-rename-report-dialog>
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('test_track.plan_view.test_result')"
|
||||
width="60%"
|
||||
:visible.sync="resVisible"
|
||||
class="api-import"
|
||||
destroy-on-close
|
||||
@close="resVisible = false"
|
||||
>
|
||||
<ms-request-result-tail
|
||||
:report-id="reportId"
|
||||
:response="response"
|
||||
ref="debugResult"
|
||||
/>
|
||||
</el-dialog>
|
||||
</ms-main-container>
|
||||
</ms-container>
|
||||
</template>
|
||||
<script>
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {REPORT_CASE_CONFIGS, REPORT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
||||
import {_filter, _sort} from "metersphere-frontend/src/utils/tableUtils";
|
||||
import MsRenameReportDialog from "metersphere-frontend/src/components/report/MsRenameReportDialog";
|
||||
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
||||
import MsRequestResultTail from "@/business/definition/components/response/RequestResultTail";
|
||||
import MsTabButton from "@/business/commons/MsTabs";
|
||||
import {getMaintainer} from "@/api/project";
|
||||
import {delBatchReport, delReport, getReportPage, reportReName} from "@/api/scenario-report";
|
||||
import {getApiReportPage} from "@/api/definition-report";
|
||||
import {REPORT_STATUS} from "@/business/commons/js/commons";
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import {
|
||||
REPORT_CASE_CONFIGS,
|
||||
REPORT_CONFIGS,
|
||||
} from 'metersphere-frontend/src/components/search/search-components';
|
||||
import { _filter, _sort } from 'metersphere-frontend/src/utils/tableUtils';
|
||||
import MsRenameReportDialog from 'metersphere-frontend/src/components/report/MsRenameReportDialog';
|
||||
import MsTableColumn from 'metersphere-frontend/src/components/table/MsTableColumn';
|
||||
import MsRequestResultTail from '@/business/definition/components/response/RequestResultTail';
|
||||
import MsTabButton from '@/business/commons/MsTabs';
|
||||
import { getMaintainer } from '@/api/project';
|
||||
import {
|
||||
delBatchReport,
|
||||
delReport,
|
||||
getReportPage,
|
||||
reportReName,
|
||||
} from '@/api/scenario-report';
|
||||
import { getApiReportPage } from '@/api/definition-report';
|
||||
import { REPORT_STATUS } from '@/business/commons/js/commons';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ReportTriggerModeItem: () => import("metersphere-frontend/src/components/tableItem/ReportTriggerModeItem"),
|
||||
MsTableOperatorButton: () => import("metersphere-frontend/src/components/MsTableOperatorButton"),
|
||||
MsApiReportStatus: () => import("./ApiReportStatus"),
|
||||
MsMainContainer: () => import("metersphere-frontend/src/components/MsMainContainer"),
|
||||
MsContainer: () => import("metersphere-frontend/src/components/MsContainer"),
|
||||
MsTableHeader: () => import("metersphere-frontend/src/components/MsTableHeader"),
|
||||
MsTablePagination: () => import("metersphere-frontend/src/components/pagination/TablePagination"),
|
||||
ShowMoreBtn: () => import("@/business/commons/ShowMoreBtn"),
|
||||
ReportTriggerModeItem: () =>
|
||||
import(
|
||||
'metersphere-frontend/src/components/tableItem/ReportTriggerModeItem'
|
||||
),
|
||||
MsTableOperatorButton: () =>
|
||||
import('metersphere-frontend/src/components/MsTableOperatorButton'),
|
||||
MsApiReportStatus: () => import('./ApiReportStatus'),
|
||||
MsMainContainer: () =>
|
||||
import('metersphere-frontend/src/components/MsMainContainer'),
|
||||
MsContainer: () =>
|
||||
import('metersphere-frontend/src/components/MsContainer'),
|
||||
MsTableHeader: () =>
|
||||
import('metersphere-frontend/src/components/MsTableHeader'),
|
||||
MsTablePagination: () =>
|
||||
import('metersphere-frontend/src/components/pagination/TablePagination'),
|
||||
ShowMoreBtn: () => import('@/business/commons/ShowMoreBtn'),
|
||||
MsRenameReportDialog,
|
||||
MsTableColumn,
|
||||
MsTabButton,
|
||||
MsRequestResultTail,
|
||||
},
|
||||
props: {
|
||||
reportType: String
|
||||
reportType: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: false,
|
||||
resVisible: false,
|
||||
response: {},
|
||||
reportId: "",
|
||||
reportId: '',
|
||||
debugVisible: false,
|
||||
condition: {
|
||||
components: REPORT_CONFIGS
|
||||
components: REPORT_CONFIGS,
|
||||
},
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
|
@ -197,29 +303,45 @@ export default {
|
|||
loadIsOver: true,
|
||||
total: 0,
|
||||
loading: false,
|
||||
currentProjectId: "",
|
||||
currentProjectId: '',
|
||||
statusFilters: REPORT_STATUS,
|
||||
reportTypeFilters: [],
|
||||
reportScenarioFilters: [
|
||||
{text: this.$t('api_test.scenario.independent') + this.$t('commons.scenario'), value: 'SCENARIO_INDEPENDENT'},
|
||||
{text: this.$t('api_test.scenario.integrated') + this.$t('commons.scenario'), value: 'SCENARIO_INTEGRATED'}
|
||||
{
|
||||
text:
|
||||
this.$t('api_test.scenario.independent') +
|
||||
this.$t('commons.scenario'),
|
||||
value: 'SCENARIO_INDEPENDENT',
|
||||
},
|
||||
{
|
||||
text:
|
||||
this.$t('api_test.scenario.integrated') +
|
||||
this.$t('commons.scenario'),
|
||||
value: 'SCENARIO_INTEGRATED',
|
||||
},
|
||||
],
|
||||
reportCaseFilters: [
|
||||
{text: this.$t('api_test.scenario.independent') + 'case', value: 'API_INDEPENDENT'},
|
||||
{text: this.$t('api_test.scenario.integrated') + 'case', value: 'API_INTEGRATED'},
|
||||
{
|
||||
text: this.$t('api_test.scenario.independent') + 'case',
|
||||
value: 'API_INDEPENDENT',
|
||||
},
|
||||
{
|
||||
text: this.$t('api_test.scenario.integrated') + 'case',
|
||||
value: 'API_INTEGRATED',
|
||||
},
|
||||
],
|
||||
triggerFilters: [
|
||||
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
|
||||
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
|
||||
{text: this.$t('commons.trigger_mode.api'), value: 'API'},
|
||||
{text: this.$t('api_test.automation.batch_execute'), value: 'BATCH'},
|
||||
{ text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL' },
|
||||
{ text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE' },
|
||||
{ text: this.$t('commons.trigger_mode.api'), value: 'API' },
|
||||
{ text: this.$t('api_test.automation.batch_execute'), value: 'BATCH' },
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
name: this.$t('api_report.batch_delete'),
|
||||
handleClick: this.handleBatchDelete,
|
||||
permissions: ['PROJECT_API_REPORT:READ+DELETE']
|
||||
}
|
||||
permissions: ['PROJECT_API_REPORT:READ+DELETE'],
|
||||
},
|
||||
],
|
||||
selectRows: new Set(),
|
||||
selectAll: false,
|
||||
|
@ -228,18 +350,18 @@ export default {
|
|||
screenHeight: 'calc(100vh - 160px)',
|
||||
activeDom: 'left',
|
||||
userFilters: [],
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
$route(to, from) {
|
||||
if (to.path.startsWith('/api/automation/report')) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
activeDom() {
|
||||
this.condition.filters = {report_type: []};
|
||||
this.condition.filters = { report_type: [] };
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
leftActive() {
|
||||
|
@ -251,9 +373,9 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
getMaintainerOptions() {
|
||||
getMaintainer().then(response => {
|
||||
this.userFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id};
|
||||
getMaintainer().then((response) => {
|
||||
this.userFilters = response.data.map((u) => {
|
||||
return { text: u.name, value: u.id };
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -276,26 +398,37 @@ export default {
|
|||
this.genRedirectParams(this.condition);
|
||||
if (this.activeDom === 'left') {
|
||||
this.reportTypeFilters = this.reportScenarioFilters;
|
||||
this.result = getReportPage(this.currentPage, this.pageSize, this.condition).then(res => {
|
||||
this.result = getReportPage(
|
||||
this.currentPage,
|
||||
this.pageSize,
|
||||
this.condition
|
||||
).then((res) => {
|
||||
this.setData(res);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this.reportTypeFilters = this.reportCaseFilters;
|
||||
this.result = getApiReportPage(this.currentPage, this.pageSize, this.condition).then(res => {
|
||||
this.result = getApiReportPage(
|
||||
this.currentPage,
|
||||
this.pageSize,
|
||||
this.condition
|
||||
).then((res) => {
|
||||
this.setData(res);
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
genRedirectParams(condition) {
|
||||
let selectDataRange = "all";
|
||||
let selectDataType = "all";
|
||||
let selectDataRange = 'all';
|
||||
let selectDataType = 'all';
|
||||
let routeParamObj = this.$route.params;
|
||||
if (routeParamObj) {
|
||||
selectDataRange = routeParamObj.dataSelectRange;
|
||||
selectDataType = routeParamObj.dataType;
|
||||
}
|
||||
|
||||
if ((this.activeDom === 'left' && selectDataType === 'scenario') || (this.activeDom === 'right' && selectDataType === 'apiCase')) {
|
||||
if (
|
||||
(this.activeDom === 'left' && selectDataType === 'scenario') ||
|
||||
(this.activeDom === 'right' && selectDataType === 'apiCase')
|
||||
) {
|
||||
condition.selectDataType = selectDataType;
|
||||
switch (selectDataRange) {
|
||||
case 'scheduleExecutionPassCount':
|
||||
|
@ -315,36 +448,43 @@ export default {
|
|||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
this.selectRows.clear();
|
||||
this.unSelection = data.listObject.map(s => s.id);
|
||||
this.unSelection = data.listObject.map((s) => s.id);
|
||||
},
|
||||
handleView(report) {
|
||||
this.reportId = report.id;
|
||||
if (report.status === 'RUNNING' || report.status === 'RERUNNING') {
|
||||
this.$warning(this.$t('commons.run_warning'))
|
||||
this.$warning(this.$t('commons.run_warning'));
|
||||
return;
|
||||
}
|
||||
if (report.reportType.indexOf('SCENARIO') !== -1 || report.reportType === 'API_INTEGRATED') {
|
||||
if (
|
||||
report.reportType.indexOf('SCENARIO') !== -1 ||
|
||||
report.reportType === 'API_INTEGRATED'
|
||||
) {
|
||||
this.currentProjectId = report.projectId;
|
||||
this.$router.push({
|
||||
path: 'report/view/' + report.id,
|
||||
query: {list: true}
|
||||
query: { list: true },
|
||||
});
|
||||
} else {
|
||||
this.resVisible = true;
|
||||
}
|
||||
},
|
||||
handleDelete(report) {
|
||||
this.$alert(this.$t('api_report.delete_confirm') + report.name + "?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
delReport(report.id).then(() => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
this.$alert(
|
||||
this.$t('api_report.delete_confirm') + report.name + '?',
|
||||
'',
|
||||
{
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
delReport(report.id).then(() => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
);
|
||||
},
|
||||
init() {
|
||||
this.testId = this.$route.params.testId;
|
||||
|
@ -360,54 +500,55 @@ export default {
|
|||
},
|
||||
handleSelect(selection, row) {
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.$set(row, 'showMore', false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.$set(row, 'showMore', true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
this.selectRowsCount(this.selectRows)
|
||||
this.selectRowsCount(this.selectRows);
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
this.tableData.forEach(item => {
|
||||
this.$set(item, "showMore", true);
|
||||
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);
|
||||
})
|
||||
this.tableData.forEach((row) => {
|
||||
this.$set(row, 'showMore', false);
|
||||
});
|
||||
}
|
||||
this.selectRowsCount(this.selectRows)
|
||||
this.selectRowsCount(this.selectRows);
|
||||
},
|
||||
handleBatchDelete() {
|
||||
this.$alert(this.$t('api_report.delete_batch_confirm') + "?", '', {
|
||||
this.$alert(this.$t('api_report.delete_batch_confirm') + '?', '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
let ids = Array.from(this.selectRows).map((row) => row.id);
|
||||
let sendParam = {};
|
||||
sendParam.ids = ids;
|
||||
sendParam.selectAllDate = this.isSelectAllDate;
|
||||
sendParam.unSelectIds = this.unSelection;
|
||||
sendParam = Object.assign(sendParam, this.condition);
|
||||
sendParam.caseType = this.activeDom === 'right' ? 'API' : 'SCENARIO';
|
||||
sendParam.caseType =
|
||||
this.activeDom === 'right' ? 'API' : 'SCENARIO';
|
||||
delBatchReport(sendParam).then(() => {
|
||||
this.selectRows.clear();
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
selectRowsCount(selection) {
|
||||
let selectedIDs = this.getIds(selection);
|
||||
let allIDs = this.tableData.map(s => s.id);
|
||||
let allIDs = this.tableData.map((s) => s.id);
|
||||
this.unSelection = allIDs.filter(function (val) {
|
||||
return selectedIDs.indexOf(val) === -1
|
||||
return selectedIDs.indexOf(val) === -1;
|
||||
});
|
||||
if (this.isSelectAllDate) {
|
||||
this.selectDataCounts = this.total - this.unSelection.length;
|
||||
|
@ -417,15 +558,15 @@ export default {
|
|||
},
|
||||
isSelectDataAll(dataType) {
|
||||
this.isSelectAllDate = dataType;
|
||||
this.selectRowsCount(this.selectRows)
|
||||
this.selectRowsCount(this.selectRows);
|
||||
//如果已经全选,不需要再操作了
|
||||
if (this.selectRows.size != this.tableData.length) {
|
||||
this.$refs.reportListTable.toggleAllSelection(true);
|
||||
}
|
||||
},
|
||||
getIds(rowSets) {
|
||||
let rowArray = Array.from(rowSets)
|
||||
let ids = rowArray.map(s => s.id);
|
||||
let rowArray = Array.from(rowSets);
|
||||
let ids = rowArray.map((s) => s.id);
|
||||
return ids;
|
||||
},
|
||||
openReNameDialog($event) {
|
||||
|
@ -433,7 +574,7 @@ export default {
|
|||
},
|
||||
rename(data) {
|
||||
reportReName(data).then(() => {
|
||||
this.$success(this.$t("organization.integration.successful_operation"));
|
||||
this.$success(this.$t('organization.integration.successful_operation'));
|
||||
this.init();
|
||||
this.$refs.renameDialog.close();
|
||||
});
|
||||
|
@ -455,8 +596,8 @@ export default {
|
|||
created() {
|
||||
this.init();
|
||||
this.getMaintainerOptions();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -467,7 +608,7 @@ export default {
|
|||
.active {
|
||||
border: solid 1px #6d317c !important;
|
||||
background-color: var(--primary_color) !important;
|
||||
color: #FFFFFF !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.item {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="item">
|
||||
<div class="item-title">
|
||||
{{title}}
|
||||
{{ title }}
|
||||
</div>
|
||||
<div>
|
||||
<slot></slot>
|
||||
|
@ -10,22 +10,20 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ApiReportRequestHeaderItem",
|
||||
props: {title: String}
|
||||
}
|
||||
export default {
|
||||
name: 'ApiReportRequestHeaderItem',
|
||||
props: { title: String },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
width: 120px;
|
||||
height: 50px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 120px;
|
||||
height: 50px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tag size="mini" type="primary" effect="plain" v-if="getStatus(status) === 'running'">
|
||||
<el-tag
|
||||
size="mini"
|
||||
type="primary"
|
||||
effect="plain"
|
||||
v-if="getStatus(status) === 'running'"
|
||||
>
|
||||
{{ showStatus(status) }}
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="success" v-else-if="getStatus(status) === 'success'">
|
||||
<el-tag
|
||||
size="mini"
|
||||
type="success"
|
||||
v-else-if="getStatus(status) === 'success'"
|
||||
>
|
||||
{{ showStatus(status) }}
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" v-else-if="getStatus(status) === 'error'">
|
||||
{{ showStatus(status) }}
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" style="background-color: #F6972A; color: #FFFFFF"
|
||||
v-else-if="getStatus(status) === 'fake_error'">
|
||||
<el-tag
|
||||
size="mini"
|
||||
type="danger"
|
||||
style="background-color: #f6972a; color: #ffffff"
|
||||
v-else-if="getStatus(status) === 'fake_error'"
|
||||
>
|
||||
FakeError
|
||||
</el-tag>
|
||||
<span v-else-if="status === '-'" size="mini" type="info">
|
||||
-
|
||||
</span>
|
||||
<span v-else-if="status === '-'" size="mini" type="info"> - </span>
|
||||
<el-tag v-else size="mini" type="info">
|
||||
{{ showStatus(status) }}
|
||||
</el-tag>
|
||||
|
@ -24,28 +35,28 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsApiReportStatus",
|
||||
name: 'MsApiReportStatus',
|
||||
|
||||
props: {
|
||||
status: String
|
||||
status: String,
|
||||
},
|
||||
methods: {
|
||||
getStatus(status) {
|
||||
if (status) {
|
||||
return status.toLowerCase();
|
||||
}
|
||||
return "PENDING";
|
||||
return 'PENDING';
|
||||
},
|
||||
showStatus(status) {
|
||||
if (!status) {
|
||||
status = 'PENDING';
|
||||
}
|
||||
return status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1)
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
:is-share="isShare"
|
||||
:is-plan="isPlanReport"
|
||||
:template-report="response"
|
||||
:is-template="isTemplate"/>
|
||||
:is-template="isTemplate"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsApiReport from "@/business/automation/report/ApiReportDetail";
|
||||
import MsApiReport from '@/business/automation/report/ApiReportDetail';
|
||||
|
||||
export default {
|
||||
name: "ApiReportView",
|
||||
components: {MsApiReport},
|
||||
name: 'ApiReportView',
|
||||
components: { MsApiReport },
|
||||
computed: {
|
||||
reportIdByPath() {
|
||||
return this.getRouteParam('reportId');
|
||||
|
@ -37,16 +38,13 @@ export default {
|
|||
methods: {
|
||||
getRouteParam(name) {
|
||||
if (this.$route) {
|
||||
return this.$route.params[name]
|
||||
return this.$route.params[name];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -3,64 +3,115 @@
|
|||
<el-row>
|
||||
<el-col>
|
||||
<span v-if="!debug">
|
||||
<el-input v-if="nameIsEdit" size="mini" @blur="handleSave(report.name)" @keyup.enter.native="handleSaveKeyUp"
|
||||
style="width: 200px" v-model="report.name" maxlength="60" show-word-limit/>
|
||||
<el-input
|
||||
v-if="nameIsEdit"
|
||||
size="mini"
|
||||
@blur="handleSave(report.name)"
|
||||
@keyup.enter.native="handleSaveKeyUp"
|
||||
style="width: 200px"
|
||||
v-model="report.name"
|
||||
maxlength="60"
|
||||
show-word-limit
|
||||
/>
|
||||
<span v-else>
|
||||
<el-link v-if="isSingleScenario"
|
||||
type="primary"
|
||||
class="report-name"
|
||||
@click="redirect">
|
||||
<el-link
|
||||
v-if="isSingleScenario"
|
||||
type="primary"
|
||||
class="report-name"
|
||||
@click="redirect"
|
||||
>
|
||||
{{ report.name }}
|
||||
</el-link>
|
||||
<span v-else>
|
||||
{{ report.name }}
|
||||
</span>
|
||||
<i v-if="showCancelButton" class="el-icon-edit" style="cursor:pointer" @click="nameIsEdit = true"
|
||||
@click.stop/>
|
||||
<i
|
||||
v-if="showCancelButton"
|
||||
class="el-icon-edit"
|
||||
style="cursor: pointer"
|
||||
@click="nameIsEdit = true"
|
||||
@click.stop
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
<span v-if="report.endTime || report.createTime">
|
||||
<span style="margin-left: 10px">{{ $t('report.test_start_time') }}:</span>
|
||||
<span style="margin-left: 10px"
|
||||
>{{ $t('report.test_start_time') }}:</span
|
||||
>
|
||||
<span class="time"> {{ report.createTime | datetimeFormat }}</span>
|
||||
<span style="margin-left: 10px">{{ $t('report.test_end_time') }}:</span>
|
||||
<span style="margin-left: 10px"
|
||||
>{{ $t('report.test_end_time') }}:</span
|
||||
>
|
||||
<span class="time"> {{ report.endTime | datetimeFormat }}</span>
|
||||
</span>
|
||||
<div style="float: right">
|
||||
<el-button v-if="!isPlan && (!debug || exportFlag) && !isTemplate"
|
||||
v-permission="['PROJECT_API_REPORT:READ+EXPORT']" :disabled="isReadOnly" class="export-button"
|
||||
plain type="primary" size="mini" @click="handleExport(report.name)" style="margin-right: 10px">
|
||||
<el-button
|
||||
v-if="!isPlan && (!debug || exportFlag) && !isTemplate"
|
||||
v-permission="['PROJECT_API_REPORT:READ+EXPORT']"
|
||||
:disabled="isReadOnly"
|
||||
class="export-button"
|
||||
plain
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleExport(report.name)"
|
||||
style="margin-right: 10px"
|
||||
>
|
||||
{{ $t('test_track.plan_view.export_report') }}
|
||||
</el-button>
|
||||
|
||||
<el-popover
|
||||
v-if="!isPlan && (!debug || exportFlag) && !isTemplate"
|
||||
v-permission="['PROJECT_PERFORMANCE_REPORT:READ+EXPORT']"
|
||||
style="margin-right: 10px;float: right;"
|
||||
style="margin-right: 10px; float: right"
|
||||
placement="bottom"
|
||||
trigger="click"
|
||||
width="300">
|
||||
width="300"
|
||||
>
|
||||
<p>{{ shareUrl }}</p>
|
||||
<span style="color: red;float: left;margin-left: 10px;" v-if="application.typeValue">{{
|
||||
$t('commons.validity_period') + application.typeValue
|
||||
}}</span>
|
||||
<span
|
||||
style="color: red; float: left; margin-left: 10px"
|
||||
v-if="application.typeValue"
|
||||
>{{ $t('commons.validity_period') + application.typeValue }}</span
|
||||
>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button type="primary" size="mini" :disabled="!shareUrl"
|
||||
v-clipboard:copy="shareUrl">{{ $t("commons.copy") }}
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
:disabled="!shareUrl"
|
||||
v-clipboard:copy="shareUrl"
|
||||
>{{ $t('commons.copy') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<template v-slot:reference>
|
||||
<el-button :disabled="isReadOnly" type="danger" plain size="mini"
|
||||
@click="handleShare(report)">
|
||||
<el-button
|
||||
:disabled="isReadOnly"
|
||||
type="danger"
|
||||
plain
|
||||
size="mini"
|
||||
@click="handleShare(report)"
|
||||
>
|
||||
{{ $t('test_track.plan_view.share_report') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
|
||||
<el-button v-if="showRerunButton" class="rerun-button" plain size="mini" @click="rerun">
|
||||
<el-button
|
||||
v-if="showRerunButton"
|
||||
class="rerun-button"
|
||||
plain
|
||||
size="mini"
|
||||
@click="rerun"
|
||||
>
|
||||
{{ $t('api_test.automation.rerun') }}
|
||||
</el-button>
|
||||
|
||||
<el-button v-if="showCancelButton" class="export-button" plain size="mini" @click="returnView">
|
||||
<el-button
|
||||
v-if="showCancelButton"
|
||||
class="export-button"
|
||||
plain
|
||||
size="mini"
|
||||
@click="returnView"
|
||||
>
|
||||
{{ $t('commons.cancel') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -68,28 +119,42 @@
|
|||
</el-row>
|
||||
<el-row v-if="showProjectEnv" type="flex">
|
||||
<span> {{ $t('commons.environment') + ':' }} </span>
|
||||
<div v-for="(values,key) in projectEnvMap" :key="key" style="margin-right: 10px">
|
||||
{{ key + ":" }}
|
||||
<ms-tag v-for="(item,index) in values" :key="index" type="success" :content="item"
|
||||
style="margin-left: 2px"/>
|
||||
<div
|
||||
v-for="(values, key) in projectEnvMap"
|
||||
:key="key"
|
||||
style="margin-right: 10px"
|
||||
>
|
||||
{{ key + ':' }}
|
||||
<ms-tag
|
||||
v-for="(item, index) in values"
|
||||
:key="index"
|
||||
type="success"
|
||||
:content="item"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</div>
|
||||
</el-row>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {generateShareInfoWithExpired, getShareRedirectUrl} from "../../../api/share";
|
||||
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import {getProjectApplicationConfig} from "../../../api/project";
|
||||
import {apiTestReRun} from "../../../api/xpack";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import {getApiScenarioIdByPlanScenarioId} from "@/api/test-plan";
|
||||
import {
|
||||
generateShareInfoWithExpired,
|
||||
getShareRedirectUrl,
|
||||
} from '../../../api/share';
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentWorkspaceId,
|
||||
} from 'metersphere-frontend/src/utils/token';
|
||||
import MsTag from 'metersphere-frontend/src/components/MsTag';
|
||||
import { getProjectApplicationConfig } from '../../../api/project';
|
||||
import { apiTestReRun } from '../../../api/xpack';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { getApiScenarioIdByPlanScenarioId } from '@/api/test-plan';
|
||||
|
||||
export default {
|
||||
name: "MsApiReportViewHeader",
|
||||
components: {MsTag},
|
||||
name: 'MsApiReportViewHeader',
|
||||
components: { MsTag },
|
||||
props: {
|
||||
report: {},
|
||||
projectEnvMap: {},
|
||||
|
@ -107,20 +172,20 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isPlan: Boolean
|
||||
isPlan: Boolean,
|
||||
},
|
||||
computed: {
|
||||
showProjectEnv() {
|
||||
return this.projectEnvMap && JSON.stringify(this.projectEnvMap) !== '{}';
|
||||
},
|
||||
path() {
|
||||
return "/api/test/edit?id=" + this.report.testId;
|
||||
return '/api/test/edit?id=' + this.report.testId;
|
||||
},
|
||||
scenarioId() {
|
||||
if (typeof this.report.scenarioId === 'string') {
|
||||
return this.report.scenarioId;
|
||||
} else {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
},
|
||||
isSingleScenario() {
|
||||
|
@ -136,9 +201,9 @@ export default {
|
|||
return {
|
||||
isReadOnly: false,
|
||||
nameIsEdit: false,
|
||||
shareUrl: "",
|
||||
application: {}
|
||||
}
|
||||
shareUrl: '',
|
||||
application: {},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleExport(name) {
|
||||
|
@ -162,21 +227,25 @@ export default {
|
|||
let uuid = getUUID().substring(1, 5);
|
||||
let projectId = getCurrentProjectID();
|
||||
let workspaceId = getCurrentWorkspaceId();
|
||||
let prefix = "/#";
|
||||
if (this.$route && this.$route.path.startsWith('/api/automation/report')
|
||||
&& this.$route.query && this.$route.query.list) {
|
||||
prefix = ""
|
||||
let prefix = '/#';
|
||||
if (
|
||||
this.$route &&
|
||||
this.$route.path.startsWith('/api/automation/report') &&
|
||||
this.$route.query &&
|
||||
this.$route.query.list
|
||||
) {
|
||||
prefix = '';
|
||||
}
|
||||
let path = `${prefix}/api/automation/?redirectID=${uuid}&dataType=scenario&projectId=${projectId}&workspaceId=${workspaceId}&resourceId=${resourceId}`;
|
||||
let data = this.$router.resolve({
|
||||
path: path
|
||||
path: path,
|
||||
});
|
||||
window.open(data.href, '_blank');
|
||||
},
|
||||
rerun() {
|
||||
let type = this.report.reportType;
|
||||
let rerunObj = {type: type, reportId: this.report.id}
|
||||
apiTestReRun(rerunObj).then(res => {
|
||||
let rerunObj = { type: type, reportId: this.report.id };
|
||||
apiTestReRun(rerunObj).then((res) => {
|
||||
if (res.data !== 'SUCCESS') {
|
||||
this.$error(res.data);
|
||||
} else {
|
||||
|
@ -201,16 +270,27 @@ export default {
|
|||
});
|
||||
},
|
||||
getProjectApplication() {
|
||||
getProjectApplicationConfig(getCurrentProjectID(), "/API_SHARE_REPORT_TIME").then(res => {
|
||||
getProjectApplicationConfig(
|
||||
getCurrentProjectID(),
|
||||
'/API_SHARE_REPORT_TIME'
|
||||
).then((res) => {
|
||||
if (res.data && res.data.typeValue) {
|
||||
let quantity = res.data.typeValue.substring(0, res.data.typeValue.length - 1);
|
||||
let unit = res.data.typeValue.substring(res.data.typeValue.length - 1);
|
||||
let quantity = res.data.typeValue.substring(
|
||||
0,
|
||||
res.data.typeValue.length - 1
|
||||
);
|
||||
let unit = res.data.typeValue.substring(
|
||||
res.data.typeValue.length - 1
|
||||
);
|
||||
if (unit === 'H') {
|
||||
res.data.typeValue = quantity + this.$t('commons.date_unit.hour');
|
||||
} else if (unit === 'D') {
|
||||
res.data.typeValue = quantity + this.$t('commons.date_unit.day');
|
||||
} else if (unit === 'M') {
|
||||
res.data.typeValue = quantity + this.$t('commons.workspace_unit') + this.$t('commons.date_unit.month');
|
||||
res.data.typeValue =
|
||||
quantity +
|
||||
this.$t('commons.workspace_unit') +
|
||||
this.$t('commons.date_unit.month');
|
||||
} else if (unit === 'Y') {
|
||||
res.data.typeValue = quantity + this.$t('commons.date_unit.year');
|
||||
}
|
||||
|
@ -218,12 +298,11 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.export-button {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
|
@ -232,8 +311,8 @@ export default {
|
|||
.rerun-button {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
background-color: #F2F9EF;
|
||||
color: #87C45D;
|
||||
background-color: #f2f9ef;
|
||||
color: #87c45d;
|
||||
}
|
||||
|
||||
.report-name {
|
||||
|
|
|
@ -11,14 +11,16 @@
|
|||
:report="report"
|
||||
:project-env-map="projectEnvMap"
|
||||
@reportExport="handleExport"
|
||||
@reportSave="handleSave"/>
|
||||
@reportSave="handleSave"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<ms-metric-chart
|
||||
:content="content"
|
||||
:totalTime="totalTime"
|
||||
:report="report"
|
||||
v-if="!loading"/>
|
||||
v-if="!loading"
|
||||
/>
|
||||
<div>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="All" name="total">
|
||||
|
@ -31,9 +33,7 @@
|
|||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="fail">
|
||||
<template slot="label">
|
||||
Error
|
||||
</template>
|
||||
<template slot="label"> Error </template>
|
||||
<ms-scenario-results
|
||||
:console="content.console"
|
||||
:report="report"
|
||||
|
@ -44,24 +44,26 @@
|
|||
</el-tab-pane>
|
||||
<el-tab-pane name="errorReport" v-if="content.errorCode > 0">
|
||||
<template slot="label">
|
||||
<span class="fail" style="color: #F6972A">
|
||||
FakeError
|
||||
</span>
|
||||
<span class="fail" style="color: #f6972a"> FakeError </span>
|
||||
</template>
|
||||
<ms-scenario-results v-on:requestResult="requestResult" :console="content.console"
|
||||
:treeData="fullTreeNodes" ref="errorReportTree"/>
|
||||
<ms-scenario-results
|
||||
v-on:requestResult="requestResult"
|
||||
:console="content.console"
|
||||
:treeData="fullTreeNodes"
|
||||
ref="errorReportTree"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="unExecute" v-if="content.unExecute > 0">
|
||||
<template slot="label">
|
||||
<span class="fail" style="color: #9C9B9A">
|
||||
Pending
|
||||
</span>
|
||||
<span class="fail" style="color: #9c9b9a"> Pending </span>
|
||||
</template>
|
||||
<ms-scenario-results v-on:requestResult="requestResult"
|
||||
:report="report"
|
||||
:console="content.console"
|
||||
:treeData="fullTreeNodes"
|
||||
ref="unExecuteTree"/>
|
||||
<ms-scenario-results
|
||||
v-on:requestResult="requestResult"
|
||||
:report="report"
|
||||
:console="content.console"
|
||||
:treeData="fullTreeNodes"
|
||||
ref="unExecuteTree"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="console">
|
||||
<template slot="label">
|
||||
|
@ -87,35 +89,39 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {baseSocket} from "@/api/base-network";
|
||||
import MsRequestResult from "./components/RequestResult";
|
||||
import MsRequestResultTail from "./components/RequestResultTail";
|
||||
import MsScenarioResult from "./components/ScenarioResult";
|
||||
import MsMetricChart from "./components/MetricChart";
|
||||
import MsScenarioResults from "./components/ScenarioResults";
|
||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||
import MsApiReportExport from "./ApiReportExport";
|
||||
import MsApiReportViewHeader from "./ApiReportViewHeader";
|
||||
import {RequestFactory} from "../../definition/model/ApiTestModel";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {windowPrint} from "metersphere-frontend/src/utils";
|
||||
import {STEP} from "../scenario/Setting";
|
||||
import {getScenarioReport, updateReport} from "@/api/scenario-report";
|
||||
import { baseSocket } from '@/api/base-network';
|
||||
import MsRequestResult from './components/RequestResult';
|
||||
import MsRequestResultTail from './components/RequestResultTail';
|
||||
import MsScenarioResult from './components/ScenarioResult';
|
||||
import MsMetricChart from './components/MetricChart';
|
||||
import MsScenarioResults from './components/ScenarioResults';
|
||||
import MsContainer from 'metersphere-frontend/src/components/MsContainer';
|
||||
import MsMainContainer from 'metersphere-frontend/src/components/MsMainContainer';
|
||||
import MsApiReportExport from './ApiReportExport';
|
||||
import MsApiReportViewHeader from './ApiReportViewHeader';
|
||||
import { RequestFactory } from '../../definition/model/ApiTestModel';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { windowPrint } from 'metersphere-frontend/src/utils';
|
||||
import { STEP } from '../scenario/Setting';
|
||||
import { getScenarioReport, updateReport } from '@/api/scenario-report';
|
||||
|
||||
export default {
|
||||
name: "SyncApiReportDetail",
|
||||
name: 'SyncApiReportDetail',
|
||||
components: {
|
||||
MsApiReportViewHeader,
|
||||
MsApiReportExport,
|
||||
MsMainContainer,
|
||||
MsContainer, MsScenarioResults, MsRequestResultTail, MsMetricChart, MsScenarioResult, MsRequestResult
|
||||
MsContainer,
|
||||
MsScenarioResults,
|
||||
MsRequestResultTail,
|
||||
MsMetricChart,
|
||||
MsScenarioResult,
|
||||
MsRequestResult,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: "total",
|
||||
content: {total: 0, scenarioTotal: 1},
|
||||
activeName: 'total',
|
||||
content: { total: 0, scenarioTotal: 1 },
|
||||
report: {},
|
||||
loading: false,
|
||||
totalTime: 0,
|
||||
|
@ -128,26 +134,25 @@ export default {
|
|||
reportExportVisible: false,
|
||||
requestType: undefined,
|
||||
fullTreeNodes: [],
|
||||
debugResult: new Map,
|
||||
scenarioMap: new Map,
|
||||
debugResult: new Map(),
|
||||
scenarioMap: new Map(),
|
||||
exportFlag: false,
|
||||
messageWebSocket: {},
|
||||
websocket: {},
|
||||
stepFilter: new STEP,
|
||||
stepFilter: new STEP(),
|
||||
tempResult: [],
|
||||
projectEnvMap: {},
|
||||
}
|
||||
};
|
||||
},
|
||||
activated() {
|
||||
this.isRequestResult = false;
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
created() {},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
if (this.scenario && this.scenario.scenarioDefinition) {
|
||||
this.content.scenarioStepTotal = this.scenario.scenarioDefinition.hashTree.length;
|
||||
this.content.scenarioStepTotal =
|
||||
this.scenario.scenarioDefinition.hashTree.length;
|
||||
this.initTree();
|
||||
this.initMessageSocket();
|
||||
this.clearDebug();
|
||||
|
@ -162,21 +167,31 @@ export default {
|
|||
scenarioId: String,
|
||||
isUi: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initTree() {
|
||||
this.fullTreeNodes = [];
|
||||
let obj = {
|
||||
resId: "root",
|
||||
resId: 'root',
|
||||
index: 1,
|
||||
label: this.scenario.name,
|
||||
value: {responseResult: {}, unexecute: true, testing: false, status: 'PENDING'},
|
||||
value: {
|
||||
responseResult: {},
|
||||
unexecute: true,
|
||||
testing: false,
|
||||
status: 'PENDING',
|
||||
},
|
||||
children: [],
|
||||
unsolicited: true
|
||||
unsolicited: true,
|
||||
};
|
||||
this.formatContent(this.scenario.scenarioDefinition.hashTree, obj, "", "root");
|
||||
this.formatContent(
|
||||
this.scenario.scenarioDefinition.hashTree,
|
||||
obj,
|
||||
'',
|
||||
'root'
|
||||
);
|
||||
this.fullTreeNodes.push(obj);
|
||||
},
|
||||
compare() {
|
||||
|
@ -184,23 +199,23 @@ export default {
|
|||
let v1 = a.value.sort;
|
||||
let v2 = b.value.sort;
|
||||
return v1 - v2;
|
||||
}
|
||||
};
|
||||
},
|
||||
getType(type) {
|
||||
switch (type) {
|
||||
case "LoopController":
|
||||
return "循环控制器";
|
||||
case "TransactionController":
|
||||
return "事物控制器";
|
||||
case "ConstantTimer":
|
||||
return "等待控制器";
|
||||
case "IfController":
|
||||
return "条件控制器";
|
||||
case 'LoopController':
|
||||
return '循环控制器';
|
||||
case 'TransactionController':
|
||||
return '事物控制器';
|
||||
case 'ConstantTimer':
|
||||
return '等待控制器';
|
||||
case 'IfController':
|
||||
return '条件控制器';
|
||||
}
|
||||
return type;
|
||||
},
|
||||
margeTransaction(item, arr) {
|
||||
arr.forEach(subItem => {
|
||||
arr.forEach((subItem) => {
|
||||
if (item.resId === subItem.resourceId) {
|
||||
item.value = subItem;
|
||||
item.testing = false;
|
||||
|
@ -209,32 +224,59 @@ export default {
|
|||
if (subItem.subRequestResults && subItem.subRequestResults.length > 0) {
|
||||
this.margeTransaction(item, subItem.subRequestResults);
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
formatContent(hashTree, tree, fullPath, pid) {
|
||||
if (hashTree) {
|
||||
hashTree.forEach(item => {
|
||||
hashTree.forEach((item) => {
|
||||
if (item.enable) {
|
||||
item.parentIndex = fullPath ? fullPath + "_" + item.index : item.index;
|
||||
item.parentIndex = fullPath
|
||||
? fullPath + '_' + item.index
|
||||
: item.index;
|
||||
let name = item.name ? item.name : this.getType(item.type);
|
||||
let id = item.type === 'JSR223Processor' || !item.id ? item.resourceId : item.id
|
||||
let id =
|
||||
item.type === 'JSR223Processor' || !item.id
|
||||
? item.resourceId
|
||||
: item.id;
|
||||
let obj = {
|
||||
pid: pid, resId: id + "_" + item.parentIndex, index: Number(item.index), label: name,
|
||||
value: {name: name, responseResult: {}, unexecute: true, testing: false, status: 'PENDING'}, children:
|
||||
[], unsolicited: true
|
||||
pid: pid,
|
||||
resId: id + '_' + item.parentIndex,
|
||||
index: Number(item.index),
|
||||
label: name,
|
||||
value: {
|
||||
name: name,
|
||||
responseResult: {},
|
||||
unexecute: true,
|
||||
testing: false,
|
||||
status: 'PENDING',
|
||||
},
|
||||
children: [],
|
||||
unsolicited: true,
|
||||
};
|
||||
tree.children.push(obj);
|
||||
if (this.stepFilter.get("AllSamplerProxy").indexOf(item.type) !== -1) {
|
||||
if (
|
||||
this.stepFilter.get('AllSamplerProxy').indexOf(item.type) !== -1
|
||||
) {
|
||||
obj.unsolicited = false;
|
||||
obj.type = item.type;
|
||||
} else if (item.type === 'scenario') {
|
||||
this.content.scenarioTotal += 1;
|
||||
}
|
||||
if (item.hashTree && item.hashTree.length > 0 && this.stepFilter && this.stepFilter.get("AllSamplerProxy").indexOf(item.type) === -1) {
|
||||
this.formatContent(item.hashTree, obj, item.parentIndex, obj.resId);
|
||||
if (
|
||||
item.hashTree &&
|
||||
item.hashTree.length > 0 &&
|
||||
this.stepFilter &&
|
||||
this.stepFilter.get('AllSamplerProxy').indexOf(item.type) === -1
|
||||
) {
|
||||
this.formatContent(
|
||||
item.hashTree,
|
||||
obj,
|
||||
item.parentIndex,
|
||||
obj.resId
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
handleExport() {
|
||||
|
@ -246,12 +288,12 @@ export default {
|
|||
});
|
||||
},
|
||||
filter(index) {
|
||||
if (index === "1") {
|
||||
if (index === '1') {
|
||||
this.$refs.failsTree.filter(index);
|
||||
} else if (this.activeName === "errorReport") {
|
||||
this.$refs.errorReportTree.filter("FAKE_ERROR");
|
||||
} else if (this.activeName === "unExecute") {
|
||||
this.$refs.unExecuteTree.filter("PENDING");
|
||||
} else if (this.activeName === 'errorReport') {
|
||||
this.$refs.errorReportTree.filter('FAKE_ERROR');
|
||||
} else if (this.activeName === 'unExecute') {
|
||||
this.$refs.unExecuteTree.filter('PENDING');
|
||||
}
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
|
@ -312,14 +354,17 @@ export default {
|
|||
}
|
||||
this.loading = true;
|
||||
this.report.projectId = this.projectId;
|
||||
let url = "/api/scenario/report/update";
|
||||
this.result = updateReport(this.report).then(response => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.loading = false;
|
||||
this.$emit('refresh');
|
||||
}, error => {
|
||||
this.loading = false;
|
||||
});
|
||||
let url = '/api/scenario/report/update';
|
||||
this.result = updateReport(this.report).then(
|
||||
(response) => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.loading = false;
|
||||
this.$emit('refresh');
|
||||
},
|
||||
(error) => {
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
initMessageSocket() {
|
||||
|
@ -328,25 +373,29 @@ export default {
|
|||
this.messageWebSocket.onerror = this.cleanHeartBeat;
|
||||
},
|
||||
getReport() {
|
||||
getScenarioReport(this.reportId).then(response => {
|
||||
getScenarioReport(this.reportId).then((response) => {
|
||||
this.report = response.data || {};
|
||||
if (response.data) {
|
||||
this.content = JSON.parse(response.data.content);
|
||||
if (!this.content) {
|
||||
this.content = {scenarios: []};
|
||||
this.content = { scenarios: [] };
|
||||
}
|
||||
if (this.content.projectEnvMap) {
|
||||
this.projectEnvMap = this.content.projectEnvMap;
|
||||
}
|
||||
this.content.error = this.content ? this.content.error : "";
|
||||
this.content.error = this.content ? this.content.error : '';
|
||||
|
||||
this.content.success = (this.content.total - this.content.error - this.content.errorCode - this.content.unExecute);
|
||||
this.content.success =
|
||||
this.content.total -
|
||||
this.content.error -
|
||||
this.content.errorCode -
|
||||
this.content.unExecute;
|
||||
this.totalTime = this.content.totalTime;
|
||||
this.fullTreeNodes = this.content.steps;
|
||||
this.recursiveSorting(this.fullTreeNodes);
|
||||
this.reload();
|
||||
}
|
||||
if ("Running" !== this.report.status) {
|
||||
if ('Running' !== this.report.status) {
|
||||
this.$emit('finish');
|
||||
}
|
||||
});
|
||||
|
@ -357,39 +406,45 @@ export default {
|
|||
}
|
||||
if (Array.isArray(origin)) {
|
||||
this.sortChildren(origin);
|
||||
origin.forEach(v => {
|
||||
origin.forEach((v) => {
|
||||
if (v.children) {
|
||||
this.checkOrder(v.children)
|
||||
this.checkOrder(v.children);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
sortChildren(source) {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
source.forEach(item => {
|
||||
source.forEach((item) => {
|
||||
let children = item.children;
|
||||
if (children && children.length > 0) {
|
||||
let tempArr = new Array(children.length);
|
||||
let tempMap = new Map();
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
if (!children[i].value || !children[i].value.startTime || children[i].value.startTime === 0) {
|
||||
if (
|
||||
!children[i].value ||
|
||||
!children[i].value.startTime ||
|
||||
children[i].value.startTime === 0
|
||||
) {
|
||||
//若没有value或未执行的,则step留在当前位置
|
||||
tempArr[i] = children[i];
|
||||
//进行标识
|
||||
tempMap.set(children[i].stepId, children[i])
|
||||
tempMap.set(children[i].stepId, children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//过滤出还没有指定好位置的step
|
||||
let arr = children.filter(m => {
|
||||
return !tempMap.get(m.stepId);
|
||||
}).sort((m, n) => {
|
||||
//按时间排序
|
||||
return m.value.startTime - n.value.startTime;
|
||||
});
|
||||
let arr = children
|
||||
.filter((m) => {
|
||||
return !tempMap.get(m.stepId);
|
||||
})
|
||||
.sort((m, n) => {
|
||||
//按时间排序
|
||||
return m.value.startTime - n.value.startTime;
|
||||
});
|
||||
|
||||
//找出arr(已经有序,从头取即可)中时间最小的插入 tempArr 可用位置
|
||||
for (let j = 0, i = 0; j < tempArr.length; j++) {
|
||||
|
@ -405,13 +460,13 @@ export default {
|
|||
//赋值
|
||||
item.children = tempArr;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
runningNodeChild(arr, resourceId) {
|
||||
arr.forEach(item => {
|
||||
arr.forEach((item) => {
|
||||
if (resourceId === item.resId) {
|
||||
item.value.testing = true;
|
||||
} else if (resourceId && resourceId.startsWith("result_")) {
|
||||
} else if (resourceId && resourceId.startsWith('result_')) {
|
||||
let data = JSON.parse(resourceId.substring(7));
|
||||
if (!data.status && data.error > 0) {
|
||||
data.status = 'ERROR';
|
||||
|
@ -419,7 +474,11 @@ export default {
|
|||
if (!data.status && data.success) {
|
||||
data.status = 'SUCCESS';
|
||||
}
|
||||
if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) {
|
||||
if (
|
||||
data.method === 'Request' &&
|
||||
data.subRequestResults &&
|
||||
data.subRequestResults.length > 0
|
||||
) {
|
||||
this.margeTransaction(item, data.subRequestResults);
|
||||
} else if (item.resId === data.resourceId) {
|
||||
if (item.value && item.value.id && !item.mark) {
|
||||
|
@ -440,14 +499,14 @@ export default {
|
|||
if (item.children && item.children.length > 0) {
|
||||
this.runningNodeChild(item.children, resourceId);
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
runningEvaluation(resourceId) {
|
||||
if (this.fullTreeNodes) {
|
||||
this.fullTreeNodes.forEach(item => {
|
||||
this.fullTreeNodes.forEach((item) => {
|
||||
if (resourceId === item.resId) {
|
||||
item.value.testing = true;
|
||||
} else if (resourceId && resourceId.startsWith("result_")) {
|
||||
} else if (resourceId && resourceId.startsWith('result_')) {
|
||||
let data = JSON.parse(resourceId.substring(7));
|
||||
if (!data.status && data.error > 0) {
|
||||
data.status = 'ERROR';
|
||||
|
@ -455,14 +514,18 @@ export default {
|
|||
if (!data.status && data.success) {
|
||||
data.status = 'SUCCESS';
|
||||
}
|
||||
if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) {
|
||||
data.subRequestResults.forEach(subItem => {
|
||||
if (
|
||||
data.method === 'Request' &&
|
||||
data.subRequestResults &&
|
||||
data.subRequestResults.length > 0
|
||||
) {
|
||||
data.subRequestResults.forEach((subItem) => {
|
||||
if (item.resId === subItem.resourceId) {
|
||||
item.value = subItem;
|
||||
item.testing = false;
|
||||
item.debug = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else if (item.resId === data.resourceId) {
|
||||
item.value = data;
|
||||
item.testing = false;
|
||||
|
@ -472,7 +535,7 @@ export default {
|
|||
if (item.children && item.children.length > 0) {
|
||||
this.runningNodeChild(item.children, resourceId);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
onMessage(e) {
|
||||
|
@ -480,7 +543,7 @@ export default {
|
|||
this.runningEvaluation(e.data);
|
||||
this.sort(this.fullTreeNodes);
|
||||
}
|
||||
if (e.data && e.data.indexOf("MS_TEST_END") !== -1) {
|
||||
if (e.data && e.data.indexOf('MS_TEST_END') !== -1) {
|
||||
this.getReport();
|
||||
this.messageWebSocket.close();
|
||||
this.cleanHeartBeat();
|
||||
|
@ -503,17 +566,17 @@ export default {
|
|||
heartBeat() {
|
||||
let msg = {
|
||||
reportId: this.reportId,
|
||||
content: "i'm alive"
|
||||
content: "i'm alive",
|
||||
};
|
||||
this.messageWebSocket.send(JSON.stringify(msg));
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
projectId() {
|
||||
return getCurrentProjectID();
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.report-container .el-tabs__header {
|
||||
|
@ -522,7 +585,6 @@ export default {
|
|||
</style>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.report-container {
|
||||
height: calc(100vh - 155px);
|
||||
min-height: 600px;
|
||||
|
@ -543,7 +605,7 @@ export default {
|
|||
}
|
||||
|
||||
.report-container .fail {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.report-container .is-active .fail {
|
||||
|
@ -561,5 +623,4 @@ export default {
|
|||
.report-body {
|
||||
min-width: 750px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,40 +1,77 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-table :data="assertions" :row-style="getRowStyle" :header-cell-style="getRowStyle">
|
||||
<el-table-column prop="name" :label="$t('api_report.assertions_name')" width="150" show-overflow-tooltip>
|
||||
<el-table
|
||||
:data="assertions"
|
||||
:row-style="getRowStyle"
|
||||
:header-cell-style="getRowStyle"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('api_report.assertions_name')"
|
||||
width="150"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ !scope.row.name || scope.row.name === 'null' ? "" : scope.row.name }}</span>
|
||||
<span>{{
|
||||
!scope.row.name || scope.row.name === 'null' ? '' : scope.row.name
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="content" v-if="showContent" :label="$t('api_report.assertions_content')" width="300"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="message" :label="$t('api_report.assertions_error_message')"/>
|
||||
<el-table-column prop="pass" :label="$t('api_report.assertions_is_success')" width="180">
|
||||
<template v-slot:default="{row}">
|
||||
<el-tag size="mini" type="success" v-if="row.pass">
|
||||
Success
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" v-else>
|
||||
Error
|
||||
</el-tag>
|
||||
<el-table-column
|
||||
prop="content"
|
||||
v-if="showContent"
|
||||
:label="$t('api_report.assertions_content')"
|
||||
width="300"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="message"
|
||||
:label="$t('api_report.assertions_error_message')"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="pass"
|
||||
:label="$t('api_report.assertions_is_success')"
|
||||
width="180"
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-tag size="mini" type="success" v-if="row.pass"> Success </el-tag>
|
||||
<el-tag size="mini" type="danger" v-else> Error </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="script">
|
||||
<template v-slot:default="{row}">
|
||||
<template v-slot:default="{ row }">
|
||||
<div class="assertion-item btn circle" v-if="row.script">
|
||||
<i class="el-icon-view el-button el-button--primary el-button--mini is-circle" circle
|
||||
@click="showPage(row.script)"/>
|
||||
<i
|
||||
class="el-icon-view el-button el-button--primary el-button--mini is-circle"
|
||||
circle
|
||||
@click="showPage(row.script)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-dialog :title="$t('api_test.request.assertions.script')" :visible.sync="visible" width="900px" modal-append-to-body append-to-body>
|
||||
<el-row type="flex" justify="space-between" align="middle" class="quick-script-block">
|
||||
<el-dialog
|
||||
:title="$t('api_test.request.assertions.script')"
|
||||
:visible.sync="visible"
|
||||
width="900px"
|
||||
modal-append-to-body
|
||||
append-to-body
|
||||
>
|
||||
<el-row
|
||||
type="flex"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
class="quick-script-block"
|
||||
>
|
||||
<el-col :span="codeSpan" class="script-content">
|
||||
<ms-code-edit v-if="isCodeEditAlive"
|
||||
:read-only="disabled"
|
||||
:data.sync="scriptContent" theme="eclipse" :modes="['java','python']"
|
||||
ref="codeEdit"/>
|
||||
<ms-code-edit
|
||||
v-if="isCodeEditAlive"
|
||||
:read-only="disabled"
|
||||
:data.sync="scriptContent"
|
||||
theme="eclipse"
|
||||
:modes="['java', 'python']"
|
||||
ref="codeEdit"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
|
@ -42,18 +79,17 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
|
||||
export default {
|
||||
name: "MsAssertionResults",
|
||||
components: {MsCodeEdit},
|
||||
name: 'MsAssertionResults',
|
||||
components: { MsCodeEdit },
|
||||
props: {
|
||||
assertions: Array,
|
||||
showContent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -62,11 +98,11 @@ export default {
|
|||
codeSpan: 20,
|
||||
isCodeEditAlive: true,
|
||||
scriptContent: '',
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getRowStyle() {
|
||||
return {backgroundColor: "#F5F5F5"};
|
||||
return { backgroundColor: '#F5F5F5' };
|
||||
},
|
||||
showPage(script) {
|
||||
this.disabled = true;
|
||||
|
@ -79,13 +115,10 @@ export default {
|
|||
this.$nextTick(() => (this.isCodeEditAlive = true));
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
.assertion-item.btn.circle {
|
||||
text-align: right;
|
||||
min-width: 80px;
|
||||
|
|
|
@ -10,32 +10,48 @@
|
|||
</el-row>
|
||||
<!-- 导出报告样式定制 -->
|
||||
<div v-if="isExport">
|
||||
<span class="ms-req ms-req-error"
|
||||
v-if="(content.error && content.error > 0 )
|
||||
|| (content.errorCode && content.errorCode > 0)
|
||||
|| (content.unExecute && content.unExecute > 0)">
|
||||
<span class="ms-req-span">
|
||||
{{ content.success + content.error + content.errorCode + content.unExecute }}
|
||||
{{ $t('api_report.request') }}
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ms-req ms-req-error"
|
||||
v-if="
|
||||
(content.error && content.error > 0) ||
|
||||
(content.errorCode && content.errorCode > 0) ||
|
||||
(content.unExecute && content.unExecute > 0)
|
||||
"
|
||||
>
|
||||
<span class="ms-req-span">
|
||||
{{
|
||||
content.success +
|
||||
content.error +
|
||||
content.errorCode +
|
||||
content.unExecute
|
||||
}}
|
||||
{{ $t('api_report.request') }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="ms-req ms-req-success" v-else>
|
||||
<span class="ms-req-span">
|
||||
{{ content.success ? content.success + content.error : 0 }} {{ $t('api_report.request') }}
|
||||
</span>
|
||||
<span class="ms-req-span">
|
||||
{{ content.success ? content.success + content.error : 0 }}
|
||||
{{ $t('api_report.request') }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- 饼图显示/成功/失败/误报 -->
|
||||
<ms-chart ref="chart"
|
||||
:options="options"
|
||||
:height="150"
|
||||
:width="150"
|
||||
:autoresize="true" v-else/>
|
||||
<ms-chart
|
||||
ref="chart"
|
||||
:options="options"
|
||||
:height="150"
|
||||
:width="150"
|
||||
:autoresize="true"
|
||||
v-else
|
||||
/>
|
||||
<!-- 总数统计 -->
|
||||
<el-row type="flex" justify="center" align="middle">
|
||||
<div style="min-width: 120px">
|
||||
<div class="metric-icon-box">
|
||||
<span class="ms-point-success" style="margin: 7px;float: left;"/>
|
||||
<span
|
||||
class="ms-point-success"
|
||||
style="margin: 7px; float: left"
|
||||
/>
|
||||
<div class="metric-box-total">
|
||||
<div class="value" style="font-size: 12px">
|
||||
{{ content.success }} Success
|
||||
|
@ -44,7 +60,7 @@
|
|||
</div>
|
||||
<el-divider></el-divider>
|
||||
<div class="metric-icon-box" style="height: 26px">
|
||||
<span class="ms-point-error" style="margin: 7px;float: left;"/>
|
||||
<span class="ms-point-error" style="margin: 7px; float: left" />
|
||||
<div class="metric-box-total">
|
||||
<div class="value" style="font-size: 12px">
|
||||
{{ content.error }} Error
|
||||
|
@ -52,8 +68,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<el-divider v-if="content.errorCode > 0"></el-divider>
|
||||
<div class="metric-icon-box" v-if="content.errorCode > 0" style="height: 26px">
|
||||
<span class="ms-point-error-code" style="margin: 7px;float: left;"/>
|
||||
<div
|
||||
class="metric-icon-box"
|
||||
v-if="content.errorCode > 0"
|
||||
style="height: 26px"
|
||||
>
|
||||
<span
|
||||
class="ms-point-error-code"
|
||||
style="margin: 7px; float: left"
|
||||
/>
|
||||
<div class="metric-box-total" v-if="content.errorCode > 0">
|
||||
<div class="value" style="font-size: 12px">
|
||||
{{ content.errorCode }} FakeError
|
||||
|
@ -61,8 +84,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<el-divider v-if="content.unExecute > 0"></el-divider>
|
||||
<div class="metric-icon-box" style="height: 26px" v-if="content.unExecute > 0">
|
||||
<span class="ms-point-unexecute" style="margin: 7px;float: left;"/>
|
||||
<div
|
||||
class="metric-icon-box"
|
||||
style="height: 26px"
|
||||
v-if="content.unExecute > 0"
|
||||
>
|
||||
<span
|
||||
class="ms-point-unexecute"
|
||||
style="margin: 7px; float: left"
|
||||
/>
|
||||
<div class="metric-box-total">
|
||||
<div class="value" style="font-size: 12px">
|
||||
{{ content.unExecute }} Pending
|
||||
|
@ -76,65 +106,120 @@
|
|||
<div class="split"></div>
|
||||
<!-- 场景统计 -->
|
||||
<div style="width: 50%">
|
||||
<el-row type="flex" justify="center" align="middle" v-if="report.reportType !== 'API_INTEGRATED'">
|
||||
<el-row
|
||||
type="flex"
|
||||
justify="center"
|
||||
align="middle"
|
||||
v-if="report.reportType !== 'API_INTEGRATED'"
|
||||
>
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.scenarioTotal ? content.scenarioTotal : 0 }}</div>
|
||||
<div class="value">
|
||||
{{ content.scenarioTotal ? content.scenarioTotal : 0 }}
|
||||
</div>
|
||||
<div class="name">{{ $t('api_test.scenario.scenario') }}</div>
|
||||
</div>
|
||||
<span class="ms-point-success"/>
|
||||
<span class="ms-point-success" />
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.scenarioSuccess ? content.scenarioSuccess : 0 }}</div>
|
||||
<div class="value">
|
||||
{{ content.scenarioSuccess ? content.scenarioSuccess : 0 }}
|
||||
</div>
|
||||
<div class="name">Success</div>
|
||||
</div>
|
||||
<span class="ms-point-error"/>
|
||||
<span class="ms-point-error" />
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.scenarioError ? content.scenarioError : 0 }}</div>
|
||||
<div class="value">
|
||||
{{ content.scenarioError ? content.scenarioError : 0 }}
|
||||
</div>
|
||||
<div class="name">Error</div>
|
||||
</div>
|
||||
<span class="ms-point-error-code"
|
||||
v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
|
||||
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
|
||||
<div class="value">{{ content.scenarioErrorReport ? content.scenarioErrorReport : 0 }}</div>
|
||||
<span
|
||||
class="ms-point-error-code"
|
||||
v-if="
|
||||
content.scenarioErrorReport > 0 ||
|
||||
content.scenarioStepErrorReport > 0
|
||||
"
|
||||
/>
|
||||
<div
|
||||
class="metric-box"
|
||||
v-if="
|
||||
content.scenarioErrorReport > 0 ||
|
||||
content.scenarioStepErrorReport > 0
|
||||
"
|
||||
>
|
||||
<div class="value">
|
||||
{{
|
||||
content.scenarioErrorReport ? content.scenarioErrorReport : 0
|
||||
}}
|
||||
</div>
|
||||
<div class="name">FakeError</div>
|
||||
</div>
|
||||
<span v-show="showUnExecuteReport" class="ms-point-unexecute"/>
|
||||
<span v-show="showUnExecuteReport" class="ms-point-unexecute" />
|
||||
<div v-show="showUnExecuteReport" class="metric-box">
|
||||
<div class="value">{{ content.scenarioUnExecute ? content.scenarioUnExecute : 0 }}</div>
|
||||
<div class="value">
|
||||
{{ content.scenarioUnExecute ? content.scenarioUnExecute : 0 }}
|
||||
</div>
|
||||
<div class="name">Pending</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-divider v-if="report.reportType !== 'API_INTEGRATED'"/>
|
||||
<el-divider v-if="report.reportType !== 'API_INTEGRATED'" />
|
||||
<el-row type="flex" justify="center" align="middle">
|
||||
<el-row type="flex" justify="center" align="middle">
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.scenarioStepTotal ? content.scenarioStepTotal : 0 }}</div>
|
||||
<div class="value">
|
||||
{{ content.scenarioStepTotal ? content.scenarioStepTotal : 0 }}
|
||||
</div>
|
||||
<div class="name" v-if="report.reportType === 'API_INTEGRATED'">
|
||||
{{ $t('api_test.definition.request.case') }}
|
||||
</div>
|
||||
<div class="name" v-else>{{ $t('test_track.plan_view.step') }}</div>
|
||||
<div class="name" v-else>
|
||||
{{ $t('test_track.plan_view.step') }}
|
||||
</div>
|
||||
</div>
|
||||
<span class="ms-point-success"/>
|
||||
<span class="ms-point-success" />
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.scenarioStepSuccess ? content.scenarioStepSuccess : 0 }}</div>
|
||||
<div class="value">
|
||||
{{
|
||||
content.scenarioStepSuccess ? content.scenarioStepSuccess : 0
|
||||
}}
|
||||
</div>
|
||||
<div class="name">Success</div>
|
||||
</div>
|
||||
<span class="ms-point-error"/>
|
||||
<span class="ms-point-error" />
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.scenarioStepError ? content.scenarioStepError : 0 }}</div>
|
||||
<div class="value">
|
||||
{{ content.scenarioStepError ? content.scenarioStepError : 0 }}
|
||||
</div>
|
||||
<div class="name">Error</div>
|
||||
</div>
|
||||
<span class="ms-point-error-code"
|
||||
v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
|
||||
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
|
||||
<span
|
||||
class="ms-point-error-code"
|
||||
v-if="
|
||||
content.scenarioErrorReport > 0 ||
|
||||
content.scenarioStepErrorReport > 0
|
||||
"
|
||||
/>
|
||||
<div
|
||||
class="metric-box"
|
||||
v-if="
|
||||
content.scenarioErrorReport > 0 ||
|
||||
content.scenarioStepErrorReport > 0
|
||||
"
|
||||
>
|
||||
<div class="value">
|
||||
{{ content.scenarioStepErrorReport ? content.scenarioStepErrorReport : 0 }}
|
||||
{{
|
||||
content.scenarioStepErrorReport
|
||||
? content.scenarioStepErrorReport
|
||||
: 0
|
||||
}}
|
||||
</div>
|
||||
<div class="name">FakeError</div>
|
||||
</div>
|
||||
<span v-show="showUnExecuteReport" class="ms-point-unexecute"/>
|
||||
<span v-show="showUnExecuteReport" class="ms-point-unexecute" />
|
||||
<div v-show="showUnExecuteReport" class="metric-box">
|
||||
<div class="value">
|
||||
{{ content.scenarioStepPending ? content.scenarioStepPending : 0 }}
|
||||
{{
|
||||
content.scenarioStepPending ? content.scenarioStepPending : 0
|
||||
}}
|
||||
</div>
|
||||
<div class="name">Pending</div>
|
||||
</div>
|
||||
|
@ -172,11 +257,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
|
||||
import MsChart from 'metersphere-frontend/src/components/chart/MsChart';
|
||||
|
||||
export default {
|
||||
name: "MsMetricChart",
|
||||
components: {MsChart},
|
||||
name: 'MsMetricChart',
|
||||
components: { MsChart },
|
||||
props: {
|
||||
report: Object,
|
||||
content: Object,
|
||||
|
@ -184,7 +269,7 @@ export default {
|
|||
isExport: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -196,7 +281,7 @@ export default {
|
|||
scenarioSuccess: 0,
|
||||
scenarioError: 0,
|
||||
reqTotal: 0,
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.initTime();
|
||||
|
@ -204,25 +289,25 @@ export default {
|
|||
methods: {
|
||||
initTime() {
|
||||
this.time = this.totalTime;
|
||||
this.seconds = (this.time) / 1000;
|
||||
this.seconds = this.time / 1000;
|
||||
if (this.seconds >= 1) {
|
||||
if (this.seconds < 60) {
|
||||
this.seconds = Math.round(this.seconds * 100 / 1) / 100;
|
||||
this.time = this.seconds + "s"
|
||||
this.seconds = Math.round((this.seconds * 100) / 1) / 100;
|
||||
this.time = this.seconds + 's';
|
||||
}
|
||||
if (this.seconds > 60) {
|
||||
this.minutes = Math.round(this.seconds / 60)
|
||||
this.seconds = Math.round(this.seconds * 100 % 60) / 100;
|
||||
this.time = this.minutes + "min" + this.seconds + "s"
|
||||
this.minutes = Math.round(this.seconds / 60);
|
||||
this.seconds = Math.round((this.seconds * 100) % 60) / 100;
|
||||
this.time = this.minutes + 'min' + this.seconds + 's';
|
||||
}
|
||||
if (this.minutes > 60) {
|
||||
this.hour = Math.round(this.minutes / 60)
|
||||
this.minutes = Math.round(this.minutes % 60)
|
||||
this.time = this.hour + "hour" + this.minutes + "min" + this.seconds + "s"
|
||||
this.hour = Math.round(this.minutes / 60);
|
||||
this.minutes = Math.round(this.minutes % 60);
|
||||
this.time =
|
||||
this.hour + 'hour' + this.minutes + 'min' + this.seconds + 's';
|
||||
}
|
||||
|
||||
} else {
|
||||
this.time = this.totalTime + "ms"
|
||||
this.time = this.totalTime + 'ms';
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -248,29 +333,31 @@ export default {
|
|||
color: ['#67C23A', '#F56C6C', '#F6972A', '#9C9B9A'],
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}: {c} ({d}%)'
|
||||
formatter: '{b}: {c} ({d}%)',
|
||||
},
|
||||
title: [{
|
||||
text: this.totalCount,
|
||||
subtext: this.$t('api_report.request'),
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
rich: {
|
||||
align: 'center',
|
||||
value: {
|
||||
fontSize: 32,
|
||||
fontWeight: 'bold',
|
||||
padding: [10, 0]
|
||||
title: [
|
||||
{
|
||||
text: this.totalCount,
|
||||
subtext: this.$t('api_report.request'),
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
rich: {
|
||||
align: 'center',
|
||||
value: {
|
||||
fontSize: 32,
|
||||
fontWeight: 'bold',
|
||||
padding: [10, 0],
|
||||
},
|
||||
name: {
|
||||
fontSize: 14,
|
||||
fontWeight: 'normal',
|
||||
color: '#7F7F7F',
|
||||
},
|
||||
},
|
||||
name: {
|
||||
fontSize: 14,
|
||||
fontWeight: 'normal',
|
||||
color: '#7F7F7F',
|
||||
}
|
||||
}
|
||||
}
|
||||
}],
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
|
@ -281,38 +368,43 @@ export default {
|
|||
show: false,
|
||||
},
|
||||
itemStyle: {
|
||||
borderColor: "#FFF",
|
||||
borderColor: '#FFF',
|
||||
shadowColor: '#E1E1E1',
|
||||
shadowBlur: 10
|
||||
shadowBlur: 10,
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
show: false,
|
||||
},
|
||||
data: [
|
||||
{value: this.content.success, name: 'Success'},
|
||||
{value: this.content.error, name: 'Error'},
|
||||
{value: this.content.errorCode, name: 'FakeError'},
|
||||
{value: this.content.unExecute, name: 'Pending'},
|
||||
]
|
||||
}
|
||||
]
|
||||
{ value: this.content.success, name: 'Success' },
|
||||
{ value: this.content.error, name: 'Error' },
|
||||
{ value: this.content.errorCode, name: 'FakeError' },
|
||||
{ value: this.content.unExecute, name: 'Pending' },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
fail() {
|
||||
return (this.content.error / this.content.total * 100).toFixed(0) + "%";
|
||||
return ((this.content.error / this.content.total) * 100).toFixed(0) + '%';
|
||||
},
|
||||
assertions() {
|
||||
return this.content.passAssertions + " / " + this.content.totalAssertions;
|
||||
return this.content.passAssertions + ' / ' + this.content.totalAssertions;
|
||||
},
|
||||
errorCodeAssertions() {
|
||||
return this.content.errorCode + " / " + this.content.totalAssertions;
|
||||
return this.content.errorCode + ' / ' + this.content.totalAssertions;
|
||||
},
|
||||
showUnExecuteReport() {
|
||||
return (this.content.scenarioStepPending && this.content.scenarioStepPending > 0)
|
||||
|| (this.content.scenarioUnExecute && this.content.scenarioUnExecute > 0) || (this.content.unExecute && this.content.unExecute > 0);
|
||||
return (
|
||||
(this.content.scenarioStepPending &&
|
||||
this.content.scenarioStepPending > 0) ||
|
||||
(this.content.scenarioUnExecute &&
|
||||
this.content.scenarioUnExecute > 0) ||
|
||||
(this.content.unExecute && this.content.unExecute > 0)
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -330,25 +422,25 @@ export default {
|
|||
.metric-container .split {
|
||||
margin: 20px;
|
||||
height: 100px;
|
||||
border-left: 1px solid #D8DBE1;
|
||||
border-left: 1px solid #d8dbe1;
|
||||
}
|
||||
|
||||
.metric-container .circle {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 20px 1px rgba(200, 216, 226, .42);
|
||||
box-shadow: 0 0 20px 1px rgba(200, 216, 226, 0.42);
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.metric-container .circle.success {
|
||||
background-color: #67C23A;
|
||||
background-color: #67c23a;
|
||||
}
|
||||
|
||||
.metric-container .circle.fail {
|
||||
background-color: #F56C6C;
|
||||
background-color: #f56c6c;
|
||||
}
|
||||
|
||||
.metric-box {
|
||||
|
@ -366,18 +458,18 @@ export default {
|
|||
.metric-box .value {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -.5px;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.metric-time .value {
|
||||
font-size: 25px;
|
||||
font-weight: 400;
|
||||
letter-spacing: -.5px;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.metric-box .name {
|
||||
font-size: 16px;
|
||||
letter-spacing: -.2px;
|
||||
letter-spacing: -0.2px;
|
||||
color: #404040;
|
||||
}
|
||||
|
||||
|
@ -390,7 +482,7 @@ export default {
|
|||
.metric-icon-box .value {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -.4px;
|
||||
letter-spacing: -0.4px;
|
||||
line-height: 28px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@ -398,12 +490,12 @@ export default {
|
|||
.metric-icon-box .name {
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
color: #BFBFBF;
|
||||
color: #bfbfbf;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.metric-icon-box .fail {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
|
@ -425,11 +517,11 @@ export default {
|
|||
}
|
||||
|
||||
.ms-req-error {
|
||||
border: 5px #F56C6C solid;
|
||||
border: 5px #f56c6c solid;
|
||||
}
|
||||
|
||||
.ms-req-success {
|
||||
border: 5px #67C23A solid;
|
||||
border: 5px #67c23a solid;
|
||||
}
|
||||
|
||||
.ms-req-span {
|
||||
|
@ -449,7 +541,7 @@ export default {
|
|||
vertical-align: top;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
background-color: #67C23A;
|
||||
background-color: #67c23a;
|
||||
}
|
||||
|
||||
.ms-point-error {
|
||||
|
@ -461,7 +553,7 @@ export default {
|
|||
vertical-align: top;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
background-color: #F56C6C;
|
||||
background-color: #f56c6c;
|
||||
}
|
||||
|
||||
.ms-point-error-code {
|
||||
|
@ -473,7 +565,7 @@ export default {
|
|||
vertical-align: top;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
background-color: #F6972A;
|
||||
background-color: #f6972a;
|
||||
}
|
||||
|
||||
.ms-point-unexecute {
|
||||
|
@ -485,6 +577,6 @@ export default {
|
|||
vertical-align: top;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
background-color: #9C9B9A;
|
||||
background-color: #9c9b9a;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,89 +2,139 @@
|
|||
<div class="metric-container">
|
||||
<el-row type="flex">
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_code')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{request.responseResult.responseCode ? request.responseResult.responseCode :'0'}}</div>
|
||||
<div style="font-size: 14px; color: #aaaaaa; float: left">
|
||||
{{ $t('api_report.response_code') }} :
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
font-size: 14px;
|
||||
color: #61c550;
|
||||
margin-top: 2px;
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
"
|
||||
>
|
||||
{{
|
||||
request.responseResult.responseCode
|
||||
? request.responseResult.responseCode
|
||||
: '0'
|
||||
}}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_time')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{request.responseResult.responseTime?request.responseResult.responseTime:0}} ms</div>
|
||||
<div style="font-size: 14px; color: #aaaaaa; float: left">
|
||||
{{ $t('api_report.response_time') }} :
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
font-size: 14px;
|
||||
color: #61c550;
|
||||
margin-top: 2px;
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
"
|
||||
>
|
||||
{{
|
||||
request.responseResult.responseTime
|
||||
? request.responseResult.responseTime
|
||||
: 0
|
||||
}}
|
||||
ms
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_size')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550; margin-top:2px;margin-left:10px;float: left">{{request.responseResult.responseSize?request.responseResult.responseSize:0}} bytes</div>
|
||||
<div style="font-size: 14px; color: #aaaaaa; float: left">
|
||||
{{ $t('api_report.response_size') }} :
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
font-size: 14px;
|
||||
color: #61c550;
|
||||
margin-top: 2px;
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
"
|
||||
>
|
||||
{{
|
||||
request.responseResult.responseSize
|
||||
? request.responseResult.responseSize
|
||||
: 0
|
||||
}}
|
||||
bytes
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsRequestMetric",
|
||||
export default {
|
||||
name: 'MsRequestMetric',
|
||||
|
||||
props: {
|
||||
request: Object
|
||||
props: {
|
||||
request: Object,
|
||||
},
|
||||
|
||||
computed: {
|
||||
error() {
|
||||
return this.request.responseResult.responseCode >= 400;
|
||||
},
|
||||
|
||||
computed: {
|
||||
error() {
|
||||
return this.request.responseResult.responseCode >= 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.metric-container {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.metric-container {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.metric {
|
||||
padding: 20px;
|
||||
border: 1px solid #EBEEF5;
|
||||
min-width: 120px;
|
||||
height: 114px;
|
||||
}
|
||||
.metric {
|
||||
padding: 20px;
|
||||
border: 1px solid #ebeef5;
|
||||
min-width: 120px;
|
||||
height: 114px;
|
||||
}
|
||||
|
||||
.metric + .metric {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.metric + .metric {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.metric .value {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
word-break: break-all;
|
||||
}
|
||||
.metric .value {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.metric .name {
|
||||
color: #404040;
|
||||
opacity: 0.5;
|
||||
padding: 5px 0;
|
||||
}
|
||||
.metric .name {
|
||||
color: #404040;
|
||||
opacity: 0.5;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.metric.horizontal {
|
||||
width: 100%;
|
||||
}
|
||||
.metric.horizontal {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.metric .code {
|
||||
min-width: 120px;
|
||||
}
|
||||
.metric .code {
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.metric .code .value {
|
||||
color: #67C23A;
|
||||
}
|
||||
.metric .code .value {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.metric .code .value.error {
|
||||
color: #F56C6C;
|
||||
}
|
||||
.metric .code .value.error {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.metric .split {
|
||||
height: 114px;
|
||||
border-left: 1px solid #EBEEF5;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.metric .split {
|
||||
height: 114px;
|
||||
border-left: 1px solid #ebeef5;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.metric .message {
|
||||
max-height: 114px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.metric .message {
|
||||
max-height: 114px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,14 +3,27 @@
|
|||
<div class="request-result">
|
||||
<div @click="active">
|
||||
<el-row :gutter="18" type="flex" align="middle" class="info">
|
||||
<el-col class="ms-req-name-col" :span="18" v-if="indexNumber!=undefined">
|
||||
<el-col
|
||||
class="ms-req-name-col"
|
||||
:span="18"
|
||||
v-if="indexNumber != undefined"
|
||||
>
|
||||
<el-tooltip :content="getName(request.name)" placement="top">
|
||||
<span class="method ms-req-name">
|
||||
<div class="el-step__icon is-text ms-api-col-create">
|
||||
<div class="el-step__icon-inner"> {{ indexNumber }}</div>
|
||||
<div class="el-step__icon-inner">{{ indexNumber }}</div>
|
||||
</div>
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': showActive}" @click="active" @click.stop/>
|
||||
<span class="report-label-req" @click="isLink" v-if="redirect && resourceId">
|
||||
<i
|
||||
class="icon el-icon-arrow-right"
|
||||
:class="{ 'is-active': showActive }"
|
||||
@click="active"
|
||||
@click.stop
|
||||
/>
|
||||
<span
|
||||
class="report-label-req"
|
||||
@click="isLink"
|
||||
v-if="redirect && resourceId"
|
||||
>
|
||||
{{ request.name }}
|
||||
</span>
|
||||
<span v-else>{{ getName(request.name) }}</span>
|
||||
|
@ -19,36 +32,72 @@
|
|||
</el-col>
|
||||
<!-- 误报 / 异常状态显示 -->
|
||||
<el-col :span="3">
|
||||
<el-tooltip effect="dark" v-if="baseErrorCode && baseErrorCode !==''" :content="baseErrorCode"
|
||||
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom"
|
||||
:open-delay="800">
|
||||
<div :style="{color: statusColor(totalStatus ? totalStatus : request.status)}">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
v-if="baseErrorCode && baseErrorCode !== ''"
|
||||
:content="baseErrorCode"
|
||||
style="
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
placement="bottom"
|
||||
:open-delay="800"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
color: statusColor(
|
||||
totalStatus ? totalStatus : request.status
|
||||
),
|
||||
}"
|
||||
>
|
||||
{{ baseErrorCode }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<!-- 请求返回状态 -->
|
||||
<el-col :span="6">
|
||||
<el-tooltip effect="dark" :content="request.responseResult.responseCode"
|
||||
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom"
|
||||
:open-delay="800">
|
||||
<div :style="{color: statusColor(totalStatus ? totalStatus : request.status)}">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="request.responseResult.responseCode"
|
||||
style="
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
placement="bottom"
|
||||
:open-delay="800"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
color: statusColor(
|
||||
totalStatus ? totalStatus : request.status
|
||||
),
|
||||
}"
|
||||
>
|
||||
{{ request.responseResult.responseCode }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<!-- 请求响应时间 -->
|
||||
<el-col :span="3">
|
||||
<div :style="{color: statusColor(totalStatus ? totalStatus : request.status)}">
|
||||
<div
|
||||
:style="{
|
||||
color: statusColor(totalStatus ? totalStatus : request.status),
|
||||
}"
|
||||
>
|
||||
{{ request.responseResult.responseTime }} ms
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-tag v-if="request.testing" class="ms-test-running" size="mini">
|
||||
<i class="el-icon-loading" style="font-size: 16px"/>
|
||||
<i class="el-icon-loading" style="font-size: 16px" />
|
||||
{{ $t('commons.testing') }}
|
||||
</el-tag>
|
||||
<ms-api-report-status :status="totalStatus || request.status" v-else/>
|
||||
<ms-api-report-status
|
||||
:status="totalStatus || request.status"
|
||||
v-else
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -61,7 +110,8 @@
|
|||
:request-type="requestType"
|
||||
:request="requestInfo"
|
||||
:console="console"
|
||||
v-if="showActive"/>
|
||||
v-if="showActive"
|
||||
/>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
|
@ -69,27 +119,28 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsRequestMetric from "./RequestMetric";
|
||||
import MsAssertionResults from "./AssertionResults";
|
||||
import MsRequestText from "./RequestText";
|
||||
import MsResponseText from "./ResponseText";
|
||||
import MsRequestResultTail from "./RequestResultTail";
|
||||
import {getCurrentByResourceId} from "../../../../api/user";
|
||||
import {getShareContent} from "../../../../api/share";
|
||||
import {getScenarioReportStepDetail} from "../../../../api/scenario-report";
|
||||
import MsApiReportStatus from "../ApiReportStatus";
|
||||
import MsRequestMetric from './RequestMetric';
|
||||
import MsAssertionResults from './AssertionResults';
|
||||
import MsRequestText from './RequestText';
|
||||
import MsResponseText from './ResponseText';
|
||||
import MsRequestResultTail from './RequestResultTail';
|
||||
import { getCurrentByResourceId } from '../../../../api/user';
|
||||
import { getShareContent } from '../../../../api/share';
|
||||
import { getScenarioReportStepDetail } from '../../../../api/scenario-report';
|
||||
import MsApiReportStatus from '../ApiReportStatus';
|
||||
|
||||
|
||||
const {getReportStatusColor} = require("../../../../business/commons/js/commons");
|
||||
const {
|
||||
getReportStatusColor,
|
||||
} = require('../../../../business/commons/js/commons');
|
||||
export default {
|
||||
name: "MsRequestResult",
|
||||
name: 'MsRequestResult',
|
||||
components: {
|
||||
MsApiReportStatus,
|
||||
MsResponseText,
|
||||
MsRequestText,
|
||||
MsAssertionResults,
|
||||
MsRequestMetric,
|
||||
MsRequestResultTail
|
||||
MsRequestResultTail,
|
||||
},
|
||||
props: {
|
||||
request: Object,
|
||||
|
@ -102,11 +153,11 @@ export default {
|
|||
redirect: Boolean,
|
||||
errorCode: {
|
||||
type: String,
|
||||
default: ""
|
||||
default: '',
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
isShare: Boolean,
|
||||
shareId: String,
|
||||
|
@ -117,12 +168,12 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
requestType: "",
|
||||
requestType: '',
|
||||
color: {
|
||||
type: String,
|
||||
default() {
|
||||
return "#B8741A";
|
||||
}
|
||||
return '#B8741A';
|
||||
},
|
||||
},
|
||||
requestInfo: {
|
||||
loading: true,
|
||||
|
@ -130,15 +181,15 @@ export default {
|
|||
responseResult: {},
|
||||
subRequestResults: [],
|
||||
},
|
||||
baseErrorCode: "",
|
||||
baseErrorCode: '',
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default() {
|
||||
return "#F9F1EA";
|
||||
}
|
||||
return '#F9F1EA';
|
||||
},
|
||||
},
|
||||
showActive: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
isActive() {
|
||||
|
@ -153,21 +204,24 @@ export default {
|
|||
handler(n) {
|
||||
if (this.request.errorCode) {
|
||||
this.baseErrorCode = this.request.errorCode;
|
||||
} else if (this.request.attachInfoMap && this.request.attachInfoMap.FAKE_ERROR) {
|
||||
if (this.request.attachInfoMap.FAKE_ERROR !== "") {
|
||||
} else if (
|
||||
this.request.attachInfoMap &&
|
||||
this.request.attachInfoMap.FAKE_ERROR
|
||||
) {
|
||||
if (this.request.attachInfoMap.FAKE_ERROR !== '') {
|
||||
this.baseErrorCode = this.request.attachInfoMap.FAKE_ERROR;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
statusColor(status) {
|
||||
return getReportStatusColor(status);
|
||||
},
|
||||
isLink() {
|
||||
let uri = "/#/api/definition?caseId=" + this.resourceId;
|
||||
this.clickResource(uri)
|
||||
let uri = '/#/api/definition?caseId=' + this.resourceId;
|
||||
this.clickResource(uri);
|
||||
},
|
||||
clickResource(uri) {
|
||||
getCurrentByResourceId(this.resourceId).then(() => {
|
||||
|
@ -175,11 +229,11 @@ export default {
|
|||
});
|
||||
},
|
||||
toPage(uri) {
|
||||
let id = "new_a";
|
||||
let a = document.createElement("a");
|
||||
a.setAttribute("href", uri);
|
||||
a.setAttribute("target", "_blank");
|
||||
a.setAttribute("id", id);
|
||||
let id = 'new_a';
|
||||
let a = document.createElement('a');
|
||||
a.setAttribute('href', uri);
|
||||
a.setAttribute('target', '_blank');
|
||||
a.setAttribute('id', id);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
|
@ -187,23 +241,26 @@ export default {
|
|||
element.parentNode.removeChild(element);
|
||||
},
|
||||
loadRequestInfoExpand() {
|
||||
if (!this.request.responseResult || this.request.responseResult.body === null || this.request.responseResult.body === undefined) {
|
||||
if (
|
||||
!this.request.responseResult ||
|
||||
this.request.responseResult.body === null ||
|
||||
this.request.responseResult.body === undefined
|
||||
) {
|
||||
if (this.isShare) {
|
||||
getShareContent(this.shareId, this.stepId).then(response => {
|
||||
getShareContent(this.shareId, this.stepId).then((response) => {
|
||||
this.requestInfo = response.data;
|
||||
this.$nextTick(() => {
|
||||
this.requestInfo.loading = false;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
getScenarioReportStepDetail(this.stepId).then(response => {
|
||||
getScenarioReportStepDetail(this.stepId).then((response) => {
|
||||
this.requestInfo = response.data;
|
||||
this.$nextTick(() => {
|
||||
this.requestInfo.loading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
this.requestInfo = this.request;
|
||||
}
|
||||
|
@ -219,30 +276,30 @@ export default {
|
|||
}
|
||||
},
|
||||
getName(name) {
|
||||
if (name && name.indexOf("<->") !== -1) {
|
||||
return name.split("<->")[0];
|
||||
if (name && name.indexOf('<->') !== -1) {
|
||||
return name.split('<->')[0];
|
||||
}
|
||||
if (name && name.indexOf("^@~@^") !== -1) {
|
||||
let arr = name.split("^@~@^");
|
||||
if (name && name.indexOf('^@~@^') !== -1) {
|
||||
let arr = name.split('^@~@^');
|
||||
let value = arr[arr.length - 1];
|
||||
if (value.indexOf("UUID=") !== -1) {
|
||||
return value.split("UUID=")[0];
|
||||
if (value.indexOf('UUID=') !== -1) {
|
||||
return value.split('UUID=')[0];
|
||||
}
|
||||
if (value && value.startsWith("UUID=")) {
|
||||
return "";
|
||||
if (value && value.startsWith('UUID=')) {
|
||||
return '';
|
||||
}
|
||||
if (value && value.indexOf("<->") !== -1) {
|
||||
return value.split("<->")[0];
|
||||
if (value && value.indexOf('<->') !== -1) {
|
||||
return value.split('<->')[0];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (name && name.startsWith("UUID=")) {
|
||||
return "";
|
||||
if (name && name.startsWith('UUID=')) {
|
||||
return '';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -257,7 +314,7 @@ export default {
|
|||
}
|
||||
|
||||
.request-result .method {
|
||||
color: #1E90FF;
|
||||
color: #1e90ff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 35px;
|
||||
|
@ -289,11 +346,11 @@ export default {
|
|||
}
|
||||
|
||||
.sub-result .info {
|
||||
background-color: #FFF;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sub-result .method {
|
||||
border-left: 5px solid #1E90FF;
|
||||
border-left: 5px solid #1e90ff;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
|
@ -302,7 +359,7 @@ export default {
|
|||
}
|
||||
|
||||
.sub-result:last-child {
|
||||
border-bottom: 1px solid #EBEEF5;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.ms-test-running {
|
||||
|
@ -310,21 +367,21 @@ export default {
|
|||
}
|
||||
|
||||
.ms-test-error_code {
|
||||
color: #F6972A;
|
||||
background-color: #FDF5EA;
|
||||
border-color: #FDF5EA;
|
||||
color: #f6972a;
|
||||
background-color: #fdf5ea;
|
||||
border-color: #fdf5ea;
|
||||
}
|
||||
|
||||
.ms-api-col {
|
||||
background-color: #EFF0F0;
|
||||
border-color: #EFF0F0;
|
||||
background-color: #eff0f0;
|
||||
border-color: #eff0f0;
|
||||
margin-right: 10px;
|
||||
font-size: 12px;
|
||||
color: #64666A;
|
||||
color: #64666a;
|
||||
}
|
||||
|
||||
.ms-api-col-create {
|
||||
background-color: #EBF2F2;
|
||||
background-color: #ebf2f2;
|
||||
border-color: #008080;
|
||||
margin-right: 10px;
|
||||
font-size: 12px;
|
||||
|
|
|
@ -8,14 +8,23 @@
|
|||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-tooltip effect="dark" :content="request.url" placement="bottom" :open-delay="800">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="request.url"
|
||||
placement="bottom"
|
||||
:open-delay="800"
|
||||
>
|
||||
<div class="url">{{ request.url }}</div>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="url">
|
||||
{{ $t('api_report.start_time') }}:{{ request.startTime | datetimeFormat(true) }}
|
||||
{{ $t('report.test_end_time') }}:{{ request.endTime | datetimeFormat(true) }}
|
||||
{{ $t('api_report.start_time') }}:{{
|
||||
request.startTime | datetimeFormat(true)
|
||||
}}
|
||||
{{ $t('report.test_end_time') }}:{{
|
||||
request.endTime | datetimeFormat(true)
|
||||
}}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -24,15 +33,31 @@
|
|||
<div v-show="isActive">
|
||||
<el-tabs v-model="activeName" v-show="isActive" v-if="hasSub">
|
||||
<el-tab-pane :label="$t('api_report.sub_result')" name="sub">
|
||||
<ms-request-sub-result class="sub-result" v-for="(sub, index) in request.subRequestResults"
|
||||
:key="index" :indexNumber="index" :request="sub"/>
|
||||
<ms-request-sub-result
|
||||
class="sub-result"
|
||||
v-for="(sub, index) in request.subRequestResults"
|
||||
:key="index"
|
||||
:indexNumber="index"
|
||||
:request="sub"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_report.request_result')" name="result">
|
||||
<ms-response-text :console="console" :request-type="requestType" :response="request.responseResult" :request="request"/>
|
||||
<ms-response-text
|
||||
:console="console"
|
||||
:request-type="requestType"
|
||||
:response="request.responseResult"
|
||||
:request="request"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-else>
|
||||
<ms-response-text :console="console" :request-type="requestType" v-if="isCodeEditAlive" :response="request.responseResult" :request="request"/>
|
||||
<ms-response-text
|
||||
:console="console"
|
||||
:request-type="requestType"
|
||||
v-if="isCodeEditAlive"
|
||||
:response="request.responseResult"
|
||||
:request="request"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
|
@ -40,16 +65,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsRequestMetric from "./RequestMetric";
|
||||
import MsAssertionResults from "./AssertionResults";
|
||||
import MsRequestText from "./RequestText";
|
||||
import MsResponseText from "./ResponseText";
|
||||
import MsRequestResult from "./RequestResult";
|
||||
import MsRequestSubResult from "./RequestSubResult";
|
||||
import MsRequestMetric from './RequestMetric';
|
||||
import MsAssertionResults from './AssertionResults';
|
||||
import MsRequestText from './RequestText';
|
||||
import MsResponseText from './ResponseText';
|
||||
import MsRequestResult from './RequestResult';
|
||||
import MsRequestSubResult from './RequestSubResult';
|
||||
|
||||
export default {
|
||||
name: "MsRequestResultTail",
|
||||
components: {MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestResult, MsRequestSubResult},
|
||||
name: 'MsRequestResultTail',
|
||||
components: {
|
||||
MsResponseText,
|
||||
MsRequestText,
|
||||
MsAssertionResults,
|
||||
MsRequestMetric,
|
||||
MsRequestResult,
|
||||
MsRequestSubResult,
|
||||
},
|
||||
props: {
|
||||
request: Object,
|
||||
scenarioName: String,
|
||||
|
@ -60,9 +92,9 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
isActive: true,
|
||||
activeName: "sub",
|
||||
isCodeEditAlive: true
|
||||
}
|
||||
activeName: 'sub',
|
||||
isCodeEditAlive: true,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -72,24 +104,24 @@ export default {
|
|||
reload() {
|
||||
this.isCodeEditAlive = false;
|
||||
this.$nextTick(() => (this.isCodeEditAlive = true));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
'request.responseResult'() {
|
||||
this.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
assertion() {
|
||||
return this.request.passAssertions + " / " + this.request.totalAssertions;
|
||||
return this.request.passAssertions + ' / ' + this.request.totalAssertions;
|
||||
},
|
||||
hasSub() {
|
||||
return this.request.subRequestResults.length > 0;
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -100,13 +132,13 @@ export default {
|
|||
}
|
||||
|
||||
.request-result .info {
|
||||
background-color: #F9F9F9;
|
||||
background-color: #f9f9f9;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.request-result .method {
|
||||
color: #1E90FF;
|
||||
color: #1e90ff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
|
@ -134,20 +166,19 @@ export default {
|
|||
}
|
||||
|
||||
.sub-result .info {
|
||||
background-color: #FFF;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sub-result .method {
|
||||
border-left: 5px solid #1E90FF;
|
||||
border-left: 5px solid #1e90ff;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.sub-result:last-child {
|
||||
border-bottom: 1px solid #EBEEF5;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.request-result .icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -3,17 +3,30 @@
|
|||
<p class="el-divider--horizontal"></p>
|
||||
<div @click="active">
|
||||
<el-row :gutter="10" type="flex" align="middle" class="info">
|
||||
<el-col :span="6" v-if="indexNumber!=undefined">
|
||||
<el-col :span="6" v-if="indexNumber != undefined">
|
||||
<div class="method">
|
||||
|
||||
<div style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">
|
||||
<div class="el-step__icon is-text ms-api-col" v-if="indexNumber%2 ==0">
|
||||
<div class="el-step__icon-inner"> {{ indexNumber + 1 }}</div>
|
||||
<div
|
||||
style="
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="el-step__icon is-text ms-api-col"
|
||||
v-if="indexNumber % 2 == 0"
|
||||
>
|
||||
<div class="el-step__icon-inner">{{ indexNumber + 1 }}</div>
|
||||
</div>
|
||||
<div class="el-step__icon is-text ms-api-col-create" v-else>
|
||||
<div class="el-step__icon-inner"> {{ indexNumber + 1 }}</div>
|
||||
<div class="el-step__icon-inner">{{ indexNumber + 1 }}</div>
|
||||
</div>
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': isActive}" @click="active" @click.stop/>
|
||||
<i
|
||||
class="icon el-icon-arrow-right"
|
||||
:class="{ 'is-active': isActive }"
|
||||
@click="active"
|
||||
@click.stop
|
||||
/>
|
||||
{{ getName(request.name) }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -25,7 +38,16 @@
|
|||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="url">
|
||||
<el-tooltip :content="request.url " style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom" :open-delay="800">
|
||||
<el-tooltip
|
||||
:content="request.url"
|
||||
style="
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
placement="bottom"
|
||||
:open-delay="800"
|
||||
>
|
||||
<div>
|
||||
{{ request.url }}
|
||||
</div>
|
||||
|
@ -33,8 +55,15 @@
|
|||
</div>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-tooltip effect="dark" :content="request.responseResult.responseCode" placement="bottom" :open-delay="800">
|
||||
<div class="url" style="color: #5daf34">{{ request.responseResult.responseCode }}</div>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="request.responseResult.responseCode"
|
||||
placement="bottom"
|
||||
:open-delay="800"
|
||||
>
|
||||
<div class="url" style="color: #5daf34">
|
||||
{{ request.responseResult.responseCode }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
|
@ -46,34 +75,39 @@
|
|||
<el-tag size="mini" type="success" v-if="request.success">
|
||||
Success
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" v-else>
|
||||
Error
|
||||
</el-tag>
|
||||
<el-tag size="mini" type="danger" v-else> Error </el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div v-show="isActive" style="width: 99%">
|
||||
<ms-request-sub-result-tail :scenario-name="scenarioName"
|
||||
:request-type="requestType" v-if="isActive"
|
||||
:request="request"/>
|
||||
<ms-request-sub-result-tail
|
||||
:scenario-name="scenarioName"
|
||||
:request-type="requestType"
|
||||
v-if="isActive"
|
||||
:request="request"
|
||||
/>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsRequestMetric from "./RequestMetric";
|
||||
import MsAssertionResults from "./AssertionResults";
|
||||
import MsRequestText from "./RequestText";
|
||||
import MsResponseText from "./ResponseText";
|
||||
import MsRequestSubResultTail from "./RequestSubResultTail";
|
||||
import MsRequestMetric from './RequestMetric';
|
||||
import MsAssertionResults from './AssertionResults';
|
||||
import MsRequestText from './RequestText';
|
||||
import MsResponseText from './ResponseText';
|
||||
import MsRequestSubResultTail from './RequestSubResultTail';
|
||||
|
||||
export default {
|
||||
name: "MsRequestSubResult",
|
||||
name: 'MsRequestSubResult',
|
||||
components: {
|
||||
MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestSubResultTail
|
||||
MsResponseText,
|
||||
MsRequestText,
|
||||
MsAssertionResults,
|
||||
MsRequestMetric,
|
||||
MsRequestSubResultTail,
|
||||
},
|
||||
props: {
|
||||
request: Object,
|
||||
|
@ -81,37 +115,37 @@ export default {
|
|||
indexNumber: Number,
|
||||
},
|
||||
data() {
|
||||
return {isActive: false, requestType: undefined,}
|
||||
return { isActive: false, requestType: undefined };
|
||||
},
|
||||
methods: {
|
||||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
},
|
||||
getName(name) {
|
||||
if (name && name.indexOf("<->") !== -1) {
|
||||
return name.split("<->")[0];
|
||||
if (name && name.indexOf('<->') !== -1) {
|
||||
return name.split('<->')[0];
|
||||
}
|
||||
if (name && name.indexOf("^@~@^") !== -1) {
|
||||
let arr = name.split("^@~@^");
|
||||
if (name && name.indexOf('^@~@^') !== -1) {
|
||||
let arr = name.split('^@~@^');
|
||||
let value = arr[arr.length - 1];
|
||||
if (value.indexOf("UUID=") !== -1) {
|
||||
return value.split("UUID=")[0];
|
||||
if (value.indexOf('UUID=') !== -1) {
|
||||
return value.split('UUID=')[0];
|
||||
}
|
||||
if (value && value.startsWith("UUID=")) {
|
||||
return "";
|
||||
if (value && value.startsWith('UUID=')) {
|
||||
return '';
|
||||
}
|
||||
if (value && value.indexOf("<->") !== -1) {
|
||||
return value.split("<->")[0];
|
||||
if (value && value.indexOf('<->') !== -1) {
|
||||
return value.split('<->')[0];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (name && name.startsWith("UUID=")) {
|
||||
return "";
|
||||
if (name && name.startsWith('UUID=')) {
|
||||
return '';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -127,7 +161,7 @@ export default {
|
|||
}
|
||||
|
||||
.request-result .method {
|
||||
color: #1E90FF;
|
||||
color: #1e90ff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
|
@ -155,28 +189,28 @@ export default {
|
|||
}
|
||||
|
||||
.sub-result .info {
|
||||
background-color: #FFF;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sub-result .method {
|
||||
border-left: 5px solid #1E90FF;
|
||||
border-left: 5px solid #1e90ff;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.sub-result:last-child {
|
||||
border-bottom: 1px solid #EBEEF5;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.ms-api-col {
|
||||
background-color: #EFF0F0;
|
||||
border-color: #EFF0F0;
|
||||
background-color: #eff0f0;
|
||||
border-color: #eff0f0;
|
||||
margin-right: 10px;
|
||||
font-size: 12px;
|
||||
color: #64666A;
|
||||
color: #64666a;
|
||||
}
|
||||
|
||||
.ms-api-col-create {
|
||||
background-color: #EBF2F2;
|
||||
background-color: #ebf2f2;
|
||||
border-color: #008080;
|
||||
margin-right: 10px;
|
||||
font-size: 12px;
|
||||
|
|
|
@ -4,135 +4,154 @@
|
|||
<el-row :gutter="8" type="flex" align="middle" class="info">
|
||||
<el-col :span="2">
|
||||
<div class="method">
|
||||
{{request.method}}
|
||||
{{ request.method }}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-tooltip effect="dark" :content="request.url" placement="bottom" :open-delay="800">
|
||||
<div class="url">{{request.url}}</div>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="request.url"
|
||||
placement="bottom"
|
||||
:open-delay="800"
|
||||
>
|
||||
<div class="url">{{ request.url }}</div>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="url"> {{$t('api_report.start_time')}}:{{request.startTime | datetimeFormat(true) }}
|
||||
<div class="url">
|
||||
{{ $t('api_report.start_time') }}:{{
|
||||
request.startTime | datetimeFormat(true)
|
||||
}}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div v-show="isActive">
|
||||
<ms-response-text :request-type="requestType" v-if="isCodeEditAlive" :response="request.responseResult" :request="request"/>
|
||||
<ms-response-text
|
||||
:request-type="requestType"
|
||||
v-if="isCodeEditAlive"
|
||||
:response="request.responseResult"
|
||||
:request="request"
|
||||
/>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsRequestMetric from "./RequestMetric";
|
||||
import MsAssertionResults from "./AssertionResults";
|
||||
import MsRequestText from "./RequestText";
|
||||
import MsResponseText from "./ResponseText";
|
||||
import MsRequestResult from "./RequestResult";
|
||||
import MsRequestSubResult from "./RequestSubResult";
|
||||
import MsRequestMetric from './RequestMetric';
|
||||
import MsAssertionResults from './AssertionResults';
|
||||
import MsRequestText from './RequestText';
|
||||
import MsResponseText from './ResponseText';
|
||||
import MsRequestResult from './RequestResult';
|
||||
import MsRequestSubResult from './RequestSubResult';
|
||||
|
||||
export default {
|
||||
name: "MsRequestSubResultTail",
|
||||
components: {MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestResult, MsRequestSubResult},
|
||||
props: {
|
||||
request: Object,
|
||||
scenarioName: String,
|
||||
requestType: String
|
||||
},
|
||||
export default {
|
||||
name: 'MsRequestSubResultTail',
|
||||
components: {
|
||||
MsResponseText,
|
||||
MsRequestText,
|
||||
MsAssertionResults,
|
||||
MsRequestMetric,
|
||||
MsRequestResult,
|
||||
MsRequestSubResult,
|
||||
},
|
||||
props: {
|
||||
request: Object,
|
||||
scenarioName: String,
|
||||
requestType: String,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
isActive: true,
|
||||
activeName: "sub",
|
||||
isCodeEditAlive: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isActive: true,
|
||||
activeName: 'sub',
|
||||
isCodeEditAlive: true,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
},
|
||||
reload() {
|
||||
this.isCodeEditAlive = false;
|
||||
this.$nextTick(() => (this.isCodeEditAlive = true));
|
||||
}
|
||||
methods: {
|
||||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
},
|
||||
watch: {
|
||||
'request.responseResult'() {
|
||||
this.reload();
|
||||
}
|
||||
reload() {
|
||||
this.isCodeEditAlive = false;
|
||||
this.$nextTick(() => (this.isCodeEditAlive = true));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'request.responseResult'() {
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
assertion() {
|
||||
return this.request.passAssertions + " / " + this.request.totalAssertions;
|
||||
},
|
||||
hasSub() {
|
||||
return this.request.subRequestResults.length > 0;
|
||||
},
|
||||
}
|
||||
}
|
||||
computed: {
|
||||
assertion() {
|
||||
return this.request.passAssertions + ' / ' + this.request.totalAssertions;
|
||||
},
|
||||
hasSub() {
|
||||
return this.request.subRequestResults.length > 0;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.request-result {
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
.request-result {
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.request-result .info {
|
||||
background-color: #F9F9F9;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.request-result .info {
|
||||
background-color: #f9f9f9;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.request-result .method {
|
||||
color: #1E90FF;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.request-result .method {
|
||||
color: #1e90ff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.request-result .url {
|
||||
color: #7f7f7f;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
margin-top: 4px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
.request-result .url {
|
||||
color: #7f7f7f;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
margin-top: 4px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.request-result .tab .el-tabs__header {
|
||||
margin: 0;
|
||||
}
|
||||
.request-result .tab .el-tabs__header {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.request-result .text {
|
||||
height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.request-result .text {
|
||||
height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sub-result .info {
|
||||
background-color: #FFF;
|
||||
}
|
||||
.sub-result .info {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sub-result .method {
|
||||
border-left: 5px solid #1E90FF;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.sub-result .method {
|
||||
border-left: 5px solid #1e90ff;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.sub-result:last-child {
|
||||
border-bottom: 1px solid #EBEEF5;
|
||||
}
|
||||
|
||||
.request-result .icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.sub-result:last-child {
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.request-result .icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<template>
|
||||
<div class="text-container">
|
||||
<div @click="active" class="collapse">
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': isActive}"/>
|
||||
{{$t('api_report.request')}}
|
||||
<i class="icon el-icon-arrow-right" :class="{ 'is-active': isActive }" />
|
||||
{{ $t('api_report.request') }}
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<el-tabs v-model="activeName" v-show="isActive">
|
||||
<el-tab-pane label="Body" name="body" class="pane">
|
||||
<pre>{{request.body}}</pre>
|
||||
<pre>{{ request.body }}</pre>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Headers" name="headers" class="pane">
|
||||
<pre>{{request.headers}}</pre>
|
||||
<pre>{{ request.headers }}</pre>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Cookies" name="cookies" class="pane">
|
||||
<pre>{{request.cookies}}</pre>
|
||||
<pre>{{ request.cookies }}</pre>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-collapse-transition>
|
||||
|
@ -21,53 +21,53 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsRequestText",
|
||||
export default {
|
||||
name: 'MsRequestText',
|
||||
|
||||
props: {
|
||||
request: Object
|
||||
},
|
||||
props: {
|
||||
request: Object,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
isActive: true,
|
||||
activeName: "body",
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isActive: true,
|
||||
activeName: 'body',
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
}
|
||||
methods: {
|
||||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.text-container .icon {
|
||||
padding: 5px;
|
||||
}
|
||||
.text-container .icon {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.text-container .collapse {
|
||||
cursor: pointer;
|
||||
}
|
||||
.text-container .collapse {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.text-container .collapse:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.text-container .collapse:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.text-container .icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.text-container .icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.text-container .pane {
|
||||
background-color: #F9F9F9;
|
||||
padding: 1px 0;
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.text-container .pane {
|
||||
background-color: #f9f9f9;
|
||||
padding: 1px 0;
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,24 +2,52 @@
|
|||
<div class="text-container">
|
||||
<el-collapse-transition>
|
||||
<el-tabs v-model="activeName" v-show="isActive">
|
||||
<el-tab-pane :class="'body-pane'" :label="$t('api_test.definition.request.response_body')" name="body" class="pane">
|
||||
<ms-sql-result-table v-if="isSqlType" :body="response.body"/>
|
||||
<ms-code-edit v-if="!isSqlType" :mode="mode" :read-only="true" :data="response.body" :modes="modes" ref="codeEdit"/>
|
||||
<el-tab-pane
|
||||
:class="'body-pane'"
|
||||
:label="$t('api_test.definition.request.response_body')"
|
||||
name="body"
|
||||
class="pane"
|
||||
>
|
||||
<ms-sql-result-table v-if="isSqlType" :body="response.body" />
|
||||
<ms-code-edit
|
||||
v-if="!isSqlType"
|
||||
:mode="mode"
|
||||
:read-only="true"
|
||||
:data="response.body"
|
||||
:modes="modes"
|
||||
ref="codeEdit"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('api_test.definition.request.response_header')" name="headers" class="pane">
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.definition.request.response_header')"
|
||||
name="headers"
|
||||
class="pane"
|
||||
>
|
||||
<pre>{{ response.headers }}</pre>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('api_report.assertions')" name="assertions" class="pane assertions">
|
||||
<ms-assertion-results :assertions="response.assertions"/>
|
||||
<el-tab-pane
|
||||
:label="$t('api_report.assertions')"
|
||||
name="assertions"
|
||||
class="pane assertions"
|
||||
>
|
||||
<ms-assertion-results :assertions="response.assertions" />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('api_test.request.extract.label')" name="label" class="pane">
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.request.extract.label')"
|
||||
name="label"
|
||||
class="pane"
|
||||
>
|
||||
<pre>{{ response.vars }}</pre>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('api_report.request_body')" name="request_body" class="pane">
|
||||
<el-tab-pane
|
||||
:label="$t('api_report.request_body')"
|
||||
name="request_body"
|
||||
class="pane"
|
||||
>
|
||||
<div class="ms-div">
|
||||
{{ $t('api_test.request.address') }} :
|
||||
<pre>{{ request.url }}</pre>
|
||||
|
@ -36,13 +64,28 @@
|
|||
Body :
|
||||
<pre>{{ request.body }}</pre>
|
||||
</div>
|
||||
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane v-if="activeName == 'body'" :disabled="true" name="mode" class="pane assertions">
|
||||
<el-tab-pane
|
||||
v-if="activeName == 'body'"
|
||||
:disabled="true"
|
||||
name="mode"
|
||||
class="pane assertions"
|
||||
>
|
||||
<template v-slot:label>
|
||||
<ms-dropdown v-if="request.method==='SQL'" :commands="sqlModes" :default-command="mode" @command="sqlModeChange"/>
|
||||
<ms-dropdown v-else :commands="modes" :default-command="mode" @command="modeChange" ref="modeDropdown"/>
|
||||
<ms-dropdown
|
||||
v-if="request.method === 'SQL'"
|
||||
:commands="sqlModes"
|
||||
:default-command="mode"
|
||||
@command="sqlModeChange"
|
||||
/>
|
||||
<ms-dropdown
|
||||
v-else
|
||||
:commands="modes"
|
||||
:default-command="mode"
|
||||
@command="modeChange"
|
||||
ref="modeDropdown"
|
||||
/>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
@ -51,14 +94,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsAssertionResults from "./AssertionResults";
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
import MsDropdown from "../../../../business/commons/MsDropdown";
|
||||
import {BODY_FORMAT, RequestFactory, Request, SqlRequest} from "../../../../business/definition/model/ApiTestModel";
|
||||
import MsSqlResultTable from "./SqlResultTable";
|
||||
import MsAssertionResults from './AssertionResults';
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
import MsDropdown from '../../../../business/commons/MsDropdown';
|
||||
import {
|
||||
BODY_FORMAT,
|
||||
RequestFactory,
|
||||
Request,
|
||||
SqlRequest,
|
||||
} from '../../../../business/definition/model/ApiTestModel';
|
||||
import MsSqlResultTable from './SqlResultTable';
|
||||
|
||||
export default {
|
||||
name: "MsResponseText",
|
||||
name: 'MsResponseText',
|
||||
|
||||
components: {
|
||||
MsSqlResultTable,
|
||||
|
@ -77,11 +125,11 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
isActive: true,
|
||||
activeName: "body",
|
||||
activeName: 'body',
|
||||
modes: ['text', 'json', 'xml', 'html'],
|
||||
sqlModes: ['text', 'table'],
|
||||
mode: BODY_FORMAT.TEXT
|
||||
}
|
||||
mode: BODY_FORMAT.TEXT,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -93,28 +141,32 @@ export default {
|
|||
},
|
||||
sqlModeChange(mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (!this.response.headers) {
|
||||
return;
|
||||
}
|
||||
if (this.response.headers.indexOf("Content-Type: application/json") > 0) {
|
||||
if (this.response.headers.indexOf('Content-Type: application/json') > 0) {
|
||||
this.mode = BODY_FORMAT.JSON;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
isSqlType() {
|
||||
return ((this.requestType === RequestFactory.TYPES.SQL || this.request.method === RequestFactory.TYPES.SQL) && this.response.responseCode === '200' && this.mode === 'table');
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
(this.requestType === RequestFactory.TYPES.SQL ||
|
||||
this.request.method === RequestFactory.TYPES.SQL) &&
|
||||
this.response.responseCode === '200' &&
|
||||
this.mode === 'table'
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.body-pane {
|
||||
padding: 10px !important;
|
||||
background: white !important;
|
||||
|
@ -137,7 +189,7 @@ export default {
|
|||
}
|
||||
|
||||
.text-container .pane {
|
||||
background-color: #F5F5F5;
|
||||
background-color: #f5f5f5;
|
||||
padding: 1px 0;
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
<template>
|
||||
<div class="scenario-result">
|
||||
<div v-if="(node.children && node.children.length >0) || node.unsolicited
|
||||
|| (node.type && this.stepFilter.get('AllSamplerProxy').indexOf(node.type) === -1)">
|
||||
<div
|
||||
v-if="
|
||||
(node.children && node.children.length > 0) ||
|
||||
node.unsolicited ||
|
||||
(node.type &&
|
||||
this.stepFilter.get('AllSamplerProxy').indexOf(node.type) === -1)
|
||||
"
|
||||
>
|
||||
<el-card class="ms-card">
|
||||
<div class="el-step__icon is-text ms-api-col">
|
||||
<div class="el-step__icon-inner">
|
||||
|
@ -9,7 +15,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<el-tooltip effect="dark" :content="node.label" placement="top">
|
||||
<el-link v-if="node.redirect" class="report-label-head" @click="isLink">
|
||||
<el-link
|
||||
v-if="node.redirect"
|
||||
class="report-label-head"
|
||||
@click="isLink"
|
||||
>
|
||||
{{ getLabel(node.label) }}
|
||||
</el-link>
|
||||
<span v-else>{{ getLabel(node.label) }}</span>
|
||||
|
@ -37,14 +47,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsRequestResult from "./RequestResult";
|
||||
import {STEP} from "../../../../business/automation/scenario/Setting";
|
||||
import {getCurrentByResourceId} from "../../../../api/user";
|
||||
import MsRequestResult from './RequestResult';
|
||||
import { STEP } from '../../../../business/automation/scenario/Setting';
|
||||
import { getCurrentByResourceId } from '../../../../api/user';
|
||||
|
||||
export default {
|
||||
name: "MsScenarioResult",
|
||||
name: 'MsScenarioResult',
|
||||
components: {
|
||||
MsRequestResult
|
||||
MsRequestResult,
|
||||
},
|
||||
props: {
|
||||
scenario: Object,
|
||||
|
@ -56,25 +66,25 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
stepFilter: new STEP,
|
||||
}
|
||||
stepFilter: new STEP(),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getLabel(label) {
|
||||
switch (label) {
|
||||
case "ConstantTimer":
|
||||
return "等待控制器";
|
||||
case "LoopController":
|
||||
return "循环控制器";
|
||||
case "Assertion":
|
||||
return "场景断言";
|
||||
case 'ConstantTimer':
|
||||
return '等待控制器';
|
||||
case 'LoopController':
|
||||
return '循环控制器';
|
||||
case 'Assertion':
|
||||
return '场景断言';
|
||||
default:
|
||||
return label;
|
||||
}
|
||||
},
|
||||
isLink() {
|
||||
let uri = "/#/api/automation?resourceId=" + this.node.resourceId;
|
||||
this.clickResource(uri)
|
||||
let uri = '/#/api/automation?resourceId=' + this.node.resourceId;
|
||||
this.clickResource(uri);
|
||||
},
|
||||
clickResource(uri) {
|
||||
getCurrentByResourceId(this.node.resourceId).then(() => {
|
||||
|
@ -82,11 +92,11 @@ export default {
|
|||
});
|
||||
},
|
||||
toPage(uri) {
|
||||
let id = "new_a";
|
||||
let a = document.createElement("a");
|
||||
a.setAttribute("href", uri);
|
||||
a.setAttribute("target", "_blank");
|
||||
a.setAttribute("id", id);
|
||||
let id = 'new_a';
|
||||
let a = document.createElement('a');
|
||||
a.setAttribute('href', uri);
|
||||
a.setAttribute('target', '_blank');
|
||||
a.setAttribute('id', id);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
|
@ -97,19 +107,21 @@ export default {
|
|||
this.isActive = !this.isActive;
|
||||
},
|
||||
requestResult(requestResult) {
|
||||
this.$emit("requestResult", requestResult);
|
||||
}
|
||||
this.$emit('requestResult', requestResult);
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
assertion() {
|
||||
return this.scenario.passAssertions + " / " + this.scenario.totalAssertions;
|
||||
return (
|
||||
this.scenario.passAssertions + ' / ' + this.scenario.totalAssertions
|
||||
);
|
||||
},
|
||||
success() {
|
||||
return this.scenario.error === 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -119,7 +131,7 @@ export default {
|
|||
}
|
||||
|
||||
.scenario-result + .scenario-result {
|
||||
border-top: 1px solid #DCDFE6;
|
||||
border-top: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.ms-card :deep(.el-card__body) {
|
||||
|
@ -143,15 +155,15 @@ export default {
|
|||
}
|
||||
|
||||
.ms-api-col {
|
||||
background-color: #EFF0F0;
|
||||
border-color: #EFF0F0;
|
||||
background-color: #eff0f0;
|
||||
border-color: #eff0f0;
|
||||
margin-right: 10px;
|
||||
font-size: 12px;
|
||||
color: #64666A;
|
||||
color: #64666a;
|
||||
}
|
||||
|
||||
.ms-card .ms-api-col-create {
|
||||
background-color: #EBF2F2;
|
||||
background-color: #ebf2f2;
|
||||
border-color: #008080;
|
||||
margin-right: 10px;
|
||||
font-size: 12px;
|
||||
|
@ -161,7 +173,8 @@ export default {
|
|||
.report-label-head {
|
||||
border-bottom: 1px solid #303133;
|
||||
color: #303133;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
|
||||
Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,62 @@
|
|||
<template>
|
||||
<el-card class="scenario-results">
|
||||
<div v-if="errorReport > 0">
|
||||
<el-tooltip :content="$t('api_test.automation.open_expansion')" placement="top" effect="light">
|
||||
<i class="el-icon-circle-plus-outline ms-open-btn ms-open-btn-left" v-prevent-re-click @click="openExpansion"/>
|
||||
<el-tooltip
|
||||
:content="$t('api_test.automation.open_expansion')"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<i
|
||||
class="el-icon-circle-plus-outline ms-open-btn ms-open-btn-left"
|
||||
v-prevent-re-click
|
||||
@click="openExpansion"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('api_test.automation.close_expansion')" placement="top" effect="light">
|
||||
<i class="el-icon-remove-outline ms-open-btn" size="mini" @click="closeExpansion"/>
|
||||
<el-tooltip
|
||||
:content="$t('api_test.automation.close_expansion')"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<i
|
||||
class="el-icon-remove-outline ms-open-btn"
|
||||
size="mini"
|
||||
@click="closeExpansion"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-tree :data="treeData"
|
||||
:expand-on-click-node="false"
|
||||
:default-expand-all="defaultExpand"
|
||||
:filter-node-method="filterNode"
|
||||
highlight-current
|
||||
class="ms-tree ms-report-tree" ref="resultsTree">
|
||||
<span slot-scope="{ node, data}" style="width: 99%" @click="nodeClick(node)">
|
||||
<ms-scenario-result :node="data" :console="console" v-on:requestResult="requestResult"
|
||||
:isActive="isActive" :is-share="isShare" :share-id="shareId"/>
|
||||
</span>
|
||||
<el-tree
|
||||
:data="treeData"
|
||||
:expand-on-click-node="false"
|
||||
:default-expand-all="defaultExpand"
|
||||
:filter-node-method="filterNode"
|
||||
highlight-current
|
||||
class="ms-tree ms-report-tree"
|
||||
ref="resultsTree"
|
||||
>
|
||||
<span
|
||||
slot-scope="{ node, data }"
|
||||
style="width: 99%"
|
||||
@click="nodeClick(node)"
|
||||
>
|
||||
<ms-scenario-result
|
||||
:node="data"
|
||||
:console="console"
|
||||
v-on:requestResult="requestResult"
|
||||
:isActive="isActive"
|
||||
:is-share="isShare"
|
||||
:share-id="shareId"
|
||||
/>
|
||||
</span>
|
||||
</el-tree>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsScenarioResult from "./ScenarioResult";
|
||||
import MsScenarioResult from './ScenarioResult';
|
||||
|
||||
export default {
|
||||
name: "MsScenarioResults",
|
||||
components: {MsScenarioResult},
|
||||
name: 'MsScenarioResults',
|
||||
components: { MsScenarioResult },
|
||||
props: {
|
||||
scenarios: Array,
|
||||
treeData: Array,
|
||||
|
@ -43,8 +72,8 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
isActive: false
|
||||
}
|
||||
isActive: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.$refs.resultsTree && this.$refs.resultsTree.root) {
|
||||
|
@ -53,7 +82,11 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
isUi() {
|
||||
return this.report && this.report.reportType && this.report.reportType.startsWith("UI");
|
||||
return (
|
||||
this.report &&
|
||||
this.report.reportType &&
|
||||
this.report.reportType.startsWith('UI')
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -64,7 +97,11 @@ export default {
|
|||
if (!value) return true;
|
||||
if (data.value) {
|
||||
if (value === 'FAKE_ERROR') {
|
||||
if (data.errorCode && data.errorCode !== "" && data.value.status === "FAKE_ERROR") {
|
||||
if (
|
||||
data.errorCode &&
|
||||
data.errorCode !== '' &&
|
||||
data.value.status === 'FAKE_ERROR'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
} else if (value === 'PENDING') {
|
||||
|
@ -83,20 +120,20 @@ export default {
|
|||
});
|
||||
},
|
||||
requestResult(requestResult) {
|
||||
this.$emit("requestResult", requestResult);
|
||||
this.$emit('requestResult', requestResult);
|
||||
},
|
||||
nodeClick(node) {
|
||||
node.expanded = !node.expanded;
|
||||
},
|
||||
// 改变节点的状态
|
||||
changeTreeNodeStatus(node, expandCount) {
|
||||
node.expanded = this.expandAll
|
||||
node.expanded = this.expandAll;
|
||||
for (let i = 0; i < node.childNodes.length; i++) {
|
||||
// 改变节点的自身expanded状态
|
||||
node.childNodes[i].expanded = this.expandAll
|
||||
node.childNodes[i].expanded = this.expandAll;
|
||||
// 遍历子节点
|
||||
if (node.childNodes[i].childNodes.length > 0) {
|
||||
this.changeTreeNodeStatus(node.childNodes[i])
|
||||
this.changeTreeNodeStatus(node.childNodes[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -109,10 +146,10 @@ export default {
|
|||
this.isActive = true;
|
||||
this.expandAll = true;
|
||||
// 改变每个节点的状态
|
||||
this.changeTreeNodeStatus(this.$refs.resultsTree.store.root, 0)
|
||||
this.changeTreeNodeStatus(this.$refs.resultsTree.store.root, 0);
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -143,7 +180,8 @@ export default {
|
|||
|
||||
:deep(.el-checkbox) {
|
||||
color: #303133;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
|
||||
Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -163,13 +201,12 @@ export default {
|
|||
}
|
||||
|
||||
.ms-open-btn:hover {
|
||||
background-color: #F2F9EE;
|
||||
background-color: #f2f9ee;
|
||||
cursor: pointer;
|
||||
color: #67C23A;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.ms-open-btn-left {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -6,16 +6,22 @@
|
|||
:data="table.tableData"
|
||||
border
|
||||
size="mini"
|
||||
highlight-current-row>
|
||||
<el-table-column v-for="(title, index) in table.titles" :key="index" :label="title" min-width="150px">
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
v-for="(title, index) in table.titles"
|
||||
:key="index"
|
||||
:label="title"
|
||||
min-width="150px"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="top"
|
||||
trigger="click">
|
||||
<el-popover placement="top" trigger="click">
|
||||
<el-container>
|
||||
<div>{{ scope.row[title] }}</div>
|
||||
</el-container>
|
||||
<span class="table-content" slot="reference">{{ scope.row[title] }}</span>
|
||||
<span class="table-content" slot="reference">{{
|
||||
scope.row[title]
|
||||
}}</span>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -24,98 +30,99 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsSqlResultTable",
|
||||
data() {
|
||||
return {
|
||||
tables: [],
|
||||
titles: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
body: String
|
||||
},
|
||||
created() {
|
||||
if (!this.body) {
|
||||
return;
|
||||
}
|
||||
let rowArray = this.body.split("\n");
|
||||
this.getTableData(rowArray);
|
||||
if (this.tables.length > 1) {
|
||||
for (let i = 0; i < this.tables.length; i++) {
|
||||
if (this.tables[i].titles.length === 1 && i < this.tables.length - 1) {
|
||||
this.tables[i].tableData.splice(this.tables[i].tableData.length - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
let lastTable = this.tables[this.tables.length - 1];
|
||||
if (lastTable.titles.length === 1) {
|
||||
if (lastTable.tableData.length > 4) {
|
||||
lastTable.tableData.splice(lastTable.tableData.length - 4, 4);
|
||||
} else {
|
||||
this.tables.splice(this.tables.length - 1, 1);
|
||||
}
|
||||
} else {
|
||||
this.tables.splice(this.tables.length - 1, 1);
|
||||
}
|
||||
} else {
|
||||
let table = this.tables[0];
|
||||
table.tableData.splice(table.tableData.length - 4, 4);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getTableData(rowArray) {
|
||||
let titles;
|
||||
let result = [];
|
||||
for (let i = 0; i < rowArray.length; i++) {
|
||||
let colArray = rowArray[i].split("\t");
|
||||
if (i === 0) {
|
||||
titles = colArray;
|
||||
} else {
|
||||
if (colArray.length != titles.length) {
|
||||
// 创建新的表
|
||||
if (colArray.length === 1 && colArray[0] === '') {
|
||||
this.getTableData(rowArray.slice(i + 1));
|
||||
} else {
|
||||
this.getTableData(rowArray.slice(i));
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
let item = {};
|
||||
for (let j = 0; j < colArray.length; j++) {
|
||||
item[titles[j]] = (colArray[j] ? colArray[j] : "");
|
||||
}
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.tables.splice(0, 0, {
|
||||
titles: titles,
|
||||
tableData: result
|
||||
});
|
||||
export default {
|
||||
name: 'MsSqlResultTable',
|
||||
data() {
|
||||
return {
|
||||
tables: [],
|
||||
titles: [],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
body: String,
|
||||
},
|
||||
created() {
|
||||
if (!this.body) {
|
||||
return;
|
||||
}
|
||||
let rowArray = this.body.split('\n');
|
||||
this.getTableData(rowArray);
|
||||
if (this.tables.length > 1) {
|
||||
for (let i = 0; i < this.tables.length; i++) {
|
||||
if (this.tables[i].titles.length === 1 && i < this.tables.length - 1) {
|
||||
this.tables[i].tableData.splice(
|
||||
this.tables[i].tableData.length - 1,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let lastTable = this.tables[this.tables.length - 1];
|
||||
if (lastTable.titles.length === 1) {
|
||||
if (lastTable.tableData.length > 4) {
|
||||
lastTable.tableData.splice(lastTable.tableData.length - 4, 4);
|
||||
} else {
|
||||
this.tables.splice(this.tables.length - 1, 1);
|
||||
}
|
||||
} else {
|
||||
this.tables.splice(this.tables.length - 1, 1);
|
||||
}
|
||||
} else {
|
||||
let table = this.tables[0];
|
||||
table.tableData.splice(table.tableData.length - 4, 4);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getTableData(rowArray) {
|
||||
let titles;
|
||||
let result = [];
|
||||
for (let i = 0; i < rowArray.length; i++) {
|
||||
let colArray = rowArray[i].split('\t');
|
||||
if (i === 0) {
|
||||
titles = colArray;
|
||||
} else {
|
||||
if (colArray.length != titles.length) {
|
||||
// 创建新的表
|
||||
if (colArray.length === 1 && colArray[0] === '') {
|
||||
this.getTableData(rowArray.slice(i + 1));
|
||||
} else {
|
||||
this.getTableData(rowArray.slice(i));
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
let item = {};
|
||||
for (let j = 0; j < colArray.length; j++) {
|
||||
item[titles[j]] = colArray[j] ? colArray[j] : '';
|
||||
}
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.tables.splice(0, 0, {
|
||||
titles: titles,
|
||||
tableData: result,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-table {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.el-table :deep(.cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.el-table :deep(.cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table-content {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.el-container {
|
||||
overflow:auto;
|
||||
max-height: 500px;
|
||||
}
|
||||
.table-content {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.el-container {
|
||||
overflow: auto;
|
||||
max-height: 500px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,50 +1,98 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.add_scenario')" :visible.sync="visible"
|
||||
width="45%"
|
||||
:destroy-on-close="true">
|
||||
<el-form :model="scenarioForm" label-position="right" label-width="100px" size="small" :rules="rule"
|
||||
ref="scenarioForm">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('api_test.automation.add_scenario')"
|
||||
:visible.sync="visible"
|
||||
width="45%"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<el-form
|
||||
:model="scenarioForm"
|
||||
label-position="right"
|
||||
label-width="100px"
|
||||
size="small"
|
||||
:rules="rule"
|
||||
ref="scenarioForm"
|
||||
>
|
||||
<el-form-item :label="$t('commons.name')" prop="name">
|
||||
<el-input v-model="scenarioForm.name" autocomplete="off" :placeholder="$t('commons.name')"/>
|
||||
<el-input
|
||||
v-model="scenarioForm.name"
|
||||
autocomplete="off"
|
||||
:placeholder="$t('commons.name')"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('test_track.module.module')" prop="apiScenarioModuleId">
|
||||
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="scenarioForm.apiScenarioModuleId"
|
||||
@getValue="setModule" :obj="moduleObj" clearable checkStrictly/>
|
||||
<el-form-item
|
||||
:label="$t('test_track.module.module')"
|
||||
prop="apiScenarioModuleId"
|
||||
>
|
||||
<ms-select-tree
|
||||
size="small"
|
||||
:data="moduleOptions"
|
||||
:defaultKey="scenarioForm.apiScenarioModuleId"
|
||||
@getValue="setModule"
|
||||
:obj="moduleObj"
|
||||
clearable
|
||||
checkStrictly
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('api_test.automation.scenario.principal')" prop="principal">
|
||||
<el-select v-model="scenarioForm.principal"
|
||||
:placeholder="$t('api_test.automation.scenario.principal')" filterable size="small"
|
||||
style="width: 100%">
|
||||
<el-form-item
|
||||
:label="$t('api_test.automation.scenario.principal')"
|
||||
prop="principal"
|
||||
>
|
||||
<el-select
|
||||
v-model="scenarioForm.principal"
|
||||
:placeholder="$t('api_test.automation.scenario.principal')"
|
||||
filterable
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
:label="item.id + ' (' + item.name + ')'"
|
||||
:value="item.id">
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('api_test.automation.scenario.follow_people')" prop="followPeople">
|
||||
<el-select v-model="scenarioForm.follows"
|
||||
multiple
|
||||
:placeholder="$t('api_test.automation.scenario.follow_people')" filterable size="small"
|
||||
style="width: 100%">
|
||||
<el-form-item
|
||||
:label="$t('api_test.automation.scenario.follow_people')"
|
||||
prop="followPeople"
|
||||
>
|
||||
<el-select
|
||||
v-model="scenarioForm.follows"
|
||||
multiple
|
||||
:placeholder="$t('api_test.automation.scenario.follow_people')"
|
||||
filterable
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
:label="item.id + ' (' + item.name + ')'"
|
||||
:value="item.id">
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('commons.description')" prop="description" style="margin-bottom: 29px">
|
||||
<el-input class="ms-http-textarea" v-model="scenarioForm.description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 10}"
|
||||
:rows="2" size="small"/>
|
||||
<el-form-item
|
||||
:label="$t('commons.description')"
|
||||
prop="description"
|
||||
style="margin-bottom: 29px"
|
||||
>
|
||||
<el-input
|
||||
class="ms-http-textarea"
|
||||
v-model="scenarioForm.description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 10 }"
|
||||
:rows="2"
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
@ -54,31 +102,33 @@
|
|||
:isShow="true"
|
||||
:title="$t('commons.edit_info')"
|
||||
@saveAsEdit="saveScenario(true)"
|
||||
@confirm="saveScenario">
|
||||
@confirm="saveScenario"
|
||||
>
|
||||
</ms-dialog-footer>
|
||||
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getMaintainer} from "@/api/project";
|
||||
import {getCurrentProjectID, getCurrentUser} from "metersphere-frontend/src/utils/token";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {saveScenario} from "@/business/automation/api-automation";
|
||||
import MsSelectTree from "metersphere-frontend/src/components/select-tree/SelectTree";
|
||||
import { getMaintainer } from '@/api/project';
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentUser,
|
||||
} from 'metersphere-frontend/src/utils/token';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter';
|
||||
import { saveScenario } from '@/business/automation/api-automation';
|
||||
import MsSelectTree from 'metersphere-frontend/src/components/select-tree/SelectTree';
|
||||
|
||||
export default {
|
||||
name: "MsAddBasisScenario",
|
||||
components: {MsDialogFooter, MsSelectTree},
|
||||
name: 'MsAddBasisScenario',
|
||||
components: { MsDialogFooter, MsSelectTree },
|
||||
props: {
|
||||
moduleOptions: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scenarioForm: {follows: []},
|
||||
scenarioForm: { follows: [] },
|
||||
visible: false,
|
||||
currentModule: {},
|
||||
userOptions: [],
|
||||
|
@ -88,17 +138,33 @@ export default {
|
|||
},
|
||||
rule: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
|
||||
{max: 100, message: this.$t('test_track.length_less_than') + '100', trigger: 'blur'}
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('test_track.case.input_name'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
max: 100,
|
||||
message: this.$t('test_track.length_less_than') + '100',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
apiScenarioModuleId: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('test_track.case.input_module'),
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
principal: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('api_test.automation.scenario.select_principal'),
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
apiScenarioModuleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
|
||||
principal: [{
|
||||
required: true,
|
||||
message: this.$t('api_test.automation.scenario.select_principal'),
|
||||
trigger: 'change'
|
||||
}],
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
projectId() {
|
||||
|
@ -113,12 +179,14 @@ export default {
|
|||
saveScenario(saveAs) {
|
||||
this.$refs['scenarioForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
let path = "/api/automation/create";
|
||||
let path = '/api/automation/create';
|
||||
this.setParameter();
|
||||
this.scenarioForm.status = 'Underway';
|
||||
this.scenarioForm.level = 'P0';
|
||||
if (saveAs) {
|
||||
this.scenarioForm.request = JSON.stringify(this.scenarioForm.request);
|
||||
this.scenarioForm.request = JSON.stringify(
|
||||
this.scenarioForm.request
|
||||
);
|
||||
this.$emit('saveAsEdit', this.scenarioForm);
|
||||
this.visible = false;
|
||||
} else {
|
||||
|
@ -131,7 +199,7 @@ export default {
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
setParameter() {
|
||||
this.scenarioForm.projectId = this.projectId;
|
||||
|
@ -139,28 +207,31 @@ export default {
|
|||
this.scenarioForm.protocol = this.currentProtocol;
|
||||
|
||||
if (!this.scenarioForm.modulePath) {
|
||||
this.scenarioForm.modulePath = this.$t("commons.module_title");
|
||||
this.scenarioForm.modulePath = this.$t('commons.module_title');
|
||||
}
|
||||
if (!this.scenarioForm.apiScenarioModuleId) {
|
||||
this.scenarioForm.apiScenarioModuleId = "default-module";
|
||||
this.scenarioForm.apiScenarioModuleId = 'default-module';
|
||||
}
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
getMaintainer().then(response => {
|
||||
getMaintainer().then((response) => {
|
||||
this.userOptions = response.data;
|
||||
});
|
||||
},
|
||||
open(currentModule) {
|
||||
this.scenarioForm = {principal: getCurrentUser().id};
|
||||
this.scenarioForm = { principal: getCurrentUser().id };
|
||||
this.currentModule = currentModule;
|
||||
if (this.scenarioForm.apiScenarioModuleId === undefined && !currentModule.id) {
|
||||
if (
|
||||
this.scenarioForm.apiScenarioModuleId === undefined &&
|
||||
!currentModule.id
|
||||
) {
|
||||
this.scenarioForm.apiScenarioModuleId = this.moduleOptions[0].id;
|
||||
} else if (currentModule.id) {
|
||||
this.scenarioForm.apiScenarioModuleId = currentModule.id;
|
||||
}
|
||||
this.getMaintainerOptions();
|
||||
this.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -3,9 +3,17 @@
|
|||
<el-card>
|
||||
<el-form :model="request" label-width="auto" ref="request">
|
||||
<el-form-item :label="$t('api_test.request.name')" prop="name">
|
||||
<el-input v-model="request.name" maxlength="200" show-word-limit size="small"/>
|
||||
<el-input
|
||||
v-model="request.name"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('api_test.definition.api_type')" prop="protocol">
|
||||
<el-form-item
|
||||
:label="$t('api_test.definition.api_type')"
|
||||
prop="protocol"
|
||||
>
|
||||
<el-radio v-model="request.protocol" label="HTTP">HTTP</el-radio>
|
||||
<el-radio v-model="request.protocol" label="DUBBO">DUBBO</el-radio>
|
||||
<el-radio v-model="request.protocol" label="SQL">SQL</el-radio>
|
||||
|
@ -13,37 +21,59 @@
|
|||
</el-form-item>
|
||||
</el-form>
|
||||
<!--不同协议请求-->
|
||||
<ms-debug-http-page :scenario="true" :current-api="request" @saveAs="editApi" :currentProtocol="request.protocol"
|
||||
v-if="request.protocol==='HTTP'"/>
|
||||
<ms-debug-jdbc-page :scenario="true" :currentProtocol="request.protocol" @saveAs="editApi"
|
||||
v-if="request.protocol==='SQL'"/>
|
||||
<ms-debug-tcp-page :scenario="true" :currentProtocol="request.protocol" @saveAs="editApi"
|
||||
v-if="request.protocol==='TCP'"/>
|
||||
<ms-debug-dubbo-page :scenario="true" :currentProtocol="request.protocol" @saveAs="editApi"
|
||||
v-if="request.protocol==='DUBBO'"/>
|
||||
<ms-debug-http-page
|
||||
:scenario="true"
|
||||
:current-api="request"
|
||||
@saveAs="editApi"
|
||||
:currentProtocol="request.protocol"
|
||||
v-if="request.protocol === 'HTTP'"
|
||||
/>
|
||||
<ms-debug-jdbc-page
|
||||
:scenario="true"
|
||||
:currentProtocol="request.protocol"
|
||||
@saveAs="editApi"
|
||||
v-if="request.protocol === 'SQL'"
|
||||
/>
|
||||
<ms-debug-tcp-page
|
||||
:scenario="true"
|
||||
:currentProtocol="request.protocol"
|
||||
@saveAs="editApi"
|
||||
v-if="request.protocol === 'TCP'"
|
||||
/>
|
||||
<ms-debug-dubbo-page
|
||||
:scenario="true"
|
||||
:currentProtocol="request.protocol"
|
||||
@saveAs="editApi"
|
||||
v-if="request.protocol === 'DUBBO'"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsDebugHttpPage from "../../definition/components/debug/DebugHttpPage";
|
||||
import MsDebugJdbcPage from "../../definition/components/debug/DebugJdbcPage";
|
||||
import MsDebugTcpPage from "../../definition/components/debug/DebugTcpPage";
|
||||
import MsDebugDubboPage from "../../definition/components/debug/DebugDubboPage";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import MsDebugHttpPage from '../../definition/components/debug/DebugHttpPage';
|
||||
import MsDebugJdbcPage from '../../definition/components/debug/DebugJdbcPage';
|
||||
import MsDebugTcpPage from '../../definition/components/debug/DebugTcpPage';
|
||||
import MsDebugDubboPage from '../../definition/components/debug/DebugDubboPage';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
|
||||
export default {
|
||||
name: "ApiCustomize",
|
||||
name: 'ApiCustomize',
|
||||
props: {
|
||||
node: {},
|
||||
request: {},
|
||||
},
|
||||
components: {MsDebugHttpPage, MsDebugJdbcPage, MsDebugTcpPage, MsDebugDubboPage},
|
||||
components: {
|
||||
MsDebugHttpPage,
|
||||
MsDebugJdbcPage,
|
||||
MsDebugTcpPage,
|
||||
MsDebugDubboPage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
remove() {
|
||||
|
@ -75,15 +105,13 @@ export default {
|
|||
this.$emit('addCustomizeApi', obj);
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -4,22 +4,39 @@
|
|||
:visible.sync="dialogVisible"
|
||||
width="30%"
|
||||
:destroy-on-close="true"
|
||||
:before-close="handleClose">
|
||||
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<div v-loading="result">
|
||||
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
|
||||
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px">
|
||||
{{ getProjectName(pe.id) }}
|
||||
<el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-left:10px; margin-top: 10px;"
|
||||
size="small">
|
||||
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"/>
|
||||
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
||||
<el-select
|
||||
v-model="pe['selectEnv']"
|
||||
placeholder="请选择环境"
|
||||
style="margin-left: 10px; margin-top: 10px"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="(environment, index) in pe.envs"
|
||||
:key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"
|
||||
/>
|
||||
<el-button
|
||||
class="ms-scenario-button"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="openEnvironmentConfig(pe.id)"
|
||||
>
|
||||
{{ $t('api_test.environment.environment_config') }}
|
||||
</el-button>
|
||||
<template v-slot:empty>
|
||||
<div class="empty-environment">
|
||||
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
||||
<el-button
|
||||
class="ms-scenario-button"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="openEnvironmentConfig(pe.id)"
|
||||
>
|
||||
{{ $t('api_test.environment.environment_config') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -30,27 +47,31 @@
|
|||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm" size="small">确 定</el-button>
|
||||
<el-button type="primary" @click="handleConfirm" size="small"
|
||||
>确 定</el-button
|
||||
>
|
||||
</span>
|
||||
|
||||
<!-- 环境配置 -->
|
||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||
|
||||
<api-environment-config
|
||||
ref="environmentConfig"
|
||||
@close="environmentConfigClose"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parseEnvironment} from "@/business/environment/model/EnvironmentModel";
|
||||
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
|
||||
import {getEnvironmentByProjectId} from "metersphere-frontend/src/api/environment";
|
||||
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
|
||||
import ApiEnvironmentConfig from 'metersphere-frontend/src/components/environment/ApiEnvironmentConfig';
|
||||
import { getEnvironmentByProjectId } from 'metersphere-frontend/src/api/environment';
|
||||
|
||||
export default {
|
||||
name: "ApiScenarioEnv",
|
||||
components: {ApiEnvironmentConfig},
|
||||
name: 'ApiScenarioEnv',
|
||||
components: { ApiEnvironmentConfig },
|
||||
props: {
|
||||
envMap: Map,
|
||||
projectIds: Set,
|
||||
projectList: Array
|
||||
projectList: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -59,28 +80,28 @@ export default {
|
|||
projects: [],
|
||||
environmentId: '',
|
||||
environments: [],
|
||||
dialogVisible: false
|
||||
}
|
||||
dialogVisible: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
init() {
|
||||
this.projectIds.forEach(id => {
|
||||
let item = {id: id, envs: [], selectEnv: ""};
|
||||
this.projectIds.forEach((id) => {
|
||||
let item = { id: id, envs: [], selectEnv: '' };
|
||||
this.data.push(item);
|
||||
this.result = getEnvironmentByProjectId(id).then(res => {
|
||||
this.result = getEnvironmentByProjectId(id).then((res) => {
|
||||
let envs = res.data;
|
||||
envs.forEach(environment => {
|
||||
envs.forEach((environment) => {
|
||||
parseEnvironment(environment);
|
||||
});
|
||||
// 固定环境列表渲染顺序
|
||||
let temp = this.data.find(dt => dt.id === id);
|
||||
let temp = this.data.find((dt) => dt.id === id);
|
||||
temp.envs = envs;
|
||||
temp.selectEnv = this.envMap.get(id);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
},
|
||||
open() {
|
||||
this.data = [];
|
||||
|
@ -90,8 +111,8 @@ export default {
|
|||
}
|
||||
},
|
||||
getProjectName(id) {
|
||||
const project = this.projectList.find(p => p.id === id);
|
||||
return project ? project.name : "";
|
||||
const project = this.projectList.find((p) => p.id === id);
|
||||
return project ? project.name : '';
|
||||
},
|
||||
openEnvironmentConfig(projectId) {
|
||||
if (!projectId) {
|
||||
|
@ -103,15 +124,15 @@ export default {
|
|||
handleConfirm() {
|
||||
let map = new Map();
|
||||
let sign = true;
|
||||
this.data.forEach(dt => {
|
||||
this.data.forEach((dt) => {
|
||||
if (!dt.selectEnv) {
|
||||
sign = false;
|
||||
return;
|
||||
}
|
||||
map.set(dt.id, dt.selectEnv);
|
||||
})
|
||||
});
|
||||
if (!sign) {
|
||||
this.$warning("请为当前场景选择一个运行环境!");
|
||||
this.$warning('请为当前场景选择一个运行环境!');
|
||||
return;
|
||||
}
|
||||
this.$emit('setProjectEnvMap', map);
|
||||
|
@ -120,18 +141,18 @@ export default {
|
|||
checkEnv() {
|
||||
let sign = true;
|
||||
if (this.data.length > 0) {
|
||||
this.data.forEach(dt => {
|
||||
this.data.forEach((dt) => {
|
||||
if (!dt.selectEnv) {
|
||||
sign = false;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
sign = false;
|
||||
}
|
||||
|
||||
if (!sign) {
|
||||
this.$warning("请为当前场景选择一个运行环境!");
|
||||
this.$warning('请为当前场景选择一个运行环境!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -139,9 +160,9 @@ export default {
|
|||
environmentConfigClose() {
|
||||
this.data = [];
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
|
||||
<slot name="header"></slot>
|
||||
|
||||
<ms-node-tree
|
||||
|
@ -22,39 +21,47 @@
|
|||
@refresh="list"
|
||||
@filter="filter"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
ref="nodeTree">
|
||||
|
||||
ref="nodeTree"
|
||||
>
|
||||
<template v-slot:header>
|
||||
<ms-search-bar
|
||||
:show-operator="showOperator && !isTrashData"
|
||||
:condition="condition"
|
||||
:commands="operators"/>
|
||||
<module-trash-button v-if="!isReadOnly && !isTrashData" :condition="condition" :exe="enableTrash"
|
||||
:total='total'/>
|
||||
:commands="operators"
|
||||
/>
|
||||
<module-trash-button
|
||||
v-if="!isReadOnly && !isTrashData"
|
||||
:condition="condition"
|
||||
:exe="enableTrash"
|
||||
:total="total"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</ms-node-tree>
|
||||
|
||||
<ms-add-basis-scenario
|
||||
:module-options="data"
|
||||
@saveAsEdit="saveAsEdit"
|
||||
@refresh="refresh"
|
||||
ref="basisScenario"/>
|
||||
ref="basisScenario"
|
||||
/>
|
||||
|
||||
<api-import ref="apiImport" :moduleOptions="data" @refreshAll="$emit('refreshAll')"/>
|
||||
<api-import
|
||||
ref="apiImport"
|
||||
:moduleOptions="data"
|
||||
@refreshAll="$emit('refreshAll')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectMenu from "@/business/commons/SelectMenu";
|
||||
import MsAddBasisScenario from "@/business/automation/scenario/AddBasisScenario";
|
||||
import MsNodeTree from "@/business/commons/NodeTree";
|
||||
import {buildTree} from "metersphere-frontend/src/model/NodeTree";
|
||||
import ModuleTrashButton from "../../definition/components/module/ModuleTrashButton";
|
||||
import ApiImport from "./common/ScenarioImport";
|
||||
import MsSearchBar from "metersphere-frontend/src/components/search/MsSearchBar";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import SelectMenu from '@/business/commons/SelectMenu';
|
||||
import MsAddBasisScenario from '@/business/automation/scenario/AddBasisScenario';
|
||||
import MsNodeTree from '@/business/commons/NodeTree';
|
||||
import { buildTree } from 'metersphere-frontend/src/model/NodeTree';
|
||||
import ModuleTrashButton from '../../definition/components/module/ModuleTrashButton';
|
||||
import ApiImport from './common/ScenarioImport';
|
||||
import MsSearchBar from 'metersphere-frontend/src/components/search/MsSearchBar';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import {
|
||||
addScenarioModule,
|
||||
delScenarioModule,
|
||||
|
@ -63,8 +70,8 @@ import {
|
|||
getModuleByProjectId,
|
||||
getModuleByRelevanceProjectId,
|
||||
getModuleByTrash,
|
||||
posScenarioModule
|
||||
} from "@/api/scenario-module";
|
||||
posScenarioModule,
|
||||
} from '@/api/scenario-module';
|
||||
|
||||
export default {
|
||||
name: 'MsApiScenarioModule',
|
||||
|
@ -81,7 +88,7 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
showOperator: Boolean,
|
||||
relevanceProjectId: String,
|
||||
|
@ -92,14 +99,14 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
selectProjectId: {
|
||||
type: String,
|
||||
default() {
|
||||
return getCurrentProjectID();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isRelevanceModel() {
|
||||
|
@ -111,14 +118,14 @@ export default {
|
|||
} else {
|
||||
return getCurrentProjectID();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: false,
|
||||
condition: {
|
||||
filterText: "",
|
||||
trashEnable: false
|
||||
filterText: '',
|
||||
trashEnable: false,
|
||||
},
|
||||
data: [],
|
||||
currentModule: undefined,
|
||||
|
@ -126,12 +133,12 @@ export default {
|
|||
{
|
||||
label: this.$t('api_test.automation.add_scenario'),
|
||||
callback: this.addScenario,
|
||||
permissions: ['PROJECT_API_SCENARIO:READ+CREATE']
|
||||
permissions: ['PROJECT_API_SCENARIO:READ+CREATE'],
|
||||
},
|
||||
{
|
||||
label: this.$t('api_test.api_import.label'),
|
||||
callback: this.handleImport,
|
||||
permissions: ['PROJECT_API_SCENARIO:READ+IMPORT_SCENARIO']
|
||||
permissions: ['PROJECT_API_SCENARIO:READ+IMPORT_SCENARIO'],
|
||||
},
|
||||
{
|
||||
label: this.$t('report.export'),
|
||||
|
@ -141,19 +148,19 @@ export default {
|
|||
permissions: ['PROJECT_API_SCENARIO:READ+EXPORT_SCENARIO'],
|
||||
callback: () => {
|
||||
this.exportAPI();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: this.$t('report.export_jmeter_format'),
|
||||
permissions: ['PROJECT_API_SCENARIO:READ+EXPORT_SCENARIO'],
|
||||
callback: () => {
|
||||
this.$emit('exportJmx');
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.list();
|
||||
|
@ -171,16 +178,16 @@ export default {
|
|||
isTrashData() {
|
||||
this.condition.trashEnable = this.isTrashData;
|
||||
this.list();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleImport() {
|
||||
if (this.projectId) {
|
||||
this.result = getModuleByProjectId(this.projectId).then(response => {
|
||||
this.result = getModuleByProjectId(this.projectId).then((response) => {
|
||||
if (response.data != undefined && response.data != null) {
|
||||
this.data = response.data;
|
||||
this.data.forEach(node => {
|
||||
buildTree(node, {path: ''});
|
||||
this.data.forEach((node) => {
|
||||
buildTree(node, { path: '' });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -192,15 +199,21 @@ export default {
|
|||
},
|
||||
list(projectId) {
|
||||
if (this.isRelevanceModel) {
|
||||
this.result = getModuleByRelevanceProjectId(this.relevanceProjectId).then(response => {
|
||||
this.result = getModuleByRelevanceProjectId(
|
||||
this.relevanceProjectId
|
||||
).then((response) => {
|
||||
this.setData(response);
|
||||
});
|
||||
} else if (this.isTrashData) {
|
||||
this.result = getModuleByTrash(projectId ? projectId : this.projectId).then(response => {
|
||||
this.result = getModuleByTrash(
|
||||
projectId ? projectId : this.projectId
|
||||
).then((response) => {
|
||||
this.setData(response);
|
||||
});
|
||||
} else {
|
||||
this.result = getModuleByProjectId(projectId ? projectId : this.projectId).then(response => {
|
||||
this.result = getModuleByProjectId(
|
||||
projectId ? projectId : this.projectId
|
||||
).then((response) => {
|
||||
this.setData(response);
|
||||
});
|
||||
}
|
||||
|
@ -208,9 +221,12 @@ export default {
|
|||
setData(response) {
|
||||
if (response.data != undefined && response.data != null) {
|
||||
this.data = response.data;
|
||||
this.data.forEach(node => {
|
||||
node.name = node.name === '未规划场景' ? this.$t('api_test.automation.unplanned_scenario') : node.name
|
||||
buildTree(node, {path: ''});
|
||||
this.data.forEach((node) => {
|
||||
node.name =
|
||||
node.name === '未规划场景'
|
||||
? this.$t('api_test.automation.unplanned_scenario')
|
||||
: node.name;
|
||||
buildTree(node, { path: '' });
|
||||
});
|
||||
this.$emit('setModuleOptions', this.data);
|
||||
this.$emit('setNodeTree', this.data);
|
||||
|
@ -222,13 +238,16 @@ export default {
|
|||
edit(param) {
|
||||
param.projectId = this.projectId;
|
||||
param.protocol = this.condition.protocol;
|
||||
editScenarioModule(param).then(() => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.list();
|
||||
this.refresh();
|
||||
}, (error) => {
|
||||
this.list();
|
||||
});
|
||||
editScenarioModule(param).then(
|
||||
() => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.list();
|
||||
this.refresh();
|
||||
},
|
||||
(error) => {
|
||||
this.list();
|
||||
}
|
||||
);
|
||||
},
|
||||
add(param) {
|
||||
param.projectId = this.projectId;
|
||||
|
@ -238,71 +257,83 @@ export default {
|
|||
this.$error(this.$t('commons.warning_module_add'));
|
||||
return;
|
||||
} else {
|
||||
addScenarioModule(param).then(() => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.list();
|
||||
}, (error) => {
|
||||
this.list();
|
||||
});
|
||||
addScenarioModule(param).then(
|
||||
() => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.list();
|
||||
},
|
||||
(error) => {
|
||||
this.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
remove(nodeIds) {
|
||||
delScenarioModule(nodeIds).then(() => {
|
||||
this.list();
|
||||
this.refresh();
|
||||
this.removeModuleId(nodeIds);
|
||||
}, (error) => {
|
||||
this.list();
|
||||
});
|
||||
delScenarioModule(nodeIds).then(
|
||||
() => {
|
||||
this.list();
|
||||
this.refresh();
|
||||
this.removeModuleId(nodeIds);
|
||||
},
|
||||
(error) => {
|
||||
this.list();
|
||||
}
|
||||
);
|
||||
},
|
||||
drag(param, list) {
|
||||
dragScenarioModule(param).then(() => {
|
||||
posScenarioModule(list).then(() => {
|
||||
dragScenarioModule(param).then(
|
||||
() => {
|
||||
posScenarioModule(list).then(() => {
|
||||
this.list();
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
this.list();
|
||||
});
|
||||
}, (error) => {
|
||||
this.list();
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
nodeChange(node, nodeIds, pNodes) {
|
||||
this.currentModule = node.data;
|
||||
if (node.data.id === 'root') {
|
||||
this.$emit("nodeSelectEvent", node, [], pNodes);
|
||||
this.$emit('nodeSelectEvent', node, [], pNodes);
|
||||
} else {
|
||||
this.$emit("nodeSelectEvent", node, nodeIds, pNodes);
|
||||
this.$emit('nodeSelectEvent', node, nodeIds, pNodes);
|
||||
}
|
||||
this.nohupReloadTree(node.data.id);
|
||||
},
|
||||
//后台更新节点数据
|
||||
nohupReloadTree(selectNodeId) {
|
||||
if (this.isRelevanceModel) {
|
||||
getModuleByRelevanceProjectId(this.relevanceProjectId).then(response => {
|
||||
this.setModuleList(response, selectNodeId);
|
||||
});
|
||||
getModuleByRelevanceProjectId(this.relevanceProjectId).then(
|
||||
(response) => {
|
||||
this.setModuleList(response, selectNodeId);
|
||||
}
|
||||
);
|
||||
} else if (this.isTrashData) {
|
||||
if (!this.projectId) {
|
||||
return;
|
||||
}
|
||||
getModuleByTrash(this.projectId).then(response => {
|
||||
getModuleByTrash(this.projectId).then((response) => {
|
||||
this.setModuleList(response, selectNodeId);
|
||||
});
|
||||
} else {
|
||||
if (!this.projectId) {
|
||||
return;
|
||||
}
|
||||
getModuleByProjectId(this.projectId).then(response => {
|
||||
getModuleByProjectId(this.projectId).then((response) => {
|
||||
this.setModuleList(response, selectNodeId);
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
setModuleList(response, selectNodeId) {
|
||||
if (response.data != undefined && response.data != null) {
|
||||
this.data = response.data;
|
||||
this.data.forEach(node => {
|
||||
node.name = node.name === '未规划场景' ? this.$t('api_test.automation.unplanned_scenario') : node.name
|
||||
buildTree(node, {path: ''});
|
||||
this.data.forEach((node) => {
|
||||
node.name =
|
||||
node.name === '未规划场景'
|
||||
? this.$t('api_test.automation.unplanned_scenario')
|
||||
: node.name;
|
||||
buildTree(node, { path: '' });
|
||||
});
|
||||
|
||||
this.$nextTick(() => {
|
||||
|
@ -312,7 +343,7 @@ export default {
|
|||
this.$refs.nodeTree.justSetCurrentKey(selectNodeId);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
exportAPI() {
|
||||
|
@ -322,7 +353,7 @@ export default {
|
|||
this.$emit('saveAsEdit', data);
|
||||
},
|
||||
refresh() {
|
||||
this.$emit("refreshAll");
|
||||
this.$emit('refreshAll');
|
||||
},
|
||||
addScenario() {
|
||||
if (!this.projectId) {
|
||||
|
@ -336,12 +367,15 @@ export default {
|
|||
this.$emit('enableTrash', this.condition.trashEnable);
|
||||
},
|
||||
removeModuleId(nodeIds) {
|
||||
if (localStorage.getItem('scenarioModule') && localStorage.getItem('scenarioModule') === nodeIds[0]) {
|
||||
if (
|
||||
localStorage.getItem('scenarioModule') &&
|
||||
localStorage.getItem('scenarioModule') === nodeIds[0]
|
||||
) {
|
||||
localStorage.setItem('scenarioModule', undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -394,5 +428,4 @@ export default {
|
|||
.ms-api-buttion {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -6,22 +6,47 @@
|
|||
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||
<el-col class="kv-checkbox">
|
||||
<input type="checkbox" v-if="!isDisable(index)" @change="change" :value="item.uuid" v-model="item.enable"
|
||||
:disabled="isDisable(index) || isReadOnly"/>
|
||||
<input
|
||||
type="checkbox"
|
||||
v-if="!isDisable(index)"
|
||||
@change="change"
|
||||
:value="item.uuid"
|
||||
v-model="item.enable"
|
||||
:disabled="isDisable(index) || isReadOnly"
|
||||
/>
|
||||
</el-col>
|
||||
|
||||
<el-col>
|
||||
<ms-api-variable-input :show-copy="showCopy" :show-variable="showVariable" :is-read-only="isReadOnly"
|
||||
v-model="item.name" size="small" maxlength="200" @change="change"
|
||||
:placeholder="$t('api_test.variable_name')" show-word-limit/>
|
||||
<ms-api-variable-input
|
||||
:show-copy="showCopy"
|
||||
:show-variable="showVariable"
|
||||
:is-read-only="isReadOnly"
|
||||
v-model="item.name"
|
||||
size="small"
|
||||
maxlength="200"
|
||||
@change="change"
|
||||
:placeholder="$t('api_test.variable_name')"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change"
|
||||
:placeholder="$t('api_test.value')" show-word-limit/>
|
||||
<el-input
|
||||
:disabled="isReadOnly"
|
||||
v-model="item.value"
|
||||
size="small"
|
||||
@change="change"
|
||||
:placeholder="$t('api_test.value')"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-col>
|
||||
<el-col class="kv-delete">
|
||||
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
|
||||
:disabled="isDisable(index) || isReadOnly"/>
|
||||
<el-button
|
||||
size="mini"
|
||||
class="el-icon-delete-solid"
|
||||
circle
|
||||
@click="remove(index)"
|
||||
:disabled="isDisable(index) || isReadOnly"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -29,30 +54,30 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {KeyValue} from "../../definition/model/ApiTestModel";
|
||||
import MsApiVariableInput from "./ApiVariableInput";
|
||||
import { KeyValue } from '../../definition/model/ApiTestModel';
|
||||
import MsApiVariableInput from './ApiVariableInput';
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioVariables",
|
||||
components: {MsApiVariableInput},
|
||||
name: 'MsApiScenarioVariables',
|
||||
components: { MsApiVariableInput },
|
||||
props: {
|
||||
description: String,
|
||||
items: Array,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
showVariable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
showCopy: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
remove: function (index) {
|
||||
|
@ -77,22 +102,22 @@ export default {
|
|||
});
|
||||
}
|
||||
if (isNeedCreate) {
|
||||
this.items.push(new KeyValue({enable: true}));
|
||||
this.items.push(new KeyValue({ enable: true }));
|
||||
}
|
||||
this.$emit('change', this.items);
|
||||
// TODO 检查key重复
|
||||
},
|
||||
isDisable: function (index) {
|
||||
return this.items.length - 1 === index;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.items.length === 0) {
|
||||
this.items.push(new KeyValue({enable: true}));
|
||||
this.items.push(new KeyValue({ enable: true }));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,123 +1,142 @@
|
|||
<template>
|
||||
<div class="variable-input" :class="{'show-copy': !showCopy}">
|
||||
<el-input class="el-input__inner_pd" :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||
<div :class="{'hidden': !showVariable}" class="variable-combine" v-if="value">
|
||||
<div v-if="showCopy" class="variable">{{variable}}</div>
|
||||
<el-tooltip v-if="showCopy" :content="$t('api_test.copied')" manual v-model="visible" placement="top" :visible-arrow="false">
|
||||
<i class="el-icon-copy-document copy" @click="copy"/>
|
||||
<div class="variable-input" :class="{ 'show-copy': !showCopy }">
|
||||
<el-input
|
||||
class="el-input__inner_pd"
|
||||
:disabled="isReadOnly"
|
||||
:value="value"
|
||||
v-bind="$attrs"
|
||||
:size="size"
|
||||
@change="change"
|
||||
@input="input"
|
||||
/>
|
||||
<div
|
||||
:class="{ hidden: !showVariable }"
|
||||
class="variable-combine"
|
||||
v-if="value"
|
||||
>
|
||||
<div v-if="showCopy" class="variable">{{ variable }}</div>
|
||||
<el-tooltip
|
||||
v-if="showCopy"
|
||||
:content="$t('api_test.copied')"
|
||||
manual
|
||||
v-model="visible"
|
||||
placement="top"
|
||||
:visible-arrow="false"
|
||||
>
|
||||
<i class="el-icon-copy-document copy" @click="copy" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsApiVariableInput",
|
||||
export default {
|
||||
name: 'MsApiVariableInput',
|
||||
|
||||
props: {
|
||||
value: String,
|
||||
size: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showVariable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCopy: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCopyTipWithMultiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
props: {
|
||||
value: String,
|
||||
size: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
showVariable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
|
||||
methods: {
|
||||
copy() {
|
||||
let input = document.createElement("input");
|
||||
document.body.appendChild(input);
|
||||
input.value = this.variable;
|
||||
input.select();
|
||||
if (input.setSelectionRange) {
|
||||
input.setSelectionRange(0, input.value.length);
|
||||
}
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(input);
|
||||
this.visible = true;
|
||||
setTimeout(() => {
|
||||
this.visible = false;
|
||||
}, 1000);
|
||||
},
|
||||
change(value) {
|
||||
this.$emit('change', value);
|
||||
},
|
||||
input(value) {
|
||||
this.$emit('input', value);
|
||||
}
|
||||
showCopy: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showCopyTipWithMultiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
variable() {
|
||||
return "${" + (this.showCopyTipWithMultiple ? (this.value + "_n") : this.value) + "}";
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
copy() {
|
||||
let input = document.createElement('input');
|
||||
document.body.appendChild(input);
|
||||
input.value = this.variable;
|
||||
input.select();
|
||||
if (input.setSelectionRange) {
|
||||
input.setSelectionRange(0, input.value.length);
|
||||
}
|
||||
}
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(input);
|
||||
this.visible = true;
|
||||
setTimeout(() => {
|
||||
this.visible = false;
|
||||
}, 1000);
|
||||
},
|
||||
change(value) {
|
||||
this.$emit('change', value);
|
||||
},
|
||||
input(value) {
|
||||
this.$emit('input', value);
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
computed: {
|
||||
variable() {
|
||||
return (
|
||||
'${' +
|
||||
(this.showCopyTipWithMultiple ? this.value + '_n' : this.value) +
|
||||
'}'
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.variable-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.variable-input {
|
||||
position: relative;
|
||||
}
|
||||
.el-input__inner_pd :deep(.el-input__inner) {
|
||||
padding-right: 135px;
|
||||
}
|
||||
|
||||
.el-input__inner_pd :deep(.el-input__inner) {
|
||||
padding-right: 135px;
|
||||
}
|
||||
.show-copy .el-input__inner_pd :deep(.el-input__inner) {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.show-copy .el-input__inner_pd :deep(.el-input__inner) {
|
||||
padding-right: 0px;
|
||||
}
|
||||
.variable-combine {
|
||||
color: #7f7f7f;
|
||||
max-width: 80px;
|
||||
line-height: 32px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 70px;
|
||||
margin-right: -20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.variable-combine .variable {
|
||||
display: inline-block;
|
||||
max-width: 60px;
|
||||
margin-right: 10px;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.variable-combine {
|
||||
color: #7F7F7F;
|
||||
max-width: 80px;
|
||||
line-height: 32px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 70px;
|
||||
margin-right: -20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.variable-combine .variable {
|
||||
display: inline-block;
|
||||
max-width: 60px;
|
||||
margin-right: 10px;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.variable-combine .copy {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: #1E90FF;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
.variable-combine .copy {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: #1e90ff;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {strMapToObj} from "metersphere-frontend/src/utils";
|
||||
import {createComponent} from "../../definition/components/jmeter/components";
|
||||
import {saveScenario} from "@/business/automation/api-automation";
|
||||
import {TYPE_TO_C} from "@/business/automation/scenario/Setting";
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { strMapToObj } from 'metersphere-frontend/src/utils';
|
||||
import { createComponent } from '../../definition/components/jmeter/components';
|
||||
import { saveScenario } from '@/business/automation/api-automation';
|
||||
import { TYPE_TO_C } from '@/business/automation/scenario/Setting';
|
||||
|
||||
export default {
|
||||
name: 'MsDebugRun',
|
||||
|
@ -23,37 +23,52 @@ export default {
|
|||
saved: Boolean,
|
||||
environmentType: String,
|
||||
environmentGroupId: String,
|
||||
browserLanguage: String
|
||||
browserLanguage: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: false,
|
||||
loading: false,
|
||||
reqNumber: 0,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
// 初始化
|
||||
reportId() {
|
||||
this.run()
|
||||
}
|
||||
this.run();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
sort(stepArray) {
|
||||
if (stepArray) {
|
||||
for (let i in stepArray) {
|
||||
if (stepArray[i] && TYPE_TO_C.get(stepArray[i].type) && !stepArray[i].clazzName) {
|
||||
if (
|
||||
stepArray[i] &&
|
||||
TYPE_TO_C.get(stepArray[i].type) &&
|
||||
!stepArray[i].clazzName
|
||||
) {
|
||||
stepArray[i].clazzName = TYPE_TO_C.get(stepArray[i].type);
|
||||
}
|
||||
if (stepArray[i].type === "Assertions" && !stepArray[i].document) {
|
||||
if (stepArray[i].type === 'Assertions' && !stepArray[i].document) {
|
||||
stepArray[i].document = {
|
||||
type: "JSON",
|
||||
data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}
|
||||
type: 'JSON',
|
||||
data: {
|
||||
xmlFollowAPI: false,
|
||||
jsonFollowAPI: false,
|
||||
json: [],
|
||||
xml: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
if (stepArray[i] && stepArray[i].authManager && !stepArray[i].authManager.clazzName) {
|
||||
stepArray[i].authManager.clazzName = TYPE_TO_C.get(stepArray[i].authManager.type);
|
||||
if (
|
||||
stepArray[i] &&
|
||||
stepArray[i].authManager &&
|
||||
!stepArray[i].authManager.clazzName
|
||||
) {
|
||||
stepArray[i].authManager.clazzName = TYPE_TO_C.get(
|
||||
stepArray[i].authManager.type
|
||||
);
|
||||
}
|
||||
if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) {
|
||||
this.sort(stepArray[i].hashTree);
|
||||
|
@ -89,7 +104,7 @@ export default {
|
|||
environmentMap: strMapToObj(map),
|
||||
environmentType: this.environmentType,
|
||||
environmentGroupId: this.environmentGroupId,
|
||||
environmentJson: JSON.stringify(strMapToObj(map))
|
||||
environmentJson: JSON.stringify(strMapToObj(map)),
|
||||
};
|
||||
if (this.runData.variables) {
|
||||
reqObj.variables = this.runData.variables;
|
||||
|
@ -101,12 +116,14 @@ export default {
|
|||
|
||||
let url = '/api/automation/run/debug';
|
||||
saveScenario(url, reqObj, this.runData.hashTree, this, (response) => {
|
||||
if (response.data !== "SUCCESS") {
|
||||
this.$error(response.data ? response.data : this.$t('commons.run_fail'));
|
||||
if (response.data !== 'SUCCESS') {
|
||||
this.$error(
|
||||
response.data ? response.data : this.$t('commons.run_fail')
|
||||
);
|
||||
this.$emit('errorRefresh');
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,24 +1,43 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="margin-left: 20px;">
|
||||
<el-select v-model="envGroupId" :placeholder="$t('workspace.env_group.select')"
|
||||
style="margin-top: 8px;width: 200px;" size="small">
|
||||
<el-option v-for="(group, index) in groups" :key="index"
|
||||
:label="group.name"
|
||||
:value="group.id"/>
|
||||
<div style="margin-left: 20px">
|
||||
<el-select
|
||||
v-model="envGroupId"
|
||||
:placeholder="$t('workspace.env_group.select')"
|
||||
style="margin-top: 8px; width: 200px"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="(group, index) in groups"
|
||||
:key="index"
|
||||
:label="group.name"
|
||||
:value="group.id"
|
||||
/>
|
||||
</el-select>
|
||||
<span style="margin-left: 8px;">{{ $t('workspace.env_group.name') }}</span>
|
||||
<span style="margin-left: 8px">{{ $t('workspace.env_group.name') }}</span>
|
||||
<i class="el-icon-view icon-view-btn" @click="viewGroup"></i>
|
||||
</div>
|
||||
<el-button type="primary" @click="handleConfirm" size="small" :style="btnStyle" class="env-confirm">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleConfirm"
|
||||
size="small"
|
||||
:style="btnStyle"
|
||||
class="env-confirm"
|
||||
>
|
||||
{{ $t('workspace.env_group.confirm') }}
|
||||
</el-button>
|
||||
<el-dialog :visible="visible" append-to-body :title="$t('workspace.env_group.name')" @close="visible = false"
|
||||
style="height: 800px;">
|
||||
<el-dialog
|
||||
:visible="visible"
|
||||
append-to-body
|
||||
:title="$t('workspace.env_group.name')"
|
||||
@close="visible = false"
|
||||
style="height: 800px"
|
||||
>
|
||||
<template>
|
||||
<environment-group style="overflow-y: auto;"
|
||||
:screen-height="'350px'"
|
||||
:read-only="true"
|
||||
<environment-group
|
||||
style="overflow-y: auto"
|
||||
:screen-height="'350px'"
|
||||
:read-only="true"
|
||||
></environment-group>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -26,38 +45,41 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import EnvironmentGroup from "@/business/commons/EnvironmentGroupList";
|
||||
import {environmentGetALL, getEnvironmentMapByGroupId} from "metersphere-frontend/src/api/environment";
|
||||
import EnvironmentGroup from '@/business/commons/EnvironmentGroupList';
|
||||
import {
|
||||
environmentGetALL,
|
||||
getEnvironmentMapByGroupId,
|
||||
} from 'metersphere-frontend/src/api/environment';
|
||||
|
||||
export default {
|
||||
name: "EnvGroup",
|
||||
components: {EnvironmentGroup},
|
||||
name: 'EnvGroup',
|
||||
components: { EnvironmentGroup },
|
||||
data() {
|
||||
return {
|
||||
groups: [],
|
||||
envGroupId: this.groupId,
|
||||
visible: false
|
||||
}
|
||||
visible: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
groupId: {
|
||||
type: String,
|
||||
default() {
|
||||
return "";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
projectIds: Set,
|
||||
btnStyle: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {width: "360px"}
|
||||
}
|
||||
}
|
||||
return { width: '360px' };
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
groupId(val) {
|
||||
this.envGroupId = val;
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
|
@ -67,10 +89,10 @@ export default {
|
|||
this.envGroupId = this.groupId;
|
||||
},
|
||||
init() {
|
||||
environmentGetALL().then(res => {
|
||||
environmentGetALL().then((res) => {
|
||||
let data = res.data;
|
||||
this.groups = data ? data : [];
|
||||
})
|
||||
});
|
||||
},
|
||||
viewGroup() {
|
||||
this.visible = true;
|
||||
|
@ -78,7 +100,7 @@ export default {
|
|||
async handleConfirm() {
|
||||
const sign = await this.checkEnv();
|
||||
if (sign) {
|
||||
this.$emit("setEnvGroup", this.envGroupId);
|
||||
this.$emit('setEnvGroup', this.envGroupId);
|
||||
this.$emit('close');
|
||||
}
|
||||
},
|
||||
|
@ -89,7 +111,7 @@ export default {
|
|||
resolve(false);
|
||||
return false;
|
||||
}
|
||||
getEnvironmentMapByGroupId(this.envGroupId).then(res => {
|
||||
getEnvironmentMapByGroupId(this.envGroupId).then((res) => {
|
||||
let data = res.data;
|
||||
if (!data) {
|
||||
this.$warning(this.$t('workspace.env_group.lack_env'));
|
||||
|
@ -99,17 +121,19 @@ export default {
|
|||
let map = new Map(Object.entries(data));
|
||||
for (let id of this.projectIds) {
|
||||
if (!map.get(id)) {
|
||||
this.$warning(this.$t('workspace.env_group.lack_necessary_environment'));
|
||||
this.$warning(
|
||||
this.$t('workspace.env_group.lack_necessary_environment')
|
||||
);
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve(true);
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,33 +1,51 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="margin-left: 20px;">
|
||||
<el-select v-model="envGroupId" :placeholder="$t('workspace.env_group.select')"
|
||||
style="margin-top: 8px;width: 200px;" size="small" clearable>
|
||||
<div style="margin-left: 20px">
|
||||
<el-select
|
||||
v-model="envGroupId"
|
||||
:placeholder="$t('workspace.env_group.select')"
|
||||
style="margin-top: 8px; width: 200px"
|
||||
size="small"
|
||||
clearable
|
||||
>
|
||||
<el-option-group
|
||||
v-for="group in groups"
|
||||
:key="group.label"
|
||||
:label="group.label">
|
||||
:label="group.label"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in group.options"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
:disabled="item.disabled"
|
||||
:value="item.id">
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
<span style="margin-left: 8px;">{{ $t('workspace.env_group.name') }}</span>
|
||||
<span style="margin-left: 8px">{{ $t('workspace.env_group.name') }}</span>
|
||||
<i class="el-icon-view icon-view-btn" @click="viewGroup"></i>
|
||||
</div>
|
||||
<el-button type="primary" @click="handleConfirm" size="small" class="env-confirm">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleConfirm"
|
||||
size="small"
|
||||
class="env-confirm"
|
||||
>
|
||||
{{ $t('workspace.env_group.confirm') }}
|
||||
</el-button>
|
||||
<el-dialog :visible="visible" append-to-body :title="$t('workspace.env_group.name')" @close="visible = false"
|
||||
style="height: 800px;">
|
||||
<el-dialog
|
||||
:visible="visible"
|
||||
append-to-body
|
||||
:title="$t('workspace.env_group.name')"
|
||||
@close="visible = false"
|
||||
style="height: 800px"
|
||||
>
|
||||
<template>
|
||||
<environment-group style="overflow-y: auto;"
|
||||
:screen-height="'350px'"
|
||||
:read-only="true"
|
||||
<environment-group
|
||||
style="overflow-y: auto"
|
||||
:screen-height="'350px'"
|
||||
:read-only="true"
|
||||
></environment-group>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -35,12 +53,15 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import EnvironmentGroup from "@/business/commons/EnvironmentGroupList";
|
||||
import {getEnvironmentMapByGroupId, getEnvironmentOptions} from "metersphere-frontend/src/api/environment";
|
||||
import EnvironmentGroup from '@/business/commons/EnvironmentGroupList';
|
||||
import {
|
||||
getEnvironmentMapByGroupId,
|
||||
getEnvironmentOptions,
|
||||
} from 'metersphere-frontend/src/api/environment';
|
||||
|
||||
export default {
|
||||
name: "EnvGroupWithOption",
|
||||
components: {EnvironmentGroup},
|
||||
name: 'EnvGroupWithOption',
|
||||
components: { EnvironmentGroup },
|
||||
data() {
|
||||
return {
|
||||
groups: [],
|
||||
|
@ -48,22 +69,22 @@ export default {
|
|||
visible: false,
|
||||
disabledGroups: [],
|
||||
notDisabledGroups: [],
|
||||
result: false
|
||||
}
|
||||
result: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
groupId: {
|
||||
type: String,
|
||||
default() {
|
||||
return "";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
projectIds: Set,
|
||||
},
|
||||
watch: {
|
||||
groupId(val) {
|
||||
this.envGroupId = val;
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
|
@ -73,19 +94,23 @@ export default {
|
|||
this.envGroupId = this.groupId;
|
||||
},
|
||||
init() {
|
||||
this.result = getEnvironmentOptions({projectIds: [...this.projectIds]}).then(res => {
|
||||
this.result = getEnvironmentOptions({
|
||||
projectIds: [...this.projectIds],
|
||||
}).then((res) => {
|
||||
let groups = res.data;
|
||||
this.disabledGroups = groups.filter(group => group.disabled === true);
|
||||
this.notDisabledGroups = groups.filter(group => group.disabled === false);
|
||||
this.disabledGroups = groups.filter((group) => group.disabled === true);
|
||||
this.notDisabledGroups = groups.filter(
|
||||
(group) => group.disabled === false
|
||||
);
|
||||
this.$set(this.groups, 0, {
|
||||
label: this.$t('workspace.env_group.available_group'),
|
||||
options: this.notDisabledGroups
|
||||
options: this.notDisabledGroups,
|
||||
});
|
||||
this.$set(this.groups, 1, {
|
||||
label: this.$t('workspace.env_group.not_available_group'),
|
||||
options: this.disabledGroups
|
||||
options: this.disabledGroups,
|
||||
});
|
||||
})
|
||||
});
|
||||
},
|
||||
viewGroup() {
|
||||
this.visible = true;
|
||||
|
@ -93,7 +118,7 @@ export default {
|
|||
async handleConfirm() {
|
||||
const sign = await this.checkEnv();
|
||||
if (sign) {
|
||||
this.$emit("setEnvGroup", this.envGroupId);
|
||||
this.$emit('setEnvGroup', this.envGroupId);
|
||||
this.$emit('close');
|
||||
}
|
||||
},
|
||||
|
@ -104,7 +129,7 @@ export default {
|
|||
resolve(false);
|
||||
return false;
|
||||
}
|
||||
getEnvironmentMapByGroupId(this.envGroupId).then(res => {
|
||||
getEnvironmentMapByGroupId(this.envGroupId).then((res) => {
|
||||
let data = res.data;
|
||||
if (!data) {
|
||||
this.$warning(this.$t('workspace.env_group.lack_env'));
|
||||
|
@ -114,17 +139,19 @@ export default {
|
|||
let map = new Map(Object.entries(data));
|
||||
for (let id of this.projectIds) {
|
||||
if (!map.get(id)) {
|
||||
this.$warning(this.$t('workspace.env_group.lack_necessary_environment'));
|
||||
this.$warning(
|
||||
this.$t('workspace.env_group.lack_necessary_environment')
|
||||
);
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve(true);
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -5,30 +5,58 @@
|
|||
:width="width"
|
||||
:disabled="isReadOnly"
|
||||
@show="showPopover"
|
||||
trigger="click">
|
||||
<el-radio-group v-model="radio" style="margin-left: 20px;" @change="radioChange">
|
||||
<el-radio :label="ENV_TYPE.JSON">{{ $t('workspace.env_group.env_list') }}</el-radio>
|
||||
<el-radio v-if="showEnvGroup" :label="ENV_TYPE.GROUP">{{ $t('workspace.env_group.name') }}</el-radio>
|
||||
trigger="click"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="radio"
|
||||
style="margin-left: 20px"
|
||||
@change="radioChange"
|
||||
>
|
||||
<el-radio :label="ENV_TYPE.JSON">{{
|
||||
$t('workspace.env_group.env_list')
|
||||
}}</el-radio>
|
||||
<el-radio v-if="showEnvGroup" :label="ENV_TYPE.GROUP">{{
|
||||
$t('workspace.env_group.name')
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
<env-select :project-ids="projectIds"
|
||||
:result="result"
|
||||
:show-config-button-with-out-permission="showConfigButtonWithOutPermission"
|
||||
:env-map="envMap"
|
||||
:project-list="projectList"
|
||||
@close="visible = false"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
v-show="!radio || radio === ENV_TYPE.JSON"
|
||||
:btnStyle="btnStyle"
|
||||
ref="envSelect"/>
|
||||
<env-group ref="envGroup" v-show="radio === ENV_TYPE.GROUP && !hasOptionGroup" @close="visible = false"
|
||||
:project-ids="projectIds"
|
||||
@setEnvGroup="setEnvGroup" :group-id="groupId" :btnStyle="btnStyle"></env-group>
|
||||
<env-select
|
||||
:project-ids="projectIds"
|
||||
:result="result"
|
||||
:show-config-button-with-out-permission="
|
||||
showConfigButtonWithOutPermission
|
||||
"
|
||||
:env-map="envMap"
|
||||
:project-list="projectList"
|
||||
@close="visible = false"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
v-show="!radio || radio === ENV_TYPE.JSON"
|
||||
:btnStyle="btnStyle"
|
||||
ref="envSelect"
|
||||
/>
|
||||
<env-group
|
||||
ref="envGroup"
|
||||
v-show="radio === ENV_TYPE.GROUP && !hasOptionGroup"
|
||||
@close="visible = false"
|
||||
:project-ids="projectIds"
|
||||
@setEnvGroup="setEnvGroup"
|
||||
:group-id="groupId"
|
||||
:btnStyle="btnStyle"
|
||||
></env-group>
|
||||
<!-- 对环境组选项进行分类 可用|不可用 -->
|
||||
<env-group-with-option ref="envOptionGroup" v-show="radio === ENV_TYPE.GROUP && hasOptionGroup"
|
||||
@close="visible = false"
|
||||
:project-ids="projectIds"
|
||||
@setEnvGroup="setEnvGroup" :group-id="groupId"></env-group-with-option>
|
||||
<el-button type="primary" slot="reference" size="mini" style="margin-top: 2px;">
|
||||
<env-group-with-option
|
||||
ref="envOptionGroup"
|
||||
v-show="radio === ENV_TYPE.GROUP && hasOptionGroup"
|
||||
@close="visible = false"
|
||||
:project-ids="projectIds"
|
||||
@setEnvGroup="setEnvGroup"
|
||||
:group-id="groupId"
|
||||
></env-group-with-option>
|
||||
<el-button
|
||||
type="primary"
|
||||
slot="reference"
|
||||
size="mini"
|
||||
style="margin-top: 2px"
|
||||
>
|
||||
{{ $t('api_test.definition.request.run_env') }}
|
||||
<i class="el-icon-caret-bottom el-icon--right"></i>
|
||||
</el-button>
|
||||
|
@ -36,18 +64,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import EnvSelect from "@/business/automation/scenario/EnvSelect";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import EnvGroup from "@/business/automation/scenario/EnvGroup";
|
||||
import EnvGroupWithOption from "@/business/automation/scenario/EnvGroupWithOption";
|
||||
import EnvSelect from '@/business/automation/scenario/EnvSelect';
|
||||
import { ENV_TYPE } from 'metersphere-frontend/src/utils/constants';
|
||||
import EnvGroup from '@/business/automation/scenario/EnvGroup';
|
||||
import EnvGroupWithOption from '@/business/automation/scenario/EnvGroupWithOption';
|
||||
|
||||
export default {
|
||||
name: "EnvPopover",
|
||||
components: {EnvGroup, EnvSelect, EnvGroupWithOption},
|
||||
name: 'EnvPopover',
|
||||
components: { EnvGroup, EnvSelect, EnvGroupWithOption },
|
||||
props: {
|
||||
width: {
|
||||
type: String,
|
||||
default: "400"
|
||||
default: '400',
|
||||
},
|
||||
envMap: Map,
|
||||
projectIds: Set,
|
||||
|
@ -56,78 +84,78 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
result: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {loading: false}
|
||||
}
|
||||
return { loading: false };
|
||||
},
|
||||
},
|
||||
groupId: {
|
||||
type: String,
|
||||
default() {
|
||||
return "";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
environmentType: String,
|
||||
isScenario: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
showEnvGroup: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
placement: {
|
||||
type: String,
|
||||
default() {
|
||||
return "bottom";
|
||||
}
|
||||
return 'bottom';
|
||||
},
|
||||
},
|
||||
hasOptionGroup: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
btnStyle: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {width: "360px"}
|
||||
}
|
||||
}
|
||||
return { width: '360px' };
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
radio: this.environmentType,
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
environmentType(val) {
|
||||
this.radio = val;
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
ENV_TYPE() {
|
||||
return ENV_TYPE;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showPopover() {
|
||||
if (this.isScenario) {
|
||||
this.$emit("showPopover");
|
||||
this.$emit('showPopover');
|
||||
} else {
|
||||
this.$refs.envSelect.open();
|
||||
}
|
||||
|
@ -143,16 +171,16 @@ export default {
|
|||
}
|
||||
},
|
||||
setProjectEnvMap(map) {
|
||||
this.$emit("setProjectEnvMap", map);
|
||||
this.$emit('setProjectEnvMap', map);
|
||||
},
|
||||
setEnvGroup(envGroupId) {
|
||||
this.$emit("setEnvGroup", envGroupId);
|
||||
this.$emit('setEnvGroup', envGroupId);
|
||||
},
|
||||
initEnv() {
|
||||
return this.$refs.envSelect.initEnv();
|
||||
},
|
||||
checkEnv(data) {
|
||||
return new Promise((resolve => {
|
||||
return new Promise((resolve) => {
|
||||
if (data) {
|
||||
// 所有请求全路径不检查环境
|
||||
resolve(true);
|
||||
|
@ -164,23 +192,21 @@ export default {
|
|||
let res = this.$refs.envSelect.checkEnv(data);
|
||||
resolve(res);
|
||||
} else if (this.environmentType === ENV_TYPE.GROUP) {
|
||||
let res = !this.hasOptionGroup ? this.$refs.envGroup.checkEnv() :
|
||||
this.$refs.envOptionGroup.checkEnv();
|
||||
res.then(r => {
|
||||
let res = !this.hasOptionGroup
|
||||
? this.$refs.envGroup.checkEnv()
|
||||
: this.$refs.envOptionGroup.checkEnv();
|
||||
res.then((r) => {
|
||||
resolve(r);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}))
|
||||
});
|
||||
},
|
||||
radioChange(val) {
|
||||
this.$emit("update:environmentType", val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.$emit('update:environmentType', val);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -1,19 +1,35 @@
|
|||
<template>
|
||||
<div v-loading="result.loading">
|
||||
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
|
||||
<el-select v-model="pe['selectEnv']" :placeholder="$t('workspace.env_group.please_select_env')"
|
||||
style="margin-top: 8px;width: 200px;" size="small">
|
||||
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"/>
|
||||
<el-button class="ms-scenario-button" v-if="isShowConfirmButton(pe.id)" size="mini" type="primary"
|
||||
@click="openEnvironmentConfig(pe.id, pe['selectEnv'])">
|
||||
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px">
|
||||
<el-select
|
||||
v-model="pe['selectEnv']"
|
||||
:placeholder="$t('workspace.env_group.please_select_env')"
|
||||
style="margin-top: 8px; width: 200px"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="(environment, index) in pe.envs"
|
||||
:key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"
|
||||
/>
|
||||
<el-button
|
||||
class="ms-scenario-button"
|
||||
v-if="isShowConfirmButton(pe.id)"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="openEnvironmentConfig(pe.id, pe['selectEnv'])"
|
||||
>
|
||||
{{ $t('api_test.environment.environment_config') }}
|
||||
</el-button>
|
||||
<template v-slot:empty>
|
||||
<div v-if="isShowConfirmButton(pe.id)" class="empty-environment">
|
||||
<el-button class="ms-scenario-button" size="mini" type="primary"
|
||||
@click="openEnvironmentConfig(pe.id, pe['selectEnv'])">
|
||||
<el-button
|
||||
class="ms-scenario-button"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="openEnvironmentConfig(pe.id, pe['selectEnv'])"
|
||||
>
|
||||
{{ $t('api_test.environment.environment_config') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -24,24 +40,33 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<el-button type="primary" @click="handleConfirm" size="small" :style="btnStyle" class="env-confirm">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleConfirm"
|
||||
size="small"
|
||||
:style="btnStyle"
|
||||
class="env-confirm"
|
||||
>
|
||||
{{ $t('workspace.env_group.confirm') }}
|
||||
</el-button>
|
||||
|
||||
<!-- 环境配置 -->
|
||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||
<api-environment-config
|
||||
ref="environmentConfig"
|
||||
@close="environmentConfigClose"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parseEnvironment} from "@/business/environment/model/EnvironmentModel";
|
||||
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
|
||||
import {getEnvironmentByProjectId} from "metersphere-frontend/src/api/environment";
|
||||
import {getOwnerProjectIds} from "@/api/project";
|
||||
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
|
||||
import ApiEnvironmentConfig from 'metersphere-frontend/src/components/environment/ApiEnvironmentConfig';
|
||||
import { getEnvironmentByProjectId } from 'metersphere-frontend/src/api/environment';
|
||||
import { getOwnerProjectIds } from '@/api/project';
|
||||
|
||||
export default {
|
||||
name: "EnvironmentSelect",
|
||||
components: {ApiEnvironmentConfig},
|
||||
name: 'EnvironmentSelect',
|
||||
components: { ApiEnvironmentConfig },
|
||||
props: {
|
||||
envMap: Map,
|
||||
projectIds: Set,
|
||||
|
@ -50,20 +75,20 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
result: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {loading: false}
|
||||
}
|
||||
return { loading: false };
|
||||
},
|
||||
},
|
||||
btnStyle: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {width: "360px"}
|
||||
}
|
||||
}
|
||||
return { width: '360px' };
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -73,7 +98,7 @@ export default {
|
|||
permissionProjectIds: [],
|
||||
dialogVisible: false,
|
||||
isFullUrl: true,
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
isShowConfirmButton(projectId) {
|
||||
|
@ -98,38 +123,39 @@ export default {
|
|||
}
|
||||
|
||||
let arr = [];
|
||||
this.projectIds.forEach(id => {
|
||||
const project = this.projectList.find(p => p.id === id);
|
||||
this.projectIds.forEach((id) => {
|
||||
const project = this.projectList.find((p) => p.id === id);
|
||||
if (project) {
|
||||
let item = {id: id, envs: [], selectEnv: ""};
|
||||
let item = { id: id, envs: [], selectEnv: '' };
|
||||
this.data.push(item);
|
||||
let p = new Promise(resolve => {
|
||||
getEnvironmentByProjectId(id).then(res => {
|
||||
let p = new Promise((resolve) => {
|
||||
getEnvironmentByProjectId(id).then((res) => {
|
||||
let envs = res.data;
|
||||
envs.forEach(environment => {
|
||||
envs.forEach((environment) => {
|
||||
parseEnvironment(environment);
|
||||
});
|
||||
// 固定环境列表渲染顺序
|
||||
let temp = this.data.find(dt => dt.id === id);
|
||||
let temp = this.data.find((dt) => dt.id === id);
|
||||
temp.envs = envs;
|
||||
let envId = undefined;
|
||||
if (this.envMap) {
|
||||
envId = this.envMap.get(id);
|
||||
}
|
||||
// 选中环境是否存在
|
||||
temp.selectEnv = envs.filter(e => e.id === envId).length === 0 ? null : envId;
|
||||
temp.selectEnv =
|
||||
envs.filter((e) => e.id === envId).length === 0 ? null : envId;
|
||||
resolve();
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
arr.push(p);
|
||||
}
|
||||
})
|
||||
});
|
||||
return arr;
|
||||
},
|
||||
getUserPermissionProjectIds() {
|
||||
getOwnerProjectIds().then(res => {
|
||||
getOwnerProjectIds().then((res) => {
|
||||
this.permissionProjectIds = res.data;
|
||||
})
|
||||
});
|
||||
},
|
||||
open() {
|
||||
this.data = [];
|
||||
|
@ -142,8 +168,8 @@ export default {
|
|||
return Promise.all(this.init());
|
||||
},
|
||||
getProjectName(id) {
|
||||
const project = this.projectList.find(p => p.id === id);
|
||||
return project ? project.name : "";
|
||||
const project = this.projectList.find((p) => p.id === id);
|
||||
return project ? project.name : '';
|
||||
},
|
||||
openEnvironmentConfig(projectId, envId) {
|
||||
if (!projectId) {
|
||||
|
@ -155,15 +181,17 @@ export default {
|
|||
handleConfirm() {
|
||||
let map = new Map();
|
||||
let sign = true;
|
||||
this.data.forEach(dt => {
|
||||
this.data.forEach((dt) => {
|
||||
if (!dt.selectEnv) {
|
||||
sign = false;
|
||||
return;
|
||||
}
|
||||
map.set(dt.id, dt.selectEnv);
|
||||
})
|
||||
});
|
||||
if (!sign) {
|
||||
this.$warning(this.$t('workspace.env_group.please_select_env_for_current_scenario'));
|
||||
this.$warning(
|
||||
this.$t('workspace.env_group.please_select_env_for_current_scenario')
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.$emit('setProjectEnvMap', map);
|
||||
|
@ -176,35 +204,37 @@ export default {
|
|||
return true;
|
||||
}
|
||||
if (this.data.length > 0) {
|
||||
this.data.forEach(dt => {
|
||||
this.data.forEach((dt) => {
|
||||
if (!dt.selectEnv) {
|
||||
sign = false;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// 如果有环境,检查环境
|
||||
if (this.envMap && this.envMap.size > 0) {
|
||||
this.projectIds.forEach(id => {
|
||||
this.projectIds.forEach((id) => {
|
||||
if (!this.envMap.get(id)) {
|
||||
sign = false;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!sign) {
|
||||
this.$warning(this.$t('workspace.env_group.please_select_env_for_current_scenario'));
|
||||
this.$warning(
|
||||
this.$t('workspace.env_group.please_select_env_for_current_scenario')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
environmentConfigClose() {
|
||||
// todo 关闭处理
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,24 +1,61 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-for="(pe, pIndex) in eventData" :key="pe.id">
|
||||
<el-card shadow="never" style="margin-top: 8px;background: #F5F6F7;border-radius: 4px;">
|
||||
<i @click="expandCard(pIndex)" v-if="pe.expendStatus==='close'" class="el-icon-caret-right" style="color: var(--primary_color)"/>
|
||||
<i @click="expandCard(pIndex)" v-else class="el-icon-caret-bottom" style="color: var(--primary_color)"/>
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="margin-top: 8px; background: #f5f6f7; border-radius: 4px"
|
||||
>
|
||||
<i
|
||||
@click="expandCard(pIndex)"
|
||||
v-if="pe.expendStatus === 'close'"
|
||||
class="el-icon-caret-right"
|
||||
style="color: var(--primary_color)"
|
||||
/>
|
||||
<i
|
||||
@click="expandCard(pIndex)"
|
||||
v-else
|
||||
class="el-icon-caret-bottom"
|
||||
style="color: var(--primary_color)"
|
||||
/>
|
||||
<span class="project-name" :title="getProjectName(pe.id)">
|
||||
{{ getProjectName(pe.id) }}
|
||||
</span><br/>
|
||||
<div v-if="pe.expendStatus==='open'">
|
||||
<el-radio-group v-model="pe.envRadio" style="width: 100%;" @change="envRadioChange(pe.envRadio,pIndex)" class="radio-change">
|
||||
<el-radio label="DEFAULT_ENV" style="margin-top: 7px">{{$t('api_test.environment.default_environment') }}</el-radio>
|
||||
<el-radio label="CUSTOMIZE_ENV" style="margin-top: 7px">{{$t('api_test.environment.choose_new_environment')}}</el-radio>
|
||||
{{ getProjectName(pe.id) }} </span
|
||||
><br />
|
||||
<div v-if="pe.expendStatus === 'open'">
|
||||
<el-radio-group
|
||||
v-model="pe.envRadio"
|
||||
style="width: 100%"
|
||||
@change="envRadioChange(pe.envRadio, pIndex)"
|
||||
class="radio-change"
|
||||
>
|
||||
<el-radio label="DEFAULT_ENV" style="margin-top: 7px">{{
|
||||
$t('api_test.environment.default_environment')
|
||||
}}</el-radio>
|
||||
<el-radio label="CUSTOMIZE_ENV" style="margin-top: 7px">{{
|
||||
$t('api_test.environment.choose_new_environment')
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tag v-show="!pe.showEnvSelect" v-for="(itemName,index) in selectedEnvName.get(pe.id)" :key="index" size="mini"
|
||||
style="margin-left: 0; margin-right: 2px;margin-top: 8px">{{ itemName }}</el-tag>
|
||||
<el-select v-show="pe.showEnvSelect" v-model="pe['selectEnv']" :placeholder="$t('api_test.environment.select_environment')"
|
||||
style="margin-top: 8px;width: 100%;" size="small" @change="chooseEnv">
|
||||
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"/>
|
||||
<el-tag
|
||||
v-show="!pe.showEnvSelect"
|
||||
v-for="(itemName, index) in selectedEnvName.get(pe.id)"
|
||||
:key="index"
|
||||
size="mini"
|
||||
style="margin-left: 0; margin-right: 2px; margin-top: 8px"
|
||||
>{{ itemName }}</el-tag
|
||||
>
|
||||
<el-select
|
||||
v-show="pe.showEnvSelect"
|
||||
v-model="pe['selectEnv']"
|
||||
:placeholder="$t('api_test.environment.select_environment')"
|
||||
style="margin-top: 8px; width: 100%"
|
||||
size="small"
|
||||
@change="chooseEnv"
|
||||
>
|
||||
<el-option
|
||||
v-for="(environment, index) in pe.envs"
|
||||
:key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-card>
|
||||
|
@ -26,155 +63,157 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {environmentGetALL} from "metersphere-frontend/src/api/environment";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import {parseEnvironment} from "metersphere-frontend/src/model/EnvironmentModel";
|
||||
import {getEnvironmentByProjectId} from "@/api/api-environment";
|
||||
import { ENV_TYPE } from 'metersphere-frontend/src/utils/constants';
|
||||
import { environmentGetALL } from 'metersphere-frontend/src/api/environment';
|
||||
import MsTag from 'metersphere-frontend/src/components/MsTag';
|
||||
import { parseEnvironment } from 'metersphere-frontend/src/model/EnvironmentModel';
|
||||
import { getEnvironmentByProjectId } from '@/api/api-environment';
|
||||
|
||||
export default {
|
||||
name: "EnvSelectPopover",
|
||||
components: {MsTag},
|
||||
data(){
|
||||
name: 'EnvSelectPopover',
|
||||
components: { MsTag },
|
||||
data() {
|
||||
return {
|
||||
radio:ENV_TYPE.JSON,
|
||||
radio: ENV_TYPE.JSON,
|
||||
visible: false,
|
||||
groups:[],
|
||||
selectedEnvName:new Map(),
|
||||
showEnvName:false,
|
||||
eventData:[],
|
||||
evnList:[],
|
||||
selectEnvMap:new Map(),
|
||||
}
|
||||
groups: [],
|
||||
selectedEnvName: new Map(),
|
||||
showEnvName: false,
|
||||
eventData: [],
|
||||
evnList: [],
|
||||
selectEnvMap: new Map(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
ENV_TYPE() {
|
||||
return ENV_TYPE;
|
||||
}
|
||||
},
|
||||
},
|
||||
props:{
|
||||
props: {
|
||||
projectIds: Set,
|
||||
projectList:Array,
|
||||
projectEnvMap:Object,
|
||||
caseIdEnvNameMap:Object,
|
||||
projectList: Array,
|
||||
projectEnvMap: Object,
|
||||
caseIdEnvNameMap: Object,
|
||||
envMap: Map,
|
||||
groupId: {
|
||||
type: String,
|
||||
default() {
|
||||
return "";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
isScenario: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open(){
|
||||
open() {
|
||||
this.initDefaultEnv();
|
||||
this.getgroups();
|
||||
},
|
||||
radioChange(val){
|
||||
radioChange(val) {
|
||||
this.radio = val;
|
||||
},
|
||||
getProjectName(id) {
|
||||
const project = this.projectList.find(p => p.id === id);
|
||||
return project ? project.name : "";
|
||||
const project = this.projectList.find((p) => p.id === id);
|
||||
return project ? project.name : '';
|
||||
},
|
||||
envRadioChange(val,index){
|
||||
this.eventData[index].envRadio = val
|
||||
this.eventData[index].showEnvSelect = this.eventData[index].envRadio === "CUSTOMIZE_ENV";
|
||||
envRadioChange(val, index) {
|
||||
this.eventData[index].envRadio = val;
|
||||
this.eventData[index].showEnvSelect =
|
||||
this.eventData[index].envRadio === 'CUSTOMIZE_ENV';
|
||||
},
|
||||
viewGroup() {
|
||||
this.visible = true;
|
||||
},
|
||||
getgroups(){
|
||||
environmentGetALL().then(res => {
|
||||
getgroups() {
|
||||
environmentGetALL().then((res) => {
|
||||
let data = res.data;
|
||||
this.groups = data ? data : [];
|
||||
})
|
||||
});
|
||||
},
|
||||
chooseEnv(val){
|
||||
let filter = this.evnList.filter(e => e.id === val);
|
||||
this.selectEnvMap.set(filter[0].projectId,val);
|
||||
chooseEnv(val) {
|
||||
let filter = this.evnList.filter((e) => e.id === val);
|
||||
this.selectEnvMap.set(filter[0].projectId, val);
|
||||
this.$emit('setProjectEnvMap', this.selectEnvMap);
|
||||
},
|
||||
initDefaultEnv(){
|
||||
initDefaultEnv() {
|
||||
this.selectedEnvName = new Map();
|
||||
this.evnList = [];
|
||||
this.projectIds.forEach(d => {
|
||||
let item = {id: d, envs: [], selectEnv: "",envRadio:"DEFAULT_ENV",showEnvSelect:false,expendStatus:"open"};
|
||||
this.projectIds.forEach((d) => {
|
||||
let item = {
|
||||
id: d,
|
||||
envs: [],
|
||||
selectEnv: '',
|
||||
envRadio: 'DEFAULT_ENV',
|
||||
showEnvSelect: false,
|
||||
expendStatus: 'open',
|
||||
};
|
||||
this.eventData.push(item);
|
||||
getEnvironmentByProjectId(d)
|
||||
.then(res => {
|
||||
let envs = res.data;
|
||||
envs.forEach(environment => {
|
||||
parseEnvironment(environment);
|
||||
});
|
||||
// 固定环境列表渲染顺序
|
||||
let temp = this.eventData.find(dt => dt.id === d);
|
||||
temp.envs = envs;
|
||||
envs.forEach(t=>{
|
||||
this.evnList.push(t);
|
||||
})
|
||||
if (this.envMap && this.envMap.size > 0) {
|
||||
let envId = this.envMap.get(id);
|
||||
// 选中环境是否存在
|
||||
temp.selectEnv = envs.filter(e => e.id === envId).length === 0 ? null : envId;
|
||||
}
|
||||
if (this.isScenario){
|
||||
if (this.projectEnvMap) {
|
||||
let projectEnvMapElement = this.projectEnvMap[d];
|
||||
if (projectEnvMapElement.length>0) {
|
||||
projectEnvMapElement.forEach(envId => {
|
||||
let filter = envs.filter(e => e.id === envId);
|
||||
if (!this.selectedEnvName.has(d)) {
|
||||
let name = [];
|
||||
name.push(filter[0].name)
|
||||
this.selectedEnvName.set(d,name);
|
||||
} else {
|
||||
this.selectedEnvName.get(d).push(filter[0].name);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.caseIdEnvNameMap) {
|
||||
let envName = new Set();
|
||||
for (let key in this.caseIdEnvNameMap) {
|
||||
envName.add(this.caseIdEnvNameMap[key])
|
||||
}
|
||||
this.selectedEnvName.set(d,envName);
|
||||
}
|
||||
}
|
||||
getEnvironmentByProjectId(d).then((res) => {
|
||||
let envs = res.data;
|
||||
envs.forEach((environment) => {
|
||||
parseEnvironment(environment);
|
||||
});
|
||||
})
|
||||
// 固定环境列表渲染顺序
|
||||
let temp = this.eventData.find((dt) => dt.id === d);
|
||||
temp.envs = envs;
|
||||
envs.forEach((t) => {
|
||||
this.evnList.push(t);
|
||||
});
|
||||
if (this.envMap && this.envMap.size > 0) {
|
||||
let envId = this.envMap.get(id);
|
||||
// 选中环境是否存在
|
||||
temp.selectEnv =
|
||||
envs.filter((e) => e.id === envId).length === 0 ? null : envId;
|
||||
}
|
||||
if (this.isScenario) {
|
||||
if (this.projectEnvMap) {
|
||||
let projectEnvMapElement = this.projectEnvMap[d];
|
||||
if (projectEnvMapElement.length > 0) {
|
||||
projectEnvMapElement.forEach((envId) => {
|
||||
let filter = envs.filter((e) => e.id === envId);
|
||||
if (!this.selectedEnvName.has(d)) {
|
||||
let name = [];
|
||||
name.push(filter[0].name);
|
||||
this.selectedEnvName.set(d, name);
|
||||
} else {
|
||||
this.selectedEnvName.get(d).push(filter[0].name);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.caseIdEnvNameMap) {
|
||||
let envName = new Set();
|
||||
for (let key in this.caseIdEnvNameMap) {
|
||||
envName.add(this.caseIdEnvNameMap[key]);
|
||||
}
|
||||
this.selectedEnvName.set(d, envName);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
expandCard(index){
|
||||
if (this.eventData[index].expendStatus === "open") {
|
||||
this.eventData[index].expendStatus = "close"
|
||||
}else {
|
||||
this.eventData[index].expendStatus = "open"
|
||||
expandCard(index) {
|
||||
if (this.eventData[index].expendStatus === 'open') {
|
||||
this.eventData[index].expendStatus = 'close';
|
||||
} else {
|
||||
this.eventData[index].expendStatus = 'open';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mode-span{
|
||||
.mode-span {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss" scoped>
|
||||
.radio-change:deep(.el-radio__input.is-checked + .el-radio__label) {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<template>
|
||||
<ms-container>
|
||||
<ms-aside-container>
|
||||
<ms-api-scenario-module @selectModule="selectModule" @getApiModuleTree="initTree"
|
||||
@refresh="refresh" @saveAsEdit="editScenario"/>
|
||||
<ms-api-scenario-module
|
||||
@selectModule="selectModule"
|
||||
@getApiModuleTree="initTree"
|
||||
@refresh="refresh"
|
||||
@saveAsEdit="editScenario"
|
||||
/>
|
||||
</ms-aside-container>
|
||||
<ms-main-container>
|
||||
<ms-api-scenario-list
|
||||
|
@ -11,36 +15,42 @@
|
|||
@selection="setData"
|
||||
:referenced="true"
|
||||
:select-project-id="cuurentProjectId"
|
||||
ref="apiScenarioList"/>
|
||||
ref="apiScenarioList"
|
||||
/>
|
||||
|
||||
<el-button style="float: right;margin: 10px" @click="importApiScenario" type="primary">
|
||||
<el-button
|
||||
style="float: right; margin: 10px"
|
||||
@click="importApiScenario"
|
||||
type="primary"
|
||||
>
|
||||
{{ $t('api_test.scenario.reference') }}
|
||||
</el-button>
|
||||
<el-button style="float: right;margin: 10px" @click="copyApiScenario">{{ $t('commons.copy') }}</el-button>
|
||||
<el-button style="float: right; margin: 10px" @click="copyApiScenario">{{
|
||||
$t('commons.copy')
|
||||
}}</el-button>
|
||||
</ms-main-container>
|
||||
</ms-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {getApiScenarios} from "@/api/scenario";
|
||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||
import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer";
|
||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||
import MsApiScenarioList from "@/business/automation/scenario/ApiScenarioList";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import MsApiScenarioModule from "@/business/automation/scenario/ApiScenarioModule";
|
||||
import MsEditApiScenario from "../scenario/EditApiScenario";
|
||||
import { getApiScenarios } from '@/api/scenario';
|
||||
import MsContainer from 'metersphere-frontend/src/components/MsContainer';
|
||||
import MsAsideContainer from 'metersphere-frontend/src/components/MsAsideContainer';
|
||||
import MsMainContainer from 'metersphere-frontend/src/components/MsMainContainer';
|
||||
import MsApiScenarioList from '@/business/automation/scenario/ApiScenarioList';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import MsApiScenarioModule from '@/business/automation/scenario/ApiScenarioModule';
|
||||
import MsEditApiScenario from '../scenario/EditApiScenario';
|
||||
|
||||
export default {
|
||||
name: "ImportApiScenario",
|
||||
name: 'ImportApiScenario',
|
||||
components: {
|
||||
MsApiScenarioModule,
|
||||
MsApiScenarioList,
|
||||
MsMainContainer,
|
||||
MsAsideContainer,
|
||||
MsContainer,
|
||||
MsEditApiScenario
|
||||
MsEditApiScenario,
|
||||
},
|
||||
comments: {},
|
||||
data() {
|
||||
|
@ -51,15 +61,15 @@ export default {
|
|||
currentScenario: [],
|
||||
currentScenarioIds: [],
|
||||
moduleOptions: {},
|
||||
cuurentProjectId: "",
|
||||
cuurentProjectId: '',
|
||||
scenarioDefinition: Object,
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
setData(data) {
|
||||
this.currentScenario = Array.from(data).map(row => row);
|
||||
this.currentScenarioIds = Array.from(data).map(row => row.id);
|
||||
this.currentScenario = Array.from(data).map((row) => row);
|
||||
this.currentScenarioIds = Array.from(data).map((row) => row.id);
|
||||
},
|
||||
selectModule(data) {
|
||||
this.currentModule = data;
|
||||
|
@ -67,32 +77,43 @@ export default {
|
|||
importApiScenario() {
|
||||
let scenarios = [];
|
||||
if (this.currentScenario) {
|
||||
this.currentScenario.forEach(item => {
|
||||
let obj = {id: item.id, name: item.name, type: "scenario", referenced: 'REF', resourceId: getUUID()};
|
||||
this.currentScenario.forEach((item) => {
|
||||
let obj = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: 'scenario',
|
||||
referenced: 'REF',
|
||||
resourceId: getUUID(),
|
||||
};
|
||||
scenarios.push(obj);
|
||||
})
|
||||
});
|
||||
}
|
||||
this.$emit('addScenario', scenarios);
|
||||
},
|
||||
getApiScenario() {
|
||||
let scenarios = [];
|
||||
this.result = getApiScenarios(this.currentScenarioIds).then(response => {
|
||||
if (response.data) {
|
||||
response.data.forEach(item => {
|
||||
let scenarioDefinition = JSON.parse(item.scenarioDefinition);
|
||||
let obj = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: "scenario",
|
||||
referenced: 'Copy',
|
||||
resourceId: getUUID(),
|
||||
hashTree: scenarioDefinition && scenarioDefinition.hashTree ? scenarioDefinition.hashTree : []
|
||||
};
|
||||
scenarios.push(obj);
|
||||
})
|
||||
this.$emit('addScenario', scenarios);
|
||||
this.result = getApiScenarios(this.currentScenarioIds).then(
|
||||
(response) => {
|
||||
if (response.data) {
|
||||
response.data.forEach((item) => {
|
||||
let scenarioDefinition = JSON.parse(item.scenarioDefinition);
|
||||
let obj = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: 'scenario',
|
||||
referenced: 'Copy',
|
||||
resourceId: getUUID(),
|
||||
hashTree:
|
||||
scenarioDefinition && scenarioDefinition.hashTree
|
||||
? scenarioDefinition.hashTree
|
||||
: [],
|
||||
};
|
||||
scenarios.push(obj);
|
||||
});
|
||||
this.$emit('addScenario', scenarios);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
copyApiScenario() {
|
||||
if (this.currentScenarioIds) {
|
||||
|
@ -108,13 +129,10 @@ export default {
|
|||
},
|
||||
editScenario(row) {
|
||||
this.currentScenario = row;
|
||||
this.addTab({name: 'add'});
|
||||
this.addTab({ name: 'add' });
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
class="el-input-tag input-tag-wrapper"
|
||||
:class="[size ? 'el-input-tag--' + size : '']"
|
||||
style="height: auto"
|
||||
@click="foucusTagInput">
|
||||
|
||||
@click="foucusTagInput"
|
||||
>
|
||||
<el-tag
|
||||
class="ms-top"
|
||||
v-for="(tag, idx) in innerTags"
|
||||
|
@ -14,17 +14,19 @@
|
|||
:size="size"
|
||||
:closable="!readOnly"
|
||||
:disable-transitions="false"
|
||||
@close="remove(idx)">
|
||||
{{ tag && tag.length > 10 ? tag.substring(0, 10) + "..." : tag }}
|
||||
@close="remove(idx)"
|
||||
>
|
||||
{{ tag && tag.length > 10 ? tag.substring(0, 10) + '...' : tag }}
|
||||
</el-tag>
|
||||
<input
|
||||
:disabled="readOnly"
|
||||
class="tag-input el-input"
|
||||
v-model="newTag"
|
||||
:placeholder=defaultPlaceHolder
|
||||
:placeholder="defaultPlaceHolder"
|
||||
@keydown.delete.stop="removeLastTag"
|
||||
@keydown="addNew"
|
||||
@blur="addNew"/>
|
||||
@blur="addNew"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -39,17 +41,17 @@ export default {
|
|||
errorInfo: String,
|
||||
addTagOnKeys: {
|
||||
type: Array,
|
||||
default: () => [13, 188, 9]
|
||||
default: () => [13, 188, 9],
|
||||
},
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
size: {type: String, default: "small"},
|
||||
size: { type: String, default: 'small' },
|
||||
prop: {
|
||||
type: String,
|
||||
default: "tags"
|
||||
}
|
||||
default: 'tags',
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (!this.currentScenario[this.prop]) {
|
||||
|
@ -63,8 +65,10 @@ export default {
|
|||
return {
|
||||
defaultPlaceHolder: this.$t('commons.tag_tip'),
|
||||
newTag: '',
|
||||
innerTags: this.currentScenario[this.prop] ? [...this.currentScenario[this.prop]] : []
|
||||
}
|
||||
innerTags: this.currentScenario[this.prop]
|
||||
? [...this.currentScenario[this.prop]]
|
||||
: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
innerTags() {
|
||||
|
@ -72,79 +76,82 @@ export default {
|
|||
},
|
||||
'currentScenario.tags'() {
|
||||
if (this.prop === 'tags') {
|
||||
if (!this.currentScenario[this.prop] || this.currentScenario[this.prop] === '' || this.currentScenario[this.prop].length === 0) {
|
||||
if (
|
||||
!this.currentScenario[this.prop] ||
|
||||
this.currentScenario[this.prop] === '' ||
|
||||
this.currentScenario[this.prop].length === 0
|
||||
) {
|
||||
if (this.innerTags.length !== 0) {
|
||||
this.innerTags = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
foucusTagInput() {
|
||||
if (!this.readOnly && this.$el.querySelector('.tag-input')) {
|
||||
this.$el.querySelector('.tag-input').focus()
|
||||
this.$el.querySelector('.tag-input').focus();
|
||||
}
|
||||
},
|
||||
addNew(e) {
|
||||
if (e && (!this.addTagOnKeys.includes(e.keyCode)) && (e.type !== 'blur')) {
|
||||
return
|
||||
if (e && !this.addTagOnKeys.includes(e.keyCode) && e.type !== 'blur') {
|
||||
return;
|
||||
}
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
let addSuucess = false
|
||||
let addSuucess = false;
|
||||
if (this.newTag.includes(',')) {
|
||||
this.newTag.split(',').forEach(item => {
|
||||
this.newTag.split(',').forEach((item) => {
|
||||
if (this.addTag(item.trim())) {
|
||||
addSuucess = true
|
||||
addSuucess = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
if (this.addTag(this.newTag.trim())) {
|
||||
addSuucess = true
|
||||
addSuucess = true;
|
||||
}
|
||||
}
|
||||
if (addSuucess) {
|
||||
this.tagChange()
|
||||
this.newTag = ''
|
||||
this.tagChange();
|
||||
this.newTag = '';
|
||||
}
|
||||
this.$emit("onblur");
|
||||
this.$emit('onblur');
|
||||
},
|
||||
addTag(tag) {
|
||||
tag = tag.trim()
|
||||
tag = tag.trim();
|
||||
if (tag && !this.innerTags.includes(tag)) {
|
||||
this.innerTags.push(tag)
|
||||
return true
|
||||
this.innerTags.push(tag);
|
||||
return true;
|
||||
} else {
|
||||
if (tag !== "" && this.errorInfo) {
|
||||
if (tag !== '' && this.errorInfo) {
|
||||
this.$error(this.errorInfo);
|
||||
}
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
},
|
||||
remove(index) {
|
||||
this.innerTags.splice(index, 1);
|
||||
this.tagChange();
|
||||
this.$nextTick(() => {
|
||||
//删除tag元素操作是在输入框中去掉元素,也应当触发onblur操作
|
||||
this.$emit("onblur");
|
||||
this.$emit('onblur');
|
||||
});
|
||||
},
|
||||
removeLastTag() {
|
||||
if (this.newTag) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.innerTags.pop()
|
||||
this.tagChange()
|
||||
this.innerTags.pop();
|
||||
this.tagChange();
|
||||
},
|
||||
tagChange() {
|
||||
this.$emit('input', this.innerTags)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$emit('input', this.innerTags);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -160,7 +167,7 @@ export default {
|
|||
display: inline-block;
|
||||
outline: none;
|
||||
padding: 0 10px 0 5px;
|
||||
transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
|
||||
transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -173,7 +180,8 @@ export default {
|
|||
border: 0;
|
||||
color: #303133;
|
||||
font-size: 12px;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
|
||||
Arial, sans-serif;
|
||||
outline: none;
|
||||
padding-left: 0;
|
||||
width: 100px;
|
||||
|
@ -198,5 +206,4 @@ export default {
|
|||
height: 36px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -6,31 +6,31 @@
|
|||
width="30%"
|
||||
>
|
||||
<el-radio-group v-model="deleteCurrentVersion">
|
||||
<el-radio :label="true">{{ $t('commons.delete_current_version') }}</el-radio>
|
||||
<el-radio :label="true">{{
|
||||
$t('commons.delete_current_version')
|
||||
}}</el-radio>
|
||||
<el-radio :label="false">{{ $t('commons.delete_all_version') }}</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer
|
||||
@cancel="close"
|
||||
@confirm="handleDelete">
|
||||
<ms-dialog-footer @cancel="close" @confirm="handleDelete">
|
||||
</ms-dialog-footer>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter';
|
||||
|
||||
export default {
|
||||
name: "ListItemDeleteConfirm",
|
||||
components: {MsDialogFooter},
|
||||
name: 'ListItemDeleteConfirm',
|
||||
components: { MsDialogFooter },
|
||||
data() {
|
||||
return {
|
||||
deleteApiVisible: false,
|
||||
title: null,
|
||||
deleteCurrentVersion: true,
|
||||
api: {}
|
||||
api: {},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -46,10 +46,8 @@ export default {
|
|||
handleDelete() {
|
||||
this.$emit('handleDelete', this.api, this.deleteCurrentVersion);
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -5,51 +5,62 @@
|
|||
<el-icon class="el-icon-more"></el-icon>
|
||||
</el-link>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="schedule" v-permission="['PROJECT_API_SCENARIO:READ+SCHEDULE']">
|
||||
<el-dropdown-item command="ref">{{
|
||||
$t('api_test.automation.view_ref')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
command="schedule"
|
||||
v-permission="['PROJECT_API_SCENARIO:READ+SCHEDULE']"
|
||||
>
|
||||
{{ $t('api_test.automation.schedule') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="create_performance" v-permission="['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE']"
|
||||
v-modules="['performance']">
|
||||
<el-dropdown-item
|
||||
command="create_performance"
|
||||
v-permission="['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE']"
|
||||
v-modules="['performance']"
|
||||
>
|
||||
{{ $t('api_test.create_performance_test') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="refreshTable" :request="request"/>
|
||||
|
||||
<ms-schedule-maintain
|
||||
ref="scheduleMaintain"
|
||||
@refreshTable="refreshTable"
|
||||
:request="request"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {genPerformanceTestJmx} from "@/api/scenario";
|
||||
import MsScheduleMaintain from "@/business/automation/schedule/ScheduleMaintain";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {hasPermission} from "metersphere-frontend/src/utils/permission";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import {usePerformanceStore} from "@/store";
|
||||
import { genPerformanceTestJmx } from '@/api/scenario';
|
||||
import MsScheduleMaintain from '@/business/automation/schedule/ScheduleMaintain';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { hasPermission } from 'metersphere-frontend/src/utils/permission';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { usePerformanceStore } from '@/store';
|
||||
|
||||
const performanceStore = usePerformanceStore();
|
||||
|
||||
export default {
|
||||
name: "MsScenarioExtendButtons",
|
||||
components: {MsScheduleMaintain},
|
||||
name: 'MsScenarioExtendButtons',
|
||||
components: { MsScheduleMaintain },
|
||||
props: {
|
||||
row: Object,
|
||||
request: {}
|
||||
request: {},
|
||||
},
|
||||
methods: {
|
||||
hasPermission,
|
||||
handleCommand(cmd) {
|
||||
switch (cmd) {
|
||||
case "ref":
|
||||
this.$emit("showCaseRef", this.row);
|
||||
case 'ref':
|
||||
this.$emit('showCaseRef', this.row);
|
||||
break;
|
||||
case "schedule":
|
||||
case 'schedule':
|
||||
this.$emit('openSchedule');
|
||||
this.$refs.scheduleMaintain.open(this.row);
|
||||
break;
|
||||
case "create_performance":
|
||||
case 'create_performance':
|
||||
this.createPerformance(this.row);
|
||||
break;
|
||||
}
|
||||
|
@ -67,7 +78,7 @@ export default {
|
|||
run.ids = scenarioIds;
|
||||
run.id = getUUID();
|
||||
run.name = row.name;
|
||||
genPerformanceTestJmx(run).then(response => {
|
||||
genPerformanceTestJmx(run).then((response) => {
|
||||
let jmxInfo = response.data.jmxInfoDTO;
|
||||
if (jmxInfo) {
|
||||
let projectEnvMap = response.data.projectEnvMap;
|
||||
|
@ -79,9 +90,9 @@ export default {
|
|||
jmxObj.scenarioId = row.id;
|
||||
jmxObj.version = row.version;
|
||||
jmxObj.projectEnvMap = projectEnvMap;
|
||||
performanceStore.$patch({'test': {name: row.name, jmx: jmxObj}});
|
||||
performanceStore.$patch({ test: { name: row.name, jmx: jmxObj } });
|
||||
this.$router.push({
|
||||
path: "/performance/test/create"
|
||||
path: '/performance/test/create',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -89,10 +100,8 @@ export default {
|
|||
openScenario(item) {
|
||||
this.$emit('openScenario', item);
|
||||
},
|
||||
refreshTable() {
|
||||
|
||||
},
|
||||
}
|
||||
refreshTable() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ import {
|
|||
PRIORITY,
|
||||
STEP_COUNT,
|
||||
TAGS,
|
||||
UPDATE_TIME
|
||||
} from "metersphere-frontend/src/components/search/search-components";
|
||||
UPDATE_TIME,
|
||||
} from 'metersphere-frontend/src/components/search/search-components';
|
||||
|
||||
export function STEP() {
|
||||
let map = new Map([
|
||||
|
@ -37,12 +37,65 @@ export function STEP() {
|
|||
['CustomizeReq', getDefaultSamplerMenu()],
|
||||
['MaxSamplerProxy', getDefaultSamplerMenu()],
|
||||
['GenericController', getAll()],
|
||||
['SpecialSteps', ['HTTPSamplerProxy', 'Assertions', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'Sampler', 'AbstractSampler', 'JSR223Processor', 'API', 'MsUiCommand']],
|
||||
['AllSamplerProxy', ['GenericController', 'HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'Sampler', 'AbstractSampler', 'JSR223Processor', 'API', 'MsUiCommand']],
|
||||
['DEFINITION', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler']],
|
||||
['ALlSamplerStep', ['JSR223PreProcessor', 'JSR223PostProcessor', 'JDBCPreProcessor', 'JDBCPostProcessor', 'Assertions', 'Extract', 'ConstantTimer']],
|
||||
['AllCanExecType', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'JSR223Processor', 'AbstractSampler']]]);
|
||||
return map
|
||||
[
|
||||
'SpecialSteps',
|
||||
[
|
||||
'HTTPSamplerProxy',
|
||||
'Assertions',
|
||||
'DubboSampler',
|
||||
'JDBCSampler',
|
||||
'TCPSampler',
|
||||
'Sampler',
|
||||
'AbstractSampler',
|
||||
'JSR223Processor',
|
||||
'API',
|
||||
'MsUiCommand',
|
||||
],
|
||||
],
|
||||
[
|
||||
'AllSamplerProxy',
|
||||
[
|
||||
'GenericController',
|
||||
'HTTPSamplerProxy',
|
||||
'DubboSampler',
|
||||
'JDBCSampler',
|
||||
'TCPSampler',
|
||||
'Sampler',
|
||||
'AbstractSampler',
|
||||
'JSR223Processor',
|
||||
'API',
|
||||
'MsUiCommand',
|
||||
],
|
||||
],
|
||||
[
|
||||
'DEFINITION',
|
||||
['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler'],
|
||||
],
|
||||
[
|
||||
'ALlSamplerStep',
|
||||
[
|
||||
'JSR223PreProcessor',
|
||||
'JSR223PostProcessor',
|
||||
'JDBCPreProcessor',
|
||||
'JDBCPostProcessor',
|
||||
'Assertions',
|
||||
'Extract',
|
||||
'ConstantTimer',
|
||||
],
|
||||
],
|
||||
[
|
||||
'AllCanExecType',
|
||||
[
|
||||
'HTTPSamplerProxy',
|
||||
'DubboSampler',
|
||||
'JDBCSampler',
|
||||
'TCPSampler',
|
||||
'JSR223Processor',
|
||||
'AbstractSampler',
|
||||
],
|
||||
],
|
||||
]);
|
||||
return map;
|
||||
}
|
||||
|
||||
export const ELEMENT_TYPE = {
|
||||
|
@ -61,48 +114,274 @@ export const ELEMENT_TYPE = {
|
|||
Extract: 'Extract',
|
||||
CustomizeReq: 'CustomizeReq',
|
||||
LoopController: 'LoopController',
|
||||
Plugin: 'Plugin'
|
||||
}
|
||||
Plugin: 'Plugin',
|
||||
};
|
||||
|
||||
export const TYPE_TO_C = new Map([
|
||||
['scenario', 'io.metersphere.api.dto.definition.request.MsScenario'],
|
||||
['UiScenario', 'io.metersphere.xpack.ui.hashtree.MsUiScenario'],
|
||||
['HTTPSamplerProxy', 'io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy'],
|
||||
['DubboSampler', 'io.metersphere.api.dto.definition.request.sampler.MsDubboSampler'],
|
||||
['JDBCSampler', 'io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler'],
|
||||
['TCPSampler', 'io.metersphere.api.dto.definition.request.sampler.MsTCPSampler'],
|
||||
['IfController', 'io.metersphere.api.dto.definition.request.controller.MsIfController'],
|
||||
['TransactionController', 'io.metersphere.api.dto.definition.request.controller.MsTransactionController'],
|
||||
['LoopController', 'io.metersphere.api.dto.definition.request.controller.MsLoopController'],
|
||||
['ConstantTimer', 'io.metersphere.api.dto.definition.request.timer.MsConstantTimer'],
|
||||
['JSR223Processor', 'io.metersphere.api.dto.definition.request.processors.MsJSR223Processor'],
|
||||
['JSR223PreProcessor', 'io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor'],
|
||||
['JSR223PostProcessor', 'io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor'],
|
||||
['JDBCPreProcessor', 'io.metersphere.api.dto.definition.request.processors.pre.MsJDBCPreProcessor'],
|
||||
['JDBCPostProcessor', 'io.metersphere.api.dto.definition.request.processors.post.MsJDBCPostProcessor'],
|
||||
['Assertions', 'io.metersphere.api.dto.definition.request.assertions.MsAssertions'],
|
||||
[
|
||||
'HTTPSamplerProxy',
|
||||
'io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy',
|
||||
],
|
||||
[
|
||||
'DubboSampler',
|
||||
'io.metersphere.api.dto.definition.request.sampler.MsDubboSampler',
|
||||
],
|
||||
[
|
||||
'JDBCSampler',
|
||||
'io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler',
|
||||
],
|
||||
[
|
||||
'TCPSampler',
|
||||
'io.metersphere.api.dto.definition.request.sampler.MsTCPSampler',
|
||||
],
|
||||
[
|
||||
'IfController',
|
||||
'io.metersphere.api.dto.definition.request.controller.MsIfController',
|
||||
],
|
||||
[
|
||||
'TransactionController',
|
||||
'io.metersphere.api.dto.definition.request.controller.MsTransactionController',
|
||||
],
|
||||
[
|
||||
'LoopController',
|
||||
'io.metersphere.api.dto.definition.request.controller.MsLoopController',
|
||||
],
|
||||
[
|
||||
'ConstantTimer',
|
||||
'io.metersphere.api.dto.definition.request.timer.MsConstantTimer',
|
||||
],
|
||||
[
|
||||
'JSR223Processor',
|
||||
'io.metersphere.api.dto.definition.request.processors.MsJSR223Processor',
|
||||
],
|
||||
[
|
||||
'JSR223PreProcessor',
|
||||
'io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor',
|
||||
],
|
||||
[
|
||||
'JSR223PostProcessor',
|
||||
'io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor',
|
||||
],
|
||||
[
|
||||
'JDBCPreProcessor',
|
||||
'io.metersphere.api.dto.definition.request.processors.pre.MsJDBCPreProcessor',
|
||||
],
|
||||
[
|
||||
'JDBCPostProcessor',
|
||||
'io.metersphere.api.dto.definition.request.processors.post.MsJDBCPostProcessor',
|
||||
],
|
||||
[
|
||||
'Assertions',
|
||||
'io.metersphere.api.dto.definition.request.assertions.MsAssertions',
|
||||
],
|
||||
['Extract', 'io.metersphere.api.dto.definition.request.extract.MsExtract'],
|
||||
['JmeterElement', 'io.metersphere.api.dto.definition.request.unknown.MsJmeterElement'],
|
||||
[
|
||||
'JmeterElement',
|
||||
'io.metersphere.api.dto.definition.request.unknown.MsJmeterElement',
|
||||
],
|
||||
['TestPlan', 'io.metersphere.api.dto.definition.request.MsTestPlan'],
|
||||
['ThreadGroup', 'io.metersphere.api.dto.definition.request.MsThreadGroup'],
|
||||
['DNSCacheManager', 'io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager'],
|
||||
['DebugSampler', 'io.metersphere.api.dto.definition.request.sampler.MsDebugSampler'],
|
||||
['AuthManager', 'io.metersphere.api.dto.definition.request.auth.MsAuthManager']
|
||||
])
|
||||
[
|
||||
'DNSCacheManager',
|
||||
'io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager',
|
||||
],
|
||||
[
|
||||
'DebugSampler',
|
||||
'io.metersphere.api.dto.definition.request.sampler.MsDebugSampler',
|
||||
],
|
||||
[
|
||||
'AuthManager',
|
||||
'io.metersphere.api.dto.definition.request.auth.MsAuthManager',
|
||||
],
|
||||
]);
|
||||
|
||||
export const PLUGIN_ELEMENTS = new Map([
|
||||
['menu_post_processors', ['HtmlExtractor', 'JMESPathExtractor', 'JSONPostProcessor', 'RegexExtractor', 'BoundaryExtractor', 'Separator', 'XPath2Extractor', 'XPathExtractor', 'ResultAction', 'DebugPostProcessor', 'BeanShellPostProcessor']],
|
||||
['menu_assertions', ['JSONPathAssertion', 'SizeAssertion', 'JSR223Assertion', 'XPath2Assertion', 'Separator', 'HTMLAssertion', 'JMESPathAssertion', 'MD5HexAssertion', 'SMIMEAssertion', 'XMLSchemaAssertion', 'XMLAssertion', 'XPathAssertion', 'DurationAssertion', 'CompareAssertion', 'BeanShellAssertion']],
|
||||
['menu_listener', ['AbstractVisualizer', 'AbstractListener', 'ViewResultsFullVisualizer', 'SummaryReport', 'StatVisualizer', 'BackendListener', 'Separator', 'JSR223Listener', 'ResultSaver', 'RespTimeGraphVisualizer', 'GraphVisualizer', 'AssertionVisualizer', 'ComparisonVisualizer', 'StatGraphVisualizer', 'Summariser', 'TableVisualizer', 'SimpleDataWriter', 'MailerVisualizer', 'BeanShellListener']],
|
||||
['menu_pre_processors', ['AbstractPostProcessor', 'UserParameters', 'Separator', 'AnchorModifier', 'URLRewritingModifier', 'SampleTimeout', 'RegExUserParameters', 'BeanShellPreProcessor']],
|
||||
['menu_logic_controller', ['GenericController', 'scenario', 'IfController', 'LoopController', 'IfControllerPanel', 'TransactionController', 'LoopControlPanel', 'WhileController', 'Separator', 'ForeachControlPanel', 'IncludeController', 'RunTime', 'CriticalSectionController', 'InterleaveControl', 'OnceOnlyController', 'RecordController', 'LogicController', 'RandomControl', 'RandomOrderController', 'ThroughputController', 'SwitchController', 'ModuleController']],
|
||||
[
|
||||
'menu_post_processors',
|
||||
[
|
||||
'HtmlExtractor',
|
||||
'JMESPathExtractor',
|
||||
'JSONPostProcessor',
|
||||
'RegexExtractor',
|
||||
'BoundaryExtractor',
|
||||
'Separator',
|
||||
'XPath2Extractor',
|
||||
'XPathExtractor',
|
||||
'ResultAction',
|
||||
'DebugPostProcessor',
|
||||
'BeanShellPostProcessor',
|
||||
],
|
||||
],
|
||||
[
|
||||
'menu_assertions',
|
||||
[
|
||||
'JSONPathAssertion',
|
||||
'SizeAssertion',
|
||||
'JSR223Assertion',
|
||||
'XPath2Assertion',
|
||||
'Separator',
|
||||
'HTMLAssertion',
|
||||
'JMESPathAssertion',
|
||||
'MD5HexAssertion',
|
||||
'SMIMEAssertion',
|
||||
'XMLSchemaAssertion',
|
||||
'XMLAssertion',
|
||||
'XPathAssertion',
|
||||
'DurationAssertion',
|
||||
'CompareAssertion',
|
||||
'BeanShellAssertion',
|
||||
],
|
||||
],
|
||||
[
|
||||
'menu_listener',
|
||||
[
|
||||
'AbstractVisualizer',
|
||||
'AbstractListener',
|
||||
'ViewResultsFullVisualizer',
|
||||
'SummaryReport',
|
||||
'StatVisualizer',
|
||||
'BackendListener',
|
||||
'Separator',
|
||||
'JSR223Listener',
|
||||
'ResultSaver',
|
||||
'RespTimeGraphVisualizer',
|
||||
'GraphVisualizer',
|
||||
'AssertionVisualizer',
|
||||
'ComparisonVisualizer',
|
||||
'StatGraphVisualizer',
|
||||
'Summariser',
|
||||
'TableVisualizer',
|
||||
'SimpleDataWriter',
|
||||
'MailerVisualizer',
|
||||
'BeanShellListener',
|
||||
],
|
||||
],
|
||||
[
|
||||
'menu_pre_processors',
|
||||
[
|
||||
'AbstractPostProcessor',
|
||||
'UserParameters',
|
||||
'Separator',
|
||||
'AnchorModifier',
|
||||
'URLRewritingModifier',
|
||||
'SampleTimeout',
|
||||
'RegExUserParameters',
|
||||
'BeanShellPreProcessor',
|
||||
],
|
||||
],
|
||||
[
|
||||
'menu_logic_controller',
|
||||
[
|
||||
'GenericController',
|
||||
'scenario',
|
||||
'IfController',
|
||||
'LoopController',
|
||||
'IfControllerPanel',
|
||||
'TransactionController',
|
||||
'LoopControlPanel',
|
||||
'WhileController',
|
||||
'Separator',
|
||||
'ForeachControlPanel',
|
||||
'IncludeController',
|
||||
'RunTime',
|
||||
'CriticalSectionController',
|
||||
'InterleaveControl',
|
||||
'OnceOnlyController',
|
||||
'RecordController',
|
||||
'LogicController',
|
||||
'RandomControl',
|
||||
'RandomOrderController',
|
||||
'ThroughputController',
|
||||
'SwitchController',
|
||||
'ModuleController',
|
||||
],
|
||||
],
|
||||
['menu_fragments', ['TestFragmentController']],
|
||||
['menu_non_test_elements', ['ProxyControl', 'HttpMirrorControl', 'GenerateTree', 'PropertyControl']],
|
||||
['menu_generative_controller', ['HTTPSamplerProxy', 'JSR223Processor', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'Sampler', 'AbstractSampler', 'CustomizeReq', 'HttpTestSample', 'TestAction', 'DebugSampler', 'JSR223Sampler', 'Separator', 'AjpSampler', 'AccessLogSampler', 'BeanShellSampler', 'BoltSampler', 'FtpTestSampler', 'GraphQLHTTPSampler', 'JDBCSampler', 'JMSPublisher', 'JMSSampler', 'JMSSubscriber', 'JUnitTestSampler', 'JavaTestSampler', 'LdapExtTestSampler', 'LdapTestSampler', 'SystemSampler', 'SmtpSampler', 'TCPSampler', 'MailReaderSampler']],
|
||||
[
|
||||
'menu_non_test_elements',
|
||||
['ProxyControl', 'HttpMirrorControl', 'GenerateTree', 'PropertyControl'],
|
||||
],
|
||||
[
|
||||
'menu_generative_controller',
|
||||
[
|
||||
'HTTPSamplerProxy',
|
||||
'JSR223Processor',
|
||||
'DubboSampler',
|
||||
'JDBCSampler',
|
||||
'TCPSampler',
|
||||
'Sampler',
|
||||
'AbstractSampler',
|
||||
'CustomizeReq',
|
||||
'HttpTestSample',
|
||||
'TestAction',
|
||||
'DebugSampler',
|
||||
'JSR223Sampler',
|
||||
'Separator',
|
||||
'AjpSampler',
|
||||
'AccessLogSampler',
|
||||
'BeanShellSampler',
|
||||
'BoltSampler',
|
||||
'FtpTestSampler',
|
||||
'GraphQLHTTPSampler',
|
||||
'JDBCSampler',
|
||||
'JMSPublisher',
|
||||
'JMSSampler',
|
||||
'JMSSubscriber',
|
||||
'JUnitTestSampler',
|
||||
'JavaTestSampler',
|
||||
'LdapExtTestSampler',
|
||||
'LdapTestSampler',
|
||||
'SystemSampler',
|
||||
'SmtpSampler',
|
||||
'TCPSampler',
|
||||
'MailReaderSampler',
|
||||
],
|
||||
],
|
||||
['menu_threads', ['SetupThreadGroup', 'PostThreadGroup', 'ThreadGroup']],
|
||||
['menu_timer', ['ConstantTimer', 'UniformRandomTimer', 'PreciseThroughputTimer', 'ConstantThroughputTimer', 'Separator', 'JSR223Timer', 'SyncTimer', 'PoissonRandomTimer', 'GaussianRandomTimer', 'BeanShellTimer']],
|
||||
['menu_config_element', ['CSVDataSet', 'HeaderPanel', 'CookiePanel', 'CacheManager', 'HttpDefaults', 'Separator', 'BoltConnectionElement', 'DNSCachePanel', 'FtpConfig', 'AuthPanel', 'DataSourceElement', 'JavaConfig', 'LdapExtConfig', 'LdapConfig', 'TCPConfig', 'KeystoreConfig', 'ArgumentsPanel', 'LoginConfig', 'SimpleConfig', 'CounterConfig', 'RandomVariableConfig']],
|
||||
])
|
||||
[
|
||||
'menu_timer',
|
||||
[
|
||||
'ConstantTimer',
|
||||
'UniformRandomTimer',
|
||||
'PreciseThroughputTimer',
|
||||
'ConstantThroughputTimer',
|
||||
'Separator',
|
||||
'JSR223Timer',
|
||||
'SyncTimer',
|
||||
'PoissonRandomTimer',
|
||||
'GaussianRandomTimer',
|
||||
'BeanShellTimer',
|
||||
],
|
||||
],
|
||||
[
|
||||
'menu_config_element',
|
||||
[
|
||||
'CSVDataSet',
|
||||
'HeaderPanel',
|
||||
'CookiePanel',
|
||||
'CacheManager',
|
||||
'HttpDefaults',
|
||||
'Separator',
|
||||
'BoltConnectionElement',
|
||||
'DNSCachePanel',
|
||||
'FtpConfig',
|
||||
'AuthPanel',
|
||||
'DataSourceElement',
|
||||
'JavaConfig',
|
||||
'LdapExtConfig',
|
||||
'LdapConfig',
|
||||
'TCPConfig',
|
||||
'KeystoreConfig',
|
||||
'ArgumentsPanel',
|
||||
'LoginConfig',
|
||||
'SimpleConfig',
|
||||
'CounterConfig',
|
||||
'RandomVariableConfig',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
export function getDefaultSamplerMenu() {
|
||||
let array = [];
|
||||
|
@ -118,7 +397,12 @@ export function init() {
|
|||
let allArray = [];
|
||||
allArray = allArray.concat(PLUGIN_ELEMENTS.get('menu_generative_controller'));
|
||||
allArray = allArray.concat(PLUGIN_ELEMENTS.get('menu_logic_controller'));
|
||||
allArray = allArray.concat(['scenario', 'ConstantTimer', 'JSR223Processor', 'Assertions']);
|
||||
allArray = allArray.concat([
|
||||
'scenario',
|
||||
'ConstantTimer',
|
||||
'JSR223Processor',
|
||||
'Assertions',
|
||||
]);
|
||||
return allArray;
|
||||
}
|
||||
|
||||
|
@ -135,42 +419,55 @@ export function getAll() {
|
|||
|
||||
function _getModuleTree(options) {
|
||||
return {
|
||||
key: "moduleIds",
|
||||
key: 'moduleIds',
|
||||
name: 'MsTableSearchNodeTree',
|
||||
label: "test_track.case.module",
|
||||
label: 'test_track.case.module',
|
||||
operator: {
|
||||
value: OPERATORS.IN.value,
|
||||
options: [OPERATORS.IN, OPERATORS.NOT_IN]
|
||||
options: [OPERATORS.IN, OPERATORS.NOT_IN],
|
||||
},
|
||||
options: options,
|
||||
init: undefined // 高级搜索框非首次打开时会执行该函数,在组件首次created时给其赋值
|
||||
}
|
||||
init: undefined, // 高级搜索框非首次打开时会执行该函数,在组件首次created时给其赋值
|
||||
};
|
||||
}
|
||||
|
||||
export const SCENARIO_MODULE_TREE = _getModuleTree({
|
||||
url: "/api/automation/module/list",
|
||||
type: "GET",
|
||||
params: {}
|
||||
})
|
||||
url: '/api/automation/module/list',
|
||||
type: 'GET',
|
||||
params: {},
|
||||
});
|
||||
|
||||
export const SCENARIO_MODULE_TRASH_TREE = _getModuleTree({
|
||||
url: "/api/automation/module/trash/list",
|
||||
type: "GET",
|
||||
params: {}
|
||||
})
|
||||
url: '/api/automation/module/trash/list',
|
||||
type: 'GET',
|
||||
params: {},
|
||||
});
|
||||
|
||||
export const API_STATUS_TRASH = {
|
||||
key: "status",
|
||||
key: 'status',
|
||||
name: 'MsTableSearchSelect',
|
||||
label: 'commons.status',
|
||||
operator: {
|
||||
options: [OPERATORS.IN, OPERATORS.NOT_IN]
|
||||
options: [OPERATORS.IN, OPERATORS.NOT_IN],
|
||||
},
|
||||
options: [{value: 'Trash', label: 'test_track.plan.plan_status_trash'}],
|
||||
props: { // 尾部控件的props,一般为element ui控件的props
|
||||
multiple: true
|
||||
}
|
||||
}
|
||||
|
||||
export const API_SCENARIO_CONFIGS_TRASH = [ID, NAME, PRIORITY, TAGS, API_SCENARIO_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, FOLLOW_PEOPLE, STEP_COUNT, SCENARIO_MODULE_TRASH_TREE, API_STATUS_TRASH];
|
||||
options: [{ value: 'Trash', label: 'test_track.plan.plan_status_trash' }],
|
||||
props: {
|
||||
// 尾部控件的props,一般为element ui控件的props
|
||||
multiple: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const API_SCENARIO_CONFIGS_TRASH = [
|
||||
ID,
|
||||
NAME,
|
||||
PRIORITY,
|
||||
TAGS,
|
||||
API_SCENARIO_RESULT,
|
||||
UPDATE_TIME,
|
||||
CREATE_TIME,
|
||||
CREATOR,
|
||||
FOLLOW_PEOPLE,
|
||||
STEP_COUNT,
|
||||
SCENARIO_MODULE_TRASH_TREE,
|
||||
API_STATUS_TRASH,
|
||||
];
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
<div v-if="isShow" style="float: right">
|
||||
<el-dropdown placement="bottom" trigger="click" size="medium">
|
||||
<div @click.stop class="show-more-btn">
|
||||
<i class="el-icon-more ms-icon-more"/>
|
||||
<i class="el-icon-more ms-icon-more" />
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown" class="dropdown-menu-class">
|
||||
<el-dropdown-item v-for="(btn,index) in buttons" :key="index" @click.native.stop="click(btn)">
|
||||
{{btn.name}}
|
||||
<el-dropdown-item
|
||||
v-for="(btn, index) in buttons"
|
||||
:key="index"
|
||||
@click.native.stop="click(btn)"
|
||||
>
|
||||
{{ btn.name }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
@ -14,47 +18,47 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ShowMoreBtn",
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
buttons: Array,
|
||||
row: Object,
|
||||
size: Number
|
||||
export default {
|
||||
name: 'ShowMoreBtn',
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
methods: {
|
||||
click(btn) {
|
||||
if (btn.handleClick instanceof Function) {
|
||||
btn.handleClick(this.row);
|
||||
}
|
||||
buttons: Array,
|
||||
row: Object,
|
||||
size: Number,
|
||||
},
|
||||
methods: {
|
||||
click(btn) {
|
||||
if (btn.handleClick instanceof Function) {
|
||||
btn.handleClick(this.row);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ms-icon-more {
|
||||
margin-top: 15px;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.ms-icon-more {
|
||||
margin-top: 15px;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.show-more-btn {
|
||||
width: 20px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
}
|
||||
.show-more-btn {
|
||||
width: 20px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.show-more-btn-title {
|
||||
color: #696969;
|
||||
background-color: #e2e2e2;
|
||||
padding: 5px;
|
||||
}
|
||||
.show-more-btn-title {
|
||||
color: #696969;
|
||||
background-color: #e2e2e2;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.dropdown-menu-class {
|
||||
padding: 1px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.dropdown-menu-class {
|
||||
padding: 1px 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,34 +1,50 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.definition.request.save_as_case')"
|
||||
:visible.sync="httpVisible"
|
||||
width="30%"
|
||||
:destroy-on-close="true" append-to-body>
|
||||
<el-form :model="httpForm" label-position="right" label-width="80px" size="small" :rules="rule" ref="httpForm"
|
||||
v-if="!loading">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('api_test.definition.request.save_as_case')"
|
||||
:visible.sync="httpVisible"
|
||||
width="30%"
|
||||
:destroy-on-close="true"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
:model="httpForm"
|
||||
label-position="right"
|
||||
label-width="80px"
|
||||
size="small"
|
||||
:rules="rule"
|
||||
ref="httpForm"
|
||||
v-if="!loading"
|
||||
>
|
||||
<el-form-item :label="$t('api_definition.case_name')" prop="name">
|
||||
<el-input v-model="httpForm.name" autocomplete="off" :placeholder="$t('api_definition.case_name')"
|
||||
show-word-limit maxlength="100"/>
|
||||
<el-input
|
||||
v-model="httpForm.name"
|
||||
autocomplete="off"
|
||||
:placeholder="$t('api_definition.case_name')"
|
||||
show-word-limit
|
||||
maxlength="100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer
|
||||
@cancel="httpVisible = false"
|
||||
@confirm="saveApi" v-prevent-re-click>
|
||||
@confirm="saveApi"
|
||||
v-prevent-re-click
|
||||
>
|
||||
</ms-dialog-footer>
|
||||
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApiCase} from "@/api/api-test-case";
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import { createApiCase } from '@/api/api-test-case';
|
||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
|
||||
export default {
|
||||
name: "MsAddApiCase",
|
||||
components: {MsDialogFooter},
|
||||
name: 'MsAddApiCase',
|
||||
components: { MsDialogFooter },
|
||||
data() {
|
||||
return {
|
||||
httpVisible: false,
|
||||
|
@ -36,13 +52,20 @@ export default {
|
|||
httpForm: {},
|
||||
rule: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
|
||||
{max: 100, message: this.$t('test_track.length_less_than') + '100', trigger: 'blur'}
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('test_track.case.input_name'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
max: 100,
|
||||
message: this.$t('test_track.length_less_than') + '100',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
saveApi() {
|
||||
this.$refs.httpForm.validate(async (valid) => {
|
||||
|
@ -58,7 +81,7 @@ export default {
|
|||
priority: 'P0',
|
||||
active: true,
|
||||
uuid: getUUID(),
|
||||
request: api
|
||||
request: api,
|
||||
};
|
||||
obj.projectId = api.projectId;
|
||||
obj.id = obj.uuid;
|
||||
|
@ -75,9 +98,9 @@ export default {
|
|||
let request = data.request;
|
||||
if (request.body) {
|
||||
if (request.body.kvs) {
|
||||
request.body.kvs.forEach(param => {
|
||||
request.body.kvs.forEach((param) => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
param.files.forEach((item) => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
|
@ -90,9 +113,9 @@ export default {
|
|||
});
|
||||
}
|
||||
if (request.body.binary) {
|
||||
request.body.binary.forEach(param => {
|
||||
request.body.binary.forEach((param) => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
param.files.forEach((item) => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
|
@ -108,10 +131,10 @@ export default {
|
|||
return bodyUploadFiles;
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
open(api) {
|
||||
if (api) {
|
||||
|
@ -119,14 +142,12 @@ export default {
|
|||
this.httpVisible = true;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.create-tip {
|
||||
color: #8c939d;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,46 +1,102 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.definition.request.title')" :visible.sync="httpVisible"
|
||||
width="45%"
|
||||
:destroy-on-close="true" append-to-body>
|
||||
<el-form :model="httpForm" label-position="right" label-width="80px" size="small" :rules="rule" ref="httpForm"
|
||||
v-if="!loading">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('api_test.definition.request.title')"
|
||||
:visible.sync="httpVisible"
|
||||
width="45%"
|
||||
:destroy-on-close="true"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
:model="httpForm"
|
||||
label-position="right"
|
||||
label-width="80px"
|
||||
size="small"
|
||||
:rules="rule"
|
||||
ref="httpForm"
|
||||
v-if="!loading"
|
||||
>
|
||||
<el-form-item :label="$t('commons.name')" prop="name">
|
||||
<el-input v-model="httpForm.name" autocomplete="off" :placeholder="$t('commons.name')"/>
|
||||
<el-input
|
||||
v-model="httpForm.name"
|
||||
autocomplete="off"
|
||||
:placeholder="$t('commons.name')"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!--HTTP 协议特有参数-->
|
||||
<el-form-item :label="$t('api_report.request')" prop="path" v-if="currentProtocol==='HTTP'">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="httpForm.path"
|
||||
class="ms-http-input" size="small">
|
||||
<el-select v-model="httpForm.method" slot="prepend" style="width: 100px" size="small">
|
||||
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
<el-form-item
|
||||
:label="$t('api_report.request')"
|
||||
prop="path"
|
||||
v-if="currentProtocol === 'HTTP'"
|
||||
>
|
||||
<el-input
|
||||
:placeholder="$t('api_test.definition.request.path_info')"
|
||||
v-model="httpForm.path"
|
||||
class="ms-http-input"
|
||||
size="small"
|
||||
>
|
||||
<el-select
|
||||
v-model="httpForm.method"
|
||||
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>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="userId">
|
||||
<el-select v-model="httpForm.userId"
|
||||
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
|
||||
style="width: 100%">
|
||||
<el-form-item
|
||||
:label="$t('api_test.definition.request.responsible')"
|
||||
prop="userId"
|
||||
>
|
||||
<el-select
|
||||
v-model="httpForm.userId"
|
||||
:placeholder="$t('api_test.definition.request.responsible')"
|
||||
filterable
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in maintainerOptions"
|
||||
:key="item.id"
|
||||
:label="item.id + ' (' + item.name + ')'"
|
||||
:value="item.id">
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('test_track.module.module')" prop="moduleId">
|
||||
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="httpForm.moduleId" @getValue="setModule"
|
||||
:obj="moduleObj" clearable checkStrictly/>
|
||||
<ms-select-tree
|
||||
size="small"
|
||||
:data="moduleOptions"
|
||||
:defaultKey="httpForm.moduleId"
|
||||
@getValue="setModule"
|
||||
:obj="moduleObj"
|
||||
clearable
|
||||
checkStrictly
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('commons.description')" prop="description" style="margin-bottom: 29px">
|
||||
<el-input class="ms-http-textarea" v-model="httpForm.description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 10}"
|
||||
:rows="2" size="small"/>
|
||||
<el-form-item
|
||||
:label="$t('commons.description')"
|
||||
prop="description"
|
||||
style="margin-bottom: 29px"
|
||||
>
|
||||
<el-input
|
||||
class="ms-http-textarea"
|
||||
v-model="httpForm.description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 10 }"
|
||||
:rows="2"
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="create-tip">
|
||||
{{ $t('api_test.definition.create_tip') }}
|
||||
|
@ -50,46 +106,51 @@
|
|||
<template v-slot:footer>
|
||||
<ms-dialog-footer
|
||||
@cancel="httpVisible = false"
|
||||
@confirm="saveApi" v-prevent-re-click>
|
||||
@confirm="saveApi"
|
||||
v-prevent-re-click
|
||||
>
|
||||
</ms-dialog-footer>
|
||||
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApiCase} from "@/api/api-test-case";
|
||||
import {createDefinition} from "@/api/definition";
|
||||
import {getApiModules} from "@/api/definition-module";
|
||||
import {getMaintainer} from "@/api/project";
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {REQ_METHOD} from "@/business/definition/model/JsonData";
|
||||
import {getCurrentProjectID, getCurrentUser} from "metersphere-frontend/src/utils/token";
|
||||
import {createComponent, Request} from "@/business/definition/components/jmeter/components";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import MsSelectTree from "metersphere-frontend/src/components/select-tree/SelectTree";
|
||||
import {buildTree} from "metersphere-frontend/src/model/NodeTree";
|
||||
|
||||
import { createApiCase } from '@/api/api-test-case';
|
||||
import { createDefinition } from '@/api/definition';
|
||||
import { getApiModules } from '@/api/definition-module';
|
||||
import { getMaintainer } from '@/api/project';
|
||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter';
|
||||
import { REQ_METHOD } from '@/business/definition/model/JsonData';
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentUser,
|
||||
} from 'metersphere-frontend/src/utils/token';
|
||||
import {
|
||||
createComponent,
|
||||
Request,
|
||||
} from '@/business/definition/components/jmeter/components';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import MsSelectTree from 'metersphere-frontend/src/components/select-tree/SelectTree';
|
||||
import { buildTree } from 'metersphere-frontend/src/model/NodeTree';
|
||||
|
||||
export default {
|
||||
name: "MsAddBasisApi",
|
||||
components: {MsDialogFooter, MsSelectTree},
|
||||
name: 'MsAddBasisApi',
|
||||
components: { MsDialogFooter, MsSelectTree },
|
||||
props: {
|
||||
currentProtocol: {
|
||||
type: String,
|
||||
default: "HTTP"
|
||||
default: 'HTTP',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
let validateURL = (rule, value, callback) => {
|
||||
if (!this.httpForm.path.startsWith("/")) {
|
||||
if (!this.httpForm.path.startsWith('/')) {
|
||||
callback(this.$t('api_test.definition.request.path_valid_info'));
|
||||
}
|
||||
callback();
|
||||
};
|
||||
return {
|
||||
httpForm: {environmentId: "", moduleId: "default-module"},
|
||||
httpForm: { environmentId: '', moduleId: 'default-module' },
|
||||
moduleOptions: [],
|
||||
httpVisible: false,
|
||||
currentModule: {},
|
||||
|
@ -101,22 +162,38 @@ export default {
|
|||
},
|
||||
rule: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
|
||||
{max: 100, message: this.$t('test_track.length_less_than') + '100', trigger: 'blur'}
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('test_track.case.input_name'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
max: 100,
|
||||
message: this.$t('test_track.length_less_than') + '100',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
path: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('api_test.definition.request.path_info'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{ validator: validateURL, trigger: 'blur' },
|
||||
],
|
||||
userId: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('test_track.case.input_maintainer'),
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
path: [{
|
||||
required: true,
|
||||
message: this.$t('api_test.definition.request.path_info'),
|
||||
trigger: 'blur'
|
||||
}, {validator: validateURL, trigger: 'blur'}],
|
||||
userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
||||
// moduleId: [{required: true, message: this.$t('test_track.module.module'), trigger: 'change'}],
|
||||
},
|
||||
value: REQ_METHOD[0].id,
|
||||
options: REQ_METHOD,
|
||||
}
|
||||
}
|
||||
,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
saveApi() {
|
||||
this.$refs['httpForm'].validate((valid) => {
|
||||
|
@ -125,7 +202,7 @@ export default {
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
save(data) {
|
||||
this.setParameters(data);
|
||||
|
@ -141,7 +218,7 @@ export default {
|
|||
priority: 'P0',
|
||||
active: true,
|
||||
uuid: getUUID(),
|
||||
request: api.request
|
||||
request: api.request,
|
||||
};
|
||||
obj.projectId = getCurrentProjectID();
|
||||
obj.id = obj.uuid;
|
||||
|
@ -155,8 +232,8 @@ export default {
|
|||
setParameters(data) {
|
||||
data.projectId = getCurrentProjectID();
|
||||
data.request.name = data.name;
|
||||
if (data.protocol === "DUBBO" || data.protocol === "dubbo://") {
|
||||
data.request.protocol = "dubbo://";
|
||||
if (data.protocol === 'DUBBO' || data.protocol === 'dubbo://') {
|
||||
data.request.protocol = 'dubbo://';
|
||||
}
|
||||
data.id = data.request.id;
|
||||
if (!data.method) {
|
||||
|
@ -164,13 +241,21 @@ export default {
|
|||
}
|
||||
data.request.path = this.httpForm.path;
|
||||
if (data.request.hashTree && data.request.hashTree.length > 0) {
|
||||
let arrays = ["Extract", "JSR223PreProcessor", "JDBCPreProcessor", "ConstantTimer", "JSR223PostProcessor", "JDBCPostProcessor", "Assertions"];
|
||||
let arrays = [
|
||||
'Extract',
|
||||
'JSR223PreProcessor',
|
||||
'JDBCPreProcessor',
|
||||
'ConstantTimer',
|
||||
'JSR223PostProcessor',
|
||||
'JDBCPostProcessor',
|
||||
'Assertions',
|
||||
];
|
||||
let hashTree = [];
|
||||
data.request.hashTree.forEach(item => {
|
||||
data.request.hashTree.forEach((item) => {
|
||||
if (arrays.indexOf(item.type) !== -1) {
|
||||
hashTree.push(item);
|
||||
}
|
||||
})
|
||||
});
|
||||
data.request.hashTree = hashTree;
|
||||
}
|
||||
},
|
||||
|
@ -180,9 +265,9 @@ export default {
|
|||
let request = data.request;
|
||||
if (request.body) {
|
||||
if (request.body.kvs) {
|
||||
request.body.kvs.forEach(param => {
|
||||
request.body.kvs.forEach((param) => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
param.files.forEach((item) => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
|
@ -195,9 +280,9 @@ export default {
|
|||
});
|
||||
}
|
||||
if (request.body.binary) {
|
||||
request.body.binary.forEach(param => {
|
||||
request.body.binary.forEach((param) => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
param.files.forEach((item) => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
|
@ -239,61 +324,65 @@ export default {
|
|||
this.httpForm.request.path = this.httpForm.path;
|
||||
}
|
||||
if (this.currentModule != null) {
|
||||
this.httpForm.modulePath = this.currentModule.method != undefined ? this.currentModule.method : null;
|
||||
this.httpForm.modulePath =
|
||||
this.currentModule.method != undefined
|
||||
? this.currentModule.method
|
||||
: null;
|
||||
this.httpForm.moduleId = this.currentModule.id;
|
||||
}
|
||||
|
||||
},
|
||||
initHTTP() {
|
||||
let request = createComponent("HTTPSamplerProxy");
|
||||
let request = createComponent('HTTPSamplerProxy');
|
||||
request.path = this.httpForm.path;
|
||||
this.httpForm.request = request;
|
||||
},
|
||||
initSQL() {
|
||||
this.httpForm.method = Request.TYPES.SQL;
|
||||
this.httpForm.request = createComponent("JDBCSampler");
|
||||
this.httpForm.request = createComponent('JDBCSampler');
|
||||
},
|
||||
initTCP() {
|
||||
this.httpForm.method = Request.TYPES.TCP;
|
||||
this.httpForm.request = createComponent("TCPSampler");
|
||||
this.httpForm.request = createComponent('TCPSampler');
|
||||
},
|
||||
initDUBBO() {
|
||||
this.httpForm.method = "dubbo://";
|
||||
this.httpForm.request = createComponent("DubboSampler");
|
||||
this.httpForm.method = 'dubbo://';
|
||||
this.httpForm.request = createComponent('DubboSampler');
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
getMaintainer().then(response => {
|
||||
getMaintainer().then((response) => {
|
||||
this.maintainerOptions = response.data;
|
||||
});
|
||||
},
|
||||
list(data) {
|
||||
if (data.protocol === "dubbo://") {
|
||||
data.protocol = "DUBBO";
|
||||
if (data.protocol === 'dubbo://') {
|
||||
data.protocol = 'DUBBO';
|
||||
}
|
||||
this.result = getApiModules(getCurrentProjectID(), data.protocol).then(response => {
|
||||
if (response.data != undefined && response.data != null) {
|
||||
this.moduleOptions = response.data;
|
||||
this.moduleOptions.forEach(node => {
|
||||
buildTree(node, {path: ''});
|
||||
});
|
||||
this.result = getApiModules(getCurrentProjectID(), data.protocol).then(
|
||||
(response) => {
|
||||
if (response.data != undefined && response.data != null) {
|
||||
this.moduleOptions = response.data;
|
||||
this.moduleOptions.forEach((node) => {
|
||||
buildTree(node, { path: '' });
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
},
|
||||
setModule(id, data) {
|
||||
this.httpForm.moduleId = id;
|
||||
this.httpForm.modulePath = data.path;
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
open(api) {
|
||||
if (api) {
|
||||
let data = JSON.parse(JSON.stringify(api));
|
||||
if (data.protocol === "dubbo://") {
|
||||
data.protocol = "DUBBO";
|
||||
if (data.protocol === 'dubbo://') {
|
||||
data.protocol = 'DUBBO';
|
||||
}
|
||||
data.id = getUUID();
|
||||
data.path = this.httpForm.path;
|
||||
|
@ -305,21 +394,19 @@ export default {
|
|||
method: api.method,
|
||||
userId: getCurrentUser().id,
|
||||
request: data,
|
||||
moduleId: "default-module"
|
||||
moduleId: 'default-module',
|
||||
};
|
||||
this.getMaintainerOptions();
|
||||
this.list(data);
|
||||
this.httpVisible = true;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.create-tip {
|
||||
color: #8c939d;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
:is-across-space="isAcrossSpace"
|
||||
@setProject="setProject"
|
||||
:dialog-title="$t('api_test.definition.api_import')"
|
||||
ref="baseRelevance">
|
||||
ref="baseRelevance"
|
||||
>
|
||||
<template v-slot:aside>
|
||||
<ms-api-module
|
||||
@nodeSelectEvent="nodeChange"
|
||||
|
@ -13,7 +14,8 @@
|
|||
:is-relevance="true"
|
||||
:is-read-only="true"
|
||||
:select-project-id="projectId"
|
||||
ref="nodeTree"/>
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<scenario-relevance-api-list
|
||||
|
@ -26,10 +28,15 @@
|
|||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiList">
|
||||
ref="apiList"
|
||||
>
|
||||
<template v-slot:version>
|
||||
<mx-version-select v-xpack :project-id="projectId" :default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange"/>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
:default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange"
|
||||
/>
|
||||
</template>
|
||||
</scenario-relevance-api-list>
|
||||
|
||||
|
@ -43,23 +50,43 @@
|
|||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiCaseList">
|
||||
ref="apiCaseList"
|
||||
>
|
||||
<template v-slot:version>
|
||||
<mx-version-select v-xpack :project-id="projectId" :default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange"/>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
:default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange"
|
||||
/>
|
||||
</template>
|
||||
</scenario-relevance-case-list>
|
||||
|
||||
<template v-slot:headerBtn>
|
||||
<!-- 显示数量 -->
|
||||
<table-select-count-bar :count="selectCounts" style="float: left; margin: 5px;"/>
|
||||
<table-select-count-bar
|
||||
:count="selectCounts"
|
||||
style="float: left; margin: 5px"
|
||||
/>
|
||||
|
||||
<el-button size="mini" icon="el-icon-refresh" @click="refresh"/>
|
||||
<el-button type="primary" @click="copy" :loading="buttonIsWorking" @keydown.enter.native.prevent size="mini">
|
||||
<el-button size="mini" icon="el-icon-refresh" @click="refresh" />
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="copy"
|
||||
:loading="buttonIsWorking"
|
||||
@keydown.enter.native.prevent
|
||||
size="mini"
|
||||
>
|
||||
{{ $t('commons.copy') }}
|
||||
</el-button>
|
||||
<el-button v-if="!isApiListEnable" type="primary" :loading="buttonIsWorking" @click="reference" size="mini"
|
||||
@keydown.enter.native.prevent>
|
||||
<el-button
|
||||
v-if="!isApiListEnable"
|
||||
type="primary"
|
||||
:loading="buttonIsWorking"
|
||||
@click="reference"
|
||||
size="mini"
|
||||
@keydown.enter.native.prevent
|
||||
>
|
||||
{{ $t('api_test.scenario.reference') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -67,37 +94,42 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {getApiCaseWithBLOBs} from "@/api/api-test-case";
|
||||
import {apiListBatch} from "@/api/definition";
|
||||
import {getProjectVersions} from "@/api/xpack";
|
||||
import ScenarioRelevanceCaseList from "./RelevanceCaseList";
|
||||
import MsApiModule from "../../../definition/components/module/ApiModule";
|
||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||
import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer";
|
||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||
import ScenarioRelevanceApiList from "./RelevanceApiList";
|
||||
import RelevanceDialog from "@/business/commons/RelevanceDialog";
|
||||
import TestCaseRelevanceBase from "@/business/commons/TestCaseRelevanceBase";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import TableSelectCountBar from "@/business/automation/scenario/api/TableSelectCountBar";
|
||||
import { getApiCaseWithBLOBs } from '@/api/api-test-case';
|
||||
import { apiListBatch } from '@/api/definition';
|
||||
import { getProjectVersions } from '@/api/xpack';
|
||||
import ScenarioRelevanceCaseList from './RelevanceCaseList';
|
||||
import MsApiModule from '../../../definition/components/module/ApiModule';
|
||||
import MsContainer from 'metersphere-frontend/src/components/MsContainer';
|
||||
import MsAsideContainer from 'metersphere-frontend/src/components/MsAsideContainer';
|
||||
import MsMainContainer from 'metersphere-frontend/src/components/MsMainContainer';
|
||||
import ScenarioRelevanceApiList from './RelevanceApiList';
|
||||
import RelevanceDialog from '@/business/commons/RelevanceDialog';
|
||||
import TestCaseRelevanceBase from '@/business/commons/TestCaseRelevanceBase';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
import TableSelectCountBar from '@/business/automation/scenario/api/TableSelectCountBar';
|
||||
|
||||
export default {
|
||||
name: "ApiRelevance",
|
||||
name: 'ApiRelevance',
|
||||
components: {
|
||||
MxVersionSelect: () => import("metersphere-frontend/src/components/version/MxVersionSelect"),
|
||||
MxVersionSelect: () =>
|
||||
import('metersphere-frontend/src/components/version/MxVersionSelect'),
|
||||
TableSelectCountBar,
|
||||
TestCaseRelevanceBase,
|
||||
RelevanceDialog,
|
||||
ScenarioRelevanceApiList,
|
||||
MsMainContainer, MsAsideContainer, MsContainer, MsApiModule, ScenarioRelevanceCaseList
|
||||
MsMainContainer,
|
||||
MsAsideContainer,
|
||||
MsContainer,
|
||||
MsApiModule,
|
||||
ScenarioRelevanceCaseList,
|
||||
},
|
||||
props: {
|
||||
isAcrossSpace: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -108,7 +140,7 @@ export default {
|
|||
selectNodeIds: [],
|
||||
moduleOptions: {},
|
||||
isApiListEnable: true,
|
||||
projectId: "",
|
||||
projectId: '',
|
||||
versionFilters: [],
|
||||
currentVersion: null,
|
||||
selectCounts: null,
|
||||
|
@ -119,7 +151,7 @@ export default {
|
|||
this.refresh();
|
||||
this.$refs.nodeTree.list(this.projectId);
|
||||
this.getVersionOptions();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeButtonLoadingType() {
|
||||
|
@ -137,37 +169,42 @@ export default {
|
|||
save(reference) {
|
||||
if (this.isApiListEnable) {
|
||||
let apis = this.$refs.apiList.selectRows;
|
||||
apis.forEach(api => {
|
||||
apis.forEach((api) => {
|
||||
api.projectId = this.projectId;
|
||||
});
|
||||
let params = this.$refs.apiList.getConditions();
|
||||
this.result = apiListBatch(params).then((response) => {
|
||||
let apis = response.data;
|
||||
if (apis.length === 0) {
|
||||
this.$warning('请选择接口');
|
||||
this.result = apiListBatch(params).then(
|
||||
(response) => {
|
||||
let apis = response.data;
|
||||
if (apis.length === 0) {
|
||||
this.$warning('请选择接口');
|
||||
this.buttonIsWorking = false;
|
||||
} else {
|
||||
this.$emit('save', apis, 'API', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.buttonIsWorking = false;
|
||||
} else {
|
||||
this.$emit('save', apis, 'API', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
}
|
||||
}, (error) => {
|
||||
this.buttonIsWorking = false;
|
||||
});
|
||||
|
||||
);
|
||||
} else {
|
||||
let params = this.$refs.apiCaseList.getConditions();
|
||||
this.result = getApiCaseWithBLOBs(params).then((response) => {
|
||||
let apiCases = response.data;
|
||||
if (apiCases.length === 0) {
|
||||
this.$warning('请选择案例');
|
||||
this.result = getApiCaseWithBLOBs(params).then(
|
||||
(response) => {
|
||||
let apiCases = response.data;
|
||||
if (apiCases.length === 0) {
|
||||
this.$warning('请选择案例');
|
||||
this.buttonIsWorking = false;
|
||||
} else {
|
||||
this.$emit('save', apiCases, 'CASE', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.buttonIsWorking = false;
|
||||
} else {
|
||||
this.$emit('save', apiCases, 'CASE', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
}
|
||||
}, (error) => {
|
||||
this.buttonIsWorking = false;
|
||||
});
|
||||
);
|
||||
}
|
||||
},
|
||||
close() {
|
||||
|
@ -211,14 +248,16 @@ export default {
|
|||
if (!this.projectId) {
|
||||
return;
|
||||
}
|
||||
getProjectVersions(this.projectId).then(response => {
|
||||
getProjectVersions(this.projectId).then((response) => {
|
||||
if (currentVersion) {
|
||||
this.versionFilters = response.data.filter(u => u.id === currentVersion).map(u => {
|
||||
return {text: u.name, value: u.id};
|
||||
});
|
||||
this.versionFilters = response.data
|
||||
.filter((u) => u.id === currentVersion)
|
||||
.map((u) => {
|
||||
return { text: u.name, value: u.id };
|
||||
});
|
||||
} else {
|
||||
this.versionFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id};
|
||||
this.versionFilters = response.data.map((u) => {
|
||||
return { text: u.name, value: u.id };
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -227,7 +266,7 @@ export default {
|
|||
setSelectCounts(data) {
|
||||
this.selectCounts = data;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<div v-loading="result">
|
||||
<api-list-container
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange">
|
||||
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
>
|
||||
<template>
|
||||
<slot name="version"></slot>
|
||||
</template>
|
||||
|
@ -22,34 +22,35 @@
|
|||
@setSelectRow="setSelectRow"
|
||||
@selectCountChange="selectCountChange"
|
||||
@refreshTable="initTable"
|
||||
ref="apitable">
|
||||
|
||||
ref="apitable"
|
||||
>
|
||||
<template v-slot:header>
|
||||
<ms-environment-select :project-id="projectId" v-if="isTestPlan || isScript" :is-read-only="isReadOnly"
|
||||
@setEnvironment="setEnvironment" ref="msEnvironmentSelect"/>
|
||||
<ms-environment-select
|
||||
:project-id="projectId"
|
||||
v-if="isTestPlan || isScript"
|
||||
:is-read-only="isReadOnly"
|
||||
@setEnvironment="setEnvironment"
|
||||
ref="msEnvironmentSelect"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</api-table-list>
|
||||
|
||||
</api-list-container>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {getDefinitionPage, getRelevanceDefinitionPage} from "@/api/definition";
|
||||
import ApiListContainer from "@/business/definition/components/list/ApiListContainer";
|
||||
import MsEnvironmentSelect from "@/business/definition/components/case/MsEnvironmentSelect";
|
||||
import {buildBatchParam} from "metersphere-frontend/src/utils/tableUtils";
|
||||
import {
|
||||
TEST_PLAN_RELEVANCE_API_DEFINITION_CONFIGS,
|
||||
} from "metersphere-frontend/src/components/search/search-components";
|
||||
import ApiTableList from "@/business/definition/components/complete/ApiTableList";
|
||||
getDefinitionPage,
|
||||
getRelevanceDefinitionPage,
|
||||
} from '@/api/definition';
|
||||
import ApiListContainer from '@/business/definition/components/list/ApiListContainer';
|
||||
import MsEnvironmentSelect from '@/business/definition/components/case/MsEnvironmentSelect';
|
||||
import { buildBatchParam } from 'metersphere-frontend/src/utils/tableUtils';
|
||||
import { TEST_PLAN_RELEVANCE_API_DEFINITION_CONFIGS } from 'metersphere-frontend/src/components/search/search-components';
|
||||
import ApiTableList from '@/business/definition/components/complete/ApiTableList';
|
||||
|
||||
export default {
|
||||
name: "RelevanceApiList",
|
||||
name: 'RelevanceApiList',
|
||||
components: {
|
||||
ApiTableList,
|
||||
MsEnvironmentSelect,
|
||||
|
@ -58,12 +59,12 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
condition: {
|
||||
components: TEST_PLAN_RELEVANCE_API_DEFINITION_CONFIGS
|
||||
components: TEST_PLAN_RELEVANCE_API_DEFINITION_CONFIGS,
|
||||
},
|
||||
result: false,
|
||||
screenHeight: 'calc(100vh - 400px)',//屏幕高度,
|
||||
screenHeight: 'calc(100vh - 400px)', //屏幕高度,
|
||||
tableData: [],
|
||||
environmentId: "",
|
||||
environmentId: '',
|
||||
total: 0,
|
||||
selectRows: new Set(),
|
||||
};
|
||||
|
@ -81,7 +82,7 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
isApiListEnable: {
|
||||
type: Boolean,
|
||||
|
@ -89,7 +90,7 @@ export default {
|
|||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
isCaseRelevance: {
|
||||
type: Boolean,
|
||||
|
@ -100,8 +101,8 @@ export default {
|
|||
isTestPlan: Boolean,
|
||||
versionEnable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.condition.versionId = this.currentVersion;
|
||||
|
@ -116,7 +117,7 @@ export default {
|
|||
},
|
||||
projectId() {
|
||||
this.condition = {
|
||||
components: TEST_PLAN_RELEVANCE_API_DEFINITION_CONFIGS
|
||||
components: TEST_PLAN_RELEVANCE_API_DEFINITION_CONFIGS,
|
||||
};
|
||||
this.selectNodeIds.length = 0;
|
||||
this.initTable();
|
||||
|
@ -124,7 +125,7 @@ export default {
|
|||
currentVersion() {
|
||||
this.condition.versionId = this.currentVersion;
|
||||
this.initTable();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setSelectRow(setSelectRow) {
|
||||
|
@ -139,7 +140,7 @@ export default {
|
|||
initTable(projectId) {
|
||||
this.condition.moduleIds = this.selectNodeIds;
|
||||
if (this.trashEnable) {
|
||||
this.condition.filters = {status: ["Trash"]};
|
||||
this.condition.filters = { status: ['Trash'] };
|
||||
this.condition.moduleIds = [];
|
||||
}
|
||||
if (projectId != null && typeof projectId === 'string') {
|
||||
|
@ -151,23 +152,33 @@ export default {
|
|||
if (this.currentProtocol != null) {
|
||||
this.condition.protocol = this.currentProtocol;
|
||||
} else {
|
||||
this.condition.protocol = "HTTP";
|
||||
this.condition.protocol = 'HTTP';
|
||||
}
|
||||
if (this.condition.filters) {
|
||||
this.condition.filters.status = ["Prepare", "Underway", "Completed"];
|
||||
this.condition.filters.status = ['Prepare', 'Underway', 'Completed'];
|
||||
} else {
|
||||
this.condition.filters = {status: ["Prepare", "Underway", "Completed"]};
|
||||
this.condition.filters = {
|
||||
status: ['Prepare', 'Underway', 'Completed'],
|
||||
};
|
||||
}
|
||||
if (this.isTestPlan) {
|
||||
this.condition.planId = this.planId;
|
||||
this.$nextTick(() => {
|
||||
this.result = getRelevanceDefinitionPage(this.$refs.apitable.currentPage, this.$refs.apitable.pageSize, this.condition).then(response => {
|
||||
this.result = getRelevanceDefinitionPage(
|
||||
this.$refs.apitable.currentPage,
|
||||
this.$refs.apitable.pageSize,
|
||||
this.condition
|
||||
).then((response) => {
|
||||
this.setData(response);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.result = getDefinitionPage(this.$refs.apitable.currentPage, this.$refs.apitable.pageSize, this.condition).then(response => {
|
||||
this.result = getDefinitionPage(
|
||||
this.$refs.apitable.currentPage,
|
||||
this.$refs.apitable.pageSize,
|
||||
this.condition
|
||||
).then((response) => {
|
||||
this.setData(response);
|
||||
});
|
||||
});
|
||||
|
@ -176,7 +187,7 @@ export default {
|
|||
setData(response) {
|
||||
this.total = response.data.itemCount;
|
||||
this.tableData = response.data.listObject;
|
||||
this.tableData.forEach(item => {
|
||||
this.tableData.forEach((item) => {
|
||||
if (item.tags && item.tags.length > 0) {
|
||||
item.tags = JSON.parse(item.tags);
|
||||
}
|
||||
|
@ -188,8 +199,8 @@ export default {
|
|||
getConditions() {
|
||||
let sampleSelectRows = this.selectRows;
|
||||
let param = buildBatchParam(this, undefined, this.projectId);
|
||||
param.ids = Array.from(sampleSelectRows).map(row => row.id);
|
||||
let tableDataIds = Array.from(this.tableData).map(row => row.id);
|
||||
param.ids = Array.from(sampleSelectRows).map((row) => row.id);
|
||||
let tableDataIds = Array.from(this.tableData).map((row) => row.id);
|
||||
param.ids.sort((a, b) => {
|
||||
return tableDataIds.indexOf(a) - tableDataIds.indexOf(b);
|
||||
});
|
||||
|
@ -201,16 +212,14 @@ export default {
|
|||
}
|
||||
},
|
||||
clearEnvAndSelect() {
|
||||
this.environmentId = "";
|
||||
this.environmentId = '';
|
||||
if (this.$refs.msEnvironmentSelect) {
|
||||
this.$refs.msEnvironmentSelect.environmentId = "";
|
||||
this.$refs.msEnvironmentSelect.environmentId = '';
|
||||
}
|
||||
this.clear();
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -2,44 +2,51 @@
|
|||
<div v-loading="result">
|
||||
<api-list-container
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange">
|
||||
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
>
|
||||
<template>
|
||||
<slot name="version"></slot>
|
||||
</template>
|
||||
|
||||
<ms-environment-select :project-id="projectId" v-if="isTestPlan || isScript" :is-read-only="isReadOnly"
|
||||
@setEnvironment="setEnvironment" ref="msEnvironmentSelect"/>
|
||||
<ms-search
|
||||
:condition.sync="condition"
|
||||
@search="initTable">
|
||||
</ms-search>
|
||||
<ms-table :data="tableData" :select-node-ids="selectNodeIds" :condition="condition" :page-size="pageSize"
|
||||
:total="total" enableSelection
|
||||
:screenHeight="screenHeight"
|
||||
@refresh="initTable"
|
||||
@selectCountChange="selectCountChange"
|
||||
operator-width="170px"
|
||||
ref="table"
|
||||
<ms-environment-select
|
||||
:project-id="projectId"
|
||||
v-if="isTestPlan || isScript"
|
||||
:is-read-only="isReadOnly"
|
||||
@setEnvironment="setEnvironment"
|
||||
ref="msEnvironmentSelect"
|
||||
/>
|
||||
<ms-search :condition.sync="condition" @search="initTable"> </ms-search>
|
||||
<ms-table
|
||||
:data="tableData"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:condition="condition"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
enableSelection
|
||||
:screenHeight="screenHeight"
|
||||
@refresh="initTable"
|
||||
@selectCountChange="selectCountChange"
|
||||
operator-width="170px"
|
||||
ref="table"
|
||||
>
|
||||
|
||||
<ms-table-column
|
||||
prop="num"
|
||||
label="ID"
|
||||
width="80px"
|
||||
sortable=true>
|
||||
<ms-table-column prop="num" label="ID" width="80px" sortable="true">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column prop="name" width="160px" :label="$t('test_track.case.name')"/>
|
||||
<ms-table-column
|
||||
prop="name"
|
||||
width="160px"
|
||||
:label="$t('test_track.case.name')"
|
||||
/>
|
||||
|
||||
<ms-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
width="120px"
|
||||
:label="$t('test_track.case.priority')">
|
||||
:label="$t('test_track.case.priority')"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
<priority-table-item :value="scope.row.priority" />
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
|
@ -47,12 +54,19 @@
|
|||
sortable="custom"
|
||||
prop="path"
|
||||
width="180px"
|
||||
:label="'API'+ $t('api_test.definition.api_path')"/>
|
||||
:label="'API' + $t('api_test.definition.api_path')"
|
||||
/>
|
||||
|
||||
<ms-table-column prop="tags" width="120px" :label="$t('commons.tag')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
|
||||
:content="itemName" style="margin-left: 0px; margin-right: 2px"/>
|
||||
<ms-tag
|
||||
v-for="(itemName, index) in scope.row.tags"
|
||||
:key="index"
|
||||
type="success"
|
||||
effect="plain"
|
||||
:content="itemName"
|
||||
style="margin-left: 0px; margin-right: 2px"
|
||||
/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
|
@ -61,21 +75,21 @@
|
|||
:label="$t('project.version.name')"
|
||||
:filters="versionFilters"
|
||||
min-width="100px"
|
||||
prop="versionId">
|
||||
prop="versionId"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.versionName }}</span>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
prop="createUser"
|
||||
:label="$t('commons.create_user')"/>
|
||||
<ms-table-column prop="createUser" :label="$t('commons.create_user')" />
|
||||
|
||||
<ms-table-column
|
||||
sortable="createTime"
|
||||
width="160px"
|
||||
:label="$t('commons.create_time')"
|
||||
prop="createTime">
|
||||
prop="createTime"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
|
@ -85,48 +99,55 @@
|
|||
sortable="updateTime"
|
||||
width="160px"
|
||||
:label="$t('api_test.definition.api_last_time')"
|
||||
prop="updateTime">
|
||||
prop="updateTime"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
</ms-table>
|
||||
<ms-table-pagination :change="initTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
<ms-table-pagination
|
||||
:change="initTable"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:total="total"
|
||||
/>
|
||||
</api-list-container>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {apiTestCasePage} from "@/api/api-test-case";
|
||||
import {getDefinitionById} from "@/api/definition";
|
||||
import {versionEnableByProjectId} from "@/api/xpack";
|
||||
import MsTable from "metersphere-frontend/src/components/table/MsTable";
|
||||
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
||||
import MsTableOperator from "metersphere-frontend/src/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "metersphere-frontend/src/components/MsTableOperatorButton";
|
||||
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import MsBottomContainer from "@/business/definition/components/BottomContainer";
|
||||
import ShowMoreBtn from "@/business/commons/ShowMoreBtn";
|
||||
import MsBatchEdit from "@/business/definition/components/basis/BatchEdit";
|
||||
import {API_METHOD_COLOUR, CASE_PRIORITY} from "@/business/definition/model/JsonData";
|
||||
import ApiListContainer from "@/business/definition/components/list/ApiListContainer";
|
||||
import PriorityTableItem from "@/business/commons/PriorityTableItem";
|
||||
import MsEnvironmentSelect from "@/business/definition/components/case/MsEnvironmentSelect";
|
||||
import {_filter, _sort, buildBatchParam} from "metersphere-frontend/src/utils/tableUtils";
|
||||
import MsTableAdvSearchBar from "metersphere-frontend/src/components/search/MsTableAdvSearchBar";
|
||||
import { apiTestCasePage } from '@/api/api-test-case';
|
||||
import { getDefinitionById } from '@/api/definition';
|
||||
import { versionEnableByProjectId } from '@/api/xpack';
|
||||
import MsTable from 'metersphere-frontend/src/components/table/MsTable';
|
||||
import MsTableColumn from 'metersphere-frontend/src/components/table/MsTableColumn';
|
||||
import MsTableOperator from 'metersphere-frontend/src/components/MsTableOperator';
|
||||
import MsTableOperatorButton from 'metersphere-frontend/src/components/MsTableOperatorButton';
|
||||
import MsTablePagination from 'metersphere-frontend/src/components/pagination/TablePagination';
|
||||
import MsTag from 'metersphere-frontend/src/components/MsTag';
|
||||
import MsBottomContainer from '@/business/definition/components/BottomContainer';
|
||||
import ShowMoreBtn from '@/business/commons/ShowMoreBtn';
|
||||
import MsBatchEdit from '@/business/definition/components/basis/BatchEdit';
|
||||
import {
|
||||
TEST_PLAN_RELEVANCE_API_CASE_CONFIGS
|
||||
} from "metersphere-frontend/src/components/search/search-components";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import MsSearch from "metersphere-frontend/src/components/search/MsSearch";
|
||||
API_METHOD_COLOUR,
|
||||
CASE_PRIORITY,
|
||||
} from '@/business/definition/model/JsonData';
|
||||
import ApiListContainer from '@/business/definition/components/list/ApiListContainer';
|
||||
import PriorityTableItem from '@/business/commons/PriorityTableItem';
|
||||
import MsEnvironmentSelect from '@/business/definition/components/case/MsEnvironmentSelect';
|
||||
import {
|
||||
_filter,
|
||||
_sort,
|
||||
buildBatchParam,
|
||||
} from 'metersphere-frontend/src/utils/tableUtils';
|
||||
import MsTableAdvSearchBar from 'metersphere-frontend/src/components/search/MsTableAdvSearchBar';
|
||||
import { TEST_PLAN_RELEVANCE_API_CASE_CONFIGS } from 'metersphere-frontend/src/components/search/search-components';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
import MsSearch from 'metersphere-frontend/src/components/search/MsSearch';
|
||||
|
||||
export default {
|
||||
name: "RelevanceCaseList",
|
||||
name: 'RelevanceCaseList',
|
||||
components: {
|
||||
MsEnvironmentSelect,
|
||||
PriorityTableItem,
|
||||
|
@ -141,35 +162,33 @@ export default {
|
|||
MsTable,
|
||||
MsTableColumn,
|
||||
MsSearch,
|
||||
MsTableAdvSearchBar
|
||||
MsTableAdvSearchBar,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
condition: {
|
||||
components: TEST_PLAN_RELEVANCE_API_CASE_CONFIGS
|
||||
components: TEST_PLAN_RELEVANCE_API_CASE_CONFIGS,
|
||||
},
|
||||
selectCase: {},
|
||||
result: false,
|
||||
moduleId: "",
|
||||
typeArr: [
|
||||
{id: 'priority', name: this.$t('test_track.case.priority')},
|
||||
],
|
||||
moduleId: '',
|
||||
typeArr: [{ id: 'priority', name: this.$t('test_track.case.priority') }],
|
||||
priorityFilters: [
|
||||
{text: 'P0', value: 'P0'},
|
||||
{text: 'P1', value: 'P1'},
|
||||
{text: 'P2', value: 'P2'},
|
||||
{text: 'P3', value: 'P3'}
|
||||
{ text: 'P0', value: 'P0' },
|
||||
{ text: 'P1', value: 'P1' },
|
||||
{ text: 'P2', value: 'P2' },
|
||||
{ text: 'P3', value: 'P3' },
|
||||
],
|
||||
valueArr: {
|
||||
priority: CASE_PRIORITY,
|
||||
},
|
||||
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||
screenHeight: 'calc(100vh - 400px)',//屏幕高度
|
||||
screenHeight: 'calc(100vh - 400px)', //屏幕高度
|
||||
tableData: [],
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
environmentId: "",
|
||||
environmentId: '',
|
||||
versionEnable: false,
|
||||
};
|
||||
},
|
||||
|
@ -190,11 +209,11 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
isCaseRelevance: {
|
||||
type: Boolean,
|
||||
|
@ -218,7 +237,7 @@ export default {
|
|||
},
|
||||
projectId() {
|
||||
this.condition = {
|
||||
components: TEST_PLAN_RELEVANCE_API_CASE_CONFIGS
|
||||
components: TEST_PLAN_RELEVANCE_API_CASE_CONFIGS,
|
||||
};
|
||||
this.selectNodeIds.length = 0;
|
||||
this.initTable();
|
||||
|
@ -227,7 +246,7 @@ export default {
|
|||
currentVersion() {
|
||||
this.condition.versionId = this.currentVersion;
|
||||
this.initTable();
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
selectRows() {
|
||||
|
@ -236,7 +255,7 @@ export default {
|
|||
} else {
|
||||
return new Set();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isApiListEnableChange(data) {
|
||||
|
@ -246,7 +265,7 @@ export default {
|
|||
this.$emit('selectCountChange', data);
|
||||
},
|
||||
initTable(projectId) {
|
||||
this.condition.status = "";
|
||||
this.condition.status = '';
|
||||
this.condition.moduleIds = this.selectNodeIds;
|
||||
if (projectId != null && typeof projectId === 'string') {
|
||||
this.condition.projectId = projectId;
|
||||
|
@ -257,14 +276,18 @@ export default {
|
|||
this.condition.protocol = this.currentProtocol;
|
||||
}
|
||||
this.condition.ids = [];
|
||||
this.result = apiTestCasePage(this.currentPage, this.pageSize, this.condition).then(response => {
|
||||
this.result = apiTestCasePage(
|
||||
this.currentPage,
|
||||
this.pageSize,
|
||||
this.condition
|
||||
).then((response) => {
|
||||
this.setData(response);
|
||||
});
|
||||
},
|
||||
setData(response) {
|
||||
this.total = response.data.itemCount;
|
||||
this.tableData = response.data.listObject;
|
||||
this.tableData.forEach(item => {
|
||||
this.tableData.forEach((item) => {
|
||||
if (item.tags && item.tags.length > 0) {
|
||||
item.tags = JSON.parse(item.tags);
|
||||
}
|
||||
|
@ -276,9 +299,9 @@ export default {
|
|||
}
|
||||
},
|
||||
clearEnvAndSelect() {
|
||||
this.environmentId = "";
|
||||
this.environmentId = '';
|
||||
if (this.$refs.msEnvironmentSelect) {
|
||||
this.$refs.msEnvironmentSelect.environmentId = "";
|
||||
this.$refs.msEnvironmentSelect.environmentId = '';
|
||||
}
|
||||
this.clear();
|
||||
},
|
||||
|
@ -299,14 +322,19 @@ export default {
|
|||
this.initTable();
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
return path + '/' + this.currentPage + '/' + this.pageSize;
|
||||
},
|
||||
handleTestCase(testCase) {
|
||||
getDefinitionById(testCase.apiDefinitionId).then((response) => {
|
||||
let api = response.data;
|
||||
let selectApi = api;
|
||||
let request = {};
|
||||
if (Object.prototype.toString.call(api.request).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
|
||||
if (
|
||||
Object.prototype.toString
|
||||
.call(api.request)
|
||||
.match(/\[object (\w+)\]/)[1]
|
||||
.toLowerCase() === 'object'
|
||||
) {
|
||||
request = api.request;
|
||||
} else {
|
||||
request = JSON.parse(api.request);
|
||||
|
@ -337,8 +365,8 @@ export default {
|
|||
} else {
|
||||
param = batchParam;
|
||||
}
|
||||
param.ids = Array.from(sampleSelectRows).map(row => row.id);
|
||||
let tableDataIds = Array.from(this.tableData).map(row => row.id);
|
||||
param.ids = Array.from(sampleSelectRows).map((row) => row.id);
|
||||
let tableDataIds = Array.from(this.tableData).map((row) => row.id);
|
||||
param.ids.sort((a, b) => {
|
||||
return tableDataIds.indexOf(a) - tableDataIds.indexOf(b);
|
||||
});
|
||||
|
@ -349,11 +377,11 @@ export default {
|
|||
return;
|
||||
}
|
||||
if (hasLicense()) {
|
||||
versionEnableByProjectId(this.projectId).then(response => {
|
||||
versionEnableByProjectId(this.projectId).then((response) => {
|
||||
this.versionEnable = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -366,7 +394,7 @@ export default {
|
|||
|
||||
.request-method {
|
||||
padding: 0 5px;
|
||||
color: #1E90FF;
|
||||
color: #1e90ff;
|
||||
}
|
||||
|
||||
.api-el-tag {
|
||||
|
@ -383,5 +411,4 @@ export default {
|
|||
margin-top: 5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -3,103 +3,163 @@
|
|||
<ms-search
|
||||
:base-search-tip="$t('api_test.definition.request.select_case')"
|
||||
:condition.sync="condition"
|
||||
@search="search">
|
||||
@search="search"
|
||||
>
|
||||
</ms-search>
|
||||
<mx-version-select v-xpack :project-id="projectId" @changeVersion="changeVersion"
|
||||
style="float: left"
|
||||
class="search-input"/>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion"
|
||||
style="float: left"
|
||||
class="search-input"
|
||||
/>
|
||||
|
||||
<ms-table ref="scenarioTable"
|
||||
v-loading="result"
|
||||
:data="tableData"
|
||||
:condition="condition"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:remember-order="true"
|
||||
row-key="id"
|
||||
:row-order-group-id="projectId"
|
||||
@refresh="search"
|
||||
:disable-header-config="true"
|
||||
@selectCountChange="selectCountChange">
|
||||
|
||||
<el-table-column v-if="!customNum" prop="num" label="ID"
|
||||
show-overflow-tooltip>
|
||||
<ms-table
|
||||
ref="scenarioTable"
|
||||
v-loading="result"
|
||||
:data="tableData"
|
||||
:condition="condition"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:remember-order="true"
|
||||
row-key="id"
|
||||
:row-order-group-id="projectId"
|
||||
@refresh="search"
|
||||
:disable-header-config="true"
|
||||
@selectCountChange="selectCountChange"
|
||||
>
|
||||
<el-table-column
|
||||
v-if="!customNum"
|
||||
prop="num"
|
||||
label="ID"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="customNum" prop="customNum" label="ID"
|
||||
show-overflow-tooltip>
|
||||
<el-table-column
|
||||
v-if="customNum"
|
||||
prop="customNum"
|
||||
label="ID"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" :label="$t('api_test.automation.scenario_name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('api_test.automation.scenario_name')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="versionEnable"
|
||||
column-key="version_id"
|
||||
:filters="versionFilters"
|
||||
:label="$t('commons.version')"
|
||||
min-width="120px">
|
||||
min-width="120px"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.versionName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="level" :label="$t('api_test.automation.case_level')"
|
||||
show-overflow-tooltip>
|
||||
<el-table-column
|
||||
prop="level"
|
||||
:label="$t('api_test.automation.case_level')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.level" ref="level"/>
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
<el-table-column prop="tagNames" :label="$t('api_test.automation.tag')" min-width="120">
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag v-for="itemName in scope.row.tags" :key="itemName" type="success" effect="plain" :content="itemName"
|
||||
style="margin-left: 0px; margin-right: 2px"/>
|
||||
<priority-table-item :value="scope.row.level" ref="level" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="userId" :label="$t('api_test.automation.creator')" show-overflow-tooltip/>
|
||||
<el-table-column prop="updateTime" :label="$t('api_test.automation.update_time')" width="180">
|
||||
<el-table-column
|
||||
prop="tagNames"
|
||||
:label="$t('api_test.automation.tag')"
|
||||
min-width="120"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag
|
||||
v-for="itemName in scope.row.tags"
|
||||
:key="itemName"
|
||||
type="success"
|
||||
effect="plain"
|
||||
:content="itemName"
|
||||
style="margin-left: 0px; margin-right: 2px"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="userId"
|
||||
:label="$t('api_test.automation.creator')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('api_test.automation.update_time')"
|
||||
width="180"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stepTotal" :label="$t('api_test.automation.step')" show-overflow-tooltip/>
|
||||
<el-table-column prop="lastResult" :label="$t('api_test.automation.last_result')">
|
||||
<template v-slot:default="{row}">
|
||||
<el-link type="success" @click="showReport(row)" v-if="row.lastResult === 'SUCCESS'">
|
||||
<el-table-column
|
||||
prop="stepTotal"
|
||||
:label="$t('api_test.automation.step')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="lastResult"
|
||||
:label="$t('api_test.automation.last_result')"
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-link
|
||||
type="success"
|
||||
@click="showReport(row)"
|
||||
v-if="row.lastResult === 'SUCCESS'"
|
||||
>
|
||||
{{ $t('api_test.automation.success') }}
|
||||
</el-link>
|
||||
<el-link type="danger" @click="showReport(row)" v-if="row.lastResult === 'ERROR'">
|
||||
<el-link
|
||||
type="danger"
|
||||
@click="showReport(row)"
|
||||
v-if="row.lastResult === 'ERROR'"
|
||||
>
|
||||
{{ $t('api_test.automation.fail') }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="passRate" :label="$t('api_test.automation.passing_rate')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column
|
||||
prop="passRate"
|
||||
:label="$t('api_test.automation.passing_rate')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</ms-table>
|
||||
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
<ms-table-pagination
|
||||
:change="search"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:total="total"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getProjectVersions} from "@/api/xpack";
|
||||
import {getScenarioList} from "@/api/scenario";
|
||||
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
||||
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
|
||||
import ShowMoreBtn from "@/business/commons/ShowMoreBtn";
|
||||
import MsApiReportDetail from "@/business/automation/report/ApiReportDetail";
|
||||
import MsTableMoreBtn from "@/business/automation/scenario/TableMoreBtn";
|
||||
import PriorityTableItem from "@/business/commons/PriorityTableItem";
|
||||
import MsTableAdvSearchBar from "metersphere-frontend/src/components/search/MsTableAdvSearchBar";
|
||||
import {API_SCENARIO_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import MsTable from "metersphere-frontend/src/components/table/MsTable";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import MsSearch from "metersphere-frontend/src/components/search/MsSearch";
|
||||
import {getOwnerProjects, getProjectConfig} from "@/api/project";
|
||||
import { getProjectVersions } from '@/api/xpack';
|
||||
import { getScenarioList } from '@/api/scenario';
|
||||
import MsTableHeader from 'metersphere-frontend/src/components/MsTableHeader';
|
||||
import MsTablePagination from 'metersphere-frontend/src/components/pagination/TablePagination';
|
||||
import ShowMoreBtn from '@/business/commons/ShowMoreBtn';
|
||||
import MsApiReportDetail from '@/business/automation/report/ApiReportDetail';
|
||||
import MsTableMoreBtn from '@/business/automation/scenario/TableMoreBtn';
|
||||
import PriorityTableItem from '@/business/commons/PriorityTableItem';
|
||||
import MsTableAdvSearchBar from 'metersphere-frontend/src/components/search/MsTableAdvSearchBar';
|
||||
import { API_SCENARIO_CONFIGS } from 'metersphere-frontend/src/components/search/search-components';
|
||||
import { ENV_TYPE } from 'metersphere-frontend/src/utils/constants';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
import MsTable from 'metersphere-frontend/src/components/table/MsTable';
|
||||
import MsTag from 'metersphere-frontend/src/components/MsTag';
|
||||
import MsSearch from 'metersphere-frontend/src/components/search/MsSearch';
|
||||
import { getOwnerProjects, getProjectConfig } from '@/api/project';
|
||||
|
||||
export default {
|
||||
name: "RelevanceScenarioList",
|
||||
name: 'RelevanceScenarioList',
|
||||
components: {
|
||||
MsTable,
|
||||
PriorityTableItem,
|
||||
|
@ -111,7 +171,8 @@ export default {
|
|||
MsApiReportDetail,
|
||||
MsTableAdvSearchBar,
|
||||
MsSearch,
|
||||
MxVersionSelect: () => import("metersphere-frontend/src/components/version/MxVersionSelect"),
|
||||
MxVersionSelect: () =>
|
||||
import('metersphere-frontend/src/components/version/MxVersionSelect'),
|
||||
},
|
||||
props: {
|
||||
referenced: {
|
||||
|
@ -128,7 +189,7 @@ export default {
|
|||
result: false,
|
||||
showConfigButtonWithOutPermission: false,
|
||||
condition: {
|
||||
components: API_SCENARIO_CONFIGS
|
||||
components: API_SCENARIO_CONFIGS,
|
||||
},
|
||||
currentScenario: {},
|
||||
schedule: {},
|
||||
|
@ -137,7 +198,7 @@ export default {
|
|||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
reportId: "",
|
||||
reportId: '',
|
||||
infoDb: false,
|
||||
selectRows: new Set(),
|
||||
projectEnvMap: new Map(),
|
||||
|
@ -146,14 +207,14 @@ export default {
|
|||
map: new Map(),
|
||||
customNum: false,
|
||||
environmentType: ENV_TYPE.JSON,
|
||||
envGroupId: "",
|
||||
envGroupId: '',
|
||||
versionFilters: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
ENV_TYPE() {
|
||||
return ENV_TYPE;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectNodeIds() {
|
||||
|
@ -161,7 +222,7 @@ export default {
|
|||
},
|
||||
projectId() {
|
||||
this.condition = {
|
||||
components: API_SCENARIO_CONFIGS
|
||||
components: API_SCENARIO_CONFIGS,
|
||||
};
|
||||
this.selectNodeIds.length = 0;
|
||||
this.search();
|
||||
|
@ -176,7 +237,7 @@ export default {
|
|||
this.selectRows = new Set();
|
||||
this.condition.moduleIds = this.selectNodeIds;
|
||||
if (this.trashEnable) {
|
||||
this.condition.filters = {status: ["Trash"]};
|
||||
this.condition.filters = { status: ['Trash'] };
|
||||
this.condition.moduleIds = [];
|
||||
}
|
||||
if (typeof currentProjectId === 'string') {
|
||||
|
@ -186,11 +247,15 @@ export default {
|
|||
}
|
||||
|
||||
if (this.condition.projectId) {
|
||||
this.result = getScenarioList(this.currentPage, this.pageSize, this.condition).then(response => {
|
||||
this.result = getScenarioList(
|
||||
this.currentPage,
|
||||
this.pageSize,
|
||||
this.condition
|
||||
).then((response) => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
this.tableData.forEach(item => {
|
||||
this.tableData.forEach((item) => {
|
||||
if (item.tags && item.tags.length > 0) {
|
||||
item.tags = JSON.parse(item.tags);
|
||||
}
|
||||
|
@ -208,13 +273,13 @@ export default {
|
|||
this.envGroupId = id;
|
||||
},
|
||||
getWsProjects() {
|
||||
getOwnerProjects().then(res => {
|
||||
getOwnerProjects().then((res) => {
|
||||
this.projectList = res.data;
|
||||
});
|
||||
},
|
||||
getProject(projectId) {
|
||||
if (projectId) {
|
||||
getProjectConfig(projectId, "/SCENARIO_CUSTOM_NUM").then(result => {
|
||||
getProjectConfig(projectId, '/SCENARIO_CUSTOM_NUM').then((result) => {
|
||||
let data = result.data;
|
||||
if (data) {
|
||||
this.customNum = data.scenarioCustomNum;
|
||||
|
@ -223,7 +288,9 @@ export default {
|
|||
}
|
||||
},
|
||||
getConditions() {
|
||||
this.condition.tableDataIds = Array.from(this.tableData).map(row => row.id);
|
||||
this.condition.tableDataIds = Array.from(this.tableData).map(
|
||||
(row) => row.id
|
||||
);
|
||||
return this.condition;
|
||||
},
|
||||
checkEnv() {
|
||||
|
@ -235,9 +302,9 @@ export default {
|
|||
},
|
||||
getVersionOptions() {
|
||||
if (hasLicense()) {
|
||||
getProjectVersions(getCurrentProjectID()).then(response => {
|
||||
this.versionFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id};
|
||||
getProjectVersions(getCurrentProjectID()).then((response) => {
|
||||
this.versionFilters = response.data.map((u) => {
|
||||
return { text: u.name, value: u.id };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -248,9 +315,9 @@ export default {
|
|||
},
|
||||
selectCountChange(data) {
|
||||
this.selectRows = this.$refs.scenarioTable.selectRows;
|
||||
this.$emit("selectCountChange", data);
|
||||
}
|
||||
}
|
||||
this.$emit('selectCountChange', data);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,17 +4,19 @@
|
|||
:dialog-title="$t('api_test.automation.scenario_import')"
|
||||
@setProject="setProject"
|
||||
@refreshNode="refresh"
|
||||
ref="baseRelevance">
|
||||
ref="baseRelevance"
|
||||
>
|
||||
<template v-slot:aside>
|
||||
<ms-api-scenario-module
|
||||
style="margin-top: 5px;"
|
||||
style="margin-top: 5px"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
@enableTrash="false"
|
||||
:is-read-only="true"
|
||||
:select-project-id="projectId"
|
||||
ref="nodeTree"/>
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<relevance-scenario-list
|
||||
|
@ -24,17 +26,33 @@
|
|||
:referenced="true"
|
||||
:trash-enable="false"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiScenarioList">
|
||||
ref="apiScenarioList"
|
||||
>
|
||||
</relevance-scenario-list>
|
||||
|
||||
<template v-slot:headerBtn>
|
||||
<table-select-count-bar :count="selectCounts" style="float: left; margin: 5px;"/>
|
||||
<table-select-count-bar
|
||||
:count="selectCounts"
|
||||
style="float: left; margin: 5px"
|
||||
/>
|
||||
|
||||
<el-button size="mini" icon="el-icon-refresh" @click="refresh"/>
|
||||
<el-button type="primary" @click="copy" :loading="buttonIsWorking" @keydown.enter.native.prevent size="mini">
|
||||
<el-button size="mini" icon="el-icon-refresh" @click="refresh" />
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="copy"
|
||||
:loading="buttonIsWorking"
|
||||
@keydown.enter.native.prevent
|
||||
size="mini"
|
||||
>
|
||||
{{ $t('commons.copy') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="reference" :loading="buttonIsWorking" @keydown.enter.native.prevent size="mini">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="reference"
|
||||
:loading="buttonIsWorking"
|
||||
@keydown.enter.native.prevent
|
||||
size="mini"
|
||||
>
|
||||
{{ $t('api_test.scenario.reference') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -42,30 +60,29 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {getProjectVersions, versionEnableByProjectId} from "@/api/xpack";
|
||||
import {apiScenarioAll, getApiScenarios} from "@/api/scenario";
|
||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||
import MsAsideContainer from "metersphere-frontend/src/components/MsAsideContainer";
|
||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||
import MsApiScenarioModule from "../ApiScenarioModule";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import RelevanceDialog from "@/business/commons/RelevanceDialog";
|
||||
import RelevanceScenarioList from "./RelevanceScenarioList";
|
||||
import TestCaseRelevanceBase from "../../../commons/TestCaseRelevanceBase";
|
||||
import TableSelectCountBar from "@/business/automation/scenario/api/TableSelectCountBar";
|
||||
import {getProjectConfig} from "@/api/project";
|
||||
|
||||
import { getProjectVersions, versionEnableByProjectId } from '@/api/xpack';
|
||||
import { apiScenarioAll, getApiScenarios } from '@/api/scenario';
|
||||
import MsContainer from 'metersphere-frontend/src/components/MsContainer';
|
||||
import MsAsideContainer from 'metersphere-frontend/src/components/MsAsideContainer';
|
||||
import MsMainContainer from 'metersphere-frontend/src/components/MsMainContainer';
|
||||
import MsApiScenarioModule from '../ApiScenarioModule';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
import RelevanceDialog from '@/business/commons/RelevanceDialog';
|
||||
import RelevanceScenarioList from './RelevanceScenarioList';
|
||||
import TestCaseRelevanceBase from '../../../commons/TestCaseRelevanceBase';
|
||||
import TableSelectCountBar from '@/business/automation/scenario/api/TableSelectCountBar';
|
||||
import { getProjectConfig } from '@/api/project';
|
||||
|
||||
export default {
|
||||
name: "ScenarioRelevance",
|
||||
name: 'ScenarioRelevance',
|
||||
props: {
|
||||
isAcrossSpace: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
TableSelectCountBar,
|
||||
|
@ -73,7 +90,9 @@ export default {
|
|||
RelevanceScenarioList,
|
||||
RelevanceDialog,
|
||||
MsApiScenarioModule,
|
||||
MsMainContainer, MsAsideContainer, MsContainer
|
||||
MsMainContainer,
|
||||
MsAsideContainer,
|
||||
MsContainer,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -97,7 +116,7 @@ export default {
|
|||
projectId(val) {
|
||||
this.$refs.nodeTree.list(this.projectId);
|
||||
if (val) {
|
||||
getProjectConfig(val, "/SCENARIO_CUSTOM_NUM").then(result => {
|
||||
getProjectConfig(val, '/SCENARIO_CUSTOM_NUM').then((result) => {
|
||||
let data = result.data;
|
||||
if (data) {
|
||||
this.customNum = data.scenarioCustomNum;
|
||||
|
@ -107,24 +126,24 @@ export default {
|
|||
this.$refs.apiScenarioList.search(this.projectId);
|
||||
this.getVersionOptionList(this.projectId);
|
||||
this.checkVersionEnable(this.projectId);
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeButtonLoadingType() {
|
||||
this.buttonIsWorking = false;
|
||||
},
|
||||
createScenarioDefinition(scenarios, data, referenced) {
|
||||
let emptyStepScenarios = "";
|
||||
data.forEach(item => {
|
||||
let emptyStepScenarios = '';
|
||||
data.forEach((item) => {
|
||||
if (!item.stepTotal || item.stepTotal == 0) {
|
||||
emptyStepScenarios += item.name + ",";
|
||||
emptyStepScenarios += item.name + ',';
|
||||
} else {
|
||||
let scenarioDefinition = JSON.parse(item.scenarioDefinition);
|
||||
if (scenarioDefinition && scenarioDefinition.hashTree) {
|
||||
let obj = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: "scenario",
|
||||
type: 'scenario',
|
||||
headers: scenarioDefinition.headers,
|
||||
variables: scenarioDefinition.variables,
|
||||
environmentMap: scenarioDefinition.environmentMap,
|
||||
|
@ -134,16 +153,23 @@ export default {
|
|||
projectId: item.projectId,
|
||||
num: item.num,
|
||||
versionName: item.versionName,
|
||||
versionEnable: item.versionEnable
|
||||
versionEnable: item.versionEnable,
|
||||
};
|
||||
scenarios.push(obj);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (emptyStepScenarios !== "") {
|
||||
if (emptyStepScenarios.endsWith(",")) {
|
||||
emptyStepScenarios = emptyStepScenarios.substring(0, emptyStepScenarios.length - 1);
|
||||
this.$error(this.$t('api_test.scenario.scenario_step_is_empty', [emptyStepScenarios]));
|
||||
if (emptyStepScenarios !== '') {
|
||||
if (emptyStepScenarios.endsWith(',')) {
|
||||
emptyStepScenarios = emptyStepScenarios.substring(
|
||||
0,
|
||||
emptyStepScenarios.length - 1
|
||||
);
|
||||
this.$error(
|
||||
this.$t('api_test.scenario.scenario_step_is_empty', [
|
||||
emptyStepScenarios,
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -152,56 +178,79 @@ export default {
|
|||
let scenarios = [];
|
||||
let conditions = this.getConditions();
|
||||
this.currentScenarioIds.sort((a, b) => {
|
||||
return conditions.tableDataIds.indexOf(a) - conditions.tableDataIds.indexOf(b);
|
||||
return (
|
||||
conditions.tableDataIds.indexOf(a) -
|
||||
conditions.tableDataIds.indexOf(b)
|
||||
);
|
||||
});
|
||||
if (conditions.selectAll) {
|
||||
let params = {};
|
||||
params.ids = this.currentScenarioIds;
|
||||
params.condition = conditions;
|
||||
apiScenarioAll(params).then((response) => {
|
||||
this.currentScenarioIds = response.data;
|
||||
if (!this.currentScenarioIds || this.currentScenarioIds.length < 1) {
|
||||
this.$warning('请选择场景');
|
||||
this.buttonIsWorking = false;
|
||||
return;
|
||||
}
|
||||
this.result = getApiScenarios(this.currentScenarioIds).then(response => {
|
||||
if (response.data) {
|
||||
this.createScenarioDefinition(scenarios, response.data, referenced);
|
||||
this.$emit('save', scenarios);
|
||||
this.$refs.baseRelevance.close();
|
||||
apiScenarioAll(params).then(
|
||||
(response) => {
|
||||
this.currentScenarioIds = response.data;
|
||||
if (
|
||||
!this.currentScenarioIds ||
|
||||
this.currentScenarioIds.length < 1
|
||||
) {
|
||||
this.$warning('请选择场景');
|
||||
this.buttonIsWorking = false;
|
||||
return;
|
||||
}
|
||||
}, (error) => {
|
||||
this.result = getApiScenarios(this.currentScenarioIds).then(
|
||||
(response) => {
|
||||
if (response.data) {
|
||||
this.createScenarioDefinition(
|
||||
scenarios,
|
||||
response.data,
|
||||
referenced
|
||||
);
|
||||
this.$emit('save', scenarios);
|
||||
this.$refs.baseRelevance.close();
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
(error) => {
|
||||
this.buttonIsWorking = false;
|
||||
});
|
||||
}, (error) => {
|
||||
this.buttonIsWorking = false;
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (!this.currentScenarioIds || this.currentScenarioIds.length < 1) {
|
||||
this.$warning('请选择场景');
|
||||
this.buttonIsWorking = false;
|
||||
return;
|
||||
}
|
||||
this.result = getApiScenarios(this.currentScenarioIds).then(response => {
|
||||
if (response.data) {
|
||||
this.currentScenarioIds = [];
|
||||
this.createScenarioDefinition(scenarios, response.data, referenced);
|
||||
this.$emit('save', scenarios);
|
||||
this.$refs.baseRelevance.close();
|
||||
this.result = getApiScenarios(this.currentScenarioIds).then(
|
||||
(response) => {
|
||||
if (response.data) {
|
||||
this.currentScenarioIds = [];
|
||||
this.createScenarioDefinition(
|
||||
scenarios,
|
||||
response.data,
|
||||
referenced
|
||||
);
|
||||
this.$emit('save', scenarios);
|
||||
this.$refs.baseRelevance.close();
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
}, (error) => {
|
||||
this.buttonIsWorking = false;
|
||||
});
|
||||
);
|
||||
}
|
||||
},
|
||||
reference() {
|
||||
this.getScenarioDefinition("REF");
|
||||
this.getScenarioDefinition('REF');
|
||||
},
|
||||
copy() {
|
||||
this.getScenarioDefinition("Copy");
|
||||
this.getScenarioDefinition('Copy');
|
||||
},
|
||||
close() {
|
||||
this.$emit('close');
|
||||
|
@ -229,8 +278,8 @@ export default {
|
|||
this.$refs.apiScenarioList.search(this.projectId);
|
||||
},
|
||||
setData(data) {
|
||||
this.currentScenario = Array.from(data).map(row => row);
|
||||
this.currentScenarioIds = Array.from(data).map(row => row.id);
|
||||
this.currentScenario = Array.from(data).map((row) => row);
|
||||
this.currentScenarioIds = Array.from(data).map((row) => row.id);
|
||||
},
|
||||
setProject(projectId) {
|
||||
this.projectId = projectId;
|
||||
|
@ -240,7 +289,7 @@ export default {
|
|||
},
|
||||
getVersionOptionList(projectId) {
|
||||
if (hasLicense()) {
|
||||
getProjectVersions(projectId).then(response => {
|
||||
getProjectVersions(projectId).then((response) => {
|
||||
this.versionOptions = response.data;
|
||||
});
|
||||
}
|
||||
|
@ -256,7 +305,7 @@ export default {
|
|||
return;
|
||||
}
|
||||
if (hasLicense()) {
|
||||
versionEnableByProjectId(projectId).then(response => {
|
||||
versionEnableByProjectId(projectId).then((response) => {
|
||||
this.versionEnable = false;
|
||||
this.$nextTick(() => {
|
||||
this.versionEnable = true;
|
||||
|
@ -267,11 +316,9 @@ export default {
|
|||
setSelectCounts(data) {
|
||||
this.selectCounts = data;
|
||||
this.setData(this.$refs.apiScenarioList.selectRows);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
<template>
|
||||
<div v-if="count && count > 0" class="content">
|
||||
{{$t('commons.table.select_tip', [this.count])}}
|
||||
</div>
|
||||
<div v-if="count && count > 0" class="content">
|
||||
{{ $t('commons.table.select_tip', [this.count]) }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "TableSelectCountBar",
|
||||
props: ['count']
|
||||
}
|
||||
export default {
|
||||
name: 'TableSelectCountBar',
|
||||
props: ['count'],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -158,19 +158,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import StepExtendBtns from "../component/StepExtendBtns";
|
||||
import { STEP } from "../Setting";
|
||||
import { useApiStore } from "@/store";
|
||||
import StepExtendBtns from '../component/StepExtendBtns';
|
||||
import { STEP } from '../Setting';
|
||||
import { useApiStore } from '@/store';
|
||||
|
||||
let store = useApiStore();
|
||||
|
||||
export default {
|
||||
name: "ApiBaseComponent",
|
||||
name: 'ApiBaseComponent',
|
||||
components: { StepExtendBtns },
|
||||
data() {
|
||||
return {
|
||||
isShowInput: false,
|
||||
colorStyle: "",
|
||||
colorStyle: '',
|
||||
stepFilter: new STEP(),
|
||||
};
|
||||
},
|
||||
|
@ -201,13 +201,13 @@ export default {
|
|||
color: {
|
||||
type: String,
|
||||
default() {
|
||||
return "#B8741A";
|
||||
return '#B8741A';
|
||||
},
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default() {
|
||||
return "#F9F1EA";
|
||||
return '#F9F1EA';
|
||||
},
|
||||
},
|
||||
showCollapse: {
|
||||
|
@ -251,7 +251,7 @@ export default {
|
|||
) {
|
||||
this.colorStyle = this.color;
|
||||
} else {
|
||||
this.colorStyle = "";
|
||||
this.colorStyle = '';
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -266,7 +266,7 @@ export default {
|
|||
}
|
||||
if (
|
||||
this.data &&
|
||||
this.stepFilter.get("AllSamplerProxy").indexOf(this.data.type) != -1
|
||||
this.stepFilter.get('AllSamplerProxy').indexOf(this.data.type) != -1
|
||||
) {
|
||||
if (!this.data.method) {
|
||||
this.data.method = this.data.protocol;
|
||||
|
@ -282,62 +282,63 @@ export default {
|
|||
},
|
||||
isSingleButton() {
|
||||
if (
|
||||
this.data.type === "ConstantTimer" ||
|
||||
this.data.type === "Assertions"
|
||||
this.data.type === 'ConstantTimer' ||
|
||||
this.data.type === 'Assertions'
|
||||
) {
|
||||
return (
|
||||
this.innerStep &&
|
||||
this.showVersion &&
|
||||
this.stepFilter.get("ALlSamplerStep").indexOf(this.data.type) !== -1
|
||||
this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) !== -1
|
||||
);
|
||||
}
|
||||
return (
|
||||
this.showVersion &&
|
||||
this.stepFilter.get("ALlSamplerStep").indexOf(this.data.type) !== -1
|
||||
this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) !== -1
|
||||
);
|
||||
},
|
||||
isMoreButton() {
|
||||
if (
|
||||
this.data.type === "ConstantTimer" ||
|
||||
this.data.type === "Assertions"
|
||||
this.data.type === 'ConstantTimer' ||
|
||||
this.data.type === 'Assertions'
|
||||
) {
|
||||
return (
|
||||
!this.innerStep ||
|
||||
(this.showBtn &&
|
||||
(!this.data.disabled || this.data.root) &&
|
||||
this.showVersion &&
|
||||
this.stepFilter.get("ALlSamplerStep").indexOf(this.data.type) === -1)
|
||||
this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) ===
|
||||
-1)
|
||||
);
|
||||
}
|
||||
return (
|
||||
this.showBtn &&
|
||||
(!this.data.disabled || this.data.root || this.isDeleted) &&
|
||||
this.showVersion &&
|
||||
this.stepFilter.get("ALlSamplerStep").indexOf(this.data.type) === -1
|
||||
this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) === -1
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
active() {
|
||||
this.$emit("active");
|
||||
this.$emit('active');
|
||||
},
|
||||
getMethod() {
|
||||
if (this.data.protocol === "HTTP") {
|
||||
if (this.data.protocol === 'HTTP') {
|
||||
return this.data.method;
|
||||
} else if (this.data.protocol === "dubbo://") {
|
||||
return "DUBBO";
|
||||
} else if (this.data.protocol === 'dubbo://') {
|
||||
return 'DUBBO';
|
||||
} else {
|
||||
return this.data.protocol;
|
||||
}
|
||||
},
|
||||
copyRow() {
|
||||
this.$emit("copy");
|
||||
this.$emit('copy');
|
||||
},
|
||||
remove() {
|
||||
this.$emit("remove");
|
||||
this.$emit('remove');
|
||||
},
|
||||
openScenario(data) {
|
||||
this.$emit("openScenario", data);
|
||||
this.$emit('openScenario', data);
|
||||
},
|
||||
editName() {
|
||||
this.isShowInput = true;
|
||||
|
@ -347,16 +348,16 @@ export default {
|
|||
},
|
||||
enter($event) {
|
||||
if (this.showVersion) {
|
||||
$event.currentTarget.className = "scenario-name";
|
||||
$event.currentTarget.className = 'scenario-name';
|
||||
} else {
|
||||
$event.currentTarget.className = "scenario-version";
|
||||
$event.currentTarget.className = 'scenario-version';
|
||||
}
|
||||
},
|
||||
leave($event) {
|
||||
if (this.showVersion) {
|
||||
$event.currentTarget.className = "scenario-unscroll";
|
||||
$event.currentTarget.className = 'scenario-unscroll';
|
||||
} else {
|
||||
$event.currentTarget.className = "scenario-version";
|
||||
$event.currentTarget.className = 'scenario-version';
|
||||
}
|
||||
},
|
||||
enable() {
|
||||
|
|
|
@ -4,167 +4,187 @@
|
|||
:title="$t('load_test.runtime_config')"
|
||||
width="550px"
|
||||
@close="close"
|
||||
:visible.sync="runModeVisible">
|
||||
:visible.sync="runModeVisible"
|
||||
>
|
||||
<div class="env-container">
|
||||
<div>
|
||||
<div>{{ $t("commons.environment") }}:</div>
|
||||
<env-select-popover :project-ids="projectIds"
|
||||
:project-list="projectList"
|
||||
:case-id-env-name-map="caseIdEnvNameMap"
|
||||
:is-scenario="isScenario"
|
||||
:project-env-map="projectEnvListMap"
|
||||
:group-id="runConfig.environmentGroupId"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
@setEnvGroup="setEnvGroup"
|
||||
ref="envSelectPopover"
|
||||
class="mode-row"
|
||||
<div>{{ $t('commons.environment') }}:</div>
|
||||
<env-select-popover
|
||||
:project-ids="projectIds"
|
||||
:project-list="projectList"
|
||||
:case-id-env-name-map="caseIdEnvNameMap"
|
||||
:is-scenario="isScenario"
|
||||
:project-env-map="projectEnvListMap"
|
||||
:group-id="runConfig.environmentGroupId"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
@setEnvGroup="setEnvGroup"
|
||||
ref="envSelectPopover"
|
||||
class="mode-row"
|
||||
></env-select-popover>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="mode-row">{{ $t("run_mode.title") }}:</div>
|
||||
<div >
|
||||
<div class="mode-row">{{ $t('run_mode.title') }}:</div>
|
||||
<div>
|
||||
<el-radio-group
|
||||
v-model="runConfig.mode"
|
||||
@change="changeMode"
|
||||
style="width: 100%"
|
||||
class="radio-change mode-row"
|
||||
>
|
||||
<el-radio label="serial">{{ $t("run_mode.serial") }}</el-radio>
|
||||
<el-radio label="parallel">{{ $t("run_mode.parallel") }}</el-radio>
|
||||
<el-radio label="serial">{{ $t('run_mode.serial') }}</el-radio>
|
||||
<el-radio label="parallel">{{ $t('run_mode.parallel') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 资源池 -->
|
||||
<div>
|
||||
<div class="mode-row">{{ $t("run_mode.other_config") }}:</div>
|
||||
<div class="mode-row">{{ $t('run_mode.other_config') }}:</div>
|
||||
<div class="mode-row">
|
||||
<el-radio-group v-model="runConfig.reportType">
|
||||
<el-radio label="iddReport">{{ $t("run_mode.idd_report") }}</el-radio>
|
||||
<el-radio label="setReport">{{ $t("run_mode.set_report") }}</el-radio>
|
||||
<el-radio label="iddReport">{{
|
||||
$t('run_mode.idd_report')
|
||||
}}</el-radio>
|
||||
<el-radio label="setReport">{{
|
||||
$t('run_mode.set_report')
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="ms-mode-span-label" style="margin-top: 8px" v-if="runConfig.reportType === 'setReport'">{{ $t("run_mode.report_name") }}:</div>
|
||||
<div
|
||||
class="ms-mode-span-label"
|
||||
style="margin-top: 8px"
|
||||
v-if="runConfig.reportType === 'setReport'"
|
||||
>
|
||||
{{ $t('run_mode.report_name') }}:
|
||||
</div>
|
||||
<div class="mode-row" v-if="runConfig.reportType === 'setReport'">
|
||||
<el-input
|
||||
v-model="runConfig.reportName"
|
||||
:placeholder="$t('commons.input_content')"
|
||||
size="small"
|
||||
style="width: 100%"/>
|
||||
style="width: 100%"
|
||||
/>
|
||||
</div>
|
||||
<div class="mode-row">
|
||||
<el-checkbox v-model="runConfig.runWithinResourcePool"
|
||||
:disabled="runMode === 'POOL'">
|
||||
{{ $t('run_mode.run_with_resource_pool') }}
|
||||
</el-checkbox><br/>
|
||||
<el-select :disabled="!runConfig.runWithinResourcePool" v-model="runConfig.resourcePoolId" size="mini" class="mode-row" style="width: 100%">
|
||||
<el-checkbox
|
||||
v-model="runConfig.runWithinResourcePool"
|
||||
:disabled="runMode === 'POOL'"
|
||||
>
|
||||
{{ $t('run_mode.run_with_resource_pool') }} </el-checkbox
|
||||
><br />
|
||||
<el-select
|
||||
:disabled="!runConfig.runWithinResourcePool"
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
class="mode-row"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:disabled="!item.api"
|
||||
:value="item.id">
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- 失败停止 -->
|
||||
<div class="mode-row" v-if="runConfig.mode === 'serial'">
|
||||
<el-checkbox v-model="runConfig.onSampleError" class="radio-change">{{
|
||||
$t("api_test.fail_to_stop")
|
||||
}}
|
||||
<el-checkbox v-model="runConfig.onSampleError" class="radio-change"
|
||||
>{{ $t('api_test.fail_to_stop') }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer @cancel="close" @confirm="handleRunBatch"/>
|
||||
<ms-dialog-footer @cancel="close" @confirm="handleRunBatch" />
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import {apiScenarioEnvMap} from "@/api/scenario";
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {strMapToObj} from "metersphere-frontend/src/utils";
|
||||
import {getOwnerProjects, getProjectConfig} from "@/api/project";
|
||||
import {getTestResourcePools} from "@/api/test-resource-pool";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {getSystemBaseSetting} from "metersphere-frontend/src/api/system";
|
||||
import EnvSelectPopover from "@/business/automation/scenario/EnvSelectPopover";
|
||||
import {getApiCaseEnvironments} from "@/api/api-test-case";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import { apiScenarioEnvMap } from '@/api/scenario';
|
||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter';
|
||||
import { ENV_TYPE } from 'metersphere-frontend/src/utils/constants';
|
||||
import { strMapToObj } from 'metersphere-frontend/src/utils';
|
||||
import { getOwnerProjects, getProjectConfig } from '@/api/project';
|
||||
import { getTestResourcePools } from '@/api/test-resource-pool';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { getSystemBaseSetting } from 'metersphere-frontend/src/api/system';
|
||||
import EnvSelectPopover from '@/business/automation/scenario/EnvSelectPopover';
|
||||
import { getApiCaseEnvironments } from '@/api/api-test-case';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
|
||||
export default {
|
||||
name: "ApiRunMode",
|
||||
components: {MsDialogFooter, EnvSelectPopover},
|
||||
name: 'ApiRunMode',
|
||||
components: { MsDialogFooter, EnvSelectPopover },
|
||||
data() {
|
||||
return {
|
||||
runMode: "",
|
||||
runMode: '',
|
||||
loading: false,
|
||||
runModeVisible: false,
|
||||
testType: null,
|
||||
resourcePools: [],
|
||||
runConfig: {
|
||||
reportName: "",
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
reportName: '',
|
||||
mode: 'serial',
|
||||
reportType: 'iddReport',
|
||||
onSampleError: false,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
envMap: new Map(),
|
||||
environmentGroupId: "",
|
||||
environmentType: ENV_TYPE.JSON
|
||||
environmentGroupId: '',
|
||||
environmentType: ENV_TYPE.JSON,
|
||||
},
|
||||
projectEnvListMap: {},
|
||||
projectList: [],
|
||||
projectIds: new Set(),
|
||||
caseIdEnvNameMap:{},
|
||||
caseIdEnvNameMap: {},
|
||||
};
|
||||
},
|
||||
props: {
|
||||
runCaseIds:Array,
|
||||
runCaseIds: Array,
|
||||
request: Object,
|
||||
isScenario: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'runConfig.runWithinResourcePool'() {
|
||||
if (!this.runConfig.runWithinResourcePool) {
|
||||
this.runConfig = {
|
||||
mode: this.runConfig.mode,
|
||||
reportType: "iddReport",
|
||||
reportName: "",
|
||||
reportType: 'iddReport',
|
||||
reportName: '',
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.runModeVisible = true;
|
||||
this.getResourcePools();
|
||||
this.getWsProjects();
|
||||
if(hasLicense()) {
|
||||
if (hasLicense()) {
|
||||
this.query();
|
||||
}
|
||||
this.showPopover();
|
||||
this.runConfig.environmentType = ENV_TYPE.JSON;
|
||||
},
|
||||
changeMode() {
|
||||
this.runConfig.reportType = "iddReport";
|
||||
this.runConfig.reportName = "";
|
||||
this.runConfig.reportType = 'iddReport';
|
||||
this.runConfig.reportName = '';
|
||||
},
|
||||
close() {
|
||||
this.runConfig = {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
reportName: "",
|
||||
mode: 'serial',
|
||||
reportType: 'iddReport',
|
||||
reportName: '',
|
||||
environmentType: ENV_TYPE.JSON,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
|
@ -173,32 +193,42 @@ export default {
|
|||
this.$emit('close');
|
||||
},
|
||||
getWsProjects() {
|
||||
getOwnerProjects().then(res => {
|
||||
getOwnerProjects().then((res) => {
|
||||
this.projectList = res.data;
|
||||
})
|
||||
});
|
||||
},
|
||||
handleRunBatch() {
|
||||
if ((this.runConfig.mode === 'serial' || this.runConfig.mode === 'parallel') && this.runConfig.reportType === 'setReport' && this.runConfig.reportName.trim() === "") {
|
||||
if (
|
||||
(this.runConfig.mode === 'serial' ||
|
||||
this.runConfig.mode === 'parallel') &&
|
||||
this.runConfig.reportType === 'setReport' &&
|
||||
this.runConfig.reportName.trim() === ''
|
||||
) {
|
||||
this.$warning(this.$t('commons.input_name'));
|
||||
return;
|
||||
}
|
||||
if (this.runConfig.runWithinResourcePool && this.runConfig.resourcePoolId == null) {
|
||||
this.$warning(this.$t('workspace.env_group.please_select_run_within_resource_pool'));
|
||||
if (
|
||||
this.runConfig.runWithinResourcePool &&
|
||||
this.runConfig.resourcePoolId == null
|
||||
) {
|
||||
this.$warning(
|
||||
this.$t('workspace.env_group.please_select_run_within_resource_pool')
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.$emit("handleRunBatch", this.runConfig);
|
||||
this.$emit('handleRunBatch', this.runConfig);
|
||||
this.close();
|
||||
},
|
||||
getResourcePools() {
|
||||
this.result = getTestResourcePools().then(response => {
|
||||
this.result = getTestResourcePools().then((response) => {
|
||||
this.resourcePools = response.data;
|
||||
});
|
||||
},
|
||||
query() {
|
||||
this.loading = true;
|
||||
this.result = getSystemBaseSetting().then(response => {
|
||||
this.result = getSystemBaseSetting().then((response) => {
|
||||
if (!response.data.runMode) {
|
||||
response.data.runMode = 'LOCAL'
|
||||
response.data.runMode = 'LOCAL';
|
||||
}
|
||||
this.runMode = response.data.runMode;
|
||||
if (this.runMode === 'POOL') {
|
||||
|
@ -207,10 +237,10 @@ export default {
|
|||
} else {
|
||||
this.loading = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
getProjectApplication() {
|
||||
getProjectConfig(getCurrentProjectID(), "").then(res => {
|
||||
getProjectConfig(getCurrentProjectID(), '').then((res) => {
|
||||
if (res.data && res.data.poolEnable && res.data.resourcePoolId) {
|
||||
this.runConfig.resourcePoolId = res.data.resourcePoolId;
|
||||
}
|
||||
|
@ -245,7 +275,7 @@ export default {
|
|||
showScenarioPopover() {
|
||||
let currentProjectID = getCurrentProjectID();
|
||||
this.projectIds.clear();
|
||||
apiScenarioEnvMap(this.request).then(res => {
|
||||
apiScenarioEnvMap(this.request).then((res) => {
|
||||
let data = res.data;
|
||||
this.projectEnvListMap = data;
|
||||
if (data) {
|
||||
|
@ -253,10 +283,10 @@ export default {
|
|||
this.projectIds.add(d);
|
||||
}
|
||||
}
|
||||
if (this.projectIds.size===0){
|
||||
if (this.projectIds.size === 0) {
|
||||
this.projectIds.add(currentProjectID);
|
||||
}
|
||||
this.$refs.envSelectPopover.open();
|
||||
this.$refs.envSelectPopover.open();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
@ -284,13 +314,11 @@ export default {
|
|||
|
||||
.ms-mode-span-label:before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss" scoped>
|
||||
.radio-change:deep(.el-radio__input.is-checked + .el-radio__label) {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -2,31 +2,86 @@
|
|||
<div>
|
||||
<div v-if="request.protocol === 'HTTP'">
|
||||
<div v-if="isCustomizeReq">
|
||||
<el-select v-model="request.method" class="ms-select" size="small" :disabled="request.disabled">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
<el-select
|
||||
v-model="request.method"
|
||||
class="ms-select"
|
||||
size="small"
|
||||
:disabled="request.disabled"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in reqOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-model="request.domain" v-if="request.isRefEnvironment && request.domain" size="small" readonly
|
||||
class="ms-input"/>
|
||||
<el-input
|
||||
v-model="request.domain"
|
||||
v-if="request.isRefEnvironment && request.domain"
|
||||
size="small"
|
||||
readonly
|
||||
class="ms-input"
|
||||
/>
|
||||
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-model="request.path"
|
||||
style="width: 50%" size="small" @blur="urlChange" :disabled="request.disabled"
|
||||
v-if="request.isRefEnvironment"/>
|
||||
<el-input
|
||||
:placeholder="$t('api_test.definition.request.path_all_info')"
|
||||
v-model="request.path"
|
||||
style="width: 50%"
|
||||
size="small"
|
||||
@blur="urlChange"
|
||||
:disabled="request.disabled"
|
||||
v-if="request.isRefEnvironment"
|
||||
/>
|
||||
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-model="request.url"
|
||||
style="width: 50%" size="small" @blur="urlChange" :disabled="request.disabled" v-else/>
|
||||
<el-checkbox v-if="isCustomizeReq" class="is-ref-environment" v-model="request.isRefEnvironment"
|
||||
@change="setDomain" :disabled="request.disabled">
|
||||
<el-input
|
||||
:placeholder="$t('api_test.definition.request.path_all_info')"
|
||||
v-model="request.url"
|
||||
style="width: 50%"
|
||||
size="small"
|
||||
@blur="urlChange"
|
||||
:disabled="request.disabled"
|
||||
v-else
|
||||
/>
|
||||
<el-checkbox
|
||||
v-if="isCustomizeReq"
|
||||
class="is-ref-environment"
|
||||
v-model="request.isRefEnvironment"
|
||||
@change="setDomain"
|
||||
:disabled="request.disabled"
|
||||
>
|
||||
{{ $t('api_test.request.refer_to_environment') }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-select v-model="request.method" class="ms-select" size="small" :disabled="request.disabled">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
<el-select
|
||||
v-model="request.method"
|
||||
class="ms-select"
|
||||
size="small"
|
||||
:disabled="request.disabled"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in reqOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-model="request.domain" v-if="request.domain" size="small" readonly class="ms-input"
|
||||
:disabled="request.disabled"/>
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" style="width: 50%"
|
||||
v-model="request.path" size="small" @blur="pathChange" :disabled="request.disabled"/>
|
||||
<el-input
|
||||
v-model="request.domain"
|
||||
v-if="request.domain"
|
||||
size="small"
|
||||
readonly
|
||||
class="ms-input"
|
||||
:disabled="request.disabled"
|
||||
/>
|
||||
<el-input
|
||||
:placeholder="$t('api_test.definition.request.path_all_info')"
|
||||
style="width: 50%"
|
||||
v-model="request.path"
|
||||
size="small"
|
||||
@blur="pathChange"
|
||||
:disabled="request.disabled"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -34,13 +89,26 @@
|
|||
<el-form>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('api_test.request.tcp.server')" prop="server">
|
||||
<el-input class="server-input" v-model="request.server" maxlength="300" show-word-limit size="small"/>
|
||||
<el-form-item
|
||||
:label="$t('api_test.request.tcp.server')"
|
||||
prop="server"
|
||||
>
|
||||
<el-input
|
||||
class="server-input"
|
||||
v-model="request.server"
|
||||
maxlength="300"
|
||||
show-word-limit
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.request.tcp.port')" prop="port" label-width="60px">
|
||||
<el-input v-model="request.port" size="small"/>
|
||||
<el-form-item
|
||||
:label="$t('api_test.request.tcp.port')"
|
||||
prop="port"
|
||||
label-width="60px"
|
||||
>
|
||||
<el-input v-model="request.port" size="small" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -50,17 +118,17 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {REQ_METHOD} from "@/business/definition/model/JsonData";
|
||||
import {KeyValue} from "../../../definition/model/ApiTestModel";
|
||||
import { REQ_METHOD } from '@/business/definition/model/JsonData';
|
||||
import { KeyValue } from '../../../definition/model/ApiTestModel';
|
||||
|
||||
export default {
|
||||
name: "CustomizeReqInfo",
|
||||
name: 'CustomizeReqInfo',
|
||||
props: ['request', 'isCustomizeReq'],
|
||||
data() {
|
||||
return {
|
||||
reqOptions: REQ_METHOD,
|
||||
isUrl: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
pathChange() {
|
||||
|
@ -68,7 +136,9 @@ export default {
|
|||
if (!this.request.path || this.request.path.indexOf('?') === -1) return;
|
||||
let url = this.getURL(this.addProtocol(this.request.path));
|
||||
if (url) {
|
||||
this.request.path = decodeURIComponent(this.request.path.substr(0, this.request.path.indexOf("?")));
|
||||
this.request.path = decodeURIComponent(
|
||||
this.request.path.substr(0, this.request.path.indexOf('?'))
|
||||
);
|
||||
}
|
||||
},
|
||||
urlChange() {
|
||||
|
@ -79,17 +149,24 @@ export default {
|
|||
if (!this.request.url || this.request.url.indexOf('?') === -1) return;
|
||||
let url = this.getURL(this.addProtocol(this.request.url));
|
||||
if (url) {
|
||||
let paramUrl = this.request.url.substr(this.request.url.indexOf("?") + 1);
|
||||
let paramUrl = this.request.url.substr(
|
||||
this.request.url.indexOf('?') + 1
|
||||
);
|
||||
if (paramUrl) {
|
||||
this.request.url = decodeURIComponent(this.request.url.substr(0, this.request.url.indexOf("?")));
|
||||
this.request.url = decodeURIComponent(
|
||||
this.request.url.substr(0, this.request.url.indexOf('?'))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
addProtocol(url) {
|
||||
if (url) {
|
||||
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
|
||||
return "https://" + url;
|
||||
if (
|
||||
!url.toLowerCase().startsWith('https') &&
|
||||
!url.toLowerCase().startsWith('http')
|
||||
) {
|
||||
return 'https://' + url;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
|
@ -98,17 +175,21 @@ export default {
|
|||
try {
|
||||
let url = new URL(urlStr);
|
||||
if (url.search && url.search.length > 1) {
|
||||
let params = url.search.substr(1).split("&");
|
||||
params.forEach(param => {
|
||||
let params = url.search.substr(1).split('&');
|
||||
params.forEach((param) => {
|
||||
if (param) {
|
||||
let keyValues = param.split("=");
|
||||
let keyValues = param.split('=');
|
||||
if (keyValues) {
|
||||
this.isUrl = true;
|
||||
this.request.arguments.splice(0, 0, new KeyValue({
|
||||
name: keyValues[0],
|
||||
required: false,
|
||||
value: keyValues[1]
|
||||
}));
|
||||
this.request.arguments.splice(
|
||||
0,
|
||||
0,
|
||||
new KeyValue({
|
||||
name: keyValues[0],
|
||||
required: false,
|
||||
value: keyValues[1],
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -127,12 +208,12 @@ export default {
|
|||
this.request.path = url.pathname;
|
||||
}
|
||||
} else {
|
||||
this.request.path = this.request.url
|
||||
this.request.path = this.request.url;
|
||||
}
|
||||
this.$emit("setDomain");
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$emit('setDomain');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,24 +1,51 @@
|
|||
<template>
|
||||
<div v-loading="isReloadData || result">
|
||||
<div class="jdbc-class">
|
||||
<el-form :model="request" :rules="rules" ref="request" label-width="100px" :disabled="request.disabled"
|
||||
style="margin: 10px">
|
||||
<el-form
|
||||
:model="request"
|
||||
:rules="rules"
|
||||
ref="request"
|
||||
label-width="100px"
|
||||
:disabled="request.disabled"
|
||||
style="margin: 10px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="environmentId" :label="$t('api_test.definition.request.run_env')">
|
||||
<el-select v-model="request.environmentId" size="small" class="ms-htt-width"
|
||||
:placeholder="$t('api_test.definition.request.run_env')"
|
||||
@change="environmentChange" clearable :disabled="isReadOnly">
|
||||
<el-option v-for="(environment, index) in environments" :key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"/>
|
||||
<el-button class="environment-button" size="small" type="primary" @click="openEnvironmentConfig">
|
||||
<el-form-item
|
||||
prop="environmentId"
|
||||
:label="$t('api_test.definition.request.run_env')"
|
||||
>
|
||||
<el-select
|
||||
v-model="request.environmentId"
|
||||
size="small"
|
||||
class="ms-htt-width"
|
||||
:placeholder="$t('api_test.definition.request.run_env')"
|
||||
@change="environmentChange"
|
||||
clearable
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
<el-option
|
||||
v-for="(environment, index) in environments"
|
||||
:key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"
|
||||
/>
|
||||
<el-button
|
||||
class="environment-button"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="openEnvironmentConfig"
|
||||
>
|
||||
{{ $t('api_test.environment.environment_config') }}
|
||||
</el-button>
|
||||
<template v-slot:empty>
|
||||
<div class="empty-environment">
|
||||
<el-button class="environment-button" size="small" type="primary"
|
||||
@click="openEnvironmentConfig">
|
||||
<el-button
|
||||
class="environment-button"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="openEnvironmentConfig"
|
||||
>
|
||||
{{ $t('api_test.environment.environment_config') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -27,38 +54,83 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('api_test.request.sql.dataSource')" prop="dataSourceId"
|
||||
style="margin-left: 10px">
|
||||
<el-select v-model="request.dataSourceId" size="small" @change="reload" :disabled="request.disabled">
|
||||
<el-option v-for="(item, index) in databaseConfigsOptions" :key="index" :value="item.id"
|
||||
:label="item.name"/>
|
||||
<el-form-item
|
||||
:label="$t('api_test.request.sql.dataSource')"
|
||||
prop="dataSourceId"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<el-select
|
||||
v-model="request.dataSourceId"
|
||||
size="small"
|
||||
@change="reload"
|
||||
:disabled="request.disabled"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in databaseConfigsOptions"
|
||||
:key="index"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('api_test.request.sql.timeout')" prop="queryTimeout" style="margin-left: 10px">
|
||||
<el-input-number :disabled="request.disabled" size="small" v-model="request.queryTimeout"
|
||||
:placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="0"/>
|
||||
<el-form-item
|
||||
:label="$t('api_test.request.sql.timeout')"
|
||||
prop="queryTimeout"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<el-input-number
|
||||
:disabled="request.disabled"
|
||||
size="small"
|
||||
v-model="request.queryTimeout"
|
||||
:placeholder="$t('commons.millisecond')"
|
||||
:max="1000 * 10000000"
|
||||
:min="0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<el-form-item :label="$t('api_test.request.sql.result_variable')" prop="resultVariable">
|
||||
<el-input v-model="request.resultVariable" maxlength="500" show-word-limit size="small"/>
|
||||
<el-form-item
|
||||
:label="$t('api_test.request.sql.result_variable')"
|
||||
prop="resultVariable"
|
||||
>
|
||||
<el-input
|
||||
v-model="request.resultVariable"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('api_test.request.sql.variable_names')" prop="variableNames">
|
||||
<el-input v-model="request.variableNames" maxlength="500" show-word-limit size="small"/>
|
||||
<el-form-item
|
||||
:label="$t('api_test.request.sql.variable_names')"
|
||||
prop="variableNames"
|
||||
>
|
||||
<el-input
|
||||
v-model="request.variableNames"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-tabs v-model="activeName" class="ms-sql-tabs">
|
||||
<el-tab-pane :label="$t('api_test.scenario.variables')" name="variables">
|
||||
<ms-api-scenario-variables :is-read-only="isReadOnly" :items="request.variables"
|
||||
:description="$t('api_test.scenario.kv_description')"/>
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.scenario.variables')"
|
||||
name="variables"
|
||||
>
|
||||
<ms-api-scenario-variables
|
||||
:is-read-only="isReadOnly"
|
||||
:items="request.variables"
|
||||
:description="$t('api_test.scenario.kv_description')"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.sql.sql_script')" name="sql">
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.request.sql.sql_script')"
|
||||
name="sql"
|
||||
>
|
||||
<ms-code-edit
|
||||
:height="120"
|
||||
:read-only="isReadOnly"
|
||||
|
@ -66,40 +138,46 @@
|
|||
:data.sync="request.query"
|
||||
theme="eclipse"
|
||||
mode="sql"
|
||||
ref="codeEdit"/>
|
||||
ref="codeEdit"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 环境 -->
|
||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||
<api-environment-config
|
||||
ref="environmentConfig"
|
||||
@close="environmentConfigClose"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsApiKeyValue from "@/business/definition/components/ApiKeyValue";
|
||||
import MsApiExtract from "@/business/definition/components/extract/ApiExtract";
|
||||
import ApiRequestMethodSelect from "@/business/definition/components/collapse/ApiRequestMethodSelect";
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
import MsApiScenarioVariables from "@/business/definition/components/ApiScenarioVariables";
|
||||
import {parseEnvironment} from "@/business/environment/model/EnvironmentModel";
|
||||
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {getUUID, objToStrMap} from "metersphere-frontend/src/utils";
|
||||
import MsJsr233Processor from "@/business/automation/scenario/component/Jsr233Processor";
|
||||
import {getEnvironmentByProjectId} from "metersphere-frontend/src/api/environment";
|
||||
import {useApiStore} from "@/store";
|
||||
import MsApiKeyValue from '@/business/definition/components/ApiKeyValue';
|
||||
import MsApiExtract from '@/business/definition/components/extract/ApiExtract';
|
||||
import ApiRequestMethodSelect from '@/business/definition/components/collapse/ApiRequestMethodSelect';
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
import MsApiScenarioVariables from '@/business/definition/components/ApiScenarioVariables';
|
||||
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
|
||||
import ApiEnvironmentConfig from 'metersphere-frontend/src/components/environment/ApiEnvironmentConfig';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { getUUID, objToStrMap } from 'metersphere-frontend/src/utils';
|
||||
import MsJsr233Processor from '@/business/automation/scenario/component/Jsr233Processor';
|
||||
import { getEnvironmentByProjectId } from 'metersphere-frontend/src/api/environment';
|
||||
import { useApiStore } from '@/store';
|
||||
|
||||
const store = useApiStore();
|
||||
export default {
|
||||
name: "JdbcProcessorContent",
|
||||
name: 'JdbcProcessorContent',
|
||||
components: {
|
||||
MsJsr233Processor,
|
||||
MsApiScenarioVariables,
|
||||
MsCodeEdit,
|
||||
ApiRequestMethodSelect, MsApiExtract, MsApiKeyValue, ApiEnvironmentConfig
|
||||
ApiRequestMethodSelect,
|
||||
MsApiExtract,
|
||||
MsApiKeyValue,
|
||||
ApiEnvironmentConfig,
|
||||
},
|
||||
props: {
|
||||
request: {},
|
||||
|
@ -112,7 +190,7 @@ export default {
|
|||
scenarioId: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
|
@ -122,9 +200,9 @@ export default {
|
|||
currentEnvironment: {},
|
||||
databaseConfigsOptions: [],
|
||||
isReloadData: false,
|
||||
activeName: "variables",
|
||||
activeName: 'variables',
|
||||
rules: {},
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getEnvironments();
|
||||
|
@ -142,14 +220,14 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
// 场景环境监听
|
||||
'storeScenarioEnvMap': {
|
||||
storeScenarioEnvMap: {
|
||||
handler(v) {
|
||||
this.getEnvironments();
|
||||
},
|
||||
deep: true
|
||||
deep: true,
|
||||
},
|
||||
// 接口/用例 右上角公共环境监听
|
||||
'storeUseEnvironment': function () {
|
||||
storeUseEnvironment: function () {
|
||||
if (!this.scenarioId) {
|
||||
this.getEnvironments(store.useEnvironment);
|
||||
}
|
||||
|
@ -174,43 +252,41 @@ export default {
|
|||
this.reload();
|
||||
},
|
||||
reload() {
|
||||
this.isReloadData = true
|
||||
this.isReloadData = true;
|
||||
this.$nextTick(() => {
|
||||
this.isReloadData = false
|
||||
})
|
||||
this.isReloadData = false;
|
||||
});
|
||||
},
|
||||
validate() {
|
||||
this.$refs['request'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$emit('callback');
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
saveApi() {
|
||||
this.basisData.method = this.basisData.protocol;
|
||||
this.$emit('saveApi', this.basisData);
|
||||
},
|
||||
runTest() {
|
||||
|
||||
},
|
||||
runTest() {},
|
||||
itselfEnvironment(environmentId) {
|
||||
let id = this.request.projectId ? this.request.projectId : this.projectId;
|
||||
this.result = getEnvironmentByProjectId(id).then(response => {
|
||||
this.result = getEnvironmentByProjectId(id).then((response) => {
|
||||
this.environments = response.data;
|
||||
let targetDataSourceName = this.request.targetDataSourceName;
|
||||
this.environments.forEach(environment => {
|
||||
this.environments.forEach((environment) => {
|
||||
parseEnvironment(environment);
|
||||
// 找到原始环境和数据源名称
|
||||
if (environment.id === this.request.environmentId) {
|
||||
if (environment.config && environment.config.databaseConfigs) {
|
||||
environment.config.databaseConfigs.forEach(item => {
|
||||
environment.config.databaseConfigs.forEach((item) => {
|
||||
if (item.id === this.request.dataSourceId) {
|
||||
targetDataSourceName = item.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
if (environmentId) {
|
||||
this.request.environmentId = environmentId;
|
||||
}
|
||||
|
@ -218,11 +294,15 @@ export default {
|
|||
});
|
||||
},
|
||||
getEnvironments(environmentId) {
|
||||
let envId = "";
|
||||
let envId = '';
|
||||
let id = this.request.projectId ? this.request.projectId : this.projectId;
|
||||
let scenarioEnvId = this.scenarioId !== "" ? (this.scenarioId + "_" + id) : id;
|
||||
if (store.scenarioEnvMap && store.scenarioEnvMap instanceof Map
|
||||
&& store.scenarioEnvMap.has(scenarioEnvId)) {
|
||||
let scenarioEnvId =
|
||||
this.scenarioId !== '' ? this.scenarioId + '_' + id : id;
|
||||
if (
|
||||
store.scenarioEnvMap &&
|
||||
store.scenarioEnvMap instanceof Map &&
|
||||
store.scenarioEnvMap.has(scenarioEnvId)
|
||||
) {
|
||||
envId = store.scenarioEnvMap.get(scenarioEnvId);
|
||||
}
|
||||
if (!this.scenarioId && !this.request.customizeReq) {
|
||||
|
@ -232,29 +312,43 @@ export default {
|
|||
this.environments = [];
|
||||
// 场景开启自身环境
|
||||
if (this.request.environmentEnable && this.request.refEevMap) {
|
||||
let obj = Object.prototype.toString.call(this.request.refEevMap).match(/\[object (\w+)\]/)[1].toLowerCase();
|
||||
if (obj !== 'object' && obj !== "map") {
|
||||
this.request.refEevMap = objToStrMap(JSON.parse(this.request.refEevMap));
|
||||
} else if (obj === 'object' && obj !== "map") {
|
||||
let obj = Object.prototype.toString
|
||||
.call(this.request.refEevMap)
|
||||
.match(/\[object (\w+)\]/)[1]
|
||||
.toLowerCase();
|
||||
if (obj !== 'object' && obj !== 'map') {
|
||||
this.request.refEevMap = objToStrMap(
|
||||
JSON.parse(this.request.refEevMap)
|
||||
);
|
||||
} else if (obj === 'object' && obj !== 'map') {
|
||||
this.request.refEevMap = objToStrMap(this.request.refEevMap);
|
||||
}
|
||||
if (this.request.refEevMap instanceof Map && this.request.refEevMap.has(id)) {
|
||||
if (
|
||||
this.request.refEevMap instanceof Map &&
|
||||
this.request.refEevMap.has(id)
|
||||
) {
|
||||
envId = this.request.refEevMap.get(id);
|
||||
}
|
||||
}
|
||||
if (envId === this.request.originalEnvironmentId && this.request.originalDataSourceId) {
|
||||
if (
|
||||
envId === this.request.originalEnvironmentId &&
|
||||
this.request.originalDataSourceId
|
||||
) {
|
||||
this.request.dataSourceId = this.request.originalDataSourceId;
|
||||
}
|
||||
let targetDataSourceName = "";
|
||||
let targetDataSourceName = '';
|
||||
let currentEnvironment = {};
|
||||
this.result = getEnvironmentByProjectId(id).then(response => {
|
||||
this.result = getEnvironmentByProjectId(id).then((response) => {
|
||||
this.environments = response.data;
|
||||
this.environments.forEach(environment => {
|
||||
this.environments.forEach((environment) => {
|
||||
parseEnvironment(environment);
|
||||
// 找到原始环境和数据源名称
|
||||
if (environment.id === this.request.environmentId && environment.id !== envId) {
|
||||
if (
|
||||
environment.id === this.request.environmentId &&
|
||||
environment.id !== envId
|
||||
) {
|
||||
if (environment.config && environment.config.databaseConfigs) {
|
||||
environment.config.databaseConfigs.forEach(item => {
|
||||
environment.config.databaseConfigs.forEach((item) => {
|
||||
if (item.id === this.request.dataSourceId) {
|
||||
targetDataSourceName = item.name;
|
||||
}
|
||||
|
@ -273,14 +367,18 @@ export default {
|
|||
this.$refs.environmentConfig.open(getCurrentProjectID());
|
||||
},
|
||||
setStep(envId, currentEnvironment, targetDataSourceName) {
|
||||
let envs = this.environments.filter(item => this.request && item.id === this.request.environmentId);
|
||||
let envs = this.environments.filter(
|
||||
(item) => this.request && item.id === this.request.environmentId
|
||||
);
|
||||
if (envs && envs.length === 0) {
|
||||
let id = this.request.projectId ? this.request.projectId : this.projectId;
|
||||
this.result = getEnvironmentByProjectId(id).then(response => {
|
||||
let id = this.request.projectId
|
||||
? this.request.projectId
|
||||
: this.projectId;
|
||||
this.result = getEnvironmentByProjectId(id).then((response) => {
|
||||
this.environments = response.data;
|
||||
this.environments.forEach(environment => {
|
||||
this.environments.forEach((environment) => {
|
||||
parseEnvironment(environment);
|
||||
})
|
||||
});
|
||||
this.initDataSource(envId, currentEnvironment, targetDataSourceName);
|
||||
});
|
||||
} else {
|
||||
|
@ -300,8 +398,12 @@ export default {
|
|||
}
|
||||
}
|
||||
let flag = false;
|
||||
if (currentEnvironment && currentEnvironment.config && currentEnvironment.config.databaseConfigs) {
|
||||
currentEnvironment.config.databaseConfigs.forEach(item => {
|
||||
if (
|
||||
currentEnvironment &&
|
||||
currentEnvironment.config &&
|
||||
currentEnvironment.config.databaseConfigs
|
||||
) {
|
||||
currentEnvironment.config.databaseConfigs.forEach((item) => {
|
||||
if (item.id === this.request.dataSourceId) {
|
||||
flag = true;
|
||||
}
|
||||
|
@ -313,12 +415,13 @@ export default {
|
|||
this.databaseConfigsOptions.push(item);
|
||||
});
|
||||
if (!flag && currentEnvironment.config.databaseConfigs.length > 0) {
|
||||
this.request.dataSourceId = currentEnvironment.config.databaseConfigs[0].id;
|
||||
this.request.dataSourceId =
|
||||
currentEnvironment.config.databaseConfigs[0].id;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.request.dataSourceId = "";
|
||||
this.request.dataSourceId = '';
|
||||
}
|
||||
},
|
||||
setDataSource() {
|
||||
|
@ -333,7 +436,7 @@ export default {
|
|||
},
|
||||
environmentChange(value) {
|
||||
this.request.dataSource = undefined;
|
||||
this.request.dataSourceId = "";
|
||||
this.request.dataSourceId = '';
|
||||
let environment = {};
|
||||
for (let i in this.environments) {
|
||||
if (this.environments[i].id === value) {
|
||||
|
@ -343,21 +446,19 @@ export default {
|
|||
}
|
||||
this.databaseConfigsOptions = [];
|
||||
if (environment.config && environment.config.databaseConfigs) {
|
||||
environment.config.databaseConfigs.forEach(item => {
|
||||
environment.config.databaseConfigs.forEach((item) => {
|
||||
this.databaseConfigsOptions.push(item);
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
environmentConfigClose() {
|
||||
this.getEnvironments();
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.ms-sql-tabs {
|
||||
min-height: 160px;
|
||||
}
|
||||
|
@ -388,9 +489,9 @@ export default {
|
|||
}
|
||||
|
||||
.jdbc-class {
|
||||
border: 1px #DCDFE6 solid;
|
||||
border: 1px #dcdfe6 solid;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
width: 100%
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,37 +2,55 @@
|
|||
<div>
|
||||
<el-row type="flex" :gutter="10">
|
||||
<el-col :span="codeSpan" class="script-content">
|
||||
<ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223ProcessorData.scriptLanguage]"
|
||||
:read-only="isReadOnly"
|
||||
:data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="['java','python']"
|
||||
ref="codeEdit"/>
|
||||
<ms-code-edit
|
||||
v-if="isCodeEditAlive"
|
||||
:mode="codeEditModeMap[jsr223ProcessorData.scriptLanguage]"
|
||||
:read-only="isReadOnly"
|
||||
:data.sync="jsr223ProcessorData.script"
|
||||
theme="eclipse"
|
||||
:modes="['java', 'python']"
|
||||
ref="codeEdit"
|
||||
/>
|
||||
</el-col>
|
||||
<div style="width: 14px;margin-right: 5px;">
|
||||
<div style="height: 12px;width: 12px; line-height:12px;">
|
||||
<i :class="showMenu ? 'el-icon-remove-outline' : 'el-icon-circle-plus-outline'"
|
||||
class="show-menu"
|
||||
@click="switchMenu"></i>
|
||||
<div style="width: 14px; margin-right: 5px">
|
||||
<div style="height: 12px; width: 12px; line-height: 12px">
|
||||
<i
|
||||
:class="
|
||||
showMenu
|
||||
? 'el-icon-remove-outline'
|
||||
: 'el-icon-circle-plus-outline'
|
||||
"
|
||||
class="show-menu"
|
||||
@click="switchMenu"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
<el-col :span="menuSpan" class="script-index" v-if="isReadOnly !== true">
|
||||
<ms-dropdown :default-command="jsr223ProcessorData.scriptLanguage" :commands="languages"
|
||||
style="margin-bottom: 5px;margin-left: 15px;"
|
||||
@command="languageChange"/>
|
||||
<script-nav-menu ref="scriptNavMenu" :language="jsr223ProcessorData.scriptLanguage" :menus="codeTemplates"
|
||||
@handleCode="handleCodeTemplate"/>
|
||||
<ms-dropdown
|
||||
:default-command="jsr223ProcessorData.scriptLanguage"
|
||||
:commands="languages"
|
||||
style="margin-bottom: 5px; margin-left: 15px"
|
||||
@command="languageChange"
|
||||
/>
|
||||
<script-nav-menu
|
||||
ref="scriptNavMenu"
|
||||
:language="jsr223ProcessorData.scriptLanguage"
|
||||
:menus="codeTemplates"
|
||||
@handleCode="handleCodeTemplate"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCodeEdit from "../../../definition/components/MsCodeEdit";
|
||||
import MsDropdown from "@/business/commons/MsDropdown";
|
||||
import ScriptNavMenu from "./function/ScriptNavMenu";
|
||||
import MsCodeEdit from '../../../definition/components/MsCodeEdit';
|
||||
import MsDropdown from '@/business/commons/MsDropdown';
|
||||
import ScriptNavMenu from './function/ScriptNavMenu';
|
||||
|
||||
export default {
|
||||
name: "Jsr233ProcessorContent",
|
||||
components: {MsDropdown, MsCodeEdit, ScriptNavMenu},
|
||||
name: 'Jsr233ProcessorContent',
|
||||
components: { MsDropdown, MsCodeEdit, ScriptNavMenu },
|
||||
data() {
|
||||
return {
|
||||
jsr223ProcessorData: {},
|
||||
|
@ -42,76 +60,94 @@ export default {
|
|||
children: [
|
||||
{
|
||||
title: this.$t('project.code_segment.import_api_test'),
|
||||
command: "api_definition",
|
||||
command: 'api_definition',
|
||||
},
|
||||
{
|
||||
title: this.$t('project.code_segment.new_api_test'),
|
||||
command: "new_api_request",
|
||||
}
|
||||
]
|
||||
command: 'new_api_request',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t('project.code_segment.custom_value'),
|
||||
children: [
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_template_get_variable'),
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_template_get_variable'
|
||||
),
|
||||
value: 'vars.get("variable_name")',
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_template_set_variable'),
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_template_set_variable'
|
||||
),
|
||||
value: 'vars.put("variable_name", "variable_value")',
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_template_get_response_header'),
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_template_get_response_header'
|
||||
),
|
||||
value: 'prev.getResponseHeaders()',
|
||||
disabled: this.isPreProcessor
|
||||
disabled: this.isPreProcessor,
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_template_get_response_code'),
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_template_get_response_code'
|
||||
),
|
||||
value: 'prev.getResponseCode()',
|
||||
disabled: this.isPreProcessor
|
||||
disabled: this.isPreProcessor,
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_template_get_response_result'),
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_template_get_response_result'
|
||||
),
|
||||
value: 'prev.getResponseDataAsString()',
|
||||
disabled: this.isPreProcessor
|
||||
disabled: this.isPreProcessor,
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t('project.code_segment.project_env'),
|
||||
children: [
|
||||
{
|
||||
title: this.$t('api_test.request.processor.param_environment_set_global_variable'),
|
||||
value: 'vars.put(${__metersphere_env_id}+"key","value");\n' + 'vars.put("key","value")',
|
||||
title: this.$t(
|
||||
'api_test.request.processor.param_environment_set_global_variable'
|
||||
),
|
||||
value:
|
||||
'vars.put(${__metersphere_env_id}+"key","value");\n' +
|
||||
'vars.put("key","value")',
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t('project.code_segment.code_segment'),
|
||||
children: [
|
||||
{
|
||||
title: this.$t('project.code_segment.insert_segment'),
|
||||
command: "custom_function",
|
||||
}
|
||||
]
|
||||
command: 'custom_function',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t('project.code_segment.exception_handle'),
|
||||
children: [
|
||||
{
|
||||
title: this.$t('project.code_segment.stop_test'),
|
||||
value: 'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());'
|
||||
value:
|
||||
'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());',
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t('project.code_segment.report_handle'),
|
||||
hideScript: this.isHideScript(),
|
||||
children: [
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_add_report_length'),
|
||||
value: 'String report = ctx.getCurrentSampler().getRequestData();\n' +
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_add_report_length'
|
||||
),
|
||||
value:
|
||||
'String report = ctx.getCurrentSampler().getRequestData();\n' +
|
||||
'if(report!=null){\n' +
|
||||
' //补足8位长度,前置补0\n' +
|
||||
' String reportlengthStr = String.format("%08d",report.length());\n' +
|
||||
|
@ -120,8 +156,11 @@ export default {
|
|||
'}',
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_hide_report_length'),
|
||||
value: '//Get response data\n' +
|
||||
title: this.$t(
|
||||
'api_test.request.processor.code_hide_report_length'
|
||||
),
|
||||
value:
|
||||
'//Get response data\n' +
|
||||
'String returnData = prev.getResponseDataAsString();\n' +
|
||||
'if(returnData!=null&&returnData.length()>8){\n' +
|
||||
'//remove 8 report length \n' +
|
||||
|
@ -133,13 +172,11 @@ export default {
|
|||
'}',
|
||||
disabled: this.isPreProcessor,
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
isCodeEditAlive: true,
|
||||
languages: [
|
||||
'beanshell', "python", "groovy", "javascript"
|
||||
],
|
||||
languages: ['beanshell', 'python', 'groovy', 'javascript'],
|
||||
codeEditModeMap: {
|
||||
beanshell: 'java',
|
||||
python: 'python',
|
||||
|
@ -151,7 +188,7 @@ export default {
|
|||
codeSpan: 20,
|
||||
menuSpan: 4,
|
||||
showMenu: true,
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.jsr223ProcessorData = this.jsr223Processor;
|
||||
|
@ -159,8 +196,7 @@ export default {
|
|||
props: {
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default:
|
||||
false
|
||||
default: false,
|
||||
},
|
||||
jsr223Processor: {
|
||||
type: Object,
|
||||
|
@ -168,20 +204,19 @@ export default {
|
|||
protocol: String,
|
||||
isPreProcessor: {
|
||||
type: Boolean,
|
||||
default:
|
||||
false
|
||||
default: false,
|
||||
},
|
||||
node: {},
|
||||
},
|
||||
watch: {
|
||||
jsr223Processor() {
|
||||
this.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addTemplate(template) {
|
||||
if (!this.jsr223ProcessorData.script) {
|
||||
this.jsr223ProcessorData.script = "";
|
||||
this.jsr223ProcessorData.script = '';
|
||||
}
|
||||
this.jsr223ProcessorData.script += template.value;
|
||||
if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
|
||||
|
@ -198,11 +233,12 @@ export default {
|
|||
},
|
||||
languageChange(language) {
|
||||
this.jsr223ProcessorData.scriptLanguage = language;
|
||||
this.$emit("languageChange");
|
||||
this.$emit('languageChange');
|
||||
},
|
||||
addCustomFuncScript(script) {
|
||||
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script ?
|
||||
this.jsr223ProcessorData.script + '\n\n' + script : script;
|
||||
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script
|
||||
? this.jsr223ProcessorData.script + '\n\n' + script
|
||||
: script;
|
||||
this.reload();
|
||||
},
|
||||
switchMenu() {
|
||||
|
@ -220,8 +256,8 @@ export default {
|
|||
this.$refs.codeEdit.insert(code);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -268,5 +304,4 @@ export default {
|
|||
.show-menu:hover {
|
||||
color: #935aa1;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,45 +1,48 @@
|
|||
<template>
|
||||
<span>
|
||||
<el-upload
|
||||
action="#"
|
||||
class="api-body-upload"
|
||||
list-type="picture-card"
|
||||
:http-request="upload"
|
||||
:beforeUpload="uploadValidate"
|
||||
:file-list="plugin.files"
|
||||
:on-exceed="exceed"
|
||||
ref="upload">
|
||||
|
||||
<div class="upload-default">
|
||||
<i class="el-icon-plus"/>
|
||||
</div>
|
||||
<div class="upload-item" slot="file" slot-scope="{file}">
|
||||
<span>{{ file.file ? file.file.name : file.name }}</span>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
|
||||
<i class="el-icon-delete"/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</el-upload>
|
||||
</span>
|
||||
<span>
|
||||
<el-upload
|
||||
action="#"
|
||||
class="api-body-upload"
|
||||
list-type="picture-card"
|
||||
:http-request="upload"
|
||||
:beforeUpload="uploadValidate"
|
||||
:file-list="plugin.files"
|
||||
:on-exceed="exceed"
|
||||
ref="upload"
|
||||
>
|
||||
<div class="upload-default">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
<div class="upload-item" slot="file" slot-scope="{ file }">
|
||||
<span>{{ file.file ? file.file.name : file.name }}</span>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
v-if="!disabled"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</el-upload>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {useApiStore} from "@/store";
|
||||
import { useApiStore } from '@/store';
|
||||
|
||||
const store = useApiStore();
|
||||
export default {
|
||||
name: "MsPluginUpload",
|
||||
name: 'MsPluginUpload',
|
||||
data() {
|
||||
return {
|
||||
disabled: false,
|
||||
plugin: {files: []}
|
||||
plugin: { files: [] },
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: String
|
||||
value: String,
|
||||
},
|
||||
mounted() {
|
||||
if (this.value) {
|
||||
|
@ -51,8 +54,9 @@ export default {
|
|||
this.$refs.upload.handleRemove(file);
|
||||
for (let i = 0; i < this.plugin.files.length; i++) {
|
||||
let fileName = file.file ? file.file.name : file.name;
|
||||
let paramFileName = this.plugin.files[i].file ?
|
||||
this.plugin.files[i].file.name : this.plugin.files[i].name;
|
||||
let paramFileName = this.plugin.files[i].file
|
||||
? this.plugin.files[i].file.name
|
||||
: this.plugin.files[i].name;
|
||||
if (fileName === paramFileName) {
|
||||
this.plugin.files.splice(i, 1);
|
||||
this.$refs.upload.handleRemove(file);
|
||||
|
@ -69,14 +73,18 @@ export default {
|
|||
if (!(store.pluginFiles instanceof Array)) {
|
||||
store.pluginFiles = [];
|
||||
}
|
||||
this.plugin.files.forEach(item => {
|
||||
this.plugin.files.forEach((item) => {
|
||||
if (item.file) {
|
||||
files.push({uid: item.file.uid, name: item.file.name, size: item.file.size});
|
||||
store.pluginFiles.push({name: item.file.name, file: item.file});
|
||||
files.push({
|
||||
uid: item.file.uid,
|
||||
name: item.file.name,
|
||||
size: item.file.size,
|
||||
});
|
||||
store.pluginFiles.push({ name: item.file.name, file: item.file });
|
||||
} else {
|
||||
files.push(item);
|
||||
}
|
||||
})
|
||||
});
|
||||
this.$emit('input', JSON.stringify(files));
|
||||
},
|
||||
uploadValidate(file) {
|
||||
|
@ -91,12 +99,11 @@ export default {
|
|||
if (this.plugin && !this.plugin.files) {
|
||||
this.plugin.files = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.el-upload {
|
||||
background-color: black;
|
||||
}
|
||||
|
@ -128,12 +135,11 @@ export default {
|
|||
|
||||
.api-body-upload {
|
||||
min-height: 30px;
|
||||
border: 1px solid #EBEEF5;
|
||||
border: 1px solid #ebeef5;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.upload-item {
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,60 +1,146 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.scenario_import')" width="30%"
|
||||
:visible.sync="visible" class="api-import" v-loading="result" @close="close">
|
||||
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('api_test.automation.scenario_import')"
|
||||
width="30%"
|
||||
:visible.sync="visible"
|
||||
class="api-import"
|
||||
v-loading="result"
|
||||
@close="close"
|
||||
>
|
||||
<div class="header-bar">
|
||||
<div>{{ $t('api_test.api_import.data_format') }}</div>
|
||||
<el-radio-group v-model="selectedPlatformValue">
|
||||
<el-radio v-for="(item, index) in platforms" :key="index" :label="item.value">{{ item.name }}</el-radio>
|
||||
<el-radio
|
||||
v-for="(item, index) in platforms"
|
||||
:key="index"
|
||||
:label="item.value"
|
||||
>{{ item.name }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
|
||||
<div class="operate-button">
|
||||
<el-button class="save-button" type="primary" plain @click="save">
|
||||
{{ $t('commons.save') }}
|
||||
</el-button>
|
||||
<el-button class="cancel-button" type="warning" plain @click="visible = false">
|
||||
<el-button
|
||||
class="cancel-button"
|
||||
type="warning"
|
||||
plain
|
||||
@click="visible = false"
|
||||
>
|
||||
{{ $t('commons.cancel') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-form :model="formData" :rules="rules" label-width="105px" v-loading="result" ref="form">
|
||||
<el-form
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="105px"
|
||||
v-loading="result"
|
||||
ref="form"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item :label="$t('commons.import_module')">
|
||||
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="formData.moduleId" @getValue="setModule"
|
||||
:obj="moduleObj" clearable checkStrictly/>
|
||||
<ms-select-tree
|
||||
size="small"
|
||||
:data="moduleOptions"
|
||||
:defaultKey="formData.moduleId"
|
||||
@getValue="setModule"
|
||||
:obj="moduleObj"
|
||||
clearable
|
||||
checkStrictly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.import_mode')" prop="modeId">
|
||||
<el-select size="small" v-model="formData.modeId" class="project-select" clearable>
|
||||
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
<el-select
|
||||
size="small"
|
||||
v-model="formData.modeId"
|
||||
class="project-select"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in modeOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-checkbox size="mini" v-if="formData.modeId === 'fullCoverage'"
|
||||
v-model="formData.coverModule">
|
||||
<el-checkbox
|
||||
size="mini"
|
||||
v-if="formData.modeId === 'fullCoverage'"
|
||||
v-model="formData.coverModule"
|
||||
>
|
||||
{{ this.$t('commons.cover_scenario') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item v-xpack v-if="projectVersionEnable && formData.modeId === 'incrementalMerge'"
|
||||
:label="$t('api_test.api_import.import_version')" prop="versionId">
|
||||
<el-select size="small" v-model="formData.versionId" clearable style="width: 100%">
|
||||
<el-option v-for="item in versionOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
<el-form-item
|
||||
v-xpack
|
||||
v-if="
|
||||
projectVersionEnable && formData.modeId === 'incrementalMerge'
|
||||
"
|
||||
:label="$t('api_test.api_import.import_version')"
|
||||
prop="versionId"
|
||||
>
|
||||
<el-select
|
||||
size="small"
|
||||
v-model="formData.versionId"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in versionOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-xpack v-if="projectVersionEnable && formData.modeId === 'fullCoverage'"
|
||||
:label="$t('api_test.api_import.data_update_version')" prop="versionId">
|
||||
<el-select size="small" v-model="formData.updateVersionId" clearable style="width: 100%">
|
||||
<el-option v-for="item in versionOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
<el-form-item
|
||||
v-xpack
|
||||
v-if="projectVersionEnable && formData.modeId === 'fullCoverage'"
|
||||
:label="$t('api_test.api_import.data_update_version')"
|
||||
prop="versionId"
|
||||
>
|
||||
<el-select
|
||||
size="small"
|
||||
v-model="formData.updateVersionId"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in versionOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-xpack v-if="projectVersionEnable && formData.modeId === 'fullCoverage'"
|
||||
:label="$t('api_test.api_import.data_new_version')" prop="versionId">
|
||||
<el-select size="small" v-model="formData.versionId" clearable style="width: 100%">
|
||||
<el-option v-for="item in versionOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
<el-form-item
|
||||
v-xpack
|
||||
v-if="projectVersionEnable && formData.modeId === 'fullCoverage'"
|
||||
:label="$t('api_test.api_import.data_new_version')"
|
||||
prop="versionId"
|
||||
>
|
||||
<el-select
|
||||
size="small"
|
||||
v-model="formData.versionId"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in versionOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-divider direction="vertical"/>
|
||||
<el-divider direction="vertical" />
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-upload
|
||||
|
@ -67,32 +153,43 @@
|
|||
:on-remove="handleRemove"
|
||||
:file-list="fileList"
|
||||
:on-exceed="handleExceed"
|
||||
multiple>
|
||||
multiple
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
|
||||
<div class="el-upload__tip" slot="tip">{{ $t('api_test.api_import.file_size_limit') }}</div>
|
||||
<div
|
||||
class="el-upload__text"
|
||||
v-html="$t('load_test.upload_tips')"
|
||||
></div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
{{ $t('api_test.api_import.file_size_limit') }}
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="format-tip">
|
||||
<div>
|
||||
<span>{{ $t('api_test.api_import.tip') }}:{{ selectedPlatform.tip }}</span>
|
||||
<span
|
||||
>{{ $t('api_test.api_import.tip') }}:{{ selectedPlatform.tip }}</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ $t('api_test.api_import.export_tip') }}:{{ selectedPlatform.exportTip }}</span>
|
||||
<span
|
||||
>{{ $t('api_test.api_import.export_tip') }}:{{
|
||||
selectedPlatform.exportTip
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
{{ $t('api_test.api_import.cover_tip') }} :<br/>
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_1') }}<br/>
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_2') }}<br/>
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_3') }}<br/>
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_4') }}<br/>
|
||||
{{ $t('api_test.api_import.no_cover_tip') }} :<br/>
|
||||
{{ $t('api_test.api_import.no_cover_tip_scenario_1') }}<br/>
|
||||
<span>
|
||||
{{ $t('api_test.api_import.cover_tip') }} :<br />
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_1') }}<br />
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_2') }}<br />
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_3') }}<br />
|
||||
{{ $t('api_test.api_import.cover_tip_scenario_4') }}<br />
|
||||
{{ $t('api_test.api_import.no_cover_tip') }} :<br />
|
||||
{{ $t('api_test.api_import.no_cover_tip_scenario_1') }}<br />
|
||||
{{ $t('api_test.api_import.no_cover_tip_scenario_2') }}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -101,17 +198,20 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {getProjectVersions, versionEnableByProjectId} from "@/api/xpack";
|
||||
import {importScenario} from "@/api/scenario";
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import {listenGoBack, removeGoBackListener} from "metersphere-frontend/src/utils";
|
||||
import MsSelectTree from "metersphere-frontend/src/components/select-tree/SelectTree";
|
||||
import { getProjectVersions, versionEnableByProjectId } from '@/api/xpack';
|
||||
import { importScenario } from '@/api/scenario';
|
||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
|
||||
import {
|
||||
listenGoBack,
|
||||
removeGoBackListener,
|
||||
} from 'metersphere-frontend/src/utils';
|
||||
import MsSelectTree from 'metersphere-frontend/src/components/select-tree/SelectTree';
|
||||
|
||||
export default {
|
||||
name: "ScenarioImport",
|
||||
components: {MsDialogFooter, MsSelectTree},
|
||||
name: 'ScenarioImport',
|
||||
components: { MsDialogFooter, MsSelectTree },
|
||||
props: {
|
||||
saved: {
|
||||
type: Boolean,
|
||||
|
@ -125,44 +225,46 @@ export default {
|
|||
swaggerUrlEable: false,
|
||||
swaggerSynchronization: false,
|
||||
showEnvironmentSelect: true,
|
||||
modeOptions: [{
|
||||
id: 'fullCoverage',
|
||||
name: this.$t('commons.cover')
|
||||
},
|
||||
modeOptions: [
|
||||
{
|
||||
id: 'fullCoverage',
|
||||
name: this.$t('commons.cover'),
|
||||
},
|
||||
{
|
||||
id: 'incrementalMerge',
|
||||
name: this.$t('commons.not_cover')
|
||||
}],
|
||||
protocol: "",
|
||||
name: this.$t('commons.not_cover'),
|
||||
},
|
||||
],
|
||||
protocol: '',
|
||||
platforms: [
|
||||
{
|
||||
name: 'MeterSphere',
|
||||
value: 'Metersphere',
|
||||
tip: this.$t('api_test.api_import.ms_tip'),
|
||||
exportTip: this.$t('api_test.api_import.ms_export_tip'),
|
||||
suffixes: new Set(['json'])
|
||||
suffixes: new Set(['json']),
|
||||
},
|
||||
{
|
||||
name: 'Postman',
|
||||
value: 'Postman',
|
||||
tip: this.$t('api_test.api_import.postman_tip'),
|
||||
exportTip: this.$t('api_test.api_import.post_export_tip'),
|
||||
suffixes: new Set(['json'])
|
||||
suffixes: new Set(['json']),
|
||||
},
|
||||
{
|
||||
name: 'JMeter',
|
||||
value: 'Jmeter',
|
||||
tip: this.$t('api_test.api_import.jmeter_tip'),
|
||||
exportTip: this.$t('api_test.api_import.jmeter_export_tip'),
|
||||
suffixes: new Set(['jmx'])
|
||||
suffixes: new Set(['jmx']),
|
||||
},
|
||||
{
|
||||
name: 'HAR',
|
||||
value: 'Har',
|
||||
tip: this.$t('api_test.api_import.har_tip'),
|
||||
exportTip: this.$t('api_test.api_import.har_export_tip'),
|
||||
suffixes: new Set(['har'])
|
||||
}
|
||||
suffixes: new Set(['har']),
|
||||
},
|
||||
],
|
||||
selectedPlatform: {},
|
||||
selectedPlatformValue: 'Metersphere',
|
||||
|
@ -175,11 +277,15 @@ export default {
|
|||
swaggerUrl: '',
|
||||
modeId: 'incrementalMerge',
|
||||
moduleId: '',
|
||||
coverModule: false
|
||||
coverModule: false,
|
||||
},
|
||||
rules: {
|
||||
modeId: [
|
||||
{required: true, message: this.$t('commons.please_select_import_mode'), trigger: 'change'},
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('commons.please_select_import_mode'),
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
},
|
||||
currentModule: {},
|
||||
|
@ -190,7 +296,7 @@ export default {
|
|||
},
|
||||
versionOptions: [],
|
||||
projectVersionEnable: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getVersionOptions();
|
||||
|
@ -205,7 +311,7 @@ export default {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
projectId() {
|
||||
|
@ -216,7 +322,7 @@ export default {
|
|||
scheduleEdit() {
|
||||
if (!this.formData.swaggerUrl) {
|
||||
this.$warning(this.$t('commons.please_fill_path'));
|
||||
this.swaggerSynchronization = !this.swaggerSynchronization
|
||||
this.swaggerSynchronization = !this.swaggerSynchronization;
|
||||
} else {
|
||||
if (this.swaggerSynchronization) {
|
||||
this.$refs.scheduleEdit.open(this.buildParam());
|
||||
|
@ -245,7 +351,10 @@ export default {
|
|||
},
|
||||
uploadValidate(file, fileList) {
|
||||
let suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
|
||||
if (this.selectedPlatform.suffixes && !this.selectedPlatform.suffixes.has(suffix)) {
|
||||
if (
|
||||
this.selectedPlatform.suffixes &&
|
||||
!this.selectedPlatform.suffixes.has(suffix)
|
||||
) {
|
||||
this.$warning(this.$t('api_test.api_import.suffixFormatErr'));
|
||||
return false;
|
||||
}
|
||||
|
@ -258,18 +367,28 @@ export default {
|
|||
save() {
|
||||
localStorage.setItem('scenarioModule', this.formData.moduleId);
|
||||
if (!this.formData.file) {
|
||||
this.$warning("请添加一个文件");
|
||||
this.$warning('请添加一个文件');
|
||||
return;
|
||||
}
|
||||
let suffix = this.formData.file.name.substring(this.formData.file.name.lastIndexOf('.') + 1);
|
||||
if (this.selectedPlatform.suffixes && !this.selectedPlatform.suffixes.has(suffix)) {
|
||||
let suffix = this.formData.file.name.substring(
|
||||
this.formData.file.name.lastIndexOf('.') + 1
|
||||
);
|
||||
if (
|
||||
this.selectedPlatform.suffixes &&
|
||||
!this.selectedPlatform.suffixes.has(suffix)
|
||||
) {
|
||||
this.$warning(this.$t('api_test.api_import.suffixFormatErr'));
|
||||
return false;
|
||||
}
|
||||
this.$refs.form.validate(valid => {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
let param = this.buildParam();
|
||||
this.result = importScenario('/api/automation/import', param.file, null, this.buildParam()).then(response => {
|
||||
this.result = importScenario(
|
||||
'/api/automation/import',
|
||||
param.file,
|
||||
null,
|
||||
this.buildParam()
|
||||
).then((response) => {
|
||||
let res = response.data;
|
||||
this.$success(this.$t('test_track.case.import.success'));
|
||||
this.visible = false;
|
||||
|
@ -286,16 +405,16 @@ export default {
|
|||
param.platform = this.selectedPlatformValue;
|
||||
param.saved = this.saved;
|
||||
if (this.currentModule) {
|
||||
param.moduleId = this.formData.moduleId
|
||||
this.moduleOptions.filter(item => {
|
||||
param.moduleId = this.formData.moduleId;
|
||||
this.moduleOptions.filter((item) => {
|
||||
if (item.id === this.formData.moduleId) {
|
||||
param.modulePath = item.path
|
||||
param.modulePath = item.path;
|
||||
}
|
||||
})
|
||||
param.modeId = this.formData.modeId
|
||||
});
|
||||
param.modeId = this.formData.modeId;
|
||||
}
|
||||
if (this.formData.moduleId.length === 0) {
|
||||
param.moduleId = ''
|
||||
param.moduleId = '';
|
||||
}
|
||||
param.projectId = this.projectId;
|
||||
if (!this.swaggerUrlEable) {
|
||||
|
@ -310,7 +429,7 @@ export default {
|
|||
swaggerUrl: '',
|
||||
modeId: this.formData.modeId,
|
||||
moduleId: '',
|
||||
coverModule: false
|
||||
coverModule: false,
|
||||
};
|
||||
this.fileList = [];
|
||||
removeGoBackListener(this.close);
|
||||
|
@ -322,11 +441,14 @@ export default {
|
|||
},
|
||||
getVersionOptions() {
|
||||
if (hasLicense()) {
|
||||
getProjectVersions(getCurrentProjectID()).then(response => {
|
||||
this.versionOptions = response.data.filter(v => v.status === 'open');
|
||||
this.versionOptions.forEach(v => {
|
||||
getProjectVersions(getCurrentProjectID()).then((response) => {
|
||||
this.versionOptions = response.data.filter(
|
||||
(v) => v.status === 'open'
|
||||
);
|
||||
this.versionOptions.forEach((v) => {
|
||||
if (v.latest) {
|
||||
v.name = v.name + ' ' + this.$t('api_test.api_import.latest_version');
|
||||
v.name =
|
||||
v.name + ' ' + this.$t('api_test.api_import.latest_version');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -337,23 +459,22 @@ export default {
|
|||
return;
|
||||
}
|
||||
if (hasLicense()) {
|
||||
versionEnableByProjectId(this.projectId).then(response => {
|
||||
versionEnableByProjectId(this.projectId).then((response) => {
|
||||
this.projectVersionEnable = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.api-import :deep(.el-dialog) {
|
||||
min-width: 700px;
|
||||
}
|
||||
|
||||
.format-tip {
|
||||
background: #EDEDED;
|
||||
background: #ededed;
|
||||
}
|
||||
|
||||
.api-upload {
|
||||
|
@ -374,8 +495,10 @@ export default {
|
|||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.header-bar, .format-tip, .el-form {
|
||||
border: solid #E1E1E1 1px;
|
||||
.header-bar,
|
||||
.format-tip,
|
||||
.el-form {
|
||||
border: solid #e1e1e1 1px;
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
|
@ -414,6 +537,4 @@ export default {
|
|||
.el-divider {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<template>
|
||||
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="save"
|
||||
:plan-id="planId"
|
||||
:dialog-title="dialogTitle"
|
||||
ref="baseRelevance">
|
||||
|
||||
ref="baseRelevance"
|
||||
>
|
||||
<template v-slot:aside>
|
||||
<ms-api-module
|
||||
:options="options"
|
||||
|
@ -16,7 +15,8 @@
|
|||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:is-read-only="true"
|
||||
ref="nodeTree"/>
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<relevance-api-list
|
||||
|
@ -29,7 +29,8 @@
|
|||
:is-script="isScript"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiList"/>
|
||||
ref="apiList"
|
||||
/>
|
||||
|
||||
<relevance-case-list
|
||||
v-if="!isApiListEnable"
|
||||
|
@ -41,26 +42,23 @@
|
|||
:is-script="isScript"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiCaseList"/>
|
||||
|
||||
ref="apiCaseList"
|
||||
/>
|
||||
</test-case-relevance-base>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import {getApiCaseWithBLOBs} from "@/api/api-test-case";
|
||||
import {apiListBatch} from "@/api/definition";
|
||||
import RelevanceCaseList from "@/business/automation/scenario/api/RelevanceCaseList";
|
||||
import RelevanceApiList from "@/business/automation/scenario/api/RelevanceApiList";
|
||||
import MsApiModule from "@/business/definition/components/module/ApiModule";
|
||||
import {getEnvironmentById} from "metersphere-frontend/src/api/environment";
|
||||
import TestCaseRelevanceBase from "@/business/commons/TestCaseRelevanceBase";
|
||||
import {parseEnvironment} from "@/business/environment/model/EnvironmentModel";
|
||||
import { getApiCaseWithBLOBs } from '@/api/api-test-case';
|
||||
import { apiListBatch } from '@/api/definition';
|
||||
import RelevanceCaseList from '@/business/automation/scenario/api/RelevanceCaseList';
|
||||
import RelevanceApiList from '@/business/automation/scenario/api/RelevanceApiList';
|
||||
import MsApiModule from '@/business/definition/components/module/ApiModule';
|
||||
import { getEnvironmentById } from 'metersphere-frontend/src/api/environment';
|
||||
import TestCaseRelevanceBase from '@/business/commons/TestCaseRelevanceBase';
|
||||
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
|
||||
|
||||
export default {
|
||||
name: "ApiFuncRelevance",
|
||||
name: 'ApiFuncRelevance',
|
||||
components: {
|
||||
RelevanceCaseList,
|
||||
RelevanceApiList,
|
||||
|
@ -79,31 +77,33 @@ export default {
|
|||
isApiListEnable: true,
|
||||
condition: {},
|
||||
currentRow: {},
|
||||
projectId: "",
|
||||
options: [{value: 'HTTP', name: 'HTTP'}]
|
||||
projectId: '',
|
||||
options: [{ value: 'HTTP', name: 'HTTP' }],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
isTestPlan: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
isScript: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (this.isScript) {
|
||||
if (this.isApiListEnable) {
|
||||
this.dialogTitle = this.$t('permission.project_api_definition.import_api');
|
||||
this.dialogTitle = this.$t(
|
||||
'permission.project_api_definition.import_api'
|
||||
);
|
||||
} else {
|
||||
this.dialogTitle = this.$t('permission.project_track_case.import');
|
||||
}
|
||||
|
@ -116,12 +116,14 @@ export default {
|
|||
isApiListEnable() {
|
||||
if (this.isScript) {
|
||||
if (this.isApiListEnable) {
|
||||
this.dialogTitle = this.$t('permission.project_api_definition.import_api');
|
||||
this.dialogTitle = this.$t(
|
||||
'permission.project_api_definition.import_api'
|
||||
);
|
||||
} else {
|
||||
this.dialogTitle = this.$t('permission.project_track_case.import');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
|
@ -195,10 +197,10 @@ export default {
|
|||
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||
return;
|
||||
}
|
||||
getEnvironmentById(environmentId).then(response => {
|
||||
getEnvironmentById(environmentId).then((response) => {
|
||||
let environment = response.data;
|
||||
parseEnvironment(environment);
|
||||
this.$emit("save", apis, environment);
|
||||
this.$emit('save', apis, environment);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
@ -211,21 +213,19 @@ export default {
|
|||
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||
return;
|
||||
}
|
||||
getEnvironmentById(environmentId).then(response => {
|
||||
getEnvironmentById(environmentId).then((response) => {
|
||||
let environment = response.data;
|
||||
parseEnvironment(environment);
|
||||
this.$emit("save", apiCases, environment);
|
||||
this.$emit('save', apiCases, environment);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
:deep(.select-menu) {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
@ -234,5 +234,4 @@ export default {
|
|||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,47 +1,101 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('project.code_segment.code_segment')" :visible.sync="visible"
|
||||
:destroy-on-close="true"
|
||||
@close="close" width="60%" top="10vh" v-loading="result" append-to-body class="customFunc">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('project.code_segment.code_segment')"
|
||||
:visible.sync="visible"
|
||||
:destroy-on-close="true"
|
||||
@close="close"
|
||||
width="60%"
|
||||
top="10vh"
|
||||
v-loading="result"
|
||||
append-to-body
|
||||
class="customFunc"
|
||||
>
|
||||
<div>
|
||||
<el-alert
|
||||
:title="$t('project.code_segment.relate_tip')"
|
||||
type="info"
|
||||
style="width: 350px;float: left;"
|
||||
:closable="false" show-icon>
|
||||
style="width: 350px; float: left"
|
||||
:closable="false"
|
||||
show-icon
|
||||
>
|
||||
</el-alert>
|
||||
<ms-table-search-bar :condition.sync="condition" @change="init" class="search-bar"
|
||||
:tip="$t('project.code_segment.search')"/>
|
||||
<el-table border class="adjust-table" :data="data" style="width: 100%" ref="table"
|
||||
highlight-current-row @current-change="handleCurrentChange">
|
||||
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>
|
||||
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||
<ms-table-search-bar
|
||||
:condition.sync="condition"
|
||||
@change="init"
|
||||
class="search-bar"
|
||||
:tip="$t('project.code_segment.search')"
|
||||
/>
|
||||
<el-table
|
||||
border
|
||||
class="adjust-table"
|
||||
:data="data"
|
||||
style="width: 100%"
|
||||
ref="table"
|
||||
highlight-current-row
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('commons.name')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="description"
|
||||
:label="$t('commons.description')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<pre>{{ scope.row.description }}</pre>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="tags" :label="$t('api_test.automation.tag')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
|
||||
:content="itemName" style="margin-left: 0; margin-right: 2px">
|
||||
<ms-tag
|
||||
v-for="(itemName, index) in scope.row.tags"
|
||||
:key="index"
|
||||
type="success"
|
||||
effect="plain"
|
||||
:content="itemName"
|
||||
style="margin-left: 0; margin-right: 2px"
|
||||
>
|
||||
</ms-tag>
|
||||
<span></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" :label="$t('project.code_segment.language')" show-overflow-tooltip/>
|
||||
<el-table-column prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:label="$t('project.code_segment.language')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="init" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total"/>
|
||||
<ms-table-pagination
|
||||
:change="init"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:total="total"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template v-slot:footer>
|
||||
<el-button @click="close" size="medium">{{ $t('commons.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit" size="medium" style="margin-left: 10px;">
|
||||
<el-button @click="close" size="medium">{{
|
||||
$t('commons.cancel')
|
||||
}}</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submit"
|
||||
size="medium"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
{{ $t('commons.confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -49,22 +103,22 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import MsTableOperator from "metersphere-frontend/src/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "metersphere-frontend/src/components/MsTableOperatorButton";
|
||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||
import MsTableSearchBar from "metersphere-frontend/src/components/MsTableSearchBar";
|
||||
import {funcList, getFuncById} from "@/api/custom-func";
|
||||
import MsTablePagination from 'metersphere-frontend/src/components/pagination/TablePagination';
|
||||
import MsTag from 'metersphere-frontend/src/components/MsTag';
|
||||
import MsTableOperator from 'metersphere-frontend/src/components/MsTableOperator';
|
||||
import MsTableOperatorButton from 'metersphere-frontend/src/components/MsTableOperatorButton';
|
||||
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
|
||||
import MsTableSearchBar from 'metersphere-frontend/src/components/MsTableSearchBar';
|
||||
import { funcList, getFuncById } from '@/api/custom-func';
|
||||
|
||||
export default {
|
||||
name: "CustomFunctionRelate",
|
||||
name: 'CustomFunctionRelate',
|
||||
components: {
|
||||
MsTablePagination,
|
||||
MsTag,
|
||||
MsTableOperator,
|
||||
MsTableOperatorButton,
|
||||
MsTableSearchBar
|
||||
MsTableSearchBar,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -76,8 +130,8 @@ export default {
|
|||
pageSize: 10,
|
||||
total: 0,
|
||||
screenHeight: 'calc(100vh - 155px)',
|
||||
currentRow: {}
|
||||
}
|
||||
currentRow: {},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init(language) {
|
||||
|
@ -85,16 +139,20 @@ export default {
|
|||
this.condition.type = language;
|
||||
}
|
||||
this.condition.projectId = getCurrentProjectID();
|
||||
this.result = funcList(this.currentPage, this.pageSize, this.condition).then(res => {
|
||||
this.result = funcList(
|
||||
this.currentPage,
|
||||
this.pageSize,
|
||||
this.condition
|
||||
).then((res) => {
|
||||
let tableData = res.data;
|
||||
const {itemCount, listObject} = tableData;
|
||||
const { itemCount, listObject } = tableData;
|
||||
this.total = itemCount;
|
||||
this.data = listObject;
|
||||
this.data.forEach(item => {
|
||||
this.data.forEach((item) => {
|
||||
if (item.tags && item.tags.length > 0) {
|
||||
item.tags = JSON.parse(item.tags);
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
},
|
||||
open(language) {
|
||||
|
@ -112,23 +170,24 @@ export default {
|
|||
this.$warning(this.$t('project.code_segment.select_tip'));
|
||||
return;
|
||||
}
|
||||
this.result = getFuncById(this.currentRow.id).then(res => {
|
||||
this.result = getFuncById(this.currentRow.id).then((res) => {
|
||||
if (!res.data) {
|
||||
this.$warning(this.$t('project.code_segment.none_content'))
|
||||
this.$warning(this.$t('project.code_segment.none_content'));
|
||||
}
|
||||
let {script} = res.data;
|
||||
this.$emit("addCustomFuncScript", script);
|
||||
let { script } = res.data;
|
||||
this.$emit('addCustomFuncScript', script);
|
||||
this.close();
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
pre {
|
||||
margin: 0 0;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
|
||||
Arial, sans-serif;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
|
|
|
@ -1,100 +1,128 @@
|
|||
<template>
|
||||
<div style="line-height: 20px;">
|
||||
<div style="line-height: 20px">
|
||||
<div class="template-title">
|
||||
<span class="nav-font">{{ $t('api_test.request.processor.code_template') }}</span>
|
||||
<el-link href="https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_PostProcessor"
|
||||
target="componentReferenceDoc" style="margin-left: 30px; margin-bottom: 3px;"
|
||||
type="primary"><span style="font-size: 13px;">{{ $t('commons.reference_documentation') }}</span>
|
||||
<span class="nav-font">{{
|
||||
$t('api_test.request.processor.code_template')
|
||||
}}</span>
|
||||
<el-link
|
||||
href="https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_PostProcessor"
|
||||
target="componentReferenceDoc"
|
||||
style="margin-left: 30px; margin-bottom: 3px"
|
||||
type="primary"
|
||||
><span style="font-size: 13px">{{
|
||||
$t('commons.reference_documentation')
|
||||
}}</span>
|
||||
</el-link>
|
||||
</div>
|
||||
<div v-for="(menu, index) in menus" :key="index">
|
||||
<span class="link-type" v-if="!menu.hideScript">
|
||||
<i class="icon el-icon-arrow-right" style="font-weight: bold; margin-right: 2px;"
|
||||
@click="active(menu)" :class="{'is-active': menu.open}"></i>
|
||||
<span @click="active(menu)" class="nav-menu-title nav-font">{{ menu.title }}</span>
|
||||
<i
|
||||
class="icon el-icon-arrow-right"
|
||||
style="font-weight: bold; margin-right: 2px"
|
||||
@click="active(menu)"
|
||||
:class="{ 'is-active': menu.open }"
|
||||
></i>
|
||||
<span @click="active(menu)" class="nav-menu-title nav-font">{{
|
||||
menu.title
|
||||
}}</span>
|
||||
</span>
|
||||
|
||||
<el-collapse-transition>
|
||||
<div v-if="menu.open">
|
||||
<div v-for="(child, key) in menu.children" :key="key" class="func-div">
|
||||
<el-link :disabled="child.disabled" @click="handleClick(child)" class="func-link nav-font">
|
||||
<div
|
||||
v-for="(child, key) in menu.children"
|
||||
:key="key"
|
||||
class="func-div"
|
||||
>
|
||||
<el-link
|
||||
:disabled="child.disabled"
|
||||
@click="handleClick(child)"
|
||||
class="func-link nav-font"
|
||||
>
|
||||
{{ child.title }}
|
||||
</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
<custom-function-relate ref="customFunctionRelate" @addCustomFuncScript="handleCodeTemplate"/>
|
||||
<custom-function-relate
|
||||
ref="customFunctionRelate"
|
||||
@addCustomFuncScript="handleCodeTemplate"
|
||||
/>
|
||||
<!--接口列表-->
|
||||
<api-func-relevance @save="apiSave" :is-test-plan="false" :is-script="true" @close="apiClose"
|
||||
ref="apiFuncRelevance"/>
|
||||
<api-func-relevance
|
||||
@save="apiSave"
|
||||
:is-test-plan="false"
|
||||
:is-script="true"
|
||||
@close="apiClose"
|
||||
ref="apiFuncRelevance"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ApiFuncRelevance from "./ApiFuncRelevance";
|
||||
import CustomFunctionRelate from "./CustomFunctionRelate";
|
||||
import {getCodeTemplate} from "./custom-function";
|
||||
import {SCRIPT_MENU} from "./script-menu";
|
||||
import ApiFuncRelevance from './ApiFuncRelevance';
|
||||
import CustomFunctionRelate from './CustomFunctionRelate';
|
||||
import { getCodeTemplate } from './custom-function';
|
||||
import { SCRIPT_MENU } from './script-menu';
|
||||
|
||||
export default {
|
||||
name: "ScriptNavMenu",
|
||||
name: 'ScriptNavMenu',
|
||||
components: {
|
||||
ApiFuncRelevance,
|
||||
CustomFunctionRelate
|
||||
CustomFunctionRelate,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: true
|
||||
}
|
||||
value: true,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
language: {
|
||||
type: String,
|
||||
default() {
|
||||
return "beanshell"
|
||||
}
|
||||
return 'beanshell';
|
||||
},
|
||||
},
|
||||
menus: {
|
||||
type: Array,
|
||||
default() {
|
||||
return SCRIPT_MENU
|
||||
}
|
||||
}
|
||||
return SCRIPT_MENU;
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
apiSave(data, env) {
|
||||
// data:选中的多个接口定义或多个接口用例; env: 关联页面选中的环境
|
||||
let condition = env.config.httpConfig.conditions || [];
|
||||
let protocol = "";
|
||||
let host = "";
|
||||
let domain = "";
|
||||
let port = "";
|
||||
let protocol = '';
|
||||
let host = '';
|
||||
let domain = '';
|
||||
let port = '';
|
||||
if (condition && condition.length > 0) {
|
||||
// 如果有多个环境,取第一个
|
||||
protocol = condition[0].protocol ? condition[0].protocol : "http";
|
||||
protocol = condition[0].protocol ? condition[0].protocol : 'http';
|
||||
host = condition[0].socket;
|
||||
domain = condition[0].domain;
|
||||
port = condition[0].port;
|
||||
}
|
||||
// todo
|
||||
if (data.length > 5) {
|
||||
this.$warning("最多可以选择5个接口!");
|
||||
this.$warning('最多可以选择5个接口!');
|
||||
return;
|
||||
}
|
||||
let code = "";
|
||||
let code = '';
|
||||
if (data.length > 0) {
|
||||
for (let dt of data) {
|
||||
// 过滤非HTTP接口API
|
||||
if (dt.protocol !== "HTTP") {
|
||||
if (dt.protocol !== 'HTTP') {
|
||||
if (!dt.request) {
|
||||
continue;
|
||||
} else {
|
||||
// 是否是HTTP接口CASE
|
||||
if (dt.request) {
|
||||
let req = JSON.parse(dt.request);
|
||||
if (req.protocol !== "HTTP") {
|
||||
if (req.protocol !== 'HTTP') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -112,17 +140,17 @@ export default {
|
|||
this.$refs.apiFuncRelevance.close();
|
||||
},
|
||||
handleCodeTemplate(code) {
|
||||
this.$emit("handleCode", code);
|
||||
this.$emit('handleCode', code);
|
||||
},
|
||||
_parseRequestObj(data) {
|
||||
let requestHeaders = new Map();
|
||||
let requestArguments = new Map();
|
||||
let requestRest = new Map();
|
||||
let requestMethod = "";
|
||||
let requestBody = "";
|
||||
let requestMethod = '';
|
||||
let requestBody = '';
|
||||
let requestBodyKvs = new Map();
|
||||
let bodyType = "";
|
||||
let requestPath = "";
|
||||
let bodyType = '';
|
||||
let requestPath = '';
|
||||
let request = JSON.parse(data.request);
|
||||
// 拼接发送请求需要的参数
|
||||
requestPath = request.path;
|
||||
|
@ -130,14 +158,14 @@ export default {
|
|||
let headers = request.headers;
|
||||
let rest = request.rest;
|
||||
if (rest && rest.length > 0) {
|
||||
rest.forEach(r => {
|
||||
rest.forEach((r) => {
|
||||
if (r.enable) {
|
||||
requestRest.set(r.name, r.value);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
if (headers && headers.length > 0) {
|
||||
headers.forEach(header => {
|
||||
headers.forEach((header) => {
|
||||
if (header.name) {
|
||||
requestHeaders.set(header.name, header.value);
|
||||
}
|
||||
|
@ -145,29 +173,29 @@ export default {
|
|||
}
|
||||
let args = request.arguments;
|
||||
if (args && args.length) {
|
||||
args.forEach(arg => {
|
||||
args.forEach((arg) => {
|
||||
if (arg.name) {
|
||||
requestArguments.set(arg.name, arg.value);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
let body = request.body;
|
||||
if (body.type === 'XML') {
|
||||
requestBody = body.raw;
|
||||
bodyType = "xml";
|
||||
bodyType = 'xml';
|
||||
} else if (body.type === 'Raw') {
|
||||
requestBody = body.raw;
|
||||
bodyType = "raw";
|
||||
bodyType = 'raw';
|
||||
} else if (body.json) {
|
||||
requestBody = body.raw;
|
||||
bodyType = "json";
|
||||
bodyType = 'json';
|
||||
} else if (body.kvs) {
|
||||
bodyType = "kvs";
|
||||
body.kvs.forEach(arg => {
|
||||
bodyType = 'kvs';
|
||||
body.kvs.forEach((arg) => {
|
||||
if (arg.name) {
|
||||
requestBodyKvs.set(arg.name, arg.value);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
return {
|
||||
requestPath,
|
||||
|
@ -177,14 +205,12 @@ export default {
|
|||
requestBodyKvs,
|
||||
bodyType,
|
||||
requestArguments,
|
||||
requestRest
|
||||
}
|
||||
},
|
||||
apiClose() {
|
||||
|
||||
requestRest,
|
||||
};
|
||||
},
|
||||
apiClose() {},
|
||||
handleClick(obj) {
|
||||
let code = "";
|
||||
let code = '';
|
||||
if (obj.command) {
|
||||
code = this._handleCommand(obj.command);
|
||||
if (!code) {
|
||||
|
@ -193,9 +219,20 @@ export default {
|
|||
} else {
|
||||
// todo 优化
|
||||
if (this.language !== 'beanshell' && this.language !== 'groovy') {
|
||||
if (obj.title === this.$t('api_test.request.processor.code_add_report_length') ||
|
||||
obj.title === this.$t('api_test.request.processor.code_hide_report_length')) {
|
||||
this.$warning(this.$t('commons.no_corresponding') + " " + this.language + " " + this.$t('commons.code_template') + "!");
|
||||
if (
|
||||
obj.title ===
|
||||
this.$t('api_test.request.processor.code_add_report_length') ||
|
||||
obj.title ===
|
||||
this.$t('api_test.request.processor.code_hide_report_length')
|
||||
) {
|
||||
this.$warning(
|
||||
this.$t('commons.no_corresponding') +
|
||||
' ' +
|
||||
this.language +
|
||||
' ' +
|
||||
this.$t('commons.code_template') +
|
||||
'!'
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -207,33 +244,32 @@ export default {
|
|||
switch (command) {
|
||||
case 'custom_function':
|
||||
this.$refs.customFunctionRelate.open(this.language);
|
||||
return "";
|
||||
return '';
|
||||
case 'api_definition':
|
||||
this.$refs.apiFuncRelevance.open();
|
||||
return "";
|
||||
return '';
|
||||
case 'new_api_request': {
|
||||
// requestObj为空则生产默认模版
|
||||
let headers = new Map();
|
||||
headers.set('Content-type', 'application/json');
|
||||
return getCodeTemplate(this.language, {requestHeaders: headers});
|
||||
return getCodeTemplate(this.language, { requestHeaders: headers });
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
},
|
||||
active(menu) {
|
||||
if (!menu.open) {
|
||||
this.$set(menu, "open", true);
|
||||
this.$set(menu, 'open', true);
|
||||
} else {
|
||||
this.$set(menu, "open", !menu.open);
|
||||
this.$set(menu, 'open', !menu.open);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.template-title {
|
||||
margin-bottom: 4px;
|
||||
font-weight: bold;
|
||||
|
|
|
@ -1,37 +1,45 @@
|
|||
export const FUNC_TEMPLATE = {
|
||||
beanshell: "",
|
||||
groovy: "",
|
||||
python: "",
|
||||
javascript: ""
|
||||
}
|
||||
beanshell: '',
|
||||
groovy: '',
|
||||
python: '',
|
||||
javascript: '',
|
||||
};
|
||||
|
||||
export function getCodeTemplate(language, requestObj) {
|
||||
switch (language) {
|
||||
case "groovy":
|
||||
case 'groovy':
|
||||
return groovyCode(requestObj);
|
||||
case "python":
|
||||
case 'python':
|
||||
return pythonCode(requestObj);
|
||||
case "beanshell":
|
||||
case 'beanshell':
|
||||
return javaCode(requestObj);
|
||||
case "nashornScript":
|
||||
case 'nashornScript':
|
||||
return jsCode(requestObj);
|
||||
case "rhinoScript":
|
||||
case 'rhinoScript':
|
||||
return jsCode(requestObj);
|
||||
case "javascript":
|
||||
case 'javascript':
|
||||
return jsCode(requestObj);
|
||||
default:
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function groovyCode(requestObj) {
|
||||
let {
|
||||
requestHeaders = new Map(), requestBody = "", requestPath = "", domain = "", port = "",
|
||||
requestMethod = "", host = "", protocol = "", requestArguments = new Map(), requestRest = new Map(),
|
||||
requestHeaders = new Map(),
|
||||
requestBody = '',
|
||||
requestPath = '',
|
||||
domain = '',
|
||||
port = '',
|
||||
requestMethod = '',
|
||||
host = '',
|
||||
protocol = '',
|
||||
requestArguments = new Map(),
|
||||
requestRest = new Map(),
|
||||
requestBodyKvs = new Map(),
|
||||
bodyType
|
||||
bodyType,
|
||||
} = requestObj;
|
||||
let requestUrl = "";
|
||||
let requestUrl = '';
|
||||
if (requestMethod.toLowerCase() === 'get' && requestBodyKvs) {
|
||||
//如果是get方法要将kv值加入argument中
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
|
@ -42,49 +50,50 @@ function groovyCode(requestObj) {
|
|||
let path = getMockPath(domain, port, host);
|
||||
requestPath = path + replaceRestParams(requestPath, requestRest);
|
||||
if (protocol && host && requestPath) {
|
||||
requestUrl = protocol + "://" + domain + (port ? ":" + port : "") + requestPath;
|
||||
requestUrl =
|
||||
protocol + '://' + domain + (port ? ':' + port : '') + requestPath;
|
||||
}
|
||||
let body = JSON.stringify(requestBody);
|
||||
if (requestMethod === 'POST' && bodyType === 'kvs') {
|
||||
body = "\"";
|
||||
body = '"';
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
if (body !== "\"") {
|
||||
body += "&";
|
||||
if (body !== '"') {
|
||||
body += '&';
|
||||
}
|
||||
body += k + "=" + v;
|
||||
body += k + '=' + v;
|
||||
}
|
||||
body += "\"";
|
||||
body += '"';
|
||||
}
|
||||
|
||||
if (bodyType && bodyType.toUpperCase() === 'RAW') {
|
||||
requestHeaders.set("Content-type", "text/plain");
|
||||
requestHeaders.set('Content-type', 'text/plain');
|
||||
}
|
||||
let headers = getGroovyHeaders(requestHeaders);
|
||||
let obj = {requestUrl, requestMethod, headers, body};
|
||||
let obj = { requestUrl, requestMethod, headers, body };
|
||||
return _groovyCodeTemplate(obj);
|
||||
}
|
||||
|
||||
function pythonCode(requestObj) {
|
||||
let {
|
||||
requestHeaders = new Map(),
|
||||
requestBody = "",
|
||||
requestPath = "/",
|
||||
requestMethod = "",
|
||||
host = "",
|
||||
domain = "",
|
||||
port = "",
|
||||
protocol = "http",
|
||||
requestBody = '',
|
||||
requestPath = '/',
|
||||
requestMethod = '',
|
||||
host = '',
|
||||
domain = '',
|
||||
port = '',
|
||||
protocol = 'http',
|
||||
requestArguments = new Map(),
|
||||
requestBodyKvs = new Map(),
|
||||
bodyType,
|
||||
requestRest = new Map()
|
||||
requestRest = new Map(),
|
||||
} = requestObj;
|
||||
let connType = "HTTPConnection";
|
||||
let connType = 'HTTPConnection';
|
||||
if (protocol === 'https') {
|
||||
connType = "HTTPSConnection";
|
||||
connType = 'HTTPSConnection';
|
||||
}
|
||||
let headers = getHeaders(requestHeaders);
|
||||
requestBody = requestBody ? JSON.stringify(requestBody) : "{}";
|
||||
requestBody = requestBody ? JSON.stringify(requestBody) : '{}';
|
||||
if (requestMethod.toLowerCase() === 'get' && requestBodyKvs) {
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
requestArguments.set(k, v);
|
||||
|
@ -93,7 +102,17 @@ function pythonCode(requestObj) {
|
|||
requestPath = getRequestPath(requestArguments, requestPath);
|
||||
let path = getMockPath(domain, port, host);
|
||||
requestPath = path + replaceRestParams(requestPath, requestRest);
|
||||
let obj = {requestBody, headers, requestPath, requestMethod, requestBodyKvs, bodyType, connType, domain, port};
|
||||
let obj = {
|
||||
requestBody,
|
||||
headers,
|
||||
requestPath,
|
||||
requestMethod,
|
||||
requestBodyKvs,
|
||||
bodyType,
|
||||
connType,
|
||||
domain,
|
||||
port,
|
||||
};
|
||||
return _pythonCodeTemplate(obj);
|
||||
}
|
||||
|
||||
|
@ -107,13 +126,13 @@ function jsCode(requestObj) {
|
|||
|
||||
function getRequestPath(requestArgs, requestPath) {
|
||||
if (requestArgs.size > 0) {
|
||||
requestPath = requestPath + "?"
|
||||
requestPath = requestPath + '?';
|
||||
let index = 1;
|
||||
for (let [k, v] of requestArgs) {
|
||||
if (index !== 1) {
|
||||
requestPath = requestPath + "&";
|
||||
requestPath = requestPath + '&';
|
||||
}
|
||||
requestPath = requestPath + k + "=" + v;
|
||||
requestPath = requestPath + k + '=' + v;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
@ -121,39 +140,53 @@ function getRequestPath(requestArgs, requestPath) {
|
|||
}
|
||||
|
||||
function getHeaders(requestHeaders) {
|
||||
let headers = "{";
|
||||
let headers = '{';
|
||||
let index = 1;
|
||||
for (let [k, v] of requestHeaders) {
|
||||
if (index !== 1) {
|
||||
headers += ",";
|
||||
headers += ',';
|
||||
}
|
||||
// 拼装
|
||||
headers += `'${k}':'${v}'`;
|
||||
index++;
|
||||
}
|
||||
headers = headers + "}"
|
||||
headers = headers + '}';
|
||||
return headers;
|
||||
}
|
||||
|
||||
function getGroovyHeaders(requestHeaders) {
|
||||
let headers = "[";
|
||||
let headers = '[';
|
||||
let index = 1;
|
||||
for (let [k, v] of requestHeaders) {
|
||||
if (index !== 1) {
|
||||
headers += ",";
|
||||
headers += ',';
|
||||
}
|
||||
// 拼装
|
||||
headers += `'${k}':'${v}'`;
|
||||
index++;
|
||||
}
|
||||
headers = headers + "]"
|
||||
headers = headers + ']';
|
||||
return headers;
|
||||
}
|
||||
|
||||
function _pythonCodeTemplate(obj) {
|
||||
let {requestBody, requestBodyKvs, bodyType, headers, requestPath, requestMethod, connType, domain, port} = obj;
|
||||
let {
|
||||
requestBody,
|
||||
requestBodyKvs,
|
||||
bodyType,
|
||||
headers,
|
||||
requestPath,
|
||||
requestMethod,
|
||||
connType,
|
||||
domain,
|
||||
port,
|
||||
} = obj;
|
||||
let reqBody = obj.requestBody;
|
||||
if (requestMethod.toLowerCase() === 'post' && obj.bodyType === 'kvs' && obj.requestBodyKvs) {
|
||||
if (
|
||||
requestMethod.toLowerCase() === 'post' &&
|
||||
obj.bodyType === 'kvs' &&
|
||||
obj.requestBodyKvs
|
||||
) {
|
||||
reqBody = 'urllib.urlencode({';
|
||||
// 设置post参数
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
|
@ -161,11 +194,12 @@ function _pythonCodeTemplate(obj) {
|
|||
}
|
||||
reqBody += `})`;
|
||||
if (headers === '{}') {
|
||||
headers = '{\'Content-type\': \'application/x-www-form-urlencoded\', \'Accept\': \'text/plain\'}';
|
||||
headers =
|
||||
"{'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'}";
|
||||
}
|
||||
}
|
||||
|
||||
let host = domain + (port ? ":" + port : "");
|
||||
let host = domain + (port ? ':' + port : '');
|
||||
|
||||
return `import httplib,urllib
|
||||
params = ${reqBody} #例 {'username':'test'}
|
||||
|
@ -183,13 +217,13 @@ log.info(data)
|
|||
}
|
||||
|
||||
function _groovyCodeTemplate(obj) {
|
||||
let {requestUrl, requestMethod, headers, body} = obj;
|
||||
let { requestUrl, requestMethod, headers, body } = obj;
|
||||
let params = `[
|
||||
'url': '${requestUrl}',
|
||||
'method': '${requestMethod}', // POST/GET
|
||||
'headers': ${headers}, // 请求headers 例:{'Content-type':'application/json'}
|
||||
'data': ${body} // 参数
|
||||
]`
|
||||
]`;
|
||||
return `import groovy.json.JsonOutput
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
|
@ -220,17 +254,17 @@ log.info(conn.content.text)
|
|||
function _beanshellTemplate(obj) {
|
||||
let {
|
||||
requestHeaders = new Map(),
|
||||
requestBody = "",
|
||||
requestBody = '',
|
||||
requestBodyKvs = new Map(),
|
||||
bodyType = "",
|
||||
requestPath = "/",
|
||||
requestMethod = "GET",
|
||||
protocol = "http",
|
||||
bodyType = '',
|
||||
requestPath = '/',
|
||||
requestMethod = 'GET',
|
||||
protocol = 'http',
|
||||
requestArguments = new Map(),
|
||||
domain = "",
|
||||
host = "",
|
||||
port = "",
|
||||
requestRest = new Map()
|
||||
domain = '',
|
||||
host = '',
|
||||
port = '',
|
||||
requestRest = new Map(),
|
||||
} = obj;
|
||||
|
||||
let path = getMockPath(domain, port, host);
|
||||
|
@ -241,26 +275,27 @@ function _beanshellTemplate(obj) {
|
|||
.setPath("${requestPath}")
|
||||
`;
|
||||
// http 请求类型
|
||||
let method = requestMethod.toLowerCase().replace(/^\S/, s => s.toUpperCase());
|
||||
let method = requestMethod
|
||||
.toLowerCase()
|
||||
.replace(/^\S/, (s) => s.toUpperCase());
|
||||
let httpMethodCode = `Http${method} request = new Http${method}(uri);`;
|
||||
// 设置参数
|
||||
for (let [k, v] of requestArguments) {
|
||||
uri = uri + `.setParameter("${k}", "${v}")`;
|
||||
}
|
||||
if (method === "Get" && requestBodyKvs) {
|
||||
if (method === 'Get' && requestBodyKvs) {
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
uri = uri + `.setParameter("${k}", "${v}")`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let postKvsParam = "";
|
||||
let postKvsParam = '';
|
||||
if (method === 'Post') {
|
||||
// 设置post参数
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
postKvsParam += `nameValueList.add(new BasicNameValuePair("${k}", "${v}"));\r\n`;
|
||||
}
|
||||
if (postKvsParam !== "") {
|
||||
if (postKvsParam !== '') {
|
||||
postKvsParam = `List nameValueList = new ArrayList();\r\n` + postKvsParam;
|
||||
}
|
||||
}
|
||||
|
@ -275,19 +310,22 @@ function _beanshellTemplate(obj) {
|
|||
uri += ` .build();`;
|
||||
}
|
||||
// 设置请求头
|
||||
let setHeader = "";
|
||||
let setHeader = '';
|
||||
for (let [k, v] of requestHeaders) {
|
||||
setHeader = setHeader + `request.setHeader("${k}", "${v}");` + '\n';
|
||||
}
|
||||
try {
|
||||
requestBody = JSON.stringify(requestBody);
|
||||
} catch (e) {
|
||||
requestBody = "";
|
||||
requestBody = '';
|
||||
}
|
||||
let postMethodCode = "";
|
||||
if (requestMethod === "POST") {
|
||||
if (bodyType === "kvs") {
|
||||
postMethodCode = postKvsParam + "\r\n" + `request.setEntity(new UrlEncodedFormEntity(nameValueList, "UTF-8"));`;
|
||||
let postMethodCode = '';
|
||||
if (requestMethod === 'POST') {
|
||||
if (bodyType === 'kvs') {
|
||||
postMethodCode =
|
||||
postKvsParam +
|
||||
'\r\n' +
|
||||
`request.setEntity(new UrlEncodedFormEntity(nameValueList, "UTF-8"));`;
|
||||
} else {
|
||||
postMethodCode = `request.setEntity(new StringEntity(StringEscapeUtils.unescapeJava(payload)));`;
|
||||
}
|
||||
|
@ -327,32 +365,32 @@ response = httpclient.execute(request);
|
|||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||
log.info(content);
|
||||
}`
|
||||
}`;
|
||||
}
|
||||
|
||||
function _jsTemplate(obj) {
|
||||
let {
|
||||
requestHeaders = new Map(),
|
||||
requestBody = "",
|
||||
requestPath = "/",
|
||||
requestMethod = "GET",
|
||||
protocol = "http",
|
||||
requestBody = '',
|
||||
requestPath = '/',
|
||||
requestMethod = 'GET',
|
||||
protocol = 'http',
|
||||
requestArguments = new Map(),
|
||||
host = "",
|
||||
domain = "",
|
||||
port = "",
|
||||
host = '',
|
||||
domain = '',
|
||||
port = '',
|
||||
requestBodyKvs = new Map(),
|
||||
bodyType = "",
|
||||
requestRest = new Map()
|
||||
bodyType = '',
|
||||
requestRest = new Map(),
|
||||
} = obj;
|
||||
let url = "";
|
||||
let url = '';
|
||||
requestPath = replaceRestParams(requestPath, requestRest);
|
||||
if (protocol && domain && port) {
|
||||
let path = getMockPath(domain, port, host);
|
||||
requestPath = path + requestPath;
|
||||
url = protocol + "://" + domain + (port ? ":" + port : "") + requestPath;
|
||||
url = protocol + '://' + domain + (port ? ':' + port : '') + requestPath;
|
||||
} else if (protocol && domain) {
|
||||
url = protocol + "://" + domain + requestPath;
|
||||
url = protocol + '://' + domain + requestPath;
|
||||
}
|
||||
if (requestMethod.toLowerCase() === 'get' && requestBodyKvs) {
|
||||
//如果是get方法要将kv值加入argument中
|
||||
|
@ -364,29 +402,29 @@ function _jsTemplate(obj) {
|
|||
try {
|
||||
requestBody = JSON.stringify(requestBody);
|
||||
} catch (e) {
|
||||
requestBody = "";
|
||||
requestBody = '';
|
||||
}
|
||||
|
||||
let connStr = "";
|
||||
let connStr = '';
|
||||
if (bodyType && bodyType.toUpperCase() === 'RAW') {
|
||||
requestHeaders.set("Content-type", "text/plain");
|
||||
requestHeaders.set('Content-type', 'text/plain');
|
||||
}
|
||||
for (let [k, v] of requestHeaders) {
|
||||
connStr += `conn.setRequestProperty("${k}","${v}");` + '\n';
|
||||
}
|
||||
|
||||
if (requestMethod === 'POST' && bodyType === 'kvs') {
|
||||
requestBody = "\"";
|
||||
requestBody = '"';
|
||||
for (let [k, v] of requestBodyKvs) {
|
||||
if (requestBody !== "\"") {
|
||||
requestBody += "&";
|
||||
if (requestBody !== '"') {
|
||||
requestBody += '&';
|
||||
}
|
||||
requestBody += k + "=" + v;
|
||||
requestBody += k + '=' + v;
|
||||
}
|
||||
requestBody += "\"";
|
||||
requestBody += '"';
|
||||
}
|
||||
let postParamExecCode = "";
|
||||
if (requestBody && requestBody !== "" && requestBody !== "\"\"") {
|
||||
let postParamExecCode = '';
|
||||
if (requestBody && requestBody !== '' && requestBody !== '""') {
|
||||
postParamExecCode = `
|
||||
var opt = new java.io.DataOutputStream(conn.getOutputStream());
|
||||
var t = (new java.lang.String(parameterData)).getBytes("utf-8");
|
||||
|
@ -396,7 +434,6 @@ opt.close();
|
|||
`;
|
||||
}
|
||||
|
||||
|
||||
return `var urlStr = "${url}"; // 请求地址
|
||||
var requestMethod = "${requestMethod}"; // 请求类型
|
||||
var parameterData = ${requestBody}; // 请求参数
|
||||
|
@ -444,9 +481,9 @@ function replaceRestParams(path, restMap) {
|
|||
|
||||
function getMockPath(domain, port, socket) {
|
||||
if (domain === socket || !port) {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
let str = domain + ":" + port;
|
||||
let str = domain + ':' + port;
|
||||
// 获取socket之后的路径
|
||||
return socket.substring(str.length);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import i18n from "metersphere-frontend/src/i18n";
|
||||
import i18n from 'metersphere-frontend/src/i18n';
|
||||
export const SCRIPT_MENU = [
|
||||
{
|
||||
title: i18n.t('project.code_segment.api_test'),
|
||||
children: [
|
||||
{
|
||||
title: i18n.t('project.code_segment.import_api_test'),
|
||||
command: "api_definition",
|
||||
command: 'api_definition',
|
||||
},
|
||||
{
|
||||
title: i18n.t('project.code_segment.new_api_test'),
|
||||
command: "new_api_request",
|
||||
}
|
||||
]
|
||||
command: 'new_api_request',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t('project.code_segment.custom_value'),
|
||||
|
@ -25,52 +25,64 @@ export const SCRIPT_MENU = [
|
|||
value: 'vars.put("variable_name", "variable_value")',
|
||||
},
|
||||
{
|
||||
title: i18n.t('api_test.request.processor.code_template_get_response_header'),
|
||||
title: i18n.t(
|
||||
'api_test.request.processor.code_template_get_response_header'
|
||||
),
|
||||
value: 'prev.getResponseHeaders()',
|
||||
},
|
||||
{
|
||||
title: i18n.t('api_test.request.processor.code_template_get_response_code'),
|
||||
title: i18n.t(
|
||||
'api_test.request.processor.code_template_get_response_code'
|
||||
),
|
||||
value: 'prev.getResponseCode()',
|
||||
},
|
||||
{
|
||||
title: i18n.t('api_test.request.processor.code_template_get_response_result'),
|
||||
title: i18n.t(
|
||||
'api_test.request.processor.code_template_get_response_result'
|
||||
),
|
||||
value: 'prev.getResponseDataAsString()',
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t('project.code_segment.project_env'),
|
||||
children: [
|
||||
{
|
||||
title: i18n.t('api_test.request.processor.param_environment_set_global_variable'),
|
||||
value: 'vars.put(${__metersphere_env_id}+"key","value");\n'+'vars.put("key","value")',
|
||||
title: i18n.t(
|
||||
'api_test.request.processor.param_environment_set_global_variable'
|
||||
),
|
||||
value:
|
||||
'vars.put(${__metersphere_env_id}+"key","value");\n' +
|
||||
'vars.put("key","value")',
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t('project.code_segment.code_segment'),
|
||||
children: [
|
||||
{
|
||||
title: i18n.t('project.code_segment.insert_segment'),
|
||||
command: "custom_function",
|
||||
}
|
||||
]
|
||||
command: 'custom_function',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t('project.code_segment.exception_handle'),
|
||||
children: [
|
||||
{
|
||||
title: i18n.t('project.code_segment.stop_test'),
|
||||
value: 'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());'
|
||||
title: i18n.t('project.code_segment.stop_test'),
|
||||
value:
|
||||
'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());',
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t('project.code_segment.report_handle'),
|
||||
children: [
|
||||
{
|
||||
title: i18n.t('api_test.request.processor.code_add_report_length'),
|
||||
value: 'String report = ctx.getCurrentSampler().getRequestData();\n' +
|
||||
value:
|
||||
'String report = ctx.getCurrentSampler().getRequestData();\n' +
|
||||
'if(report!=null){\n' +
|
||||
' //补足8位长度,前置补0\n' +
|
||||
' String reportlengthStr = String.format("%08d",report.length());\n' +
|
||||
|
@ -80,7 +92,8 @@ export const SCRIPT_MENU = [
|
|||
},
|
||||
{
|
||||
title: i18n.t('api_test.request.processor.code_hide_report_length'),
|
||||
value: '//Get response data\n' +
|
||||
value:
|
||||
'//Get response data\n' +
|
||||
'String returnData = prev.getResponseDataAsString();\n' +
|
||||
'if(returnData!=null&&returnData.length()>8){\n' +
|
||||
'//remove 8 report length \n' +
|
||||
|
@ -91,6 +104,6 @@ export const SCRIPT_MENU = [
|
|||
' }\n' +
|
||||
'}',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -17,8 +17,7 @@ const OutsideClick = {
|
|||
el.__vueClickOutside__ = documentHandler;
|
||||
document.addEventListener('click', documentHandler);
|
||||
},
|
||||
update() {
|
||||
},
|
||||
update() {},
|
||||
unbind(el, binding) {
|
||||
// 解除事件监听
|
||||
document.removeEventListener('click', el.__vueClickOutside__);
|
||||
|
@ -27,5 +26,3 @@ const OutsideClick = {
|
|||
};
|
||||
|
||||
export default OutsideClick;
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@active="active"
|
||||
:is-show-name-input="!isDeletedOrRef"
|
||||
:data="request"
|
||||
:is-deleted="request.referenced==='REF' && !isShowNum"
|
||||
:is-deleted="request.referenced === 'REF' && !isShowNum"
|
||||
:draggable="draggable"
|
||||
:color="displayColor.color"
|
||||
:background-color="displayColor.backgroundColor"
|
||||
|
@ -14,121 +14,209 @@
|
|||
:show-btn="showBtn"
|
||||
:show-version="showVersion"
|
||||
:title="displayTitle"
|
||||
:if-from-variable-advance="ifFromVariableAdvance">
|
||||
|
||||
<template v-slot:afterTitle v-if="(request.refType==='API'|| request.refType==='CASE')">
|
||||
<span v-if="request.num" @click="clickResource(request)">{{ "( ID: " + request.num + ")" }}</span>
|
||||
:if-from-variable-advance="ifFromVariableAdvance"
|
||||
>
|
||||
<template
|
||||
v-slot:afterTitle
|
||||
v-if="request.refType === 'API' || request.refType === 'CASE'"
|
||||
>
|
||||
<span v-if="request.num" @click="clickResource(request)">{{
|
||||
'( ID: ' + request.num + ')'
|
||||
}}</span>
|
||||
<span v-else>
|
||||
<el-tooltip class="ms-num" effect="dark"
|
||||
:content="request.refType==='API'?$t('api_test.automation.scenario.api_none'):$t('api_test.automation.scenario.case_none')"
|
||||
placement="top">
|
||||
<i class="el-icon-warning"/>
|
||||
<el-tooltip
|
||||
class="ms-num"
|
||||
effect="dark"
|
||||
:content="
|
||||
request.refType === 'API'
|
||||
? $t('api_test.automation.scenario.api_none')
|
||||
: $t('api_test.automation.scenario.case_none')
|
||||
"
|
||||
placement="top"
|
||||
>
|
||||
<i class="el-icon-warning" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<span v-xpack v-if="request.versionEnable&&showVersion">{{ $t('project.version.name') }}: {{
|
||||
request.versionName
|
||||
}}</span>
|
||||
<span v-xpack v-if="request.versionEnable && showVersion"
|
||||
>{{ $t('project.version.name') }}: {{ request.versionName }}</span
|
||||
>
|
||||
</template>
|
||||
|
||||
<template v-slot:behindHeaderLeft>
|
||||
<el-tag size="small" class="ms-tag" v-if="request.referenced==='Deleted'" type="danger">
|
||||
<el-tag
|
||||
size="small"
|
||||
class="ms-tag"
|
||||
v-if="request.referenced === 'Deleted'"
|
||||
type="danger"
|
||||
>
|
||||
{{ $t('api_test.automation.reference_deleted') }}
|
||||
</el-tag>
|
||||
<el-tag size="small" class="ms-tag" v-if="request.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
|
||||
<el-tag size="small" class="ms-tag" v-if="request.referenced ==='REF'">{{
|
||||
$t('api_test.scenario.reference')
|
||||
}}
|
||||
<el-tag
|
||||
size="small"
|
||||
class="ms-tag"
|
||||
v-if="request.referenced === 'Copy'"
|
||||
>{{ $t('commons.copy') }}</el-tag
|
||||
>
|
||||
<el-tag size="small" class="ms-tag" v-if="request.referenced === 'REF'"
|
||||
>{{ $t('api_test.scenario.reference') }}
|
||||
</el-tag>
|
||||
<span class="ms-tag ms-step-name-api">{{ getProjectName(request.projectId) }}</span>
|
||||
<span class="ms-tag ms-step-name-api">{{
|
||||
getProjectName(request.projectId)
|
||||
}}</span>
|
||||
</template>
|
||||
<template v-slot:debugStepCode>
|
||||
<span v-if="request.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px"/>
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<!-- 场景调试步骤增加误报判断 -->
|
||||
<span class="ms-step-debug-code" :class="'ms-req-error-report'" v-if="!loading &&!request.testing && request.debug
|
||||
&& request.requestResult[0] && request.requestResult[0].responseResult &&
|
||||
request.requestResult[0].status==='FAKE_ERROR'">
|
||||
FakeError
|
||||
<span v-if="request.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px" />
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span class="ms-step-debug-code"
|
||||
@click="active"
|
||||
:class="request.requestResult[0].success && reqSuccess?'ms-req-success':'ms-req-error'"
|
||||
v-else-if="!loading &&!request.testing && request.debug && request.requestResult[0] && request.requestResult[0].responseResult">
|
||||
{{ request.requestResult[0].success && reqSuccess ? 'Success' : 'Error' }}
|
||||
<!-- 场景调试步骤增加误报判断 -->
|
||||
<span
|
||||
class="ms-step-debug-code"
|
||||
:class="'ms-req-error-report'"
|
||||
v-if="
|
||||
!loading &&
|
||||
!request.testing &&
|
||||
request.debug &&
|
||||
request.requestResult[0] &&
|
||||
request.requestResult[0].responseResult &&
|
||||
request.requestResult[0].status === 'FAKE_ERROR'
|
||||
"
|
||||
>
|
||||
FakeError
|
||||
</span>
|
||||
<span
|
||||
class="ms-step-debug-code"
|
||||
@click="active"
|
||||
:class="
|
||||
request.requestResult[0].success && reqSuccess
|
||||
? 'ms-req-success'
|
||||
: 'ms-req-error'
|
||||
"
|
||||
v-else-if="
|
||||
!loading &&
|
||||
!request.testing &&
|
||||
request.debug &&
|
||||
request.requestResult[0] &&
|
||||
request.requestResult[0].responseResult
|
||||
"
|
||||
>
|
||||
{{
|
||||
request.requestResult[0].success && reqSuccess ? 'Success' : 'Error'
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:button v-if="!ifFromVariableAdvance">
|
||||
<el-tooltip :content="$t('api_test.run')" placement="top" v-if="!loading">
|
||||
<el-button :disabled="!request.enable" @click="run" icon="el-icon-video-play" class="ms-btn" size="mini"
|
||||
circle/>
|
||||
<el-tooltip
|
||||
:content="$t('api_test.run')"
|
||||
placement="top"
|
||||
v-if="!loading"
|
||||
>
|
||||
<el-button
|
||||
:disabled="!request.enable"
|
||||
@click="run"
|
||||
icon="el-icon-video-play"
|
||||
class="ms-btn"
|
||||
size="mini"
|
||||
circle
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('report.stop_btn')" placement="top" :enterable="false" v-else>
|
||||
<el-button @click.once="stop" size="mini" style="color:white;padding: 0 0.1px;width: 24px;height: 24px;"
|
||||
class="stop-btn" circle>
|
||||
<el-tooltip
|
||||
:content="$t('report.stop_btn')"
|
||||
placement="top"
|
||||
:enterable="false"
|
||||
v-else
|
||||
>
|
||||
<el-button
|
||||
@click.once="stop"
|
||||
size="mini"
|
||||
style="color: white; padding: 0 0.1px; width: 24px; height: 24px"
|
||||
class="stop-btn"
|
||||
circle
|
||||
>
|
||||
<div style="transform: scale(0.66)">
|
||||
<span style="margin-left: -4.5px;font-weight: bold;">STOP</span>
|
||||
<span style="margin-left: -4.5px; font-weight: bold">STOP</span>
|
||||
</div>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<!--请求内容-->
|
||||
<template v-slot:request>
|
||||
<legend style="width: 100%;display:table-column">
|
||||
<legend style="width: 100%; display: table-column">
|
||||
<div v-if="!ifFromVariableAdvance">
|
||||
<customize-req-info :is-customize-req="isCustomizeReq" :request="request" @setDomain="setDomain"/>
|
||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||
<customize-req-info
|
||||
:is-customize-req="isCustomizeReq"
|
||||
:request="request"
|
||||
@setDomain="setDomain"
|
||||
/>
|
||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }}</p>
|
||||
<ms-api-request-form
|
||||
v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
|
||||
v-if="
|
||||
request.protocol === 'HTTP' ||
|
||||
request.type === 'HTTPSamplerProxy'
|
||||
"
|
||||
:scenario-definition="scenarioDefinition"
|
||||
@editScenarioAdvance="editScenarioAdvance"
|
||||
:isShowEnable="true"
|
||||
:response="response"
|
||||
:referenced="true"
|
||||
:scenarioId="currentScenario.id"
|
||||
:headers="request.headers "
|
||||
:headers="request.headers"
|
||||
:is-read-only="isCompReadOnly"
|
||||
:request="request"/>
|
||||
:request="request"
|
||||
/>
|
||||
<mx-esb-definition
|
||||
v-if="request.esbDataStruct!=null"
|
||||
v-if="request.esbDataStruct != null"
|
||||
v-xpack
|
||||
:request="request"
|
||||
:response="response"
|
||||
:showScript="true"
|
||||
:show-pre-script="true"
|
||||
:is-read-only="isCompReadOnly" ref="esbDefinition"/>
|
||||
:is-read-only="isCompReadOnly"
|
||||
ref="esbDefinition"
|
||||
/>
|
||||
<ms-tcp-format-parameters
|
||||
v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "
|
||||
v-if="
|
||||
(request.protocol === 'TCP' || request.type === 'TCPSampler') &&
|
||||
request.esbDataStruct == null
|
||||
"
|
||||
:is-read-only="isCompReadOnly"
|
||||
:response="response"
|
||||
:show-pre-script="true"
|
||||
:scenarioId="currentScenario.id"
|
||||
:show-script="true" :request="request"/>
|
||||
:show-script="true"
|
||||
:request="request"
|
||||
/>
|
||||
|
||||
<ms-sql-basis-parameters
|
||||
v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
|
||||
v-if="
|
||||
request.protocol === 'SQL' || request.type === 'JDBCSampler'
|
||||
"
|
||||
:request="request"
|
||||
:response="response"
|
||||
:scenarioId="currentScenario.id"
|
||||
:is-read-only="isCompReadOnly"
|
||||
:showScript="true"/>
|
||||
:showScript="true"
|
||||
/>
|
||||
|
||||
<ms-dubbo-basis-parameters
|
||||
v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
|
||||
v-if="
|
||||
request.protocol === 'DUBBO' ||
|
||||
request.protocol === 'dubbo://' ||
|
||||
request.type === 'DubboSampler'
|
||||
"
|
||||
:request="request"
|
||||
:scenarioId="currentScenario.id"
|
||||
:response="response"
|
||||
:is-read-only="isCompReadOnly"
|
||||
:showScript="true"/>
|
||||
|
||||
:showScript="true"
|
||||
/>
|
||||
</div>
|
||||
</legend>
|
||||
</template>
|
||||
<!-- 执行结果内容 -->
|
||||
<template v-slot:result>
|
||||
<div v-loading="loading">
|
||||
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
|
||||
<p class="tip">{{ $t('api_test.definition.request.res_param') }}</p>
|
||||
<div v-if="request.backEsbDataStruct != null">
|
||||
<mx-esb-definition-response
|
||||
:currentProtocol="request.protocol"
|
||||
|
@ -141,10 +229,18 @@
|
|||
/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-tabs v-model="request.activeName" closable class="ms-tabs"
|
||||
v-if="request.requestResult && request.requestResult.length > 1">
|
||||
<el-tab-pane v-for="(item,i) in request.requestResult" :label="'循环'+(i+1)" :key="i"
|
||||
style="margin-bottom: 5px">
|
||||
<el-tabs
|
||||
v-model="request.activeName"
|
||||
closable
|
||||
class="ms-tabs"
|
||||
v-if="request.requestResult && request.requestResult.length > 1"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="(item, i) in request.requestResult"
|
||||
:label="'循环' + (i + 1)"
|
||||
:key="i"
|
||||
style="margin-bottom: 5px"
|
||||
>
|
||||
<api-response-component
|
||||
:currentProtocol="request.protocol"
|
||||
:apiActive="true"
|
||||
|
@ -156,31 +252,41 @@
|
|||
:currentProtocol="request.protocol"
|
||||
:apiActive="true"
|
||||
:result="request.requestResult[0]"
|
||||
v-else/>
|
||||
v-else
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</api-base-component>
|
||||
<ms-run :debug="true" :reportId="reportId" :run-data="runData" :env-map="environmentMap"
|
||||
@runRefresh="runRefresh" @errorRefresh="errorRefresh" ref="runTest"/>
|
||||
|
||||
<ms-run
|
||||
:debug="true"
|
||||
:reportId="reportId"
|
||||
:run-data="runData"
|
||||
:env-map="environmentMap"
|
||||
@runRefresh="runRefresh"
|
||||
@errorRefresh="errorRefresh"
|
||||
ref="runTest"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getApiCaseById, getCaseById} from "@/api/api-test-case";
|
||||
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
||||
import {getUUID} from "metersphere-frontend/src/utils";
|
||||
import {getUrl} from "@/business/automation/scenario/component/urlhelper";
|
||||
import {getCurrentByResourceId} from "@/api/user";
|
||||
import {getOwnerProjectIds, getProject} from "@/api/project";
|
||||
import {execStop} from "@/api/scenario";
|
||||
import {useApiStore} from "@/store";
|
||||
import {getDefinitionById} from "@/api/definition";
|
||||
import { getApiCaseById, getCaseById } from '@/api/api-test-case';
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentWorkspaceId,
|
||||
} from 'metersphere-frontend/src/utils/token';
|
||||
import { getUUID } from 'metersphere-frontend/src/utils';
|
||||
import { getUrl } from '@/business/automation/scenario/component/urlhelper';
|
||||
import { getCurrentByResourceId } from '@/api/user';
|
||||
import { getOwnerProjectIds, getProject } from '@/api/project';
|
||||
import { execStop } from '@/api/scenario';
|
||||
import { useApiStore } from '@/store';
|
||||
import { getDefinitionById } from '@/api/definition';
|
||||
|
||||
const store = useApiStore();
|
||||
export default {
|
||||
name: "MsApiComponent",
|
||||
name: 'MsApiComponent',
|
||||
props: {
|
||||
request: {},
|
||||
currentScenario: {},
|
||||
|
@ -213,22 +319,30 @@ export default {
|
|||
},
|
||||
},
|
||||
components: {
|
||||
CustomizeReqInfo: () => import("@/business/automation/scenario/common/CustomizeReqInfo"),
|
||||
ApiBaseComponent: () => import("../common/ApiBaseComponent"),
|
||||
ApiResponseComponent: () => import("./ApiResponseComponent"),
|
||||
MsSqlBasisParameters: () => import("../../../definition/components/request/database/BasisParameters"),
|
||||
MsTcpFormatParameters: () => import("../../../definition/components/request/tcp/TcpFormatParameters"),
|
||||
MsDubboBasisParameters: () => import("../../../definition/components/request/dubbo/BasisParameters"),
|
||||
MsApiRequestForm: () => import("../../../definition/components/request/http/ApiHttpRequestForm"),
|
||||
MsRequestResultTail: () => import("../../../definition/components/response/RequestResultTail"),
|
||||
MsRun: () => import("../../../definition/components/Run"),
|
||||
MxEsbDefinition: () => import("@/business/definition/components/esb/MxEsbDefinition"),
|
||||
MxEsbDefinitionResponse: () => import("@/business/definition/components/esb/MxEsbDefinitionResponse")
|
||||
CustomizeReqInfo: () =>
|
||||
import('@/business/automation/scenario/common/CustomizeReqInfo'),
|
||||
ApiBaseComponent: () => import('../common/ApiBaseComponent'),
|
||||
ApiResponseComponent: () => import('./ApiResponseComponent'),
|
||||
MsSqlBasisParameters: () =>
|
||||
import('../../../definition/components/request/database/BasisParameters'),
|
||||
MsTcpFormatParameters: () =>
|
||||
import('../../../definition/components/request/tcp/TcpFormatParameters'),
|
||||
MsDubboBasisParameters: () =>
|
||||
import('../../../definition/components/request/dubbo/BasisParameters'),
|
||||
MsApiRequestForm: () =>
|
||||
import('../../../definition/components/request/http/ApiHttpRequestForm'),
|
||||
MsRequestResultTail: () =>
|
||||
import('../../../definition/components/response/RequestResultTail'),
|
||||
MsRun: () => import('../../../definition/components/Run'),
|
||||
MxEsbDefinition: () =>
|
||||
import('@/business/definition/components/esb/MxEsbDefinition'),
|
||||
MxEsbDefinitionResponse: () =>
|
||||
import('@/business/definition/components/esb/MxEsbDefinitionResponse'),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
reportId: "",
|
||||
reportId: '',
|
||||
runData: [],
|
||||
isShowInput: false,
|
||||
environment: {},
|
||||
|
@ -240,13 +354,17 @@ export default {
|
|||
isShowNum: false,
|
||||
response: {},
|
||||
currentScenarioData: {},
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 历史数据兼容
|
||||
if (!this.request.requestResult) {
|
||||
this.request.requestResult = [{responseResult: {}}];
|
||||
} else if (this.request.requestResult && Object.prototype.toString.call(this.request.requestResult) !== '[object Array]') {
|
||||
this.request.requestResult = [{ responseResult: {} }];
|
||||
} else if (
|
||||
this.request.requestResult &&
|
||||
Object.prototype.toString.call(this.request.requestResult) !==
|
||||
'[object Array]'
|
||||
) {
|
||||
let obj = JSON.parse(JSON.stringify(this.request.requestResult));
|
||||
this.request.requestResult = [obj];
|
||||
}
|
||||
|
@ -285,31 +403,31 @@ export default {
|
|||
this.forStatus();
|
||||
this.reload();
|
||||
},
|
||||
'storeCurrentApiCaseDebugLoop'() {
|
||||
storeCurrentApiCaseDebugLoop() {
|
||||
this.forStatus();
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
storeCurrentApiCaseDebugLoop() {
|
||||
return store.currentApiCase ? store.currentApiCase.debugLoop : "";
|
||||
return store.currentApiCase ? store.currentApiCase.debugLoop : '';
|
||||
},
|
||||
displayColor() {
|
||||
if (this.isApiImport) {
|
||||
return {
|
||||
color: "#F56C6C",
|
||||
backgroundColor: "#FCF1F1"
|
||||
}
|
||||
color: '#F56C6C',
|
||||
backgroundColor: '#FCF1F1',
|
||||
};
|
||||
} else if (this.isExternalImport) {
|
||||
return {
|
||||
color: "#409EFF",
|
||||
backgroundColor: "#EEF5FE"
|
||||
}
|
||||
color: '#409EFF',
|
||||
backgroundColor: '#EEF5FE',
|
||||
};
|
||||
} else if (this.isCustomizeReq) {
|
||||
return {
|
||||
color: "#008080",
|
||||
backgroundColor: "#EBF2F2"
|
||||
}
|
||||
color: '#008080',
|
||||
backgroundColor: '#EBF2F2',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
@ -332,21 +450,27 @@ export default {
|
|||
} else if (this.isCustomizeReq) {
|
||||
return this.$t('api_test.automation.customize_req');
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
},
|
||||
isApiImport() {
|
||||
let verifies = ['Deleted', 'REF', 'Copy'];
|
||||
return (this.request.referenced && verifies.indexOf(this.request.referenced) !== -1);
|
||||
return (
|
||||
this.request.referenced &&
|
||||
verifies.indexOf(this.request.referenced) !== -1
|
||||
);
|
||||
},
|
||||
isExternalImport() {
|
||||
return (this.request.referenced && this.request.referenced === 'TO_IMPORT');
|
||||
return this.request.referenced && this.request.referenced === 'TO_IMPORT';
|
||||
},
|
||||
isCustomizeReq() {
|
||||
return (!this.request.referenced || this.request.referenced === 'Created');
|
||||
return !this.request.referenced || this.request.referenced === 'Created';
|
||||
},
|
||||
isDeletedOrRef() {
|
||||
let verifies = ['Deleted', 'REF'];
|
||||
return (this.request.referenced && verifies.indexOf(this.request.referenced) !== -1);
|
||||
return (
|
||||
this.request.referenced &&
|
||||
verifies.indexOf(this.request.referenced) !== -1
|
||||
);
|
||||
},
|
||||
projectId() {
|
||||
return getCurrentProjectID();
|
||||
|
@ -355,11 +479,18 @@ export default {
|
|||
methods: {
|
||||
setOwnEnvironment(scenarioDefinition) {
|
||||
for (let i in scenarioDefinition) {
|
||||
let typeArray = ["JDBCPostProcessor", "JDBCSampler", "JDBCPreProcessor"]
|
||||
let typeArray = [
|
||||
'JDBCPostProcessor',
|
||||
'JDBCSampler',
|
||||
'JDBCPreProcessor',
|
||||
];
|
||||
if (typeArray.indexOf(scenarioDefinition[i].type) !== -1) {
|
||||
scenarioDefinition[i].currentScenarioId = this.currentScenario.id;
|
||||
}
|
||||
if (scenarioDefinition[i].hashTree && scenarioDefinition[i].hashTree.length > 0) {
|
||||
if (
|
||||
scenarioDefinition[i].hashTree &&
|
||||
scenarioDefinition[i].hashTree.length > 0
|
||||
) {
|
||||
this.setOwnEnvironment(scenarioDefinition[i].hashTree);
|
||||
}
|
||||
}
|
||||
|
@ -367,22 +498,25 @@ export default {
|
|||
forStatus() {
|
||||
this.reqSuccess = true;
|
||||
if (this.request.result && this.request.result.length > 0) {
|
||||
this.request.result.forEach(item => {
|
||||
item.requestResult.forEach(req => {
|
||||
this.request.result.forEach((item) => {
|
||||
item.requestResult.forEach((req) => {
|
||||
if (!req.success) {
|
||||
this.reqSuccess = req.success;
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if (this.request.requestResult && this.request.requestResult.length > 1) {
|
||||
this.request.requestResult.forEach(item => {
|
||||
});
|
||||
});
|
||||
} else if (
|
||||
this.request.requestResult &&
|
||||
this.request.requestResult.length > 1
|
||||
) {
|
||||
this.request.requestResult.forEach((item) => {
|
||||
if (!item.success) {
|
||||
this.reqSuccess = item.success;
|
||||
if (this.node && this.node.parent && this.node.parent.data) {
|
||||
this.node.parent.data.code = 'ERROR';
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
if (this.request.requestResult && this.request.requestResult.length > 0) {
|
||||
this.response = this.request.requestResult[0];
|
||||
|
@ -400,7 +534,10 @@ export default {
|
|||
new URL(url);
|
||||
this.request.url = url;
|
||||
} catch (e) {
|
||||
if (url && (!url.startsWith("http://") || !url.startsWith("https://"))) {
|
||||
if (
|
||||
url &&
|
||||
(!url.startsWith('http://') || !url.startsWith('https://'))
|
||||
) {
|
||||
if (!this.isCustomizeReq) {
|
||||
this.request.path = url;
|
||||
this.request.url = undefined;
|
||||
|
@ -411,7 +548,11 @@ export default {
|
|||
mergeHashTree(targetHashTree) {
|
||||
let sourceHashTree = this.request.hashTree;
|
||||
// 历史数据兼容
|
||||
if (sourceHashTree && targetHashTree && sourceHashTree.length < targetHashTree.length) {
|
||||
if (
|
||||
sourceHashTree &&
|
||||
targetHashTree &&
|
||||
sourceHashTree.length < targetHashTree.length
|
||||
) {
|
||||
this.request.hashTree = targetHashTree;
|
||||
return;
|
||||
}
|
||||
|
@ -420,7 +561,7 @@ export default {
|
|||
let updateMap = new Map();
|
||||
if (!sourceHashTree || sourceHashTree.length == 0) {
|
||||
if (targetHashTree) {
|
||||
targetHashTree.forEach(item => {
|
||||
targetHashTree.forEach((item) => {
|
||||
item.disabled = true;
|
||||
});
|
||||
this.request.hashTree = targetHashTree;
|
||||
|
@ -452,7 +593,11 @@ export default {
|
|||
}
|
||||
}
|
||||
// 历史数据兼容
|
||||
if (!source.id && source.label !== 'SCENARIO-REF-STEP' && index < targetHashTree.length) {
|
||||
if (
|
||||
!source.id &&
|
||||
source.label !== 'SCENARIO-REF-STEP' &&
|
||||
index < targetHashTree.length
|
||||
) {
|
||||
Object.assign(sourceHashTree[index], targetHashTree[index]);
|
||||
sourceHashTree[index].disabled = true;
|
||||
sourceHashTree[index].label = '';
|
||||
|
@ -461,19 +606,21 @@ export default {
|
|||
}
|
||||
}
|
||||
// 删除多余的步骤
|
||||
delIds.forEach(item => {
|
||||
const removeIndex = sourceHashTree.findIndex(d => d.id && d.id === item);
|
||||
delIds.forEach((item) => {
|
||||
const removeIndex = sourceHashTree.findIndex(
|
||||
(d) => d.id && d.id === item
|
||||
);
|
||||
sourceHashTree.splice(removeIndex, 1);
|
||||
})
|
||||
});
|
||||
|
||||
// 补充新增的源引用步骤
|
||||
if (targetHashTree) {
|
||||
targetHashTree.forEach(item => {
|
||||
targetHashTree.forEach((item) => {
|
||||
if (sourceIds.indexOf(item.id) === -1) {
|
||||
item.disabled = true;
|
||||
this.request.hashTree.push(item);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
sort() {
|
||||
|
@ -495,18 +642,30 @@ export default {
|
|||
run() {
|
||||
this.currentScenarioData = undefined;
|
||||
this.getParentVariables(this.node);
|
||||
getOwnerProjectIds().then(res => {
|
||||
const project = res.data.find(p => p === this.request.projectId);
|
||||
getOwnerProjectIds().then((res) => {
|
||||
const project = res.data.find((p) => p === this.request.projectId);
|
||||
if (!project) {
|
||||
this.$warning(this.$t('automation.project_no_permission'));
|
||||
} else {
|
||||
let selectEnvId;
|
||||
// 自定义请求
|
||||
if (this.isApiImport || this.request.isRefEnvironment) {
|
||||
if (this.request.type && (this.request.type === "HTTPSamplerProxy" || this.request.type === "JDBCSampler" || this.request.type === "TCPSampler")) {
|
||||
if (store.scenarioEnvMap && store.scenarioEnvMap instanceof Map
|
||||
&& store.scenarioEnvMap.has((this.currentScenario.id + "_" + this.request.projectId))) {
|
||||
selectEnvId = store.scenarioEnvMap.get((this.currentScenario.id + "_" + this.request.projectId));
|
||||
if (
|
||||
this.request.type &&
|
||||
(this.request.type === 'HTTPSamplerProxy' ||
|
||||
this.request.type === 'JDBCSampler' ||
|
||||
this.request.type === 'TCPSampler')
|
||||
) {
|
||||
if (
|
||||
store.scenarioEnvMap &&
|
||||
store.scenarioEnvMap instanceof Map &&
|
||||
store.scenarioEnvMap.has(
|
||||
this.currentScenario.id + '_' + this.request.projectId
|
||||
)
|
||||
) {
|
||||
selectEnvId = store.scenarioEnvMap.get(
|
||||
this.currentScenario.id + '_' + this.request.projectId
|
||||
);
|
||||
this.environmentMap = this.envMap;
|
||||
}
|
||||
if (!selectEnvId) {
|
||||
|
@ -531,25 +690,37 @@ export default {
|
|||
// 场景变量
|
||||
let variables = [];
|
||||
if (this.currentScenario && this.currentScenario.variables) {
|
||||
variables = JSON.parse(JSON.stringify(this.currentScenario.variables));
|
||||
variables = JSON.parse(
|
||||
JSON.stringify(this.currentScenario.variables)
|
||||
);
|
||||
}
|
||||
let debugData = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario",
|
||||
variables: variables, referenced: 'Created', headers: this.currentScenario.headers,
|
||||
enableCookieShare: this.enableCookieShare, environmentId: selectEnvId, hashTree: [this.request],
|
||||
id: this.currentScenario.id,
|
||||
name: this.currentScenario.name,
|
||||
type: 'scenario',
|
||||
variables: variables,
|
||||
referenced: 'Created',
|
||||
headers: this.currentScenario.headers,
|
||||
enableCookieShare: this.enableCookieShare,
|
||||
environmentId: selectEnvId,
|
||||
hashTree: [this.request],
|
||||
};
|
||||
// 合并自身依赖场景变量
|
||||
if (this.currentScenarioData && this.currentScenarioData.variableEnable && this.currentScenarioData.variables) {
|
||||
if (
|
||||
this.currentScenarioData &&
|
||||
this.currentScenarioData.variableEnable &&
|
||||
this.currentScenarioData.variables
|
||||
) {
|
||||
if (!debugData.variables || debugData.variables.length === 0) {
|
||||
debugData.variables = this.currentScenarioData.variables;
|
||||
} else if (this.currentScenarioData.variables) {
|
||||
// 同名合并
|
||||
debugData.variables.forEach(data => {
|
||||
this.currentScenarioData.variables.forEach(item => {
|
||||
debugData.variables.forEach((data) => {
|
||||
this.currentScenarioData.variables.forEach((item) => {
|
||||
if (data.type === item.type && data.name === item.name) {
|
||||
Object.assign(data, item);
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -559,11 +730,11 @@ export default {
|
|||
/*触发执行操作*/
|
||||
this.reportId = getUUID();
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
getParentVariables(node) {
|
||||
if (!this.currentScenarioData) {
|
||||
if (node && node.data && node.data.type === "scenario") {
|
||||
if (node && node.data && node.data.type === 'scenario') {
|
||||
this.currentScenarioData = node.data;
|
||||
} else {
|
||||
if (node.parent && node.parent.data) {
|
||||
|
@ -589,46 +760,47 @@ export default {
|
|||
this.$emit('refReload', this.request, this.node);
|
||||
},
|
||||
setDomain() {
|
||||
this.$emit("setDomain");
|
||||
this.$emit('setDomain');
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
getProjectName(id) {
|
||||
if (this.projectId !== id) {
|
||||
const project = this.projectList.find(p => p.id === id);
|
||||
return project ? project.name : "";
|
||||
const project = this.projectList.find((p) => p.id === id);
|
||||
return project ? project.name : '';
|
||||
}
|
||||
},
|
||||
|
||||
clickResource(resource) {
|
||||
let workspaceId = getCurrentWorkspaceId();
|
||||
let isTurnSpace = true
|
||||
let isTurnSpace = true;
|
||||
if (resource.num) {
|
||||
if (resource.refType === 'API') {
|
||||
getDefinitionById(resource.id).then(res => {
|
||||
getDefinitionById(resource.id).then((res) => {
|
||||
if (res.data) {
|
||||
this.getWorkspaceId(resource, res.data, isTurnSpace, workspaceId);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
getApiCaseById(resource.id).then(res => {
|
||||
getApiCaseById(resource.id).then((res) => {
|
||||
if (res.data) {
|
||||
this.getWorkspaceId(resource, res.data, isTurnSpace, workspaceId);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
clickCase(resource) {
|
||||
let uri = getUrl(resource);
|
||||
let resourceId = resource.sourceId;
|
||||
if (resourceId && resourceId.startsWith("\"" || resourceId.startsWith("["))) {
|
||||
if (
|
||||
resourceId &&
|
||||
resourceId.startsWith('"' || resourceId.startsWith('['))
|
||||
) {
|
||||
resourceId = JSON.parse(resource.sourceId);
|
||||
}
|
||||
if (resourceId instanceof Array) {
|
||||
|
@ -639,11 +811,11 @@ export default {
|
|||
});
|
||||
},
|
||||
toPage(uri) {
|
||||
let id = "new_a";
|
||||
let a = document.createElement("a");
|
||||
a.setAttribute("href", uri);
|
||||
a.setAttribute("target", "_blank");
|
||||
a.setAttribute("id", id);
|
||||
let id = 'new_a';
|
||||
let a = document.createElement('a');
|
||||
a.setAttribute('href', uri);
|
||||
a.setAttribute('target', '_blank');
|
||||
a.setAttribute('id', id);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
|
@ -656,54 +828,53 @@ export default {
|
|||
gotoTurn(resource, workspaceId, isTurnSpace) {
|
||||
if (resource.refType && resource.refType === 'API') {
|
||||
if (resource.protocol === 'dubbo://') {
|
||||
resource.protocol = 'DUBBO'
|
||||
resource.protocol = 'DUBBO';
|
||||
}
|
||||
let definitionData = this.$router.resolve({
|
||||
name: 'ApiDefinitionWithQuery',
|
||||
params: {
|
||||
redirectID: getUUID(),
|
||||
dataType: "api",
|
||||
dataType: 'api',
|
||||
dataSelectRange: 'edit:' + resource.id,
|
||||
projectId: resource.projectId,
|
||||
type: resource.protocol,
|
||||
workspaceId: workspaceId,
|
||||
}
|
||||
},
|
||||
});
|
||||
if (isTurnSpace) {
|
||||
window.open(definitionData.href, '_blank');
|
||||
}
|
||||
} else if (resource.refType && resource.refType === 'CASE') {
|
||||
getCaseById(resource.id).then(response => {
|
||||
getCaseById(resource.id).then((response) => {
|
||||
if (response.data) {
|
||||
response.data.sourceId = resource.resourceId;
|
||||
response.data.type = resource.type;
|
||||
response.data.refType = resource.refType;
|
||||
response.data.workspaceId = workspaceId;
|
||||
if (isTurnSpace) {
|
||||
this.clickCase(response.data)
|
||||
this.clickCase(response.data);
|
||||
}
|
||||
} else {
|
||||
this.$error("接口用例已经被删除");
|
||||
this.$error('接口用例已经被删除');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
checkPermission(resource, workspaceId, isTurnSpace) {
|
||||
getOwnerProjectIds().then(res => {
|
||||
const project = res.data.find(p => p === resource.projectId);
|
||||
getOwnerProjectIds().then((res) => {
|
||||
const project = res.data.find((p) => p === resource.projectId);
|
||||
if (!project) {
|
||||
this.$warning(this.$t('commons.no_permission'));
|
||||
} else {
|
||||
this.gotoTurn(resource, workspaceId, isTurnSpace)
|
||||
this.gotoTurn(resource, workspaceId, isTurnSpace);
|
||||
}
|
||||
|
||||
})
|
||||
});
|
||||
},
|
||||
getWorkspaceId(resource, data, isTurnSpace, workspaceId) {
|
||||
resource.projectId = data.projectId;
|
||||
if (data.projectId !== getCurrentProjectID()) {
|
||||
isTurnSpace = false;
|
||||
getProject(data.projectId).then(response => {
|
||||
getProject(data.projectId).then((response) => {
|
||||
if (response.data) {
|
||||
workspaceId = response.data.workspaceId;
|
||||
isTurnSpace = true;
|
||||
|
@ -713,9 +884,9 @@ export default {
|
|||
} else {
|
||||
this.checkPermission(resource, workspaceId, isTurnSpace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -724,13 +895,12 @@ export default {
|
|||
}
|
||||
|
||||
.ms-tabs :deep(.el-icon-close:before) {
|
||||
content: "";
|
||||
|
||||
content: '';
|
||||
}
|
||||
|
||||
.ms-btn {
|
||||
padding: 5px;
|
||||
background-color: #409EFF;
|
||||
background-color: #409eff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
@ -759,11 +929,11 @@ export default {
|
|||
}
|
||||
|
||||
.ms-req-error {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.ms-req-error-report {
|
||||
color: #F6972A;
|
||||
color: #f6972a;
|
||||
}
|
||||
|
||||
.ms-test-running {
|
||||
|
@ -771,12 +941,12 @@ export default {
|
|||
}
|
||||
|
||||
.ms-req-success {
|
||||
color: #67C23A;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.stop-btn {
|
||||
background-color: #E62424;
|
||||
border-color: #EE6161;
|
||||
background-color: #e62424;
|
||||
border-color: #ee6161;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
@ -785,5 +955,4 @@ export default {
|
|||
font-size: 15px;
|
||||
color: #de9d1c;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,36 +1,49 @@
|
|||
<template>
|
||||
<el-card class="api-component">
|
||||
<div class="header" @click="active">
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': isActive}"/>
|
||||
<ms-request-metric :response="response"/>
|
||||
<i class="icon el-icon-arrow-right" :class="{ 'is-active': isActive }" />
|
||||
<ms-request-metric :response="response" />
|
||||
</div>
|
||||
|
||||
<el-collapse-transition>
|
||||
<div v-if="isActive">
|
||||
<el-divider></el-divider>
|
||||
<ms-request-result-tail :currentProtocol="currentProtocol" :show-metric="false" :response="response"/>
|
||||
<ms-request-result-tail
|
||||
:currentProtocol="currentProtocol"
|
||||
:show-metric="false"
|
||||
:response="response"
|
||||
/>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</el-card>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
|
||||
import ElCollapseTransition from "element-ui/src/transitions/collapse-transition";
|
||||
import MsRequestMetric from "../../../definition/components/response/RequestMetric";
|
||||
import {getApiReportDetail} from "@/api/definition-report";
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
import MsRequestResultTail from '../../../definition/components/response/RequestResultTail';
|
||||
import ElCollapseTransition from 'element-ui/src/transitions/collapse-transition';
|
||||
import MsRequestMetric from '../../../definition/components/response/RequestMetric';
|
||||
import { getApiReportDetail } from '@/api/definition-report';
|
||||
|
||||
export default {
|
||||
name: "ApiResponseComponent",
|
||||
components: {ElCollapseTransition, MsRequestResultTail, ApiBaseComponent, MsRequestMetric},
|
||||
props: {apiItem: {}, result: {}, currentProtocol: String, apiActive: {type: Boolean, default: false}},
|
||||
name: 'ApiResponseComponent',
|
||||
components: {
|
||||
ElCollapseTransition,
|
||||
MsRequestResultTail,
|
||||
ApiBaseComponent,
|
||||
MsRequestMetric,
|
||||
},
|
||||
props: {
|
||||
apiItem: {},
|
||||
result: {},
|
||||
currentProtocol: String,
|
||||
apiActive: { type: Boolean, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isActive: false,
|
||||
response: {responseResult: {}}
|
||||
}
|
||||
response: { responseResult: {} },
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (!this.result || !this.result.responseResult) {
|
||||
|
@ -39,7 +52,7 @@ export default {
|
|||
this.response = this.result;
|
||||
}
|
||||
if (this.apiActive) {
|
||||
this.isActive = false
|
||||
this.isActive = false;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -53,13 +66,13 @@ export default {
|
|||
},
|
||||
apiItem() {
|
||||
this.getExecResult();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getExecResult() {
|
||||
// 执行结果信息
|
||||
if (this.apiItem && this.apiItem.lastResultId) {
|
||||
getApiReportDetail(this.apiItem.lastResultId).then(response => {
|
||||
getApiReportDetail(this.apiItem.lastResultId).then((response) => {
|
||||
if (response.data && response.data.content) {
|
||||
try {
|
||||
let data = JSON.parse(response.data.content);
|
||||
|
@ -77,13 +90,12 @@ export default {
|
|||
},
|
||||
active() {
|
||||
this.isActive = !this.isActive;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.header {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
@ -107,5 +119,4 @@ export default {
|
|||
.metric-container {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
>
|
||||
<template v-slot:afterTitle>
|
||||
<span v-if="isShowNum" @click="clickResource(scenario)">{{
|
||||
"( ID: " + scenario.num + ")"
|
||||
'( ID: ' + scenario.num + ')'
|
||||
}}</span>
|
||||
<span v-else>
|
||||
<el-tooltip
|
||||
|
@ -36,7 +36,7 @@
|
|||
</el-tooltip>
|
||||
</span>
|
||||
<span v-xpack v-if="scenario.versionEnable"
|
||||
>{{ $t("project.version.name") }}: {{ scenario.versionName }}</span
|
||||
>{{ $t('project.version.name') }}: {{ scenario.versionName }}</span
|
||||
>
|
||||
</template>
|
||||
|
||||
|
@ -47,16 +47,16 @@
|
|||
v-if="scenario.referenced === 'Deleted'"
|
||||
type="danger"
|
||||
>
|
||||
{{ $t("api_test.automation.reference_deleted") }}
|
||||
{{ $t('api_test.automation.reference_deleted') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
size="small"
|
||||
class="ms-tag"
|
||||
v-if="scenario.referenced === 'Copy'"
|
||||
>{{ $t("commons.copy") }}</el-tag
|
||||
>{{ $t('commons.copy') }}</el-tag
|
||||
>
|
||||
<el-tag size="small" class="ms-tag" v-if="scenario.referenced === 'REF'"
|
||||
>{{ $t("api_test.scenario.reference") }}
|
||||
>{{ $t('api_test.scenario.reference') }}
|
||||
</el-tag>
|
||||
<span class="ms-tag ms-step-name-api">{{
|
||||
getProjectName(scenario.projectId)
|
||||
|
@ -78,7 +78,7 @@
|
|||
<template v-slot:debugStepCode>
|
||||
<span v-if="node.data.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px" />
|
||||
{{ $t("commons.testing") }}
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span
|
||||
class="ms-step-debug-code"
|
||||
|
@ -128,26 +128,26 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters";
|
||||
import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters";
|
||||
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
|
||||
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import MsSqlBasisParameters from '../../../definition/components/request/database/BasisParameters';
|
||||
import MsTcpBasisParameters from '../../../definition/components/request/tcp/TcpBasisParameters';
|
||||
import MsDubboBasisParameters from '../../../definition/components/request/dubbo/BasisParameters';
|
||||
import MsApiRequestForm from '../../../definition/components/request/http/ApiHttpRequestForm';
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentWorkspaceId,
|
||||
} from "metersphere-frontend/src/utils/token";
|
||||
import { getUUID, strMapToObj } from "metersphere-frontend/src/utils";
|
||||
import { STEP } from "@/business/automation/scenario/Setting";
|
||||
import { getOwnerProjectIds, getProject } from "@/api/project";
|
||||
} from 'metersphere-frontend/src/utils/token';
|
||||
import { getUUID, strMapToObj } from 'metersphere-frontend/src/utils';
|
||||
import { STEP } from '@/business/automation/scenario/Setting';
|
||||
import { getOwnerProjectIds, getProject } from '@/api/project';
|
||||
import {
|
||||
checkScenarioEnv,
|
||||
getScenarioById,
|
||||
setScenarioDomain,
|
||||
} from "@/api/scenario";
|
||||
} from '@/api/scenario';
|
||||
|
||||
export default {
|
||||
name: "ApiScenarioComponent",
|
||||
name: 'ApiScenarioComponent',
|
||||
props: {
|
||||
scenario: {},
|
||||
currentScenario: {},
|
||||
|
@ -180,16 +180,16 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
message() {
|
||||
if (this.message === "STOPPED") {
|
||||
if (this.message === 'STOPPED') {
|
||||
this.scenario.run = false;
|
||||
}
|
||||
this.reload();
|
||||
},
|
||||
"node.data.isBatchProcess"() {
|
||||
'node.data.isBatchProcess'() {
|
||||
if (
|
||||
this.node.data &&
|
||||
this.node.data.isBatchProcess &&
|
||||
this.node.data.referenced === "REF"
|
||||
this.node.data.referenced === 'REF'
|
||||
) {
|
||||
this.node.expanded = false;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ export default {
|
|||
this.isShowNum = this.scenario.num ? true : false;
|
||||
if (
|
||||
this.scenario.id &&
|
||||
this.scenario.referenced === "REF" &&
|
||||
this.scenario.referenced === 'REF' &&
|
||||
!this.scenario.loaded &&
|
||||
this.scenario.hashTree
|
||||
) {
|
||||
|
@ -226,15 +226,15 @@ export default {
|
|||
computed: {
|
||||
isDeletedOrRef() {
|
||||
return (
|
||||
(this.scenario.referenced && this.scenario.referenced === "Deleted") ||
|
||||
this.scenario.referenced === "REF"
|
||||
(this.scenario.referenced && this.scenario.referenced === 'Deleted') ||
|
||||
this.scenario.referenced === 'REF'
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
run() {
|
||||
if (!this.scenario.enable) {
|
||||
this.$warning(this.$t("api_test.automation.debug_message"));
|
||||
this.$warning(this.$t('api_test.automation.debug_message'));
|
||||
return;
|
||||
}
|
||||
this.scenario.run = true;
|
||||
|
@ -261,18 +261,18 @@ export default {
|
|||
|
||||
runScenario.hashTree = [this.scenario];
|
||||
runScenario.stepScenario = true;
|
||||
this.$emit("runScenario", runScenario);
|
||||
this.$emit('runScenario', runScenario);
|
||||
},
|
||||
stop() {
|
||||
this.scenario.run = false;
|
||||
this.$emit("stopScenario");
|
||||
this.$emit('stopScenario');
|
||||
this.reload();
|
||||
},
|
||||
checkEnv(val) {
|
||||
checkScenarioEnv(this.scenario.id).then((res) => {
|
||||
if (this.scenario.environmentEnable && !res.data) {
|
||||
this.scenario.environmentEnable = false;
|
||||
this.$warning(this.$t("commons.scenario_warning"));
|
||||
this.$warning(this.$t('commons.scenario_warning'));
|
||||
return;
|
||||
}
|
||||
this.setDomain(val);
|
||||
|
@ -301,17 +301,17 @@ export default {
|
|||
status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1)
|
||||
);
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
},
|
||||
remove() {
|
||||
this.$emit("remove", this.scenario, this.node);
|
||||
this.$emit('remove', this.scenario, this.node);
|
||||
},
|
||||
active() {
|
||||
if (this.node) {
|
||||
if (
|
||||
this.node.data &&
|
||||
this.node.data.isBatchProcess &&
|
||||
this.node.data.referenced === "REF"
|
||||
this.node.data.referenced === 'REF'
|
||||
) {
|
||||
this.node.expanded = false;
|
||||
} else {
|
||||
|
@ -320,20 +320,20 @@ export default {
|
|||
}
|
||||
if (this.scenario && this.scenario.hashTree && this.node.expanded) {
|
||||
this.scenario.disabled =
|
||||
this.scenario.id && this.scenario.referenced === "REF";
|
||||
this.scenario.id && this.scenario.referenced === 'REF';
|
||||
this.recursive(
|
||||
this.scenario.hashTree,
|
||||
this.scenario.projectId,
|
||||
this.scenario.id && this.scenario.referenced === "REF"
|
||||
this.scenario.id && this.scenario.referenced === 'REF'
|
||||
);
|
||||
}
|
||||
this.reload();
|
||||
},
|
||||
copyRow() {
|
||||
this.$emit("copyRow", this.scenario, this.node);
|
||||
this.$emit('copyRow', this.scenario, this.node);
|
||||
},
|
||||
openScenario(data) {
|
||||
this.$emit("openScenario", data);
|
||||
this.$emit('openScenario', data);
|
||||
},
|
||||
reload() {
|
||||
this.loading = true;
|
||||
|
@ -347,9 +347,9 @@ export default {
|
|||
arr[i].projectId = this.calcProjectId(arr[i].projectId, id);
|
||||
// 处理子请求环境
|
||||
let typeArray = [
|
||||
"JDBCPostProcessor",
|
||||
"JDBCSampler",
|
||||
"JDBCPreProcessor",
|
||||
'JDBCPostProcessor',
|
||||
'JDBCSampler',
|
||||
'JDBCPreProcessor',
|
||||
];
|
||||
if (typeArray.indexOf(arr[i].type) !== -1) {
|
||||
arr[i].refEevMap = new Map();
|
||||
|
@ -377,7 +377,7 @@ export default {
|
|||
getProjectName(id) {
|
||||
if (id !== getCurrentProjectID()) {
|
||||
const project = this.projectList.find((p) => p.id === id);
|
||||
return project ? project.name + " > " : "";
|
||||
return project ? project.name + ' > ' : '';
|
||||
}
|
||||
},
|
||||
clickResource(resource) {
|
||||
|
@ -403,24 +403,24 @@ export default {
|
|||
},
|
||||
gotoTurn(resource, workspaceId, isTurnSpace) {
|
||||
let automationData = this.$router.resolve({
|
||||
name: "ApiAutomationWithQuery",
|
||||
name: 'ApiAutomationWithQuery',
|
||||
params: {
|
||||
redirectID: getUUID(),
|
||||
dataType: "scenario",
|
||||
dataSelectRange: "edit:" + resource.id,
|
||||
dataType: 'scenario',
|
||||
dataSelectRange: 'edit:' + resource.id,
|
||||
projectId: resource.projectId,
|
||||
workspaceId: workspaceId,
|
||||
},
|
||||
});
|
||||
if (isTurnSpace) {
|
||||
window.open(automationData.href, "_blank");
|
||||
window.open(automationData.href, '_blank');
|
||||
}
|
||||
},
|
||||
checkPermission(resource, workspaceId, isTurnSpace) {
|
||||
getOwnerProjectIds().then((res) => {
|
||||
const project = res.data.find((p) => p === resource.projectId);
|
||||
if (!project) {
|
||||
this.$warning(this.$t("commons.no_permission"));
|
||||
this.$warning(this.$t('commons.no_permission'));
|
||||
} else {
|
||||
this.gotoTurn(resource, workspaceId, isTurnSpace);
|
||||
}
|
||||
|
|
|
@ -43,17 +43,17 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsIfController from "./IfController";
|
||||
import MsTransactionController from "./TransactionController";
|
||||
import {ELEMENT_TYPE} from "../Setting";
|
||||
import MsApiComponent from "./ApiComponent";
|
||||
import MsLoopController from "./LoopController";
|
||||
import MsApiScenarioComponent from "./ApiScenarioComponent";
|
||||
import JmeterElementComponent from "./JmeterElementComponent";
|
||||
import PluginComponent from "./PluginComponent";
|
||||
import MsIfController from './IfController';
|
||||
import MsTransactionController from './TransactionController';
|
||||
import { ELEMENT_TYPE } from '../Setting';
|
||||
import MsApiComponent from './ApiComponent';
|
||||
import MsLoopController from './LoopController';
|
||||
import MsApiScenarioComponent from './ApiScenarioComponent';
|
||||
import JmeterElementComponent from './JmeterElementComponent';
|
||||
import PluginComponent from './PluginComponent';
|
||||
|
||||
export default {
|
||||
name: "ComponentConfig",
|
||||
name: 'ComponentConfig',
|
||||
components: {
|
||||
PluginComponent,
|
||||
MsIfController,
|
||||
|
@ -62,11 +62,14 @@ export default {
|
|||
MsLoopController,
|
||||
MsApiScenarioComponent,
|
||||
JmeterElementComponent,
|
||||
MsConstantTimer: () => import("./ConstantTimer"),
|
||||
MsJsr233Processor: () => import("./Jsr233Processor"),
|
||||
MsScenarioAssertions: () => import("../../../definition/components/assertion/ScenarioAssertions"),
|
||||
MsApiExtract: () => import("../../../definition/components/extract/ApiExtract"),
|
||||
MsJdbcProcessor: () => import("@/business/automation/scenario/component/JDBCProcessor")
|
||||
MsConstantTimer: () => import('./ConstantTimer'),
|
||||
MsJsr233Processor: () => import('./Jsr233Processor'),
|
||||
MsScenarioAssertions: () =>
|
||||
import('../../../definition/components/assertion/ScenarioAssertions'),
|
||||
MsApiExtract: () =>
|
||||
import('../../../definition/components/extract/ApiExtract'),
|
||||
MsJdbcProcessor: () =>
|
||||
import('@/business/automation/scenario/component/JDBCProcessor'),
|
||||
},
|
||||
props: {
|
||||
type: String,
|
||||
|
@ -105,24 +108,24 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
title: "",
|
||||
titleColor: "",
|
||||
backgroundColor: "",
|
||||
apiId: "",
|
||||
}
|
||||
title: '',
|
||||
titleColor: '',
|
||||
backgroundColor: '',
|
||||
apiId: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
component({type}) {
|
||||
component({ type }) {
|
||||
let name;
|
||||
switch (type) {
|
||||
case ELEMENT_TYPE.IfController:
|
||||
name = "MsIfController";
|
||||
name = 'MsIfController';
|
||||
break;
|
||||
case ELEMENT_TYPE.TransactionController:
|
||||
name = "MsTransactionController";
|
||||
name = 'MsTransactionController';
|
||||
break;
|
||||
case ELEMENT_TYPE.ConstantTimer:
|
||||
name = "MsConstantTimer";
|
||||
name = 'MsConstantTimer';
|
||||
break;
|
||||
case ELEMENT_TYPE.JSR223Processor:
|
||||
name = this.getComponent(ELEMENT_TYPE.JSR223Processor);
|
||||
|
@ -143,81 +146,86 @@ export default {
|
|||
name = this.getComponent(ELEMENT_TYPE.Assertions);
|
||||
break;
|
||||
case ELEMENT_TYPE.Extract:
|
||||
name = "MsApiExtract";
|
||||
name = 'MsApiExtract';
|
||||
break;
|
||||
case ELEMENT_TYPE.CustomizeReq:
|
||||
name = "MsApiComponent";
|
||||
name = 'MsApiComponent';
|
||||
break;
|
||||
case ELEMENT_TYPE.LoopController:
|
||||
name = "MsLoopController";
|
||||
case ELEMENT_TYPE.LoopController:
|
||||
name = 'MsLoopController';
|
||||
break;
|
||||
case ELEMENT_TYPE.scenario:
|
||||
name = "MsApiScenarioComponent";
|
||||
name = 'MsApiScenarioComponent';
|
||||
break;
|
||||
case "AuthManager":
|
||||
case 'AuthManager':
|
||||
break;
|
||||
case "JmeterElement":
|
||||
name = "JmeterElementComponent";
|
||||
case 'JmeterElement':
|
||||
name = 'JmeterElementComponent';
|
||||
break;
|
||||
case "DubboSampler":
|
||||
name = "MsApiComponent";
|
||||
case 'DubboSampler':
|
||||
name = 'MsApiComponent';
|
||||
break;
|
||||
case "HTTPSamplerProxy":
|
||||
name = "MsApiComponent";
|
||||
case 'HTTPSamplerProxy':
|
||||
name = 'MsApiComponent';
|
||||
break;
|
||||
case "JDBCSampler":
|
||||
name = "MsApiComponent";
|
||||
case 'JDBCSampler':
|
||||
name = 'MsApiComponent';
|
||||
break;
|
||||
case "TCPSampler":
|
||||
name = "MsApiComponent";
|
||||
case 'TCPSampler':
|
||||
name = 'MsApiComponent';
|
||||
break;
|
||||
default:
|
||||
name = this.getComponent(ELEMENT_TYPE.Plugin);
|
||||
break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getComponent(type) {
|
||||
if (type === ELEMENT_TYPE.JSR223PreProcessor) {
|
||||
this.title = this.$t('api_test.definition.request.pre_script');
|
||||
this.titleColor = "#b8741a";
|
||||
this.backgroundColor = "#F9F1EA";
|
||||
return "MsJsr233Processor";
|
||||
this.titleColor = '#b8741a';
|
||||
this.backgroundColor = '#F9F1EA';
|
||||
return 'MsJsr233Processor';
|
||||
} else if (type === ELEMENT_TYPE.JSR223PostProcessor) {
|
||||
this.title = this.$t('api_test.definition.request.post_script');
|
||||
this.titleColor = "#783887";
|
||||
this.backgroundColor = "#F2ECF3";
|
||||
return "MsJsr233Processor";
|
||||
this.titleColor = '#783887';
|
||||
this.backgroundColor = '#F2ECF3';
|
||||
return 'MsJsr233Processor';
|
||||
}
|
||||
if (type === ELEMENT_TYPE.JDBCPreProcessor) {
|
||||
this.title = this.$t('api_test.definition.request.pre_sql');
|
||||
this.titleColor = "#FE6F71";
|
||||
this.backgroundColor = "#F2ECF3";
|
||||
return "MsJdbcProcessor";
|
||||
this.titleColor = '#FE6F71';
|
||||
this.backgroundColor = '#F2ECF3';
|
||||
return 'MsJdbcProcessor';
|
||||
} else if (type === ELEMENT_TYPE.JDBCPostProcessor) {
|
||||
this.title = this.$t('api_test.definition.request.post_sql');
|
||||
this.titleColor = "#1483F6";
|
||||
this.backgroundColor = "#F2ECF3";
|
||||
return "MsJdbcProcessor";
|
||||
this.titleColor = '#1483F6';
|
||||
this.backgroundColor = '#F2ECF3';
|
||||
return 'MsJdbcProcessor';
|
||||
} else if (type === ELEMENT_TYPE.Plugin) {
|
||||
this.titleColor = "#1483F6";
|
||||
this.backgroundColor = "#F2ECF3";
|
||||
return "PluginComponent";
|
||||
this.titleColor = '#1483F6';
|
||||
this.backgroundColor = '#F2ECF3';
|
||||
return 'PluginComponent';
|
||||
} else if (type === ELEMENT_TYPE.Assertions) {
|
||||
if (this.node && this.node.parent && this.node.parent.data && this.node.parent.data.referenced === "REF") {
|
||||
if (
|
||||
this.node &&
|
||||
this.node.parent &&
|
||||
this.node.parent.data &&
|
||||
this.node.parent.data.referenced === 'REF'
|
||||
) {
|
||||
this.apiId = this.node.parent.data.id;
|
||||
this.scenario.document.nodeType = "scenario";
|
||||
this.scenario.document.nodeType = 'scenario';
|
||||
} else {
|
||||
this.apiId = "none";
|
||||
this.apiId = 'none';
|
||||
}
|
||||
return "MsScenarioAssertions";
|
||||
return 'MsScenarioAssertions';
|
||||
} else {
|
||||
this.title = this.$t('api_test.automation.customize_script');
|
||||
this.titleColor = "#7B4D12";
|
||||
this.backgroundColor = "#F1EEE9";
|
||||
return "MsJsr233Processor";
|
||||
this.titleColor = '#7B4D12';
|
||||
this.backgroundColor = '#F1EEE9';
|
||||
return 'MsJsr233Processor';
|
||||
}
|
||||
},
|
||||
remove(row, node) {
|
||||
|
@ -225,7 +233,6 @@ export default {
|
|||
},
|
||||
copyRow(row, node) {
|
||||
this.$emit('copyRow', row, node);
|
||||
|
||||
},
|
||||
openScenario(data) {
|
||||
this.$emit('openScenario', data);
|
||||
|
@ -243,16 +250,16 @@ export default {
|
|||
this.$emit('stopScenario');
|
||||
},
|
||||
setDomain() {
|
||||
this.$emit("setDomain");
|
||||
this.$emit('setDomain');
|
||||
},
|
||||
savePreParams(data) {
|
||||
this.$emit("savePreParams", data);
|
||||
this.$emit('savePreParams', data);
|
||||
},
|
||||
editScenarioAdvance(data) {
|
||||
this.$emit('editScenarioAdvance', data);
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -261,5 +268,4 @@ export default {
|
|||
display: block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -9,23 +9,29 @@
|
|||
:inner-step="innerStep"
|
||||
color="#67C23A"
|
||||
background-color="#F2F9EE"
|
||||
:title="$t('api_test.automation.wait_controller')">
|
||||
|
||||
:title="$t('api_test.automation.wait_controller')"
|
||||
>
|
||||
<template v-slot:headerLeft>
|
||||
<el-input-number class="time-input" size="mini" v-model="timer.delay" :min="0" :step="1000" ref="nameInput"
|
||||
:disabled="timer.disabled"/>
|
||||
<el-input-number
|
||||
class="time-input"
|
||||
size="mini"
|
||||
v-model="timer.delay"
|
||||
:min="0"
|
||||
:step="1000"
|
||||
ref="nameInput"
|
||||
:disabled="timer.disabled"
|
||||
/>
|
||||
ms
|
||||
</template>
|
||||
|
||||
</api-base-component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
|
||||
export default {
|
||||
name: "MsConstantTimer",
|
||||
components: {ApiBaseComponent},
|
||||
name: 'MsConstantTimer',
|
||||
components: { ApiBaseComponent },
|
||||
props: {
|
||||
timer: {},
|
||||
innerStep: {
|
||||
|
@ -47,7 +53,7 @@ export default {
|
|||
},
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {};
|
||||
},
|
||||
created() {
|
||||
this.$nextTick(() => {
|
||||
|
@ -61,8 +67,8 @@ export default {
|
|||
copyRow() {
|
||||
this.$emit('copyRow', this.timer, this.node);
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -11,29 +11,63 @@
|
|||
color="#E6A23C"
|
||||
background-color="#FCF6EE"
|
||||
:if-from-variable-advance="ifFromVariableAdvance"
|
||||
:title="$t('api_test.automation.if_controller')">
|
||||
|
||||
:title="$t('api_test.automation.if_controller')"
|
||||
>
|
||||
<template v-slot:headerLeft>
|
||||
<el-input
|
||||
draggable
|
||||
size="mini"
|
||||
v-model="controller.variable"
|
||||
style="width: 12%"
|
||||
:placeholder="$t('api_test.request.condition_variable')"
|
||||
/>
|
||||
|
||||
<el-input draggable size="mini" v-model="controller.variable" style="width: 12%" :placeholder="$t('api_test.request.condition_variable')"/>
|
||||
|
||||
<el-select v-model="controller.operator" :placeholder="$t('commons.please_select')" size="mini"
|
||||
@change="change" class="ms-select">
|
||||
<el-option v-for="o in operators" :key="o.value" :label="$t(o.label)" :value="o.value"/>
|
||||
<el-select
|
||||
v-model="controller.operator"
|
||||
:placeholder="$t('commons.please_select')"
|
||||
size="mini"
|
||||
@change="change"
|
||||
class="ms-select"
|
||||
>
|
||||
<el-option
|
||||
v-for="o in operators"
|
||||
:key="o.value"
|
||||
:label="$t(o.label)"
|
||||
:value="o.value"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-input draggable size="mini" v-model="controller.value" :placeholder="$t('api_test.value')" v-if="!hasEmptyOperator" class="ms-btn"/>
|
||||
|
||||
<el-input draggable size="mini" v-model="controller.remark" :placeholder="$t('commons.remark')" v-if="!hasEmptyOperator && !isMax" class="ms-btn"/>
|
||||
<el-input
|
||||
draggable
|
||||
size="mini"
|
||||
v-model="controller.value"
|
||||
:placeholder="$t('api_test.value')"
|
||||
v-if="!hasEmptyOperator"
|
||||
class="ms-btn"
|
||||
/>
|
||||
|
||||
<el-input
|
||||
draggable
|
||||
size="mini"
|
||||
v-model="controller.remark"
|
||||
:placeholder="$t('commons.remark')"
|
||||
v-if="!hasEmptyOperator && !isMax"
|
||||
class="ms-btn"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-slot:debugStepCode>
|
||||
<span v-if="node.data.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px"/>
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span class="ms-step-debug-code" :class="node.data.code ==='ERROR'?'ms-req-error':'ms-req-success'" v-if="!loading && !node.data.testing && node.data.debug && node.data.code">
|
||||
<i class="el-icon-loading" style="font-size: 16px" />
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span
|
||||
class="ms-step-debug-code"
|
||||
:class="node.data.code === 'ERROR' ? 'ms-req-error' : 'ms-req-success'"
|
||||
v-if="
|
||||
!loading && !node.data.testing && node.data.debug && node.data.code
|
||||
"
|
||||
>
|
||||
{{ getCode() }}
|
||||
</span>
|
||||
</template>
|
||||
|
@ -41,144 +75,149 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
|
||||
export default {
|
||||
name: "MsIfController",
|
||||
components: {ApiBaseComponent},
|
||||
props: {
|
||||
controller: {},
|
||||
node: {},
|
||||
message: String,
|
||||
isMax: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showVersion: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
index: Object,
|
||||
draggable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
ifFromVariableAdvance: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
export default {
|
||||
name: 'MsIfController',
|
||||
components: { ApiBaseComponent },
|
||||
props: {
|
||||
controller: {},
|
||||
node: {},
|
||||
message: String,
|
||||
isMax: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
operators: {
|
||||
EQ: {
|
||||
label: "commons.adv_search.operators.equals",
|
||||
value: "=="
|
||||
},
|
||||
NE: {
|
||||
label: "commons.adv_search.operators.not_equals",
|
||||
value: "!="
|
||||
},
|
||||
LIKE: {
|
||||
label: "commons.adv_search.operators.like",
|
||||
value: "=~"
|
||||
},
|
||||
NOT_LIKE: {
|
||||
label: "commons.adv_search.operators.not_like",
|
||||
value: "!~"
|
||||
},
|
||||
GT: {
|
||||
label: "commons.adv_search.operators.gt",
|
||||
value: ">"
|
||||
},
|
||||
LT: {
|
||||
label: "commons.adv_search.operators.lt",
|
||||
value: "<"
|
||||
},
|
||||
IS_EMPTY: {
|
||||
label: "commons.adv_search.operators.is_empty",
|
||||
value: "is empty"
|
||||
},
|
||||
IS_NOT_EMPTY: {
|
||||
label: "commons.adv_search.operators.is_not_empty",
|
||||
value: "is not empty"
|
||||
}
|
||||
}
|
||||
showBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showVersion: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
index: Object,
|
||||
draggable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
ifFromVariableAdvance: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
operators: {
|
||||
EQ: {
|
||||
label: 'commons.adv_search.operators.equals',
|
||||
value: '==',
|
||||
},
|
||||
NE: {
|
||||
label: 'commons.adv_search.operators.not_equals',
|
||||
value: '!=',
|
||||
},
|
||||
LIKE: {
|
||||
label: 'commons.adv_search.operators.like',
|
||||
value: '=~',
|
||||
},
|
||||
NOT_LIKE: {
|
||||
label: 'commons.adv_search.operators.not_like',
|
||||
value: '!~',
|
||||
},
|
||||
GT: {
|
||||
label: 'commons.adv_search.operators.gt',
|
||||
value: '>',
|
||||
},
|
||||
LT: {
|
||||
label: 'commons.adv_search.operators.lt',
|
||||
value: '<',
|
||||
},
|
||||
IS_EMPTY: {
|
||||
label: 'commons.adv_search.operators.is_empty',
|
||||
value: 'is empty',
|
||||
},
|
||||
IS_NOT_EMPTY: {
|
||||
label: 'commons.adv_search.operators.is_not_empty',
|
||||
value: 'is not empty',
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
message() {
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
getCode() {
|
||||
if (this.node && this.node.data.code && this.node.data.debug) {
|
||||
let status = this.node.data.code;
|
||||
return (
|
||||
status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1)
|
||||
);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
remove() {
|
||||
this.$emit('remove', this.controller, this.node);
|
||||
},
|
||||
copyRow() {
|
||||
this.$emit('copyRow', this.controller, this.node);
|
||||
},
|
||||
change(value) {
|
||||
if (value.indexOf('empty') > 0 && !!this.controller.value) {
|
||||
this.controller.value = '';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
message() {
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasEmptyOperator() {
|
||||
return (
|
||||
!!this.controller.operator &&
|
||||
this.controller.operator.indexOf('empty') > 0
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
getCode() {
|
||||
if (this.node && this.node.data.code && this.node.data.debug) {
|
||||
let status = this.node.data.code;
|
||||
return status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
remove() {
|
||||
this.$emit('remove', this.controller, this.node);
|
||||
},
|
||||
copyRow() {
|
||||
this.$emit('copyRow', this.controller, this.node);
|
||||
},
|
||||
change(value) {
|
||||
if (value.indexOf("empty") > 0 && !!this.controller.value) {
|
||||
this.controller.value = "";
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasEmptyOperator() {
|
||||
return !!this.controller.operator && this.controller.operator.indexOf("empty") > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ms-btn {
|
||||
width: 15%;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.ms-btn {
|
||||
width: 15%;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.ms-select {
|
||||
width: 15%;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.ms-select {
|
||||
width: 15%;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.ms-req-error {
|
||||
color: #F56C6C;
|
||||
}
|
||||
.ms-req-error {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.ms-req-success {
|
||||
color: #67C23A;
|
||||
}
|
||||
.ms-step-debug-code {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 0;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
width: 80px;
|
||||
}
|
||||
.ms-test-running {
|
||||
color: #783887;
|
||||
}
|
||||
.ms-req-success {
|
||||
color: #67c23a;
|
||||
}
|
||||
.ms-step-debug-code {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 0;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
width: 80px;
|
||||
}
|
||||
.ms-test-running {
|
||||
color: #783887;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,29 +10,34 @@
|
|||
:show-btn="showBtn"
|
||||
:show-version="showVersion"
|
||||
:background-color="backgroundColor"
|
||||
:title="title" v-loading="loading">
|
||||
|
||||
:title="title"
|
||||
v-loading="loading"
|
||||
>
|
||||
<template v-slot:request>
|
||||
<jdbc-processor-content
|
||||
:showScript="false"
|
||||
:scenarioId="scenarioId"
|
||||
:request="request"/>
|
||||
:request="request"
|
||||
/>
|
||||
</template>
|
||||
</api-base-component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||
import MsDropdown from "@/business/commons/MsDropdown";
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import JdbcProcessorContent from "@/business/automation/scenario/common/JDBCProcessorContent";
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
import MsInstructionsIcon from 'metersphere-frontend/src/components/MsInstructionsIcon';
|
||||
import MsDropdown from '@/business/commons/MsDropdown';
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
import JdbcProcessorContent from '@/business/automation/scenario/common/JDBCProcessorContent';
|
||||
|
||||
export default {
|
||||
name: "MsJdbcProcessor",
|
||||
name: 'MsJdbcProcessor',
|
||||
components: {
|
||||
JdbcProcessorContent,
|
||||
ApiBaseComponent, MsDropdown, MsInstructionsIcon, MsCodeEdit
|
||||
ApiBaseComponent,
|
||||
MsDropdown,
|
||||
MsInstructionsIcon,
|
||||
MsCodeEdit,
|
||||
},
|
||||
props: {
|
||||
scenarioId: String,
|
||||
|
@ -54,8 +59,7 @@ export default {
|
|||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default:
|
||||
false
|
||||
default: false,
|
||||
},
|
||||
request: Object,
|
||||
title: String,
|
||||
|
@ -63,10 +67,9 @@ export default {
|
|||
backgroundColor: String,
|
||||
node: {},
|
||||
},
|
||||
created() {
|
||||
},
|
||||
created() {},
|
||||
data() {
|
||||
return {loading: false};
|
||||
return { loading: false };
|
||||
},
|
||||
methods: {
|
||||
remove() {
|
||||
|
@ -85,7 +88,7 @@ export default {
|
|||
this.request.active = !this.request.active;
|
||||
this.reload();
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -98,5 +101,4 @@ export default {
|
|||
margin-left: 20px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -10,127 +10,143 @@
|
|||
:show-btn="showBtn"
|
||||
:show-version="showVersion"
|
||||
:background-color="defBackgroundColor"
|
||||
:title="request.elementType">
|
||||
<div style="height: 300px;width: 100%">
|
||||
<ms-code-edit mode="xml" :data.sync="request.jmeterElement" theme="eclipse" ref="codeEdit"/>
|
||||
:title="request.elementType"
|
||||
>
|
||||
<div style="height: 300px; width: 100%">
|
||||
<ms-code-edit
|
||||
mode="xml"
|
||||
:data.sync="request.jmeterElement"
|
||||
theme="eclipse"
|
||||
ref="codeEdit"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template v-slot:debugStepCode>
|
||||
<span v-if="node.data.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px"/>
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span class="ms-step-debug-code" :class="node.data.code ==='ERROR'?'ms-req-error':'ms-req-success'" v-if="!loading && !node.data.testing && node.data.debug">
|
||||
<i class="el-icon-loading" style="font-size: 16px" />
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span
|
||||
class="ms-step-debug-code"
|
||||
:class="node.data.code === 'ERROR' ? 'ms-req-error' : 'ms-req-success'"
|
||||
v-if="!loading && !node.data.testing && node.data.debug"
|
||||
>
|
||||
{{ getCode() }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</api-base-component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||
import MsDropdown from "@/business/commons/MsDropdown";
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import Jsr233ProcessorContent from "../common/Jsr233ProcessorContent";
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
import MsInstructionsIcon from 'metersphere-frontend/src/components/MsInstructionsIcon';
|
||||
import MsDropdown from '@/business/commons/MsDropdown';
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
import Jsr233ProcessorContent from '../common/Jsr233ProcessorContent';
|
||||
|
||||
export default {
|
||||
name: "JmeterElementComponent",
|
||||
components: {Jsr233ProcessorContent, ApiBaseComponent, MsDropdown, MsInstructionsIcon, MsCodeEdit},
|
||||
props: {
|
||||
draggable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
message: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default:
|
||||
false
|
||||
},
|
||||
isMax: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showVersion: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
request: {
|
||||
type: Object,
|
||||
},
|
||||
defTitle: {type: String, default: "Jmeter组件"},
|
||||
defColor: {type: String, default: "#606260"},
|
||||
defBackgroundColor: {type: String, default: "#F4F4FF"},
|
||||
node: {},
|
||||
export default {
|
||||
name: 'JmeterElementComponent',
|
||||
components: {
|
||||
Jsr233ProcessorContent,
|
||||
ApiBaseComponent,
|
||||
MsDropdown,
|
||||
MsInstructionsIcon,
|
||||
MsCodeEdit,
|
||||
},
|
||||
props: {
|
||||
draggable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
message: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isMax: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showVersion: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
request: {
|
||||
type: Object,
|
||||
},
|
||||
defTitle: { type: String, default: 'Jmeter组件' },
|
||||
defColor: { type: String, default: '#606260' },
|
||||
defBackgroundColor: { type: String, default: '#F4F4FF' },
|
||||
node: {},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
message() {
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
getCode() {
|
||||
if (this.node && this.node.data.code && this.node.data.debug) {
|
||||
let status = this.node.data.code;
|
||||
return (
|
||||
status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1)
|
||||
);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
remove() {
|
||||
this.$emit('remove', this.request, this.node);
|
||||
},
|
||||
copyRow() {
|
||||
this.$emit('copyRow', this.request, this.node);
|
||||
},
|
||||
active() {
|
||||
this.request.active = !this.request.active;
|
||||
if (this.node) {
|
||||
this.node.expanded = this.request.active;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
message() {
|
||||
this.reload();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
getCode() {
|
||||
if (this.node && this.node.data.code && this.node.data.debug) {
|
||||
let status = this.node.data.code;
|
||||
return status.toLowerCase()[0].toUpperCase() + status.toLowerCase().substr(1);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
remove() {
|
||||
this.$emit('remove', this.request, this.node);
|
||||
},
|
||||
copyRow() {
|
||||
this.$emit('copyRow', this.request, this.node);
|
||||
},
|
||||
active() {
|
||||
this.request.active = !this.request.active;
|
||||
if (this.node) {
|
||||
this.node.expanded = this.request.active;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.el-divider) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ms-req-error {
|
||||
color: #F56C6C;
|
||||
}
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ms-req-error {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.ms-req-success {
|
||||
color: #67C23A;
|
||||
}
|
||||
.ms-step-debug-code {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 0;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
width: 80px;
|
||||
}
|
||||
.ms-test-running {
|
||||
color: #783887;
|
||||
}
|
||||
.ms-req-success {
|
||||
color: #67c23a;
|
||||
}
|
||||
.ms-step-debug-code {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 0;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
width: 80px;
|
||||
}
|
||||
.ms-test-running {
|
||||
color: #783887;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,10 +11,15 @@
|
|||
:show-version="showVersion"
|
||||
:background-color="backgroundColor"
|
||||
:if-from-variable-advance="ifFromVariableAdvance"
|
||||
:title="title" v-loading="loading">
|
||||
:title="title"
|
||||
v-loading="loading"
|
||||
>
|
||||
<!--自定义脚本-->
|
||||
<legend style="width: 100%;display:table-column" v-if="request && this.request.type === 'JSR223Processor'">
|
||||
<p class="ms-tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||
<legend
|
||||
style="width: 100%; display: table-column"
|
||||
v-if="request && this.request.type === 'JSR223Processor'"
|
||||
>
|
||||
<p class="ms-tip">{{ $t('api_test.definition.request.req_param') }}</p>
|
||||
<el-tabs v-model="activeName" class="request-tabs" @tab-click="tabClick">
|
||||
<!-- 请求头-->
|
||||
<el-tab-pane label="脚本内容" name="baseScript">
|
||||
|
@ -23,13 +28,26 @@
|
|||
:is-pre-processor="isPreProcessor"
|
||||
:node="node"
|
||||
:protocol="protocol"
|
||||
:is-read-only="this.jsr223Processor.disabled"/>
|
||||
:is-read-only="this.jsr223Processor.disabled"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- 脚本步骤/断言步骤 -->
|
||||
<el-tab-pane :label="$t('api_test.definition.request.pre_operation')" name="preOperate">
|
||||
<span class="item-tabs" effect="dark" placement="top-start" slot="label" :key="request.preSize">
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.definition.request.pre_operation')"
|
||||
name="preOperate"
|
||||
>
|
||||
<span
|
||||
class="item-tabs"
|
||||
effect="dark"
|
||||
placement="top-start"
|
||||
slot="label"
|
||||
:key="request.preSize"
|
||||
>
|
||||
{{ $t('api_test.definition.request.pre_operation') }}
|
||||
<div class="el-step__icon is-text ms-api-col ms-header" v-if="request.preSize > 0">
|
||||
<div
|
||||
class="el-step__icon is-text ms-api-col ms-header"
|
||||
v-if="request.preSize > 0"
|
||||
>
|
||||
<div class="el-step__icon-inner">{{ request.preSize }}</div>
|
||||
</div>
|
||||
</span>
|
||||
|
@ -42,11 +60,24 @@
|
|||
v-if="activeName === 'preOperate'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.definition.request.post_operation')" name="postOperate">
|
||||
<span class="item-tabs" effect="dark" placement="top-start" slot="label">
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.definition.request.post_operation')"
|
||||
name="postOperate"
|
||||
>
|
||||
<span
|
||||
class="item-tabs"
|
||||
effect="dark"
|
||||
placement="top-start"
|
||||
slot="label"
|
||||
>
|
||||
{{ $t('api_test.definition.request.post_operation') }}
|
||||
<div class="el-step__icon is-text ms-api-col ms-header" v-if="request.postSize > 0">
|
||||
<div class="el-step__icon-inner" :key="request.postSize">{{ request.postSize }}</div>
|
||||
<div
|
||||
class="el-step__icon is-text ms-api-col ms-header"
|
||||
v-if="request.postSize > 0"
|
||||
>
|
||||
<div class="el-step__icon-inner" :key="request.postSize">
|
||||
{{ request.postSize }}
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<ms-jmx-step
|
||||
|
@ -58,11 +89,24 @@
|
|||
v-if="activeName === 'postOperate'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.definition.request.assertions_rule')" name="assertionsRule">
|
||||
<span class="item-tabs" effect="dark" placement="top-start" slot="label">
|
||||
<el-tab-pane
|
||||
:label="$t('api_test.definition.request.assertions_rule')"
|
||||
name="assertionsRule"
|
||||
>
|
||||
<span
|
||||
class="item-tabs"
|
||||
effect="dark"
|
||||
placement="top-start"
|
||||
slot="label"
|
||||
>
|
||||
{{ $t('api_test.definition.request.assertions_rule') }}
|
||||
<div class="el-step__icon is-text ms-api-col ms-header" v-if="request.ruleSize > 0">
|
||||
<div class="el-step__icon-inner" :key="request.ruleSize">{{ request.ruleSize }}</div>
|
||||
<div
|
||||
class="el-step__icon is-text ms-api-col ms-header"
|
||||
v-if="request.ruleSize > 0"
|
||||
>
|
||||
<div class="el-step__icon-inner" :key="request.ruleSize">
|
||||
{{ request.ruleSize }}
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<ms-jmx-step
|
||||
|
@ -71,7 +115,8 @@
|
|||
:response="response"
|
||||
:tab-type="'assertionsRule'"
|
||||
ref="assertionsRule"
|
||||
v-if="activeName === 'assertionsRule'"/>
|
||||
v-if="activeName === 'assertionsRule'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</legend>
|
||||
|
@ -83,52 +128,95 @@
|
|||
:is-pre-processor="isPreProcessor"
|
||||
:node="node"
|
||||
:protocol="protocol"
|
||||
:is-read-only="this.jsr223Processor.disabled"/>
|
||||
:is-read-only="this.jsr223Processor.disabled"
|
||||
/>
|
||||
</legend>
|
||||
<template v-slot:debugStepCode>
|
||||
<span v-if="jsr223Processor.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px"/>
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span class="ms-step-debug-code" :class="jsr223Processor.requestResult[0].success && reqSuccess?'ms-req-success':'ms-req-error'"
|
||||
v-if="!loading &&!jsr223Processor.testing && jsr223Processor.debug && jsr223Processor.requestResult[0] && jsr223Processor.requestResult[0].responseResult">
|
||||
{{ jsr223Processor.requestResult[0].success && reqSuccess ? 'Success' : 'Error' }}
|
||||
</span>
|
||||
<span v-if="jsr223Processor.testing" class="ms-test-running">
|
||||
<i class="el-icon-loading" style="font-size: 16px" />
|
||||
{{ $t('commons.testing') }}
|
||||
</span>
|
||||
<span
|
||||
class="ms-step-debug-code"
|
||||
:class="
|
||||
jsr223Processor.requestResult[0].success && reqSuccess
|
||||
? 'ms-req-success'
|
||||
: 'ms-req-error'
|
||||
"
|
||||
v-if="
|
||||
!loading &&
|
||||
!jsr223Processor.testing &&
|
||||
jsr223Processor.debug &&
|
||||
jsr223Processor.requestResult[0] &&
|
||||
jsr223Processor.requestResult[0].responseResult
|
||||
"
|
||||
>
|
||||
{{
|
||||
jsr223Processor.requestResult[0].success && reqSuccess
|
||||
? 'Success'
|
||||
: 'Error'
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<!-- 执行结果内容 -->
|
||||
<template v-slot:result>
|
||||
<div v-loading="loading" v-if="jsr223Processor && jsr223Processor.requestResult && jsr223Processor.requestResult.length > 0">
|
||||
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
|
||||
<el-tabs v-model="jsr223Processor.activeName" closable class="ms-tabs" v-if="jsr223Processor.requestResult && jsr223Processor.requestResult.length > 1">
|
||||
<el-tab-pane v-for="(item,i) in jsr223Processor.requestResult" :label="'循环'+(i+1)" :key="i" style="margin-bottom: 5px">
|
||||
<div
|
||||
v-loading="loading"
|
||||
v-if="
|
||||
jsr223Processor &&
|
||||
jsr223Processor.requestResult &&
|
||||
jsr223Processor.requestResult.length > 0
|
||||
"
|
||||
>
|
||||
<p class="tip">{{ $t('api_test.definition.request.res_param') }}</p>
|
||||
<el-tabs
|
||||
v-model="jsr223Processor.activeName"
|
||||
closable
|
||||
class="ms-tabs"
|
||||
v-if="
|
||||
jsr223Processor.requestResult &&
|
||||
jsr223Processor.requestResult.length > 1
|
||||
"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="(item, i) in jsr223Processor.requestResult"
|
||||
:label="'循环' + (i + 1)"
|
||||
:key="i"
|
||||
style="margin-bottom: 5px"
|
||||
>
|
||||
<api-response-component
|
||||
:currentProtocol="jsr223Processor.protocol"
|
||||
:apiActive="true"
|
||||
:result="item"/>
|
||||
:result="item"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<api-response-component
|
||||
:currentProtocol="'HTTP'"
|
||||
:apiActive="true"
|
||||
:result="jsr223Processor.requestResult[0]"
|
||||
v-else/>
|
||||
v-else
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</api-base-component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
|
||||
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||
import MsDropdown from "@/business/commons/MsDropdown";
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import Jsr233ProcessorContent from "../common/Jsr233ProcessorContent";
|
||||
import ApiResponseComponent from "./ApiResponseComponent";
|
||||
import {stepCompute, hisDataProcessing} from "@/business/definition/api-definition";
|
||||
import MsCodeEdit from 'metersphere-frontend/src/components/MsCodeEdit';
|
||||
import MsInstructionsIcon from 'metersphere-frontend/src/components/MsInstructionsIcon';
|
||||
import MsDropdown from '@/business/commons/MsDropdown';
|
||||
import ApiBaseComponent from '../common/ApiBaseComponent';
|
||||
import Jsr233ProcessorContent from '../common/Jsr233ProcessorContent';
|
||||
import ApiResponseComponent from './ApiResponseComponent';
|
||||
import {
|
||||
stepCompute,
|
||||
hisDataProcessing,
|
||||
} from '@/business/definition/api-definition';
|
||||
|
||||
export default {
|
||||
name: "MsJsr233Processor",
|
||||
name: 'MsJsr233Processor',
|
||||
components: {
|
||||
Jsr233ProcessorContent,
|
||||
ApiBaseComponent,
|
||||
|
@ -136,7 +224,7 @@ export default {
|
|||
MsInstructionsIcon,
|
||||
MsCodeEdit,
|
||||
ApiResponseComponent,
|
||||
MsJmxStep: () => import( "@/business/definition/components/step/JmxStep")
|
||||
MsJmxStep: () => import('@/business/definition/components/step/JmxStep'),
|
||||
},
|
||||
props: {
|
||||
request: {},
|
||||
|
@ -160,16 +248,14 @@ export default {
|
|||
protocol: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default:
|
||||
false
|
||||
default: false,
|
||||
},
|
||||
jsr223Processor: {
|
||||
type: Object,
|
||||
},
|
||||
isPreProcessor: {
|
||||
type: Boolean,
|
||||
default:
|
||||
false
|
||||
default: false,
|
||||
},
|
||||
title: String,
|
||||
color: String,
|
||||
|
@ -181,7 +267,11 @@ export default {
|
|||
},
|
||||
},
|
||||
created() {
|
||||
if (this.request && this.request.type === 'JSR223Processor' && this.request.hashTree) {
|
||||
if (
|
||||
this.request &&
|
||||
this.request.type === 'JSR223Processor' &&
|
||||
this.request.hashTree
|
||||
) {
|
||||
this.initStepSize(this.request.hashTree);
|
||||
this.historicalDataProcessing(this.request.hashTree);
|
||||
}
|
||||
|
@ -195,16 +285,16 @@ export default {
|
|||
handler(v) {
|
||||
this.initStepSize(this.request.hashTree);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
reqSuccess: true,
|
||||
response: {},
|
||||
activeName: "baseScript"
|
||||
}
|
||||
activeName: 'baseScript',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
historicalDataProcessing(array) {
|
||||
|
@ -234,26 +324,37 @@ export default {
|
|||
}
|
||||
},
|
||||
forStatus() {
|
||||
if (this.jsr223Processor && this.jsr223Processor.result && this.jsr223Processor.result.length > 0) {
|
||||
this.jsr223Processor.result.forEach(item => {
|
||||
item.requestResult.forEach(req => {
|
||||
if (
|
||||
this.jsr223Processor &&
|
||||
this.jsr223Processor.result &&
|
||||
this.jsr223Processor.result.length > 0
|
||||
) {
|
||||
this.jsr223Processor.result.forEach((item) => {
|
||||
item.requestResult.forEach((req) => {
|
||||
if (!req.success) {
|
||||
this.reqSuccess = req.success;
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if (this.jsr223Processor && this.jsr223Processor.requestResult && this.jsr223Processor.requestResult.length > 1) {
|
||||
this.jsr223Processor.requestResult.forEach(item => {
|
||||
});
|
||||
});
|
||||
} else if (
|
||||
this.jsr223Processor &&
|
||||
this.jsr223Processor.requestResult &&
|
||||
this.jsr223Processor.requestResult.length > 1
|
||||
) {
|
||||
this.jsr223Processor.requestResult.forEach((item) => {
|
||||
if (!item.success) {
|
||||
this.reqSuccess = item.success;
|
||||
if (this.node && this.node.parent && this.node.parent.data) {
|
||||
this.node.parent.data.code = 'ERROR';
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
if (this.jsr223Processor.requestResult && this.jsr223Processor.requestResult.length > 0) {
|
||||
this.response = this.jsr223Processor.requestResult[0]
|
||||
if (
|
||||
this.jsr223Processor.requestResult &&
|
||||
this.jsr223Processor.requestResult.length > 0
|
||||
) {
|
||||
this.response = this.jsr223Processor.requestResult[0];
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
|
@ -263,17 +364,17 @@ export default {
|
|||
this.$emit('copyRow', this.jsr223Processor, this.node);
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
active() {
|
||||
this.jsr223Processor.active = !this.jsr223Processor.active;
|
||||
this.reload();
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -282,7 +383,7 @@ export default {
|
|||
}
|
||||
|
||||
.ms-req-error {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.ms-test-running {
|
||||
|
@ -290,7 +391,7 @@ export default {
|
|||
}
|
||||
|
||||
.ms-req-success {
|
||||
color: #67C23A;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.ms-header {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue