feat(测试计划): 测试计划不再强制关联用例时选择环境
--story=1012486 --user=宋天阳 【货车之家】接口场景包含跨项目步骤时取消跨项目环境必选&测试计划关联接口、UI测试时取消运行环境必选 https://www.tapd.cn/55049933/s/1401625
This commit is contained in:
parent
eed243d40c
commit
dd92feeba2
|
@ -287,8 +287,16 @@ public class ApiExecuteService {
|
|||
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
||||
example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId());
|
||||
List<TestPlanApiCase> list = testPlanApiCaseMapper.selectByExample(example);
|
||||
request.setEnvironmentId(list.get(0).getEnvironmentId());
|
||||
element.setName(list.get(0).getId());
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
request.setEnvironmentId(list.get(0).getEnvironmentId());
|
||||
element.setName(list.get(0).getId());
|
||||
} else {
|
||||
TestPlanApiCase apiCase = testPlanApiCaseMapper.selectByPrimaryKey(request.getCaseId());
|
||||
if (apiCase != null) {
|
||||
request.setEnvironmentId(apiCase.getEnvironmentId());
|
||||
element.setName(request.getCaseId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
element.setName(request.getCaseId());
|
||||
}
|
||||
|
|
|
@ -11,10 +11,7 @@ import io.metersphere.base.mapper.ext.BaseApiExecutionQueueMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
|
||||
import io.metersphere.base.mapper.plan.ext.ExtTestPlanApiCaseMapper;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.constants.CommonConstants;
|
||||
import io.metersphere.commons.constants.KafkaTopicConstants;
|
||||
import io.metersphere.commons.constants.TestPlanReportStatus;
|
||||
import io.metersphere.commons.constants.*;
|
||||
import io.metersphere.commons.enums.ApiReportStatus;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
|
@ -89,9 +86,11 @@ public class ApiExecutionQueueService {
|
|||
Map<String, String> detailMap = new HashMap<>();
|
||||
List<ApiExecutionQueueDetail> queueDetails = new LinkedList<>();
|
||||
// 初始化API/用例队列
|
||||
String redisLockType = TestPlanExecuteCaseType.SCENARIO.name();
|
||||
if (StringUtils.equalsAnyIgnoreCase(type, ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
|
||||
Map<String, ApiDefinitionExecResult> runMap = (Map<String, ApiDefinitionExecResult>) runObj;
|
||||
initApi(runMap, resQueue, config, detailMap, queueDetails);
|
||||
redisLockType = TestPlanExecuteCaseType.API_CASE.name();
|
||||
}
|
||||
// 初始化场景
|
||||
else {
|
||||
|
@ -101,11 +100,16 @@ public class ApiExecutionQueueService {
|
|||
if (CollectionUtils.isNotEmpty(queueDetails)) {
|
||||
extApiExecutionQueueMapper.sqlInsert(queueDetails);
|
||||
}
|
||||
//redis移除key (执行测试计划时会添加key)
|
||||
redisTemplateService.unlock(reportId, redisLockType, reportId);
|
||||
resQueue.setDetailMap(detailMap);
|
||||
LoggerUtil.info("报告【" + type + "】生成执行链结束", reportId);
|
||||
return resQueue;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
|
||||
private void initScenario(Map<String, RunModeDataDTO> runMap, DBTestQueue resQueue, RunModeConfigDTO config, Map<String, String> detailMap, List<ApiExecutionQueueDetail> queueDetails) {
|
||||
final int[] sort = {0};
|
||||
runMap.forEach((k, v) -> {
|
||||
|
|
|
@ -846,9 +846,8 @@ public class MockConfigService {
|
|||
if (project != null) {
|
||||
RequestMockParams requestMockParams = MockApiUtils.genRequestMockParamsFromHttpRequest(request, true);
|
||||
String urlSuffix = this.getUrlSuffix(project.getSystemId(), request);
|
||||
LogUtil.info("Mock urlSuffix:{}", urlSuffix);
|
||||
LogUtil.info("Mock requestHeaderMap:{}", requestHeaderMap);
|
||||
LogUtil.info("Mock requestMockParams:{}", JSON.toJSONString(requestMockParams));
|
||||
LogUtil.info("Mock [" + url + "] Header:{}", requestHeaderMap);
|
||||
LogUtil.info("Mock [" + url + "] request:{}", JSON.toJSONString(requestMockParams));
|
||||
List<ApiDefinitionWithBLOBs> qualifiedApiList = apiDefinitionService.preparedUrl(project.getId(), method, urlSuffix, requestHeaderMap.get(MockApiHeaders.MOCK_API_RESOURCE_ID));
|
||||
for (ApiDefinitionWithBLOBs api : qualifiedApiList) {
|
||||
if (StringUtils.isEmpty(returnStr)) {
|
||||
|
@ -872,6 +871,7 @@ public class MockConfigService {
|
|||
response.setStatus(404);
|
||||
returnStr = Translator.get("mock_warning");
|
||||
}
|
||||
LogUtil.info("Mock [" + url + "] response:{}", returnStr);
|
||||
return returnStr;
|
||||
}
|
||||
|
||||
|
@ -883,9 +883,8 @@ public class MockConfigService {
|
|||
RequestMockParams requestMockParams = MockApiUtils.genRequestMockParamsFromHttpRequest(request, false);
|
||||
|
||||
String urlSuffix = this.getUrlSuffix(project.getSystemId(), request);
|
||||
LogUtil.info("Mock urlSuffix:{}", urlSuffix);
|
||||
LogUtil.info("Mock requestHeaderMap:{}", requestHeaderMap);
|
||||
LogUtil.info("Mock requestMockParams:{}", JSON.toJSONString(requestMockParams));
|
||||
LogUtil.info("Mock [" + url + "] Header:{}", requestHeaderMap);
|
||||
LogUtil.info("Mock [" + url + "] request:{}", JSON.toJSONString(requestMockParams));
|
||||
List<ApiDefinitionWithBLOBs> qualifiedApiList = apiDefinitionService.preparedUrl(project.getId(), method, urlSuffix, requestHeaderMap.get(MockApiHeaders.MOCK_API_RESOURCE_ID));
|
||||
/*
|
||||
GET/DELETE 这种通过url穿参数的接口,在接口路径相同的情况下可能会出现这样的情况:
|
||||
|
@ -919,6 +918,7 @@ public class MockConfigService {
|
|||
response.setStatus(404);
|
||||
returnStr = Translator.get("mock_warning");
|
||||
}
|
||||
LogUtil.info("Mock [" + url + "] response:{}", returnStr);
|
||||
return returnStr;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,4 +99,10 @@ public class RedisTemplateService {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void unlock(String testPlanReportId, String key, String value) {
|
||||
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
|
||||
this.redisTemplate.execute(redisScript, Collections.singletonList(StringUtils.join(testPlanReportId, key)), new Object[]{value});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<test-case-relevance-base
|
||||
:is-across-space="isAcrossSpace"
|
||||
@setProject="setProject"
|
||||
:dialog-title="$t('api_test.definition.api_import')"
|
||||
ref="baseRelevance">
|
||||
:is-across-space="isAcrossSpace"
|
||||
@setProject="setProject"
|
||||
:dialog-title="$t('api_test.definition.api_import')"
|
||||
ref="baseRelevance">
|
||||
<template v-slot:aside>
|
||||
<ms-api-module
|
||||
class="node-tree"
|
||||
|
@ -18,60 +18,60 @@
|
|||
</template>
|
||||
|
||||
<scenario-relevance-api-list
|
||||
v-if="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:version-filters="versionFilters"
|
||||
:current-version="currentVersion"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiList">
|
||||
v-if="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:version-filters="versionFilters"
|
||||
:current-version="currentVersion"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiList">
|
||||
<template v-slot:version>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
:default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange" />
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
:default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange"/>
|
||||
</template>
|
||||
</scenario-relevance-api-list>
|
||||
|
||||
<scenario-relevance-case-list
|
||||
v-if="!isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:version-filters="versionFilters"
|
||||
:current-version="currentVersion"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiCaseList">
|
||||
v-if="!isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:version-filters="versionFilters"
|
||||
:current-version="currentVersion"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiCaseList">
|
||||
<template v-slot:version>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
:default-version="currentVersion"
|
||||
@changeVersion="currentVersionChange" />
|
||||
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="refreshData" />
|
||||
<el-button size="mini" icon="el-icon-refresh" @click="refreshData"/>
|
||||
<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>
|
||||
v-if="!isApiListEnable"
|
||||
type="primary"
|
||||
:loading="buttonIsWorking"
|
||||
@click="reference"
|
||||
size="mini"
|
||||
@keydown.enter.native.prevent>
|
||||
{{ $t('api_test.scenario.reference') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -79,9 +79,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getApiCaseWithBLOBs } from '@/api/api-test-case';
|
||||
import { apiListBatch } from '@/api/definition';
|
||||
import { getProjectVersions } from '@/api/xpack';
|
||||
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';
|
||||
|
@ -90,9 +90,9 @@ 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 {hasLicense} from 'metersphere-frontend/src/utils/permission';
|
||||
import TableSelectCountBar from '@/business/automation/scenario/api/TableSelectCountBar';
|
||||
import { operationConfirm } from 'metersphere-frontend/src/utils';
|
||||
import {operationConfirm} from 'metersphere-frontend/src/utils';
|
||||
|
||||
export default {
|
||||
name: 'ApiRelevance',
|
||||
|
@ -166,15 +166,15 @@ export default {
|
|||
} else {
|
||||
if (params.condition.selectAll) {
|
||||
operationConfirm(
|
||||
this,
|
||||
this.$t('automation.scenario_step_ref_message') + '?',
|
||||
() => {
|
||||
this.$emit('save', apis, 'API', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
},
|
||||
() => {
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
this,
|
||||
this.$t('automation.scenario_step_ref_message') + '?',
|
||||
() => {
|
||||
this.$emit('save', apis, 'API', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
},
|
||||
() => {
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.$emit('save', apis, 'API', reference);
|
||||
|
@ -192,15 +192,15 @@ export default {
|
|||
} else {
|
||||
if (this.$refs.apiCaseList.condition.selectAll) {
|
||||
operationConfirm(
|
||||
this,
|
||||
this.$t('automation.scenario_step_ref_message') + '?',
|
||||
() => {
|
||||
this.$emit('save', apiCases, 'CASE', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
},
|
||||
() => {
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
this,
|
||||
this.$t('automation.scenario_step_ref_message') + '?',
|
||||
() => {
|
||||
this.$emit('save', apiCases, 'CASE', reference);
|
||||
this.$refs.baseRelevance.close();
|
||||
},
|
||||
() => {
|
||||
this.buttonIsWorking = false;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.$emit('save', apiCases, 'CASE', reference);
|
||||
|
@ -258,13 +258,13 @@ export default {
|
|||
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 };
|
||||
});
|
||||
.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 };
|
||||
return {text: u.name, value: u.id};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
<template>
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="save"
|
||||
:plan-id="planId"
|
||||
:dialog-title="dialogTitle"
|
||||
ref="baseRelevance">
|
||||
@setProject="setProject"
|
||||
@save="save"
|
||||
:plan-id="planId"
|
||||
:dialog-title="dialogTitle"
|
||||
ref="baseRelevance">
|
||||
<template v-slot:aside>
|
||||
<ms-api-module
|
||||
:options="options"
|
||||
:relevance-project-id="projectId"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@protocolChange="handleProtocolChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:is-read-only="true"
|
||||
:is-relevance="true"
|
||||
ref="nodeTree" />
|
||||
:options="options"
|
||||
:relevance-project-id="projectId"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@protocolChange="handleProtocolChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:is-read-only="true"
|
||||
:is-relevance="true"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<relevance-api-list
|
||||
v-if="isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="isTestPlan"
|
||||
:is-script="isScript"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiList" />
|
||||
v-if="isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="isTestPlan"
|
||||
:is-script="isScript"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiList"/>
|
||||
|
||||
<relevance-case-list
|
||||
v-if="!isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="isTestPlan"
|
||||
:is-script="isScript"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiCaseList" />
|
||||
v-if="!isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="isTestPlan"
|
||||
:is-script="isScript"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
ref="apiCaseList"/>
|
||||
</test-case-relevance-base>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getApiCaseWithBLOBs } from '@/api/api-test-case';
|
||||
import { apiListBatch } from '@/api/definition';
|
||||
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 {getEnvironmentById} from 'metersphere-frontend/src/api/environment';
|
||||
import TestCaseRelevanceBase from '@/business/commons/TestCaseRelevanceBase';
|
||||
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
|
||||
import {parseEnvironment} from '@/business/environment/model/EnvironmentModel';
|
||||
|
||||
export default {
|
||||
name: 'ApiFuncRelevance',
|
||||
|
@ -75,7 +75,7 @@ export default {
|
|||
condition: {},
|
||||
currentRow: {},
|
||||
projectId: '',
|
||||
options: [{ value: 'HTTP', name: 'HTTP' }],
|
||||
options: [{value: 'HTTP', name: 'HTTP'}],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -51,153 +51,169 @@ export const GROUP_WORKSPACE = 'WORKSPACE';
|
|||
export const GROUP_PROJECT = 'PROJECT';
|
||||
|
||||
export const GROUP_TYPE = {
|
||||
SYSTEM: 'SYSTEM',
|
||||
WORKSPACE: 'WORKSPACE',
|
||||
PROJECT: 'PROJECT'
|
||||
SYSTEM: 'SYSTEM',
|
||||
WORKSPACE: 'WORKSPACE',
|
||||
PROJECT: 'PROJECT'
|
||||
}
|
||||
|
||||
export const SCHEDULE_TYPE = {
|
||||
API_TEST: 'API_TEST',
|
||||
PERFORMANCE_TEST: 'PERFORMANCE_TEST'
|
||||
API_TEST: 'API_TEST',
|
||||
PERFORMANCE_TEST: 'PERFORMANCE_TEST'
|
||||
}
|
||||
|
||||
export const REQUEST_HEADERS = [
|
||||
{value: 'Accept'},
|
||||
{value: 'Accept-Charset'},
|
||||
{value: 'Accept-Language'},
|
||||
{value: 'Accept-Datetime'},
|
||||
{value: 'Authorization'},
|
||||
{value: 'Cache-Control'},
|
||||
{value: 'Connection'},
|
||||
{value: 'Cookie'},
|
||||
{value: 'Content-Length'},
|
||||
{value: 'Content-MD5'},
|
||||
{value: 'Content-Type'},
|
||||
{value: 'Date'},
|
||||
{value: 'Expect'},
|
||||
{value: 'From'},
|
||||
{value: 'Host'},
|
||||
{value: 'If-Match'},
|
||||
{value: 'If-Modified-Since'},
|
||||
{value: 'If-None-Match'},
|
||||
{value: 'If-Range'},
|
||||
{value: 'If-Unmodified-Since'},
|
||||
{value: 'Max-Forwards'},
|
||||
{value: 'Origin'},
|
||||
{value: 'Pragma'},
|
||||
{value: 'Proxy-Authorization'},
|
||||
{value: 'Range'},
|
||||
{value: 'Referer'},
|
||||
{value: 'TE'},
|
||||
{value: 'User-Agent'},
|
||||
{value: 'Upgrade'},
|
||||
{value: 'Via'},
|
||||
{value: 'Warning'}
|
||||
{value: 'Accept'},
|
||||
{value: 'Accept-Charset'},
|
||||
{value: 'Accept-Language'},
|
||||
{value: 'Accept-Datetime'},
|
||||
{value: 'Authorization'},
|
||||
{value: 'Cache-Control'},
|
||||
{value: 'Connection'},
|
||||
{value: 'Cookie'},
|
||||
{value: 'Content-Length'},
|
||||
{value: 'Content-MD5'},
|
||||
{value: 'Content-Type'},
|
||||
{value: 'Date'},
|
||||
{value: 'Expect'},
|
||||
{value: 'From'},
|
||||
{value: 'Host'},
|
||||
{value: 'If-Match'},
|
||||
{value: 'If-Modified-Since'},
|
||||
{value: 'If-None-Match'},
|
||||
{value: 'If-Range'},
|
||||
{value: 'If-Unmodified-Since'},
|
||||
{value: 'Max-Forwards'},
|
||||
{value: 'Origin'},
|
||||
{value: 'Pragma'},
|
||||
{value: 'Proxy-Authorization'},
|
||||
{value: 'Range'},
|
||||
{value: 'Referer'},
|
||||
{value: 'TE'},
|
||||
{value: 'User-Agent'},
|
||||
{value: 'Upgrade'},
|
||||
{value: 'Via'},
|
||||
{value: 'Warning'}
|
||||
]
|
||||
|
||||
export const MOCKJS_FUNC = [
|
||||
{name: '@boolean', des: i18n.t('api_test.request.boolean'), ex: true},
|
||||
{name: '@natural', des: i18n.t('api_test.request.natural'), ex: 72834},
|
||||
{name: '@integer', des: i18n.t('api_test.request.integer'), ex: 79750},
|
||||
{name: '@float', des: i18n.t('api_test.request.float'), ex: 24.2},
|
||||
{name: '@character', des: i18n.t('api_test.request.character'), ex: "k"},
|
||||
{name: '@string', des: i18n.t('api_test.request.string'), ex: "hello"},
|
||||
{name: '@range', des: i18n.t('api_test.request.range'), ex: "org.mozilla.javascript.NavicatArray@1739f809"},
|
||||
{name: '@date', des: i18n.t('api_test.request.date'), ex: "1973-01-08"},
|
||||
{name: '@time', des: i18n.t('api_test.request.time'), ex: "06:15:27"},
|
||||
{name: '@datetime', des: i18n.t('api_test.request.datetime'), ex: "1975-10-12 02:32:04"},
|
||||
{name: '@now', des: i18n.t('api_test.request.now'), ex: (new Date()).toLocaleTimeString().toLocaleString()},
|
||||
{name: '@img', des: i18n.t('api_test.request.img'), ex: "http://dummyimage.com/120x60"},
|
||||
{name: '@color', des: i18n.t('api_test.request.color'), ex: "#b479f2"},
|
||||
{name: '@hex', des: i18n.t('api_test.request.hex'), ex: "#f27984"},
|
||||
{name: '@rgb', des: i18n.t('api_test.request.rgb'), ex: "rgb(203, 242, 121)"},
|
||||
{name: '@rgba', des: i18n.t('api_test.request.rgba'), ex: "rgba(242, 121, 238, 0.66)"},
|
||||
{name: '@hsl', des: i18n.t('api_test.request.hsl'), ex: "hsl(164, 82, 71)"},
|
||||
{name: '@paragraph', des: i18n.t('api_test.request.paragraph'), ex: "Iwvh qxuvn uigzjw xijvntv dfidxtof"},
|
||||
{name: '@sentence', des: i18n.t('api_test.request.sentence'), ex: "Hfi fpqnqerrs sghxldx oqpghvnmy"},
|
||||
{name: '@word', des: i18n.t('api_test.request.word'), ex: "shnjlyazvi"},
|
||||
{name: '@title', des: i18n.t('api_test.request.title'), ex: "Tefsdc Vhs Ujx"},
|
||||
{name: '@cparagraph', des: i18n.t('api_test.request.cparagraph'), ex: "色青元处才不米拉律消叫别金如上。"},
|
||||
{name: '@csentence', des: i18n.t('api_test.request.csentence'), ex: "与形府部速她运改织图集料进完。"},
|
||||
{name: '@cword', des: i18n.t('api_test.request.cword'), ex: "满"},
|
||||
{name: '@ctitle', des: i18n.t('api_test.request.ctitle'), ex: "运满前省快"},
|
||||
{name: '@first', des: i18n.t('api_test.request.first'), ex: "Mary"},
|
||||
{name: '@last', des: i18n.t('api_test.request.last'), ex: "Miller"},
|
||||
{name: '@name', des: i18n.t('api_test.request.name'), ex: "Robert Lee"},
|
||||
{name: '@cfirst', des: i18n.t('api_test.request.cfirst'), ex: "龚"},
|
||||
{name: '@clast', des: i18n.t('api_test.request.clast'), ex: "刚"},
|
||||
{name: '@cname', des: i18n.t('api_test.request.cname'), ex: "江娟"},
|
||||
{name: '@url', des: i18n.t('api_test.request.url'), ex: "wais://jopnwwj.bh/lqnhn"},
|
||||
{name: '@domain', des: i18n.t('api_test.request.domain'), ex: "rsh.bt"},
|
||||
{name: '@protocol', des: i18n.t('api_test.request.protocol'), ex: "rlogin"},
|
||||
{name: '@tld', des: i18n.t('api_test.request.tld'), ex: "sa"},
|
||||
{name: '@email', des: i18n.t('api_test.request.email'), ex: "d.somdg@edntlm.cd"},
|
||||
{name: '@ip', des: i18n.t('api_test.request.ip'), ex: "22.151.93.255"},
|
||||
{name: '@region', des: i18n.t('api_test.request.region'), ex: "东北"},
|
||||
{name: '@province', des: i18n.t('api_test.request.province'), ex: "陕西省"},
|
||||
{name: '@city', des: i18n.t('api_test.request.city'), ex: "珠海市"},
|
||||
{name: '@county', des: i18n.t('api_test.request.county'), ex: "正宁县"},
|
||||
{name: '@zip', des: i18n.t('api_test.request.zip'), ex: 873247},
|
||||
{name: '@capitalize', des: i18n.t('api_test.request.capitalize'), ex: "Undefined"},
|
||||
{name: '@upper', des: i18n.t('api_test.request.upper'), ex: "UNDEFINED"},
|
||||
{name: '@lower', des: i18n.t('api_test.request.lower'), ex: "undefined"},
|
||||
{name: '@pick', des: i18n.t('api_test.request.pick'), ex: "None example"},
|
||||
{name: '@shuffle', des: i18n.t('api_test.request.shuffle'), ex: "org.mozilla.javascript.NavicatArray@2264545d"},
|
||||
{name: '@guid', des: i18n.t('api_test.request.guid'), ex: "4f9CeC2c-8d59-40f6-ec4F-2Abbc5C94Ddf"},
|
||||
{name: '@id', des: i18n.t('api_test.request.id'), ex: "450000197511051762"},
|
||||
{name: '@increment', des: i18n.t('api_test.request.increment'), ex: 1}
|
||||
{name: '@boolean', des: i18n.t('api_test.request.boolean'), ex: true},
|
||||
{name: '@natural', des: i18n.t('api_test.request.natural'), ex: 72834},
|
||||
{name: '@integer', des: i18n.t('api_test.request.integer'), ex: 79750},
|
||||
{name: '@float', des: i18n.t('api_test.request.float'), ex: 24.2},
|
||||
{name: '@character', des: i18n.t('api_test.request.character'), ex: "k"},
|
||||
{name: '@string', des: i18n.t('api_test.request.string'), ex: "hello"},
|
||||
{name: '@range', des: i18n.t('api_test.request.range'), ex: "org.mozilla.javascript.NavicatArray@1739f809"},
|
||||
{name: '@date', des: i18n.t('api_test.request.date'), ex: "1973-01-08"},
|
||||
{name: '@time', des: i18n.t('api_test.request.time'), ex: "06:15:27"},
|
||||
{name: '@datetime', des: i18n.t('api_test.request.datetime'), ex: "1975-10-12 02:32:04"},
|
||||
{name: '@now', des: i18n.t('api_test.request.now'), ex: (new Date()).toLocaleTimeString().toLocaleString()},
|
||||
{name: '@img', des: i18n.t('api_test.request.img'), ex: "http://dummyimage.com/120x60"},
|
||||
{name: '@color', des: i18n.t('api_test.request.color'), ex: "#b479f2"},
|
||||
{name: '@hex', des: i18n.t('api_test.request.hex'), ex: "#f27984"},
|
||||
{name: '@rgb', des: i18n.t('api_test.request.rgb'), ex: "rgb(203, 242, 121)"},
|
||||
{name: '@rgba', des: i18n.t('api_test.request.rgba'), ex: "rgba(242, 121, 238, 0.66)"},
|
||||
{name: '@hsl', des: i18n.t('api_test.request.hsl'), ex: "hsl(164, 82, 71)"},
|
||||
{name: '@paragraph', des: i18n.t('api_test.request.paragraph'), ex: "Iwvh qxuvn uigzjw xijvntv dfidxtof"},
|
||||
{name: '@sentence', des: i18n.t('api_test.request.sentence'), ex: "Hfi fpqnqerrs sghxldx oqpghvnmy"},
|
||||
{name: '@word', des: i18n.t('api_test.request.word'), ex: "shnjlyazvi"},
|
||||
{name: '@title', des: i18n.t('api_test.request.title'), ex: "Tefsdc Vhs Ujx"},
|
||||
{name: '@cparagraph', des: i18n.t('api_test.request.cparagraph'), ex: "色青元处才不米拉律消叫别金如上。"},
|
||||
{name: '@csentence', des: i18n.t('api_test.request.csentence'), ex: "与形府部速她运改织图集料进完。"},
|
||||
{name: '@cword', des: i18n.t('api_test.request.cword'), ex: "满"},
|
||||
{name: '@ctitle', des: i18n.t('api_test.request.ctitle'), ex: "运满前省快"},
|
||||
{name: '@first', des: i18n.t('api_test.request.first'), ex: "Mary"},
|
||||
{name: '@last', des: i18n.t('api_test.request.last'), ex: "Miller"},
|
||||
{name: '@name', des: i18n.t('api_test.request.name'), ex: "Robert Lee"},
|
||||
{name: '@cfirst', des: i18n.t('api_test.request.cfirst'), ex: "龚"},
|
||||
{name: '@clast', des: i18n.t('api_test.request.clast'), ex: "刚"},
|
||||
{name: '@cname', des: i18n.t('api_test.request.cname'), ex: "江娟"},
|
||||
{name: '@url', des: i18n.t('api_test.request.url'), ex: "wais://jopnwwj.bh/lqnhn"},
|
||||
{name: '@domain', des: i18n.t('api_test.request.domain'), ex: "rsh.bt"},
|
||||
{name: '@protocol', des: i18n.t('api_test.request.protocol'), ex: "rlogin"},
|
||||
{name: '@tld', des: i18n.t('api_test.request.tld'), ex: "sa"},
|
||||
{name: '@email', des: i18n.t('api_test.request.email'), ex: "d.somdg@edntlm.cd"},
|
||||
{name: '@ip', des: i18n.t('api_test.request.ip'), ex: "22.151.93.255"},
|
||||
{name: '@region', des: i18n.t('api_test.request.region'), ex: "东北"},
|
||||
{name: '@province', des: i18n.t('api_test.request.province'), ex: "陕西省"},
|
||||
{name: '@city', des: i18n.t('api_test.request.city'), ex: "珠海市"},
|
||||
{name: '@county', des: i18n.t('api_test.request.county'), ex: "正宁县"},
|
||||
{name: '@zip', des: i18n.t('api_test.request.zip'), ex: 873247},
|
||||
{name: '@capitalize', des: i18n.t('api_test.request.capitalize'), ex: "Undefined"},
|
||||
{name: '@upper', des: i18n.t('api_test.request.upper'), ex: "UNDEFINED"},
|
||||
{name: '@lower', des: i18n.t('api_test.request.lower'), ex: "undefined"},
|
||||
{name: '@pick', des: i18n.t('api_test.request.pick'), ex: "None example"},
|
||||
{name: '@shuffle', des: i18n.t('api_test.request.shuffle'), ex: "org.mozilla.javascript.NavicatArray@2264545d"},
|
||||
{name: '@guid', des: i18n.t('api_test.request.guid'), ex: "4f9CeC2c-8d59-40f6-ec4F-2Abbc5C94Ddf"},
|
||||
{name: '@id', des: i18n.t('api_test.request.id'), ex: "450000197511051762"},
|
||||
{name: '@increment', des: i18n.t('api_test.request.increment'), ex: 1}
|
||||
]
|
||||
|
||||
export const JMETER_FUNC = [
|
||||
{type: "Information", name: "${__threadNum}", description: "get thread number"},
|
||||
{type: "Information", name: "${__threadGroupName}", description: "get thread group name"},
|
||||
{type: "Information", name: "${__samplerName}", description: "get the sampler name (label)"},
|
||||
{type: "Information", name: "${__machineIP}", description: "get the local machine IP address"},
|
||||
{type: "Information", name: "${__machineName}", description: "get the local machine name"},
|
||||
{type: "Information", name: "${__time}", description: "return current time in various formats"},
|
||||
{type: "Information", name: "${__timeShift}", description: "return a date in various formats with the specified amount of seconds/minutes/hours/days added"},
|
||||
{type: "Information", name: "${__log}", description: "log (or display) a message (and return the value)"},
|
||||
{type: "Information", name: "${__logn}", description: "log (or display) a message (empty return value)"},
|
||||
{type: "Input", name: "${__StringFromFile}", description: "read a line from a file"},
|
||||
{type: "Input", name: "${__FileToString}", description: "read an entire file"},
|
||||
{type: "Input", name: "${__CSVRead}", description: "read from CSV delimited file"},
|
||||
{type: "Input", name: "${__XPath}", description: "Use an XPath expression to read from a file"},
|
||||
{type: "Input", name: "${__StringToFile}", description: "write a string to a file"},
|
||||
{type: "Calculation", name: "${__counter}", description: "generate an incrementing number"},
|
||||
{type: "Formatting", name: "${__dateTimeConvert}", description: "Convert a date or time from source to target format"},
|
||||
{type: "Calculation", name: "${__digest}", description: "Generate a digest (SHA-1, SHA-256, MD5...)"},
|
||||
{type: "Calculation", name: "${__intSum}", description: "add int numbers"},
|
||||
{type: "Calculation", name: "${__longSum}", description: "add long numbers"},
|
||||
{type: "Calculation", name: "${__Random}", description: "generate a random number"},
|
||||
{type: "Calculation", name: "${__RandomDate}", description: "generate random date within a specific date range"},
|
||||
{type: "Calculation", name: "${__RandomFromMultipleVars}", description: "extracts an element from the values of a set of variables separated by |"},
|
||||
{type: "Calculation", name: "${__RandomString}", description: "generate a random string"},
|
||||
{type: "Calculation", name: "${__UUID}", description: "generate a random type 4 UUID"},
|
||||
{type: "Scripting", name: "${__groovy}", description: "run an Apache Groovy script"},
|
||||
{type: "Scripting", name: "${__BeanShell}", description: "run a BeanShell script"},
|
||||
{type: "Scripting", name: "${__javaScript}", description: "process JavaScript (Nashorn)"},
|
||||
{type: "Scripting", name: "${__jexl2}", description: "evaluate a Commons Jexl2 expression"},
|
||||
{type: "Scripting", name: "${__jexl3}", description: "evaluate a Commons Jexl3 expression"},
|
||||
{type: "Properties", name: "${__isPropDefined}", description: "Test if a property exists"},
|
||||
{type: "Properties", name: "${__property}", description: "read a property"},
|
||||
{type: "Properties", name: "${__P}", description: "read a property (shorthand method)"},
|
||||
{type: "Properties", name: "${__setProperty}", description: "set a JMeter property"},
|
||||
{type: "Variables", name: "${__split}", description: "Split a string into variables"},
|
||||
{type: "Variables", name: "${__eval}", description: "evaluate a variable expression"},
|
||||
{type: "Variables", name: "${__evalVar}", description: "evaluate an expression stored in a variable"},
|
||||
{type: "Properties", name: "${__isVarDefined}", description: "Test if a variable exists"},
|
||||
{type: "Variables", name: "${__V}", description: "evaluate a variable name"},
|
||||
{type: "String", name: "${__char}", description: "generate Unicode char values from a list of numbers"},
|
||||
{type: "String", name: "${__changeCase}", description: "Change case following different modes"},
|
||||
{type: "String", name: "${__escapeHtml}", description: "Encode strings using HTML encoding"},
|
||||
{type: "String", name: "${__escapeOroRegexpChars}", description: "quote meta chars used by ORO regular expression"},
|
||||
{type: "String", name: "${__escapeXml}", description: "Encode strings using XMl encoding"},
|
||||
{type: "String", name: "${__regexFunction}", description: "parse previous response using a regular expression"},
|
||||
{type: "String", name: "${__unescape}", description: "Process strings containing Java escapes (e.g. \n & \t)"},
|
||||
{type: "String", name: "${__unescapeHtml}", description: "Decode HTML-encoded strings"},
|
||||
{type: "String", name: "${__urldecode}", description: "Decode a application/x-www-form-urlencoded string"},
|
||||
{type: "String", name: "${__urlencode}", description: "Encode a string to a application/x-www-form-urlencoded string"},
|
||||
{type: "String", name: "${__TestPlanName}", description: "Return name of current test plan"},
|
||||
{type: "Information", name: "${__threadNum}", description: "get thread number"},
|
||||
{type: "Information", name: "${__threadGroupName}", description: "get thread group name"},
|
||||
{type: "Information", name: "${__samplerName}", description: "get the sampler name (label)"},
|
||||
{type: "Information", name: "${__machineIP}", description: "get the local machine IP address"},
|
||||
{type: "Information", name: "${__machineName}", description: "get the local machine name"},
|
||||
{type: "Information", name: "${__time}", description: "return current time in various formats"},
|
||||
{
|
||||
type: "Information",
|
||||
name: "${__timeShift}",
|
||||
description: "return a date in various formats with the specified amount of seconds/minutes/hours/days added"
|
||||
},
|
||||
{type: "Information", name: "${__log}", description: "log (or display) a message (and return the value)"},
|
||||
{type: "Information", name: "${__logn}", description: "log (or display) a message (empty return value)"},
|
||||
{type: "Input", name: "${__StringFromFile}", description: "read a line from a file"},
|
||||
{type: "Input", name: "${__FileToString}", description: "read an entire file"},
|
||||
{type: "Input", name: "${__CSVRead}", description: "read from CSV delimited file"},
|
||||
{type: "Input", name: "${__XPath}", description: "Use an XPath expression to read from a file"},
|
||||
{type: "Input", name: "${__StringToFile}", description: "write a string to a file"},
|
||||
{type: "Calculation", name: "${__counter}", description: "generate an incrementing number"},
|
||||
{
|
||||
type: "Formatting",
|
||||
name: "${__dateTimeConvert}",
|
||||
description: "Convert a date or time from source to target format"
|
||||
},
|
||||
{type: "Calculation", name: "${__digest}", description: "Generate a digest (SHA-1, SHA-256, MD5...)"},
|
||||
{type: "Calculation", name: "${__intSum}", description: "add int numbers"},
|
||||
{type: "Calculation", name: "${__longSum}", description: "add long numbers"},
|
||||
{type: "Calculation", name: "${__Random}", description: "generate a random number"},
|
||||
{type: "Calculation", name: "${__RandomDate}", description: "generate random date within a specific date range"},
|
||||
{
|
||||
type: "Calculation",
|
||||
name: "${__RandomFromMultipleVars}",
|
||||
description: "extracts an element from the values of a set of variables separated by |"
|
||||
},
|
||||
{type: "Calculation", name: "${__RandomString}", description: "generate a random string"},
|
||||
{type: "Calculation", name: "${__UUID}", description: "generate a random type 4 UUID"},
|
||||
{type: "Scripting", name: "${__groovy}", description: "run an Apache Groovy script"},
|
||||
{type: "Scripting", name: "${__BeanShell}", description: "run a BeanShell script"},
|
||||
{type: "Scripting", name: "${__javaScript}", description: "process JavaScript (Nashorn)"},
|
||||
{type: "Scripting", name: "${__jexl2}", description: "evaluate a Commons Jexl2 expression"},
|
||||
{type: "Scripting", name: "${__jexl3}", description: "evaluate a Commons Jexl3 expression"},
|
||||
{type: "Properties", name: "${__isPropDefined}", description: "Test if a property exists"},
|
||||
{type: "Properties", name: "${__property}", description: "read a property"},
|
||||
{type: "Properties", name: "${__P}", description: "read a property (shorthand method)"},
|
||||
{type: "Properties", name: "${__setProperty}", description: "set a JMeter property"},
|
||||
{type: "Variables", name: "${__split}", description: "Split a string into variables"},
|
||||
{type: "Variables", name: "${__eval}", description: "evaluate a variable expression"},
|
||||
{type: "Variables", name: "${__evalVar}", description: "evaluate an expression stored in a variable"},
|
||||
{type: "Properties", name: "${__isVarDefined}", description: "Test if a variable exists"},
|
||||
{type: "Variables", name: "${__V}", description: "evaluate a variable name"},
|
||||
{type: "String", name: "${__char}", description: "generate Unicode char values from a list of numbers"},
|
||||
{type: "String", name: "${__changeCase}", description: "Change case following different modes"},
|
||||
{type: "String", name: "${__escapeHtml}", description: "Encode strings using HTML encoding"},
|
||||
{type: "String", name: "${__escapeOroRegexpChars}", description: "quote meta chars used by ORO regular expression"},
|
||||
{type: "String", name: "${__escapeXml}", description: "Encode strings using XMl encoding"},
|
||||
{type: "String", name: "${__regexFunction}", description: "parse previous response using a regular expression"},
|
||||
{type: "String", name: "${__unescape}", description: "Process strings containing Java escapes (e.g. \n & \t)"},
|
||||
{type: "String", name: "${__unescapeHtml}", description: "Decode HTML-encoded strings"},
|
||||
{type: "String", name: "${__urldecode}", description: "Decode a application/x-www-form-urlencoded string"},
|
||||
{
|
||||
type: "String",
|
||||
name: "${__urlencode}",
|
||||
description: "Encode a string to a application/x-www-form-urlencoded string"
|
||||
},
|
||||
{type: "String", name: "${__TestPlanName}", description: "Return name of current test plan"},
|
||||
]
|
||||
|
||||
export const ORIGIN_COLOR = '#783887';
|
||||
|
@ -207,164 +223,341 @@ export const COUNT_NUMBER_SHALLOW = '#CDB9D2';
|
|||
export const PRIMARY_COLOR = '#783887';
|
||||
|
||||
export const CONFIG_TYPE = {
|
||||
NOT: "NOT",
|
||||
NORMAL: "NORMAL",
|
||||
ABNORMAL: "ABNORMAL"
|
||||
NOT: "NOT",
|
||||
NORMAL: "NORMAL",
|
||||
ABNORMAL: "ABNORMAL"
|
||||
}
|
||||
|
||||
export const WORKSTATION={
|
||||
UPCOMING:"upcoming",
|
||||
FOCUS:"focus",
|
||||
NODE:"node"
|
||||
export const WORKSTATION = {
|
||||
UPCOMING: "upcoming",
|
||||
FOCUS: "focus",
|
||||
NODE: "node"
|
||||
}
|
||||
|
||||
export const ENV_TYPE = {
|
||||
JSON: "JSON",
|
||||
GROUP: "GROUP"
|
||||
DEFAULT: "DEFAULT",
|
||||
JSON: "JSON",
|
||||
GROUP: "GROUP"
|
||||
}
|
||||
|
||||
export const DEFAULT_XSS_ATTR = ['style', 'class'];
|
||||
|
||||
export const SECOND_LEVEL_ROUTE_PERMISSION_MAP = {
|
||||
API: [
|
||||
{router: '/api/home', permission: ['PROJECT_API_HOME:READ']},
|
||||
{router: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ']},
|
||||
{router: '/api/automation', permission: ['PROJECT_API_SCENARIO:READ']},
|
||||
{router: '/api/automation/report', permission: ['PROJECT_API_REPORT:READ']},
|
||||
],
|
||||
TRACK: [
|
||||
{router: '/track/home', permission: ['PROJECT_TRACK_HOME:READ']},
|
||||
{router: '/track/case/all', permission: ['PROJECT_TRACK_CASE:READ']},
|
||||
{router: '/track/review/all', permission: ['PROJECT_TRACK_REVIEW:READ']},
|
||||
{router: '/track/plan/all', permission: ['PROJECT_TRACK_PLAN:READ']},
|
||||
{router: '/track/issue', permission: ['PROJECT_TRACK_ISSUE:READ']},
|
||||
{router: '/track/testPlan/reportList', permission: ['PROJECT_TRACK_REPORT:READ']},
|
||||
],
|
||||
LOAD: [
|
||||
{router: '/performance/home', permission: ['PROJECT_PERFORMANCE_HOME:READ']},
|
||||
{router: '/performance/test/all', permission: ['PROJECT_PERFORMANCE_TEST:READ']},
|
||||
{router: '/performance/report/all', permission: ['PROJECT_PERFORMANCE_REPORT:READ']},
|
||||
],
|
||||
UI: [
|
||||
{router: '/ui/automation', permission: ['PROJECT_UI_SCENARIO:READ']},
|
||||
{router: '/ui/element', permission: ['PROJECT_UI_ELEMENT:READ']},
|
||||
{router: '/ui/report', permission: ['PROJECT_UI_REPORT:READ']},
|
||||
],
|
||||
REPORT: [
|
||||
{router: '/report/projectStatistics', permission: ['PROJECT_REPORT_ANALYSIS:READ']},
|
||||
{
|
||||
router: '/report/projectReport',
|
||||
permission: [
|
||||
'PROJECT_ENTERPRISE_REPORT:READ+EXPORT', 'PROJECT_ENTERPRISE_REPORT:READ+CREATE',
|
||||
'PROJECT_ENTERPRISE_REPORT:READ+DELETE', 'PROJECT_ENTERPRISE_REPORT:READ+COPY',
|
||||
'PROJECT_ENTERPRISE_REPORT:READ+SCHEDULE', 'PROJECT_ENTERPRISE_REPORT:READ+EDIT'
|
||||
]
|
||||
}
|
||||
]
|
||||
API: [
|
||||
{router: '/api/home', permission: ['PROJECT_API_HOME:READ']},
|
||||
{router: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ']},
|
||||
{router: '/api/automation', permission: ['PROJECT_API_SCENARIO:READ']},
|
||||
{router: '/api/automation/report', permission: ['PROJECT_API_REPORT:READ']},
|
||||
],
|
||||
TRACK: [
|
||||
{router: '/track/home', permission: ['PROJECT_TRACK_HOME:READ']},
|
||||
{router: '/track/case/all', permission: ['PROJECT_TRACK_CASE:READ']},
|
||||
{router: '/track/review/all', permission: ['PROJECT_TRACK_REVIEW:READ']},
|
||||
{router: '/track/plan/all', permission: ['PROJECT_TRACK_PLAN:READ']},
|
||||
{router: '/track/issue', permission: ['PROJECT_TRACK_ISSUE:READ']},
|
||||
{router: '/track/testPlan/reportList', permission: ['PROJECT_TRACK_REPORT:READ']},
|
||||
],
|
||||
LOAD: [
|
||||
{router: '/performance/home', permission: ['PROJECT_PERFORMANCE_HOME:READ']},
|
||||
{router: '/performance/test/all', permission: ['PROJECT_PERFORMANCE_TEST:READ']},
|
||||
{router: '/performance/report/all', permission: ['PROJECT_PERFORMANCE_REPORT:READ']},
|
||||
],
|
||||
UI: [
|
||||
{router: '/ui/automation', permission: ['PROJECT_UI_SCENARIO:READ']},
|
||||
{router: '/ui/element', permission: ['PROJECT_UI_ELEMENT:READ']},
|
||||
{router: '/ui/report', permission: ['PROJECT_UI_REPORT:READ']},
|
||||
],
|
||||
REPORT: [
|
||||
{router: '/report/projectStatistics', permission: ['PROJECT_REPORT_ANALYSIS:READ']},
|
||||
{
|
||||
router: '/report/projectReport',
|
||||
permission: [
|
||||
'PROJECT_ENTERPRISE_REPORT:READ+EXPORT', 'PROJECT_ENTERPRISE_REPORT:READ+CREATE',
|
||||
'PROJECT_ENTERPRISE_REPORT:READ+DELETE', 'PROJECT_ENTERPRISE_REPORT:READ+COPY',
|
||||
'PROJECT_ENTERPRISE_REPORT:READ+SCHEDULE', 'PROJECT_ENTERPRISE_REPORT:READ+EDIT'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const TASK_PATH = [
|
||||
"/test/case/add",
|
||||
"/test/case/review/save",
|
||||
"/test/case/comment/save",
|
||||
"/test/plan/add",
|
||||
"/test/plan/relevance",
|
||||
"issues/add",
|
||||
"test/case/issues/relate",
|
||||
"/api/definition/create",
|
||||
"/api/definition/run/debug",
|
||||
"/api/testcase/create",
|
||||
"/share/generate/api/document",
|
||||
"/api/definition/import",
|
||||
"/api/automation/create",
|
||||
"/api/automation/schedule/create",
|
||||
"/performance/save",
|
||||
"/share/generate/expired",
|
||||
"/project/add",
|
||||
"/project/member/add",
|
||||
"/setting/user/project/member/add",
|
||||
"/environment/add",
|
||||
"/ui/element/add",
|
||||
"/ui/automation/create",
|
||||
"/ui/automation/run/debug",
|
||||
"/test/case/add",
|
||||
"/test/case/review/save",
|
||||
"/test/case/comment/save",
|
||||
"/test/plan/add",
|
||||
"/test/plan/relevance",
|
||||
"issues/add",
|
||||
"test/case/issues/relate",
|
||||
"/api/definition/create",
|
||||
"/api/definition/run/debug",
|
||||
"/api/testcase/create",
|
||||
"/share/generate/api/document",
|
||||
"/api/definition/import",
|
||||
"/api/automation/create",
|
||||
"/api/automation/schedule/create",
|
||||
"/performance/save",
|
||||
"/share/generate/expired",
|
||||
"/project/add",
|
||||
"/project/member/add",
|
||||
"/setting/user/project/member/add",
|
||||
"/environment/add",
|
||||
"/ui/element/add",
|
||||
"/ui/automation/create",
|
||||
"/ui/automation/run/debug",
|
||||
];
|
||||
|
||||
export const TASK_DATA = [
|
||||
{
|
||||
id: 1,
|
||||
name: "track",
|
||||
title: "side_task.test_tracking.title",
|
||||
percentage: 14,
|
||||
permission: ['PROJECT_MANAGER:READ', 'WORKSPACE_PROJECT_MANAGER:READ','PROJECT_TRACK_CASE:READ+CREATE','PROJECT_TRACK_REVIEW:READ+CREATE','PROJECT_TRACK_REVIEW:READ+COMMENT','PROJECT_TRACK_PLAN:READ+CREATE','PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL','PROJECT_TRACK_ISSUE:READ+CREATE','PROJECT_TRACK_CASE:READ+BATCH_ADD_PUBLIC'],
|
||||
taskData: [
|
||||
{ id: 1, name: "side_task.test_tracking.task_1", status: 1, permission: ['PROJECT_MANAGER:READ', 'WORKSPACE_PROJECT_MANAGER:READ'], api: [''], path: '/setting/project/:type', url: "" },
|
||||
{ id: 2, name: "side_task.test_tracking.task_2", status: 0, permission: ['PROJECT_TRACK_CASE:READ+CREATE'], api: ["/test/case/add"], path: '/track/case/all', url: "/assets/guide/track/task-2.gif" },
|
||||
{ id: 3, name: "side_task.test_tracking.task_3", status: 0, permission: ['PROJECT_TRACK_REVIEW:READ+CREATE'], api: ["/test/case/review/save"], path: '/track/review/all', url: "/assets/guide/track/task-3.gif" },
|
||||
{ id: 4, name: "side_task.test_tracking.task_4", status: 0, permission: ['PROJECT_TRACK_REVIEW:READ+COMMENT'], api: ["/test/case/comment/save"], path: '/track/review/all', url: "/assets/guide/track/task-4.gif" },
|
||||
{ id: 5, name: "side_task.test_tracking.task_5", status: 0, permission: ['PROJECT_TRACK_PLAN:READ+CREATE'], api: ["/test/plan/add"], path: '/track/plan/all', url: "/assets/guide/track/task-5.gif" },
|
||||
{ id: 6, name: "side_task.test_tracking.task_6", status: 0, permission: ['PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL'], api: ["/test/plan/relevance"], path: '/track/plan/all', url: "/assets/guide/track/task-6.gif" },
|
||||
{ id: 7, name: "side_task.test_tracking.task_7", status: 0, permission: ['PROJECT_TRACK_ISSUE:READ+CREATE','PROJECT_TRACK_CASE:READ+BATCH_ADD_PUBLIC'], api: ["issues/add","test/case/issues/relate"], path: '/track/issue', url: "/assets/guide/track/task-7.gif" },
|
||||
],
|
||||
rate: 1,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "api",
|
||||
title: 'side_task.api_test.title',
|
||||
percentage: 0,
|
||||
permission: ['PROJECT_API_DEFINITION:READ+CREATE_API','PROJECT_API_DEFINITION:READ+IMPORT_API','PROJECT_API_DEFINITION:READ+DEBUG','PROJECT_API_DEFINITION:READ+CREATE_CASE','PROJECT_API_DEFINITION:READ','PROJECT_API_SCENARIO:READ+CREATE','PROJECT_API_SCENARIO:READ+SCHEDULE'],
|
||||
taskData: [
|
||||
{id: 1, name: "side_task.api_test.task_1", status: 0, path: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ+CREATE_API'], api: ["/api/definition/create"], url: "/assets/guide/api/task-1.gif" },
|
||||
{id: 2, name: "side_task.api_test.task_2", status: 0, path: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ+IMPORT_API'], api: ["/api/definition/import"], url: "/assets/guide/api/task-2.gif" },
|
||||
{id: 3, name: "side_task.api_test.task_3", status: 0, path: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ+DEBUG'], api: ["/api/definition/run/debug"], url: "/assets/guide/api/task-3.gif" },
|
||||
{id: 4, name: "side_task.api_test.task_4", status: 0, path: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ+CREATE_CASE'], api: ["/api/testcase/create"], url: "/assets/guide/api/task-4.gif" },
|
||||
{id: 5, name: "side_task.api_test.task_5", status: 0, path: '/api/definition', permission: ['PROJECT_API_DEFINITION:READ'], api: ["/share/generate/api/document"], url: "/assets/guide/api/task-5.gif" },
|
||||
{id: 6, name: "side_task.api_test.task_6", status: 0, path: '/api/automation', permission: ['PROJECT_API_SCENARIO:READ+CREATE'], api: ["/api/automation/create"], url: "/assets/guide/api/task-6.gif" },
|
||||
{id: 7, name: "side_task.api_test.task_7", status: 0, path: '/api/automation', permission: ['PROJECT_API_SCENARIO:READ+SCHEDULE'], api: ["/api/automation/schedule/create"], url: "/assets/guide/api/task-7.gif" },
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "performance",
|
||||
title: 'side_task.performance_test.title',
|
||||
percentage: 0,
|
||||
permission: ['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE',"PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE_BATCH",'PROJECT_PERFORMANCE_REPORT:READ'],
|
||||
taskData: [
|
||||
{id: 1, name: 'side_task.performance_test.task_1', status: 0, path: '/performance/test/all', permission: ['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE',"PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE_BATCH"], api: ["/performance/save"], url: "/assets/guide/performance/task-1.gif" },
|
||||
{id: 2, name: 'side_task.performance_test.task_2', status: 0, path: '/performance/report/all', permission: ['PROJECT_PERFORMANCE_REPORT:READ'], api: ["/share/generate/expired"], url: "/assets/guide/performance/task-2.gif" },
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "project",
|
||||
title: 'side_task.project_setting.title',
|
||||
percentage: 0,
|
||||
permission: ['WORKSPACE_PROJECT_MANAGER:READ+CREATE','PROJECT_USER:READ+CREATE','PROJECT_ENVIRONMENT:READ+CREATE'],
|
||||
taskData: [
|
||||
{id: 1, name: 'side_task.project_setting.task_1', status: 0, permission: ['WORKSPACE_PROJECT_MANAGER:READ+CREATE'], api: ["/project/add"], path: '/setting/project/:type', url: "/assets/guide/project/task-1.gif" },
|
||||
{id: 2, name: 'side_task.project_setting.task_2', status: 0, permission: ['PROJECT_USER:READ+CREATE'], api: ["/project/member/add","/setting/user/project/member/add"], path: '/project/member', url: "/assets/guide/project/task-2.gif" },
|
||||
{id: 3, name: 'side_task.project_setting.task_3', status: 0, permission: ['PROJECT_ENVIRONMENT:READ+CREATE'], api: ["/environment/add"], path: '/project/env', url: "/assets/guide/project/task-3.gif" },
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "ui",
|
||||
title: 'side_task.ui_test.title',
|
||||
percentage: 0,
|
||||
permission: ['PROJECT_UI_ELEMENT:READ+CREATE','PROJECT_UI_SCENARIO:READ+CREATE','PROJECT_UI_SCENARIO:READ+RUN','PROJECT_UI_SCENARIO:READ+DEBUG'],
|
||||
taskData: [
|
||||
{id: 1, name: 'side_task.ui_test.task_1', status: 0, permission: ['PROJECT_UI_ELEMENT:READ+CREATE'], api: ["/ui/element/add"], path: '/ui/element', url: "/assets/guide/ui/task-1.gif" },
|
||||
{id: 2, name: 'side_task.ui_test.task_2', status: 0, permission: ['PROJECT_UI_SCENARIO:READ+CREATE'], api: ["/ui/automation/create"], path: '/ui/automation', url: "/assets/guide/ui/task-2.gif" },
|
||||
{id: 2, name: 'side_task.ui_test.task_3', status: 0, permission: ['PROJECT_UI_SCENARIO:READ+RUN','PROJECT_UI_SCENARIO:READ+DEBUG'], api: ["/ui/automation/run/debug"], path: '/ui/automation', url: "/assets/guide/ui/task-3.gif" },
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "track",
|
||||
title: "side_task.test_tracking.title",
|
||||
percentage: 14,
|
||||
permission: ['PROJECT_MANAGER:READ', 'WORKSPACE_PROJECT_MANAGER:READ', 'PROJECT_TRACK_CASE:READ+CREATE', 'PROJECT_TRACK_REVIEW:READ+CREATE', 'PROJECT_TRACK_REVIEW:READ+COMMENT', 'PROJECT_TRACK_PLAN:READ+CREATE', 'PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL', 'PROJECT_TRACK_ISSUE:READ+CREATE', 'PROJECT_TRACK_CASE:READ+BATCH_ADD_PUBLIC'],
|
||||
taskData: [
|
||||
{
|
||||
id: 1,
|
||||
name: "side_task.test_tracking.task_1",
|
||||
status: 1,
|
||||
permission: ['PROJECT_MANAGER:READ', 'WORKSPACE_PROJECT_MANAGER:READ'],
|
||||
api: [''],
|
||||
path: '/setting/project/:type',
|
||||
url: ""
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "side_task.test_tracking.task_2",
|
||||
status: 0,
|
||||
permission: ['PROJECT_TRACK_CASE:READ+CREATE'],
|
||||
api: ["/test/case/add"],
|
||||
path: '/track/case/all',
|
||||
url: "/assets/guide/track/task-2.gif"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "side_task.test_tracking.task_3",
|
||||
status: 0,
|
||||
permission: ['PROJECT_TRACK_REVIEW:READ+CREATE'],
|
||||
api: ["/test/case/review/save"],
|
||||
path: '/track/review/all',
|
||||
url: "/assets/guide/track/task-3.gif"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "side_task.test_tracking.task_4",
|
||||
status: 0,
|
||||
permission: ['PROJECT_TRACK_REVIEW:READ+COMMENT'],
|
||||
api: ["/test/case/comment/save"],
|
||||
path: '/track/review/all',
|
||||
url: "/assets/guide/track/task-4.gif"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "side_task.test_tracking.task_5",
|
||||
status: 0,
|
||||
permission: ['PROJECT_TRACK_PLAN:READ+CREATE'],
|
||||
api: ["/test/plan/add"],
|
||||
path: '/track/plan/all',
|
||||
url: "/assets/guide/track/task-5.gif"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "side_task.test_tracking.task_6",
|
||||
status: 0,
|
||||
permission: ['PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL'],
|
||||
api: ["/test/plan/relevance"],
|
||||
path: '/track/plan/all',
|
||||
url: "/assets/guide/track/task-6.gif"
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "side_task.test_tracking.task_7",
|
||||
status: 0,
|
||||
permission: ['PROJECT_TRACK_ISSUE:READ+CREATE', 'PROJECT_TRACK_CASE:READ+BATCH_ADD_PUBLIC'],
|
||||
api: ["issues/add", "test/case/issues/relate"],
|
||||
path: '/track/issue',
|
||||
url: "/assets/guide/track/task-7.gif"
|
||||
},
|
||||
],
|
||||
rate: 1,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "api",
|
||||
title: 'side_task.api_test.title',
|
||||
percentage: 0,
|
||||
permission: ['PROJECT_API_DEFINITION:READ+CREATE_API', 'PROJECT_API_DEFINITION:READ+IMPORT_API', 'PROJECT_API_DEFINITION:READ+DEBUG', 'PROJECT_API_DEFINITION:READ+CREATE_CASE', 'PROJECT_API_DEFINITION:READ', 'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+SCHEDULE'],
|
||||
taskData: [
|
||||
{
|
||||
id: 1,
|
||||
name: "side_task.api_test.task_1",
|
||||
status: 0,
|
||||
path: '/api/definition',
|
||||
permission: ['PROJECT_API_DEFINITION:READ+CREATE_API'],
|
||||
api: ["/api/definition/create"],
|
||||
url: "/assets/guide/api/task-1.gif"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "side_task.api_test.task_2",
|
||||
status: 0,
|
||||
path: '/api/definition',
|
||||
permission: ['PROJECT_API_DEFINITION:READ+IMPORT_API'],
|
||||
api: ["/api/definition/import"],
|
||||
url: "/assets/guide/api/task-2.gif"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "side_task.api_test.task_3",
|
||||
status: 0,
|
||||
path: '/api/definition',
|
||||
permission: ['PROJECT_API_DEFINITION:READ+DEBUG'],
|
||||
api: ["/api/definition/run/debug"],
|
||||
url: "/assets/guide/api/task-3.gif"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "side_task.api_test.task_4",
|
||||
status: 0,
|
||||
path: '/api/definition',
|
||||
permission: ['PROJECT_API_DEFINITION:READ+CREATE_CASE'],
|
||||
api: ["/api/testcase/create"],
|
||||
url: "/assets/guide/api/task-4.gif"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "side_task.api_test.task_5",
|
||||
status: 0,
|
||||
path: '/api/definition',
|
||||
permission: ['PROJECT_API_DEFINITION:READ'],
|
||||
api: ["/share/generate/api/document"],
|
||||
url: "/assets/guide/api/task-5.gif"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "side_task.api_test.task_6",
|
||||
status: 0,
|
||||
path: '/api/automation',
|
||||
permission: ['PROJECT_API_SCENARIO:READ+CREATE'],
|
||||
api: ["/api/automation/create"],
|
||||
url: "/assets/guide/api/task-6.gif"
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "side_task.api_test.task_7",
|
||||
status: 0,
|
||||
path: '/api/automation',
|
||||
permission: ['PROJECT_API_SCENARIO:READ+SCHEDULE'],
|
||||
api: ["/api/automation/schedule/create"],
|
||||
url: "/assets/guide/api/task-7.gif"
|
||||
},
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "performance",
|
||||
title: 'side_task.performance_test.title',
|
||||
percentage: 0,
|
||||
permission: ['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE', "PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE_BATCH", 'PROJECT_PERFORMANCE_REPORT:READ'],
|
||||
taskData: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'side_task.performance_test.task_1',
|
||||
status: 0,
|
||||
path: '/performance/test/all',
|
||||
permission: ['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE', "PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE_BATCH"],
|
||||
api: ["/performance/save"],
|
||||
url: "/assets/guide/performance/task-1.gif"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'side_task.performance_test.task_2',
|
||||
status: 0,
|
||||
path: '/performance/report/all',
|
||||
permission: ['PROJECT_PERFORMANCE_REPORT:READ'],
|
||||
api: ["/share/generate/expired"],
|
||||
url: "/assets/guide/performance/task-2.gif"
|
||||
},
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "project",
|
||||
title: 'side_task.project_setting.title',
|
||||
percentage: 0,
|
||||
permission: ['WORKSPACE_PROJECT_MANAGER:READ+CREATE', 'PROJECT_USER:READ+CREATE', 'PROJECT_ENVIRONMENT:READ+CREATE'],
|
||||
taskData: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'side_task.project_setting.task_1',
|
||||
status: 0,
|
||||
permission: ['WORKSPACE_PROJECT_MANAGER:READ+CREATE'],
|
||||
api: ["/project/add"],
|
||||
path: '/setting/project/:type',
|
||||
url: "/assets/guide/project/task-1.gif"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'side_task.project_setting.task_2',
|
||||
status: 0,
|
||||
permission: ['PROJECT_USER:READ+CREATE'],
|
||||
api: ["/project/member/add", "/setting/user/project/member/add"],
|
||||
path: '/project/member',
|
||||
url: "/assets/guide/project/task-2.gif"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'side_task.project_setting.task_3',
|
||||
status: 0,
|
||||
permission: ['PROJECT_ENVIRONMENT:READ+CREATE'],
|
||||
api: ["/environment/add"],
|
||||
path: '/project/env',
|
||||
url: "/assets/guide/project/task-3.gif"
|
||||
},
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "ui",
|
||||
title: 'side_task.ui_test.title',
|
||||
percentage: 0,
|
||||
permission: ['PROJECT_UI_ELEMENT:READ+CREATE', 'PROJECT_UI_SCENARIO:READ+CREATE', 'PROJECT_UI_SCENARIO:READ+RUN', 'PROJECT_UI_SCENARIO:READ+DEBUG'],
|
||||
taskData: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'side_task.ui_test.task_1',
|
||||
status: 0,
|
||||
permission: ['PROJECT_UI_ELEMENT:READ+CREATE'],
|
||||
api: ["/ui/element/add"],
|
||||
path: '/ui/element',
|
||||
url: "/assets/guide/ui/task-1.gif"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'side_task.ui_test.task_2',
|
||||
status: 0,
|
||||
permission: ['PROJECT_UI_SCENARIO:READ+CREATE'],
|
||||
api: ["/ui/automation/create"],
|
||||
path: '/ui/automation',
|
||||
url: "/assets/guide/ui/task-2.gif"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'side_task.ui_test.task_3',
|
||||
status: 0,
|
||||
permission: ['PROJECT_UI_SCENARIO:READ+RUN', 'PROJECT_UI_SCENARIO:READ+DEBUG'],
|
||||
api: ["/ui/automation/run/debug"],
|
||||
path: '/ui/automation',
|
||||
url: "/assets/guide/ui/task-3.gif"
|
||||
},
|
||||
],
|
||||
rate: 0,
|
||||
status: 0
|
||||
},
|
||||
]
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum TestPlanExecuteCaseType {
|
||||
API_CASE, SCENARIO, UI_SCENARIO, LOAD_CASE
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.core.script.RedisScript;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class RedisTemplateService {
|
||||
public static final long TIME_OUT = 480;
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public boolean setIfAbsent(String key, String value) {
|
||||
try {
|
||||
return redisTemplate.opsForValue().setIfAbsent(key, value);
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error(key, e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
try {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error(key, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean delete(String key) {
|
||||
try {
|
||||
return redisTemplate.delete(key);
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error(key, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加锁
|
||||
*/
|
||||
public boolean lock(String testPlanReportId, String key, String value) {
|
||||
Boolean hasReport = redisTemplate.opsForValue().setIfAbsent(
|
||||
StringUtils.join(testPlanReportId, key),
|
||||
value,
|
||||
TIME_OUT,
|
||||
TimeUnit.MINUTES);
|
||||
if (Boolean.FALSE.equals(hasReport)) {
|
||||
redisTemplate.opsForValue().setIfPresent(
|
||||
StringUtils.join(testPlanReportId, key),
|
||||
value,
|
||||
TIME_OUT,
|
||||
TimeUnit.MINUTES);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean has(String testPlanReportId, String key, String reportId) {
|
||||
try {
|
||||
Object value = redisTemplate.opsForValue().get(StringUtils.join(testPlanReportId, key));
|
||||
return ObjectUtils.isNotEmpty(value) && StringUtils.equals(reportId, String.valueOf(value));
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁
|
||||
*/
|
||||
public boolean unlock(String testPlanReportId, String key, String value) {
|
||||
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
|
||||
Long result = redisTemplate.execute(redisScript, Collections.singletonList(StringUtils.join(testPlanReportId, key)), value);
|
||||
if (Objects.equals(1L, result)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import io.metersphere.base.mapper.ApiExecutionQueueMapper;
|
|||
import io.metersphere.base.mapper.TestPlanLoadCaseMapper;
|
||||
import io.metersphere.base.mapper.ext.BaseApiExecutionQueueMapper;
|
||||
import io.metersphere.commons.constants.KafkaTopicConstants;
|
||||
import io.metersphere.commons.constants.TestPlanExecuteCaseType;
|
||||
import io.metersphere.commons.constants.TestPlanLoadCaseStatus;
|
||||
import io.metersphere.commons.constants.TriggerMode;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
|
@ -14,6 +15,7 @@ import io.metersphere.constants.RunModeConstants;
|
|||
import io.metersphere.dto.RunModeConfigDTO;
|
||||
import io.metersphere.plan.exec.queue.DBTestQueue;
|
||||
import io.metersphere.request.RunTestPlanRequest;
|
||||
import io.metersphere.service.RedisTemplateService;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
@ -175,13 +177,16 @@ public class PerfQueueService {
|
|||
return queue;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public DBTestQueue add(Object runObj, String poolId, String reportId, String reportType, String runMode, RunModeConfigDTO config) {
|
||||
LoggerUtil.info("报告【" + reportId + "】开始生成执行链");
|
||||
public DBTestQueue add(Object runObj, String poolId, String testPlanReportId, String reportType, String runMode, RunModeConfigDTO config) {
|
||||
LoggerUtil.info("报告【" + testPlanReportId + "】开始生成执行链");
|
||||
if (config.getEnvMap() == null) {
|
||||
config.setEnvMap(new LinkedHashMap<>());
|
||||
}
|
||||
ApiExecutionQueue executionQueue = getApiExecutionQueue(poolId, reportId, reportType, runMode, config);
|
||||
ApiExecutionQueue executionQueue = getApiExecutionQueue(poolId, testPlanReportId, reportType, runMode, config);
|
||||
queueMapper.insert(executionQueue);
|
||||
DBTestQueue resQueue = new DBTestQueue();
|
||||
BeanUtils.copyBean(resQueue, executionQueue);
|
||||
|
@ -196,7 +201,9 @@ public class PerfQueueService {
|
|||
extApiExecutionQueueMapper.sqlInsert(queueDetails);
|
||||
}
|
||||
resQueue.setDetailMap(detailMap);
|
||||
LoggerUtil.info("报告【" + reportId + "】生成执行链结束");
|
||||
LoggerUtil.info("报告【" + testPlanReportId + "】生成执行链结束");
|
||||
//移除Redis中的标志
|
||||
redisTemplateService.unlock(testPlanReportId, TestPlanExecuteCaseType.LOAD_CASE.name(), testPlanReportId);
|
||||
return resQueue;
|
||||
}
|
||||
|
||||
|
@ -207,7 +214,7 @@ public class PerfQueueService {
|
|||
executionQueue.setPoolId(poolId);
|
||||
executionQueue.setFailure(config.isOnSampleError());
|
||||
executionQueue.setReportId(reportId);
|
||||
executionQueue.setReportType(StringUtils.isNotEmpty(reportType) ? reportType : RunModeConstants.INDEPENDENCE.toString());
|
||||
executionQueue.setReportType(TestPlanExecuteCaseType.LOAD_CASE.name());
|
||||
executionQueue.setRunMode(runMode);
|
||||
return executionQueue;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.base.mapper.ApiExecutionQueueMapper;
|
|||
import io.metersphere.commons.constants.KafkaTopicConstants;
|
||||
import io.metersphere.plan.service.AutomationCaseExecOverService;
|
||||
import io.metersphere.plan.service.TestPlanReportService;
|
||||
import io.metersphere.service.RedisTemplateService;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import io.metersphere.utils.NamedThreadFactory;
|
||||
import jakarta.annotation.Resource;
|
||||
|
@ -28,6 +29,8 @@ public class ExecReportListener {
|
|||
@Resource
|
||||
private TestPlanReportService testPlanReportService;
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
@Resource
|
||||
private AutomationCaseExecOverService automationCaseExecOverService;
|
||||
|
||||
// 线程池维护线程的最少数量
|
||||
|
@ -57,6 +60,7 @@ public class ExecReportListener {
|
|||
task.setApiExecutionQueueDetailMapper(executionQueueDetailMapper);
|
||||
task.setAutomationCaseExecOverService(automationCaseExecOverService);
|
||||
task.setTestPlanReportService(testPlanReportService);
|
||||
task.setRedisTemplateService(redisTemplateService);
|
||||
task.setRecord(item);
|
||||
threadPool.execute(task);
|
||||
});
|
||||
|
|
|
@ -5,14 +5,16 @@ import io.metersphere.base.domain.ApiExecutionQueueDetailExample;
|
|||
import io.metersphere.base.domain.ApiExecutionQueueExample;
|
||||
import io.metersphere.base.mapper.ApiExecutionQueueDetailMapper;
|
||||
import io.metersphere.base.mapper.ApiExecutionQueueMapper;
|
||||
import io.metersphere.commons.constants.TestPlanExecuteCaseType;
|
||||
import io.metersphere.commons.constants.TestPlanReportStatus;
|
||||
import io.metersphere.plan.service.AutomationCaseExecOverService;
|
||||
import io.metersphere.plan.service.TestPlanReportService;
|
||||
import io.metersphere.service.RedisTemplateService;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -25,7 +27,7 @@ public class ExecReportListenerTask implements Runnable {
|
|||
private ApiExecutionQueueDetailMapper apiExecutionQueueDetailMapper;
|
||||
private TestPlanReportService testPlanReportService;
|
||||
private AutomationCaseExecOverService automationCaseExecOverService;
|
||||
|
||||
private RedisTemplateService redisTemplateService;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -50,15 +52,15 @@ public class ExecReportListenerTask implements Runnable {
|
|||
ApiExecutionQueueExample executionQueueExample = new ApiExecutionQueueExample();
|
||||
executionQueueExample.createCriteria().andReportIdEqualTo(testPlanReportId);
|
||||
List<ApiExecutionQueue> queues = apiExecutionQueueMapper.selectByExample(executionQueueExample);
|
||||
if (CollectionUtils.isEmpty(queues)) {
|
||||
if (CollectionUtils.isEmpty(queues) && this.isTestPlanIsEmptyInRedis(testPlanReportId)) {
|
||||
LoggerUtil.info("Normal execution completes, update test plan report status:" + testPlanReportId);
|
||||
testPlanReportService.testPlanExecuteOver(testPlanReportId, TestPlanReportStatus.COMPLETED.name());
|
||||
} else {
|
||||
} else if (CollectionUtils.isNotEmpty(queues)) {
|
||||
List<String> ids = queues.stream().map(ApiExecutionQueue::getId).collect(Collectors.toList());
|
||||
ApiExecutionQueueDetailExample detailExample = new ApiExecutionQueueDetailExample();
|
||||
detailExample.createCriteria().andQueueIdIn(ids);
|
||||
long count = apiExecutionQueueDetailMapper.countByExample(detailExample);
|
||||
if (count == 0) {
|
||||
if (count == 0 && this.isTestPlanIsEmptyInRedis(testPlanReportId)) {
|
||||
LoggerUtil.info("Normal execution completes, update test plan report status:" + testPlanReportId);
|
||||
testPlanReportService.testPlanExecuteOver(testPlanReportId, TestPlanReportStatus.COMPLETED.name());
|
||||
LoggerUtil.info("Clear Queue:" + ids);
|
||||
|
@ -68,4 +70,15 @@ public class ExecReportListenerTask implements Runnable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试计划执行时会将运行标志放入redis中。当测试计划执行队列入库后,会将redis中的标志清除。
|
||||
*/
|
||||
private boolean isTestPlanIsEmptyInRedis(String testPlanReportId) {
|
||||
Object scenarioObj = redisTemplateService.get(testPlanReportId + TestPlanExecuteCaseType.SCENARIO);
|
||||
Object apiCaseObj = redisTemplateService.get(testPlanReportId + TestPlanExecuteCaseType.API_CASE);
|
||||
Object uiObj = redisTemplateService.get(testPlanReportId + TestPlanExecuteCaseType.UI_SCENARIO);
|
||||
Object loadObj = redisTemplateService.get(testPlanReportId + TestPlanExecuteCaseType.LOAD_CASE);
|
||||
return ObjectUtils.isEmpty(scenarioObj) && ObjectUtils.isEmpty(apiCaseObj) && ObjectUtils.isEmpty(uiObj) && ObjectUtils.isEmpty(loadObj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,221 +0,0 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.base.domain.TestPlanWithBLOBs;
|
||||
import io.metersphere.base.mapper.TestPlanMapper;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.*;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.plan.dto.ExecutionWay;
|
||||
import io.metersphere.plan.request.api.TestPlanRunRequest;
|
||||
import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService;
|
||||
import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService;
|
||||
import io.metersphere.plan.service.remote.performance.PerfExecService;
|
||||
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
|
||||
import io.metersphere.plan.utils.TestPlanRequestUtil;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class TestPlanExecuteService {
|
||||
@Resource
|
||||
@Lazy
|
||||
private TestPlanService testPlanService;
|
||||
@Resource
|
||||
private TestPlanReportService testPlanReportService;
|
||||
@Resource
|
||||
private PlanTestPlanApiCaseService planTestPlanApiCaseService;
|
||||
@Resource
|
||||
private PlanTestPlanScenarioCaseService planTestPlanScenarioCaseService;
|
||||
@Resource
|
||||
private PerfExecService perfExecService;
|
||||
@Resource
|
||||
private PlanTestPlanUiScenarioCaseService planTestPlanUiScenarioCaseService;
|
||||
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
|
||||
/**
|
||||
* 执行测试计划流程是会调用其它服务的执行方法,并通过kafka传递信息给test-track服务来判断测试计划是否执行结束
|
||||
* 执行方法采用单独的事务控制,执行完了就提交,让测试报告以及包括执行内容的数据及时入库
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public String runTestPlan(String testPlanId, String projectId, String userId, String triggerMode, String planReportId, String executionWay, String apiRunConfig) {
|
||||
// 校验测试计划是否在执行中
|
||||
if (testPlanService.checkTestPlanIsRunning(testPlanId)) {
|
||||
LogUtil.info("当前测试计划正在执行中,请稍后再试", testPlanId);
|
||||
MSException.throwException(Translator.get("test_plan_run_message"));
|
||||
}
|
||||
RunModeConfigDTO runModeConfig = null;
|
||||
try {
|
||||
runModeConfig = JSON.parseObject(apiRunConfig, RunModeConfigDTO.class);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
if (runModeConfig == null) {
|
||||
runModeConfig = this.buildRunModeConfigDTO();
|
||||
}
|
||||
|
||||
//环境参数为空时,依据测试计划保存的环境执行
|
||||
if (((StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && StringUtils.isBlank(runModeConfig.getEnvironmentGroupId()))
|
||||
|| (!StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && MapUtils.isEmpty(runModeConfig.getEnvMap()) && MapUtils.isEmpty(runModeConfig.getTestPlanDefaultEnvMap())))
|
||||
&& !StringUtils.equals(executionWay, ExecutionWay.RUN.name())) {
|
||||
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
|
||||
if (StringUtils.isNotEmpty(testPlanWithBLOBs.getRunModeConfig())) {
|
||||
try {
|
||||
Map json = JSON.parseMap(testPlanWithBLOBs.getRunModeConfig());
|
||||
TestPlanRequestUtil.changeStringToBoolean(json);
|
||||
TestPlanRunRequest testPlanRunRequest = JSON.parseObject(JSON.toJSONString(json), TestPlanRunRequest.class);
|
||||
if (testPlanRunRequest != null) {
|
||||
String envType = testPlanRunRequest.getEnvironmentType();
|
||||
Map<String, String> envMap = testPlanRunRequest.getEnvMap();
|
||||
String environmentGroupId = testPlanRunRequest.getEnvironmentGroupId();
|
||||
runModeConfig = testPlanService.getRunModeConfigDTO(testPlanRunRequest, envType, envMap, environmentGroupId, testPlanId);
|
||||
runModeConfig.setTestPlanDefaultEnvMap(testPlanRunRequest.getTestPlanDefaultEnvMap());
|
||||
if (!testPlanRunRequest.isRunWithinResourcePool()) {
|
||||
runModeConfig.setResourcePoolId(null);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("获取测试计划保存的环境信息出错!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (planReportId == null) {
|
||||
planReportId = UUID.randomUUID().toString();
|
||||
}
|
||||
if (testPlanService.haveExecCase(testPlanId, true)) {
|
||||
testPlanService.verifyPool(projectId, runModeConfig);
|
||||
}
|
||||
//创建测试报告,然后返回的ID重新赋值为resourceID,作为后续的参数
|
||||
TestPlanScheduleReportInfoDTO reportInfoDTO = testPlanService.genTestPlanReport(planReportId, testPlanId, userId, triggerMode, runModeConfig);
|
||||
|
||||
LoggerUtil.info("预生成测试计划报告【" + reportInfoDTO.getTestPlanReport() != null ? reportInfoDTO.getTestPlanReport().getName() : StringUtils.EMPTY + "】计划报告ID[" + planReportId + "]");
|
||||
|
||||
List<TestPlanApiDTO> apiTestCases = null;
|
||||
List<TestPlanScenarioDTO> scenarioCases = null;
|
||||
List<TestPlanUiScenarioDTO> uiScenarios = null;
|
||||
Map<String, String> loadCaseReportMap = null;
|
||||
if (MapUtils.isNotEmpty(reportInfoDTO.getApiTestCaseDataMap())) {
|
||||
try {
|
||||
apiTestCases = planTestPlanApiCaseService.getFailureListByIds(reportInfoDTO.getApiTestCaseDataMap().keySet());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("测试计划执行查询接口用例失败!", e);
|
||||
}
|
||||
}
|
||||
if (MapUtils.isNotEmpty(reportInfoDTO.getPlanScenarioIdMap())) {
|
||||
try {
|
||||
scenarioCases = planTestPlanScenarioCaseService.getFailureListByIds(reportInfoDTO.getPlanScenarioIdMap().keySet());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("测试计划执行查询场景用例失败!", e);
|
||||
}
|
||||
}
|
||||
if (MapUtils.isNotEmpty(reportInfoDTO.getUiScenarioIdMap())) {
|
||||
try {
|
||||
uiScenarios = planTestPlanUiScenarioCaseService.getFailureListByIds(reportInfoDTO.getUiScenarioIdMap().keySet());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("测试计划执行查询UI用例失败!", e);
|
||||
}
|
||||
}
|
||||
boolean haveApiCaseExec = false, haveScenarioCaseExec = false, haveLoadCaseExec = false, haveUICaseExec = false;
|
||||
if (CollectionUtils.isNotEmpty(apiTestCases)) {
|
||||
//执行接口案例任务
|
||||
LoggerUtil.info("开始执行测试计划接口用例 " + planReportId);
|
||||
try {
|
||||
Map<String, String> apiCaseReportMap = testPlanService.executeApiTestCase(triggerMode, planReportId, userId, testPlanId, runModeConfig);
|
||||
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
|
||||
haveApiCaseExec = true;
|
||||
for (TestPlanApiDTO dto : apiTestCases) {
|
||||
dto.setReportId(apiCaseReportMap.get(dto.getId()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
apiTestCases = null;
|
||||
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划接口用例失败! ", e);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(scenarioCases)) {
|
||||
//执行场景执行任务
|
||||
LoggerUtil.info("开始执行测试计划场景用例 " + planReportId);
|
||||
try {
|
||||
Map<String, String> scenarioReportMap = testPlanService.executeScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
|
||||
if (MapUtils.isNotEmpty(scenarioReportMap)) {
|
||||
haveScenarioCaseExec = true;
|
||||
List<TestPlanScenarioDTO> removeDTO = new ArrayList<>();
|
||||
for (TestPlanScenarioDTO dto : scenarioCases) {
|
||||
if (scenarioReportMap.containsKey(dto.getId())) {
|
||||
dto.setReportId(scenarioReportMap.get(dto.getId()));
|
||||
} else {
|
||||
removeDTO.add(dto);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(removeDTO)) {
|
||||
scenarioCases.removeAll(removeDTO);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
scenarioCases = null;
|
||||
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划场景用例失败! ", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (MapUtils.isNotEmpty(reportInfoDTO.getPerformanceIdMap())) {
|
||||
//执行性能测试任务
|
||||
LoggerUtil.info("开始执行测试计划性能用例 " + planReportId);
|
||||
try {
|
||||
loadCaseReportMap = perfExecService.executeLoadCase(planReportId, runModeConfig, testPlanService.transformationPerfTriggerMode(triggerMode), reportInfoDTO.getPerformanceIdMap());
|
||||
if (MapUtils.isNotEmpty(loadCaseReportMap)) {
|
||||
haveLoadCaseExec = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划性能用例失败! ", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(uiScenarios)) {
|
||||
//执行UI场景执行任务
|
||||
LoggerUtil.info("开始执行测试计划 UI 场景用例 " + planReportId);
|
||||
try {
|
||||
Map<String, String> uiScenarioReportMap = testPlanService.executeUiScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getUiScenarioIdMap());
|
||||
if (MapUtils.isNotEmpty(uiScenarioReportMap)) {
|
||||
haveUICaseExec = true;
|
||||
for (TestPlanUiScenarioDTO dto : uiScenarios) {
|
||||
dto.setReportId(uiScenarioReportMap.get(dto.getId()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
uiScenarios = null;
|
||||
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划 UI 用例失败! ", e);
|
||||
}
|
||||
}
|
||||
|
||||
LoggerUtil.info("开始生成测试计划报告内容 " + planReportId);
|
||||
testPlanReportService.createTestPlanReportContentReportIds(planReportId, apiTestCases, scenarioCases, uiScenarios, loadCaseReportMap);
|
||||
if (!haveApiCaseExec && !haveScenarioCaseExec && !haveLoadCaseExec && !haveUICaseExec) {
|
||||
//如果没有执行的自动化用例,调用结束测试计划的方法。 因为方法中包含着测试计划执行队列的处理逻辑。
|
||||
testPlanReportService.testPlanUnExecute(reportInfoDTO.getTestPlanReport());
|
||||
}
|
||||
return planReportId;
|
||||
}
|
||||
|
||||
private RunModeConfigDTO buildRunModeConfigDTO() {
|
||||
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
|
||||
runModeConfig.setMode(RunModeConstants.SERIAL.name());
|
||||
runModeConfig.setReportType("iddReport");
|
||||
runModeConfig.setEnvMap(new HashMap<>());
|
||||
runModeConfig.setOnSampleError(false);
|
||||
return runModeConfig;
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ import org.apache.ibatis.session.SqlSession;
|
|||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
@ -622,6 +623,7 @@ public class TestPlanReportService {
|
|||
}
|
||||
}
|
||||
|
||||
@Async
|
||||
public void testPlanUnExecute(TestPlanReport testPlanReport) {
|
||||
if (testPlanReport != null && !StringUtils.equalsIgnoreCase(testPlanReport.getStatus(), TestPlanReportStatus.COMPLETED.name())) {
|
||||
testPlanReport.setIsApiCaseExecuting(false);
|
||||
|
|
|
@ -40,6 +40,7 @@ import io.metersphere.plan.request.performance.LoadPlanReportDTO;
|
|||
import io.metersphere.plan.request.ui.RunUiScenarioRequest;
|
||||
import io.metersphere.plan.request.ui.TestPlanUiExecuteReportDTO;
|
||||
import io.metersphere.plan.request.ui.UiPlanReportRequest;
|
||||
import io.metersphere.plan.service.execute.TestPlanExecuteService;
|
||||
import io.metersphere.plan.service.remote.api.PlanApiAutomationService;
|
||||
import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService;
|
||||
import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService;
|
||||
|
@ -495,6 +496,22 @@ public class TestPlanService {
|
|||
request.setProjectId(request.getProjectId());
|
||||
}
|
||||
List<TestPlanDTOWithMetric> testPlanList = extTestPlanMapper.list(request);
|
||||
|
||||
//统计测试计划的测试用例数
|
||||
List<String> testPlanIdList = testPlanList.stream().map(TestPlanDTOWithMetric::getId).collect(Collectors.toList());
|
||||
Map<String, ParamsDTO> planTestCaseCountMap = extTestPlanMapper.testPlanTestCaseCount(testPlanIdList);
|
||||
Map<String, ParamsDTO> planApiCaseMap = extTestPlanMapper.testPlanApiCaseCount(testPlanIdList);
|
||||
Map<String, ParamsDTO> planApiScenarioMap = extTestPlanMapper.testPlanApiScenarioCount(testPlanIdList);
|
||||
Map<String, ParamsDTO> planUiScenarioMap = extTestPlanMapper.testPlanUiScenarioCount(testPlanIdList);
|
||||
Map<String, ParamsDTO> planLoadCaseMap = extTestPlanMapper.testPlanLoadCaseCount(testPlanIdList);
|
||||
for (TestPlanDTOWithMetric testPlanMetric : testPlanList) {
|
||||
testPlanMetric.setTestPlanTestCaseCount(planTestCaseCountMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planTestCaseCountMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planTestCaseCountMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanApiCaseCount(planApiCaseMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planApiCaseMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planApiCaseMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanApiScenarioCount(planApiScenarioMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planApiScenarioMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planApiScenarioMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanUiScenarioCount(planUiScenarioMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planUiScenarioMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planUiScenarioMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanLoadCaseCount(planLoadCaseMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planLoadCaseMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planLoadCaseMap.get(testPlanMetric.getId()).getValue()));
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(testPlanList)) {
|
||||
List<String> changeToFinishedIds = new ArrayList<>();
|
||||
//检查定时任务的设置
|
||||
|
@ -556,17 +573,7 @@ public class TestPlanService {
|
|||
|
||||
public List<TestPlanDTOWithMetric> selectTestPlanMetricById(List<String> idList) {
|
||||
List<TestPlanDTOWithMetric> testPlanMetricList = this.calcTestPlanRateByIdList(idList);
|
||||
Map<String, ParamsDTO> planTestCaseCountMap = extTestPlanMapper.testPlanTestCaseCount(idList);
|
||||
Map<String, ParamsDTO> planApiCaseMap = extTestPlanMapper.testPlanApiCaseCount(idList);
|
||||
Map<String, ParamsDTO> planApiScenarioMap = extTestPlanMapper.testPlanApiScenarioCount(idList);
|
||||
Map<String, ParamsDTO> planUiScenarioMap = extTestPlanMapper.testPlanUiScenarioCount(idList);
|
||||
Map<String, ParamsDTO> planLoadCaseMap = extTestPlanMapper.testPlanLoadCaseCount(idList);
|
||||
for (TestPlanDTOWithMetric testPlanMetric : testPlanMetricList) {
|
||||
testPlanMetric.setTestPlanTestCaseCount(planTestCaseCountMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planTestCaseCountMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planTestCaseCountMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanApiCaseCount(planApiCaseMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planApiCaseMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planApiCaseMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanApiScenarioCount(planApiScenarioMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planApiScenarioMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planApiScenarioMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanUiScenarioCount(planUiScenarioMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planUiScenarioMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planUiScenarioMap.get(testPlanMetric.getId()).getValue()));
|
||||
testPlanMetric.setTestPlanLoadCaseCount(planLoadCaseMap.get(testPlanMetric.getId()) == null ? 0 : Integer.parseInt(planLoadCaseMap.get(testPlanMetric.getId()).getValue() == null ? "0" : planLoadCaseMap.get(testPlanMetric.getId()).getValue()));
|
||||
List<User> followUsers = this.getPlanFollow(testPlanMetric.getId());
|
||||
testPlanMetric.setFollowUsers(followUsers);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
package io.metersphere.plan.service.execute;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import io.metersphere.base.domain.TestPlanReport;
|
||||
import io.metersphere.base.domain.TestPlanWithBLOBs;
|
||||
import io.metersphere.base.mapper.TestPlanMapper;
|
||||
import io.metersphere.commons.constants.TestPlanExecuteCaseType;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.*;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.plan.dto.ExecutionWay;
|
||||
import io.metersphere.plan.request.api.TestPlanRunRequest;
|
||||
import io.metersphere.plan.service.TestPlanReportService;
|
||||
import io.metersphere.plan.service.TestPlanService;
|
||||
import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService;
|
||||
import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService;
|
||||
import io.metersphere.plan.service.remote.performance.PerfExecService;
|
||||
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
|
||||
import io.metersphere.plan.utils.TestPlanRequestUtil;
|
||||
import io.metersphere.service.RedisTemplateService;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class TestPlanExecuteService {
|
||||
@Resource
|
||||
@Lazy
|
||||
private TestPlanService testPlanService;
|
||||
@Resource
|
||||
private TestPlanReportService testPlanReportService;
|
||||
@Resource
|
||||
private PlanTestPlanApiCaseService planTestPlanApiCaseService;
|
||||
@Resource
|
||||
private PlanTestPlanScenarioCaseService planTestPlanScenarioCaseService;
|
||||
@Resource
|
||||
private PerfExecService perfExecService;
|
||||
@Resource
|
||||
private PlanTestPlanUiScenarioCaseService planTestPlanUiScenarioCaseService;
|
||||
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
|
||||
/**
|
||||
* 执行测试计划流程是会调用其它服务的执行方法,并通过kafka传递信息给test-track服务来判断测试计划是否执行结束
|
||||
* 执行方法采用单独的事务控制,执行完了就提交,让测试报告以及包括执行内容的数据及时入库
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public String runTestPlan(String testPlanId, String projectId, String userId, String triggerMode, String planReportId, String executionWay, String apiRunConfig) {
|
||||
//获取运行模式
|
||||
RunModeConfigDTO runModeConfig = this.getRunModeConfig(apiRunConfig, executionWay, testPlanId);
|
||||
if (StringUtils.isEmpty(planReportId)) {
|
||||
planReportId = UUID.randomUUID().toString();
|
||||
}
|
||||
TestPlanReport testPlanReport = null;
|
||||
try {
|
||||
this.checkTestPlanCanRunning(testPlanId, projectId, runModeConfig);
|
||||
//创建测试报告,然后返回的ID重新赋值为resourceID,作为后续的参数
|
||||
TestPlanScheduleReportInfoDTO reportInfoDTO = testPlanService.genTestPlanReport(planReportId, testPlanId, userId, triggerMode, runModeConfig);
|
||||
testPlanReport = reportInfoDTO.getTestPlanReport();
|
||||
LoggerUtil.info("预生成测试计划报告【" + (reportInfoDTO.getTestPlanReport() != null ? reportInfoDTO.getTestPlanReport().getName() : StringUtils.EMPTY) + "】计划报告ID[" + planReportId + "]");
|
||||
this.execute(reportInfoDTO, runModeConfig, triggerMode, projectId, userId);
|
||||
} catch (Exception e) {
|
||||
//如果执行失败,要保证执行队列是否不被影响
|
||||
if (testPlanReport == null) {
|
||||
testPlanReport = new TestPlanReport();
|
||||
testPlanReport.setId(planReportId);
|
||||
}
|
||||
testPlanReportService.testPlanUnExecute(testPlanReport);
|
||||
Log.error("执行测试计划失败!", e);
|
||||
}
|
||||
return planReportId;
|
||||
}
|
||||
|
||||
private void checkTestPlanCanRunning(String testPlanId, String projectId, RunModeConfigDTO runModeConfig) throws Exception {
|
||||
|
||||
// 校验测试计划是否在执行中
|
||||
if (testPlanService.checkTestPlanIsRunning(testPlanId)) {
|
||||
|
||||
LogUtil.info("当前测试计划正在执行中,请稍后再试", testPlanId);
|
||||
MSException.throwException(Translator.get("test_plan_run_message"));
|
||||
}
|
||||
//检查执行资源池
|
||||
if (testPlanService.haveExecCase(testPlanId, true)) {
|
||||
testPlanService.verifyPool(projectId, runModeConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private void execute(TestPlanScheduleReportInfoDTO reportInfoDTO, RunModeConfigDTO runModeConfig, String triggerMode, String projectId, String executeUser) throws Exception {
|
||||
CaseExecuteResult caseExecuteResult = new CaseExecuteResult();
|
||||
|
||||
CountDownLatch countDownLatch = this.countDownExecute(reportInfoDTO, caseExecuteResult, runModeConfig, triggerMode, projectId, executeUser);
|
||||
countDownLatch.await();
|
||||
LoggerUtil.info("开始生成测试计划报告内容 " + reportInfoDTO.getTestPlanReport().getId());
|
||||
testPlanReportService.createTestPlanReportContentReportIds(reportInfoDTO.getTestPlanReport().getId(),
|
||||
caseExecuteResult.getApiCaseDTO(), caseExecuteResult.getScenarioCases(), caseExecuteResult.getUiScenarios(), caseExecuteResult.getLoadCaseReportMap());
|
||||
if (!caseExecuteResult.isExecuting()) {
|
||||
MSException.throwException("测试计划执行失败,不存在可执行的用例!报告ID:[" + reportInfoDTO.getTestPlanReport().getTestPlanId() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private CountDownLatch countDownExecute(TestPlanScheduleReportInfoDTO reportInfoDTO, CaseExecuteResult caseExecuteResult, RunModeConfigDTO runModeConfig, String triggerMode, String projectId, String executeUser) {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(4);
|
||||
try {
|
||||
this.executeApiCase(caseExecuteResult, reportInfoDTO.getApiTestCaseDataMap(), triggerMode,
|
||||
reportInfoDTO.getTestPlanReport().getId(), reportInfoDTO.getTestPlanReport().getTestPlanId(), executeUser, runModeConfig);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
} finally {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
|
||||
try {
|
||||
this.executeScenarioCase(caseExecuteResult, reportInfoDTO.getPlanScenarioIdMap(), triggerMode,
|
||||
reportInfoDTO.getTestPlanReport().getId(), reportInfoDTO.getTestPlanReport().getTestPlanId(), projectId, executeUser, runModeConfig);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
} finally {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
try {
|
||||
this.executeUiCase(caseExecuteResult, reportInfoDTO.getUiScenarioIdMap(), triggerMode,
|
||||
reportInfoDTO.getTestPlanReport().getId(), reportInfoDTO.getTestPlanReport().getTestPlanId(), projectId, executeUser, runModeConfig);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
} finally {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
try {
|
||||
this.executeLoadCase(caseExecuteResult, reportInfoDTO.getPerformanceIdMap(), triggerMode,
|
||||
reportInfoDTO.getTestPlanReport().getId(), runModeConfig);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
} finally {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
return countDownLatch;
|
||||
}
|
||||
|
||||
private void executeApiCase(CaseExecuteResult executeResult, Map<String, String> executeCase, String triggerMode, String testPlanReportId, String testPlanId, String executeUser, RunModeConfigDTO runModeConfig) {
|
||||
boolean executing = false;
|
||||
List<TestPlanApiDTO> apiTestCases = null;
|
||||
if (MapUtils.isNotEmpty(executeCase)) {
|
||||
try {
|
||||
apiTestCases = planTestPlanApiCaseService.getFailureListByIds(executeCase.keySet());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("测试计划执行查询接口用例失败!", e);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(apiTestCases)) {
|
||||
//执行接口案例任务
|
||||
LoggerUtil.info("开始执行测试计划接口用例 " + testPlanReportId);
|
||||
try {
|
||||
redisTemplateService.lock(testPlanReportId, TestPlanExecuteCaseType.API_CASE.name(), testPlanReportId);
|
||||
Map<String, String> apiCaseReportMap = testPlanService.executeApiTestCase(triggerMode, testPlanReportId, executeUser, testPlanId, runModeConfig);
|
||||
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
|
||||
executing = true;
|
||||
for (TestPlanApiDTO dto : apiTestCases) {
|
||||
dto.setReportId(apiCaseReportMap.get(dto.getId()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
redisTemplateService.unlock(testPlanReportId, TestPlanExecuteCaseType.API_CASE.name(), testPlanReportId);
|
||||
apiTestCases = null;
|
||||
LoggerUtil.info("测试报告" + testPlanReportId + "本次执行测试计划接口用例失败! ", e);
|
||||
}
|
||||
}
|
||||
executeResult.setApiCaseExecuting(executing);
|
||||
executeResult.setApiCaseDTO(apiTestCases);
|
||||
}
|
||||
|
||||
private void executeScenarioCase(CaseExecuteResult executeResult, Map<String, String> executeCase, String triggerMode, String testPlanReportId, String testPlanId, String projectId, String executeUser, RunModeConfigDTO runModeConfig) {
|
||||
boolean executing = false;
|
||||
List<TestPlanScenarioDTO> scenarioCases = null;
|
||||
if (MapUtils.isNotEmpty(executeCase)) {
|
||||
try {
|
||||
scenarioCases = planTestPlanScenarioCaseService.getFailureListByIds(executeCase.keySet());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("测试计划执行查询场景用例失败!", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(scenarioCases)) {
|
||||
//执行场景执行任务
|
||||
LoggerUtil.info("开始执行测试计划场景用例 " + testPlanReportId);
|
||||
try {
|
||||
|
||||
redisTemplateService.lock(testPlanReportId, TestPlanExecuteCaseType.SCENARIO.name(), testPlanReportId);
|
||||
Map<String, String> scenarioReportMap = testPlanService.executeScenarioCase(testPlanReportId, testPlanId, projectId, runModeConfig, triggerMode, executeUser, executeCase);
|
||||
if (MapUtils.isNotEmpty(scenarioReportMap)) {
|
||||
executing = true;
|
||||
List<TestPlanScenarioDTO> removeDTO = new ArrayList<>();
|
||||
for (TestPlanScenarioDTO dto : scenarioCases) {
|
||||
if (scenarioReportMap.containsKey(dto.getId())) {
|
||||
dto.setReportId(scenarioReportMap.get(dto.getId()));
|
||||
} else {
|
||||
removeDTO.add(dto);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(removeDTO)) {
|
||||
scenarioCases.removeAll(removeDTO);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
redisTemplateService.unlock(testPlanReportId, TestPlanExecuteCaseType.SCENARIO.name(), testPlanReportId);
|
||||
scenarioCases = null;
|
||||
LoggerUtil.info("测试报告" + testPlanReportId + "本次执行测试计划场景用例失败! ", e);
|
||||
}
|
||||
}
|
||||
executeResult.setScenarioCases(scenarioCases);
|
||||
executeResult.setScenarioExecuting(executing);
|
||||
}
|
||||
|
||||
private void executeUiCase(CaseExecuteResult executeResult, Map<String, String> executeCase, String triggerMode, String testPlanReportId, String testPlanId, String projectId, String executeUser, RunModeConfigDTO runModeConfig) {
|
||||
boolean executing = false;
|
||||
List<TestPlanUiScenarioDTO> uiScenarios = null;
|
||||
if (MapUtils.isNotEmpty(executeCase)) {
|
||||
try {
|
||||
uiScenarios = planTestPlanUiScenarioCaseService.getFailureListByIds(executeCase.keySet());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("测试计划执行查询UI用例失败!", e);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(uiScenarios)) {
|
||||
//执行UI场景执行任务
|
||||
LoggerUtil.info("开始执行测试计划 UI 场景用例 " + testPlanReportId);
|
||||
try {
|
||||
redisTemplateService.lock(testPlanReportId, TestPlanExecuteCaseType.UI_SCENARIO.name(), testPlanReportId);
|
||||
Map<String, String> uiScenarioReportMap = testPlanService.executeUiScenarioCase(testPlanReportId, testPlanId, projectId, runModeConfig, triggerMode, executeUser, executeCase);
|
||||
if (MapUtils.isNotEmpty(uiScenarioReportMap)) {
|
||||
executing = true;
|
||||
for (TestPlanUiScenarioDTO dto : uiScenarios) {
|
||||
dto.setReportId(uiScenarioReportMap.get(dto.getId()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
redisTemplateService.unlock(testPlanReportId, TestPlanExecuteCaseType.UI_SCENARIO.name(), testPlanReportId);
|
||||
uiScenarios = null;
|
||||
LoggerUtil.info("测试报告" + testPlanReportId + "本次执行测试计划 UI 用例失败! ", e);
|
||||
}
|
||||
}
|
||||
executeResult.setUiScenarios(uiScenarios);
|
||||
executeResult.setUiScenarioExecuting(executing);
|
||||
}
|
||||
|
||||
private void executeLoadCase(CaseExecuteResult executeResult, Map<String, String> executeCase, String triggerMode, String testPlanReportId, RunModeConfigDTO runModeConfig) {
|
||||
boolean executing = false;
|
||||
|
||||
Map<String, String> loadCaseReportMap = null;
|
||||
|
||||
if (MapUtils.isNotEmpty(executeCase)) {
|
||||
//执行性能测试任务
|
||||
LoggerUtil.info("开始执行测试计划性能用例 " + testPlanReportId);
|
||||
try {
|
||||
redisTemplateService.lock(testPlanReportId, TestPlanExecuteCaseType.LOAD_CASE.name(), testPlanReportId);
|
||||
loadCaseReportMap = perfExecService.executeLoadCase(testPlanReportId, runModeConfig, testPlanService.transformationPerfTriggerMode(triggerMode), executeCase);
|
||||
if (MapUtils.isNotEmpty(loadCaseReportMap)) {
|
||||
executing = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
redisTemplateService.unlock(testPlanReportId, TestPlanExecuteCaseType.LOAD_CASE.name(), testPlanReportId);
|
||||
LoggerUtil.info("测试报告" + testPlanReportId + "本次执行测试计划性能用例失败! ", e);
|
||||
}
|
||||
}
|
||||
|
||||
executeResult.setLoadCaseReportMap(loadCaseReportMap);
|
||||
executeResult.setLoadCaseExecuting(executing);
|
||||
}
|
||||
|
||||
private RunModeConfigDTO getRunModeConfig(String apiRunConfig, String executionWay, String testPlanId) {
|
||||
RunModeConfigDTO runModeConfig = null;
|
||||
try {
|
||||
runModeConfig = JSON.parseObject(apiRunConfig, RunModeConfigDTO.class);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
if (runModeConfig == null) {
|
||||
runModeConfig = this.buildRunModeConfigDTO();
|
||||
}
|
||||
|
||||
//环境参数为空时,依据测试计划保存的环境执行
|
||||
if (((StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && StringUtils.isBlank(runModeConfig.getEnvironmentGroupId()))
|
||||
|| (!StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && MapUtils.isEmpty(runModeConfig.getEnvMap()) && MapUtils.isEmpty(runModeConfig.getTestPlanDefaultEnvMap())))
|
||||
&& !StringUtils.equals(executionWay, ExecutionWay.RUN.name())) {
|
||||
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
|
||||
if (StringUtils.isNotEmpty(testPlanWithBLOBs.getRunModeConfig())) {
|
||||
try {
|
||||
Map json = JSON.parseMap(testPlanWithBLOBs.getRunModeConfig());
|
||||
TestPlanRequestUtil.changeStringToBoolean(json);
|
||||
TestPlanRunRequest testPlanRunRequest = JSON.parseObject(JSON.toJSONString(json), TestPlanRunRequest.class);
|
||||
if (testPlanRunRequest != null) {
|
||||
String envType = testPlanRunRequest.getEnvironmentType();
|
||||
Map<String, String> envMap = testPlanRunRequest.getEnvMap();
|
||||
String environmentGroupId = testPlanRunRequest.getEnvironmentGroupId();
|
||||
runModeConfig = testPlanService.getRunModeConfigDTO(testPlanRunRequest, envType, envMap, environmentGroupId, testPlanId);
|
||||
runModeConfig.setTestPlanDefaultEnvMap(testPlanRunRequest.getTestPlanDefaultEnvMap());
|
||||
if (!testPlanRunRequest.isRunWithinResourcePool()) {
|
||||
runModeConfig.setResourcePoolId(null);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("获取测试计划保存的环境信息出错!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return runModeConfig;
|
||||
}
|
||||
|
||||
private RunModeConfigDTO buildRunModeConfigDTO() {
|
||||
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
|
||||
runModeConfig.setMode(RunModeConstants.SERIAL.name());
|
||||
runModeConfig.setReportType("iddReport");
|
||||
runModeConfig.setEnvMap(new HashMap<>());
|
||||
runModeConfig.setOnSampleError(false);
|
||||
return runModeConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
class CaseExecuteResult {
|
||||
private boolean apiCaseExecuting;
|
||||
private boolean scenarioExecuting;
|
||||
private boolean uiScenarioExecuting;
|
||||
private boolean loadCaseExecuting;
|
||||
|
||||
|
||||
private List<TestPlanApiDTO> apiCaseDTO;
|
||||
private List<TestPlanScenarioDTO> scenarioCases;
|
||||
private List<TestPlanUiScenarioDTO> uiScenarios;
|
||||
private Map<String, String> loadCaseReportMap;
|
||||
|
||||
public boolean isExecuting() {
|
||||
return apiCaseExecuting || scenarioExecuting || uiScenarioExecuting || loadCaseExecuting;
|
||||
}
|
||||
}
|
|
@ -1,43 +1,45 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
destroy-on-close
|
||||
:title="$t('load_test.runtime_config')"
|
||||
width="550px"
|
||||
style="margin-top: -8.65vh; max-height: 87.3vh"
|
||||
@close="close"
|
||||
:visible.sync="runModeVisible"
|
||||
destroy-on-close
|
||||
:title="$t('load_test.runtime_config')"
|
||||
width="550px"
|
||||
style="margin-top: -8.65vh; max-height: 87.3vh"
|
||||
@close="close"
|
||||
:visible.sync="runModeVisible"
|
||||
>
|
||||
|
||||
<div class="env-container">
|
||||
<div>
|
||||
<div>{{ $t("commons.environment") }}:</div>
|
||||
<env-select-popover
|
||||
:project-ids="projectIds"
|
||||
:project-list="projectList"
|
||||
:project-env-map="projectEnvListMap"
|
||||
:environment-type.sync="runConfig.environmentType"
|
||||
:has-option-group="true"
|
||||
:group-id="runConfig.environmentGroupId"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
@setDefaultEnv="setDefaultEnv"
|
||||
@setEnvGroup="setEnvGroup"
|
||||
ref="envSelectPopover"
|
||||
class="mode-row"
|
||||
:project-ids="projectIds"
|
||||
:project-list="projectList"
|
||||
:project-env-map="projectEnvListMap"
|
||||
:environment-type.sync="runConfig.environmentType"
|
||||
:has-option-group="true"
|
||||
:is-env-saved="isEnvSaved"
|
||||
:group-id="runConfig.environmentGroupId"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
@setDefaultEnv="setDefaultEnv"
|
||||
@setEnvGroup="setEnvGroup"
|
||||
ref="envSelectPopover"
|
||||
class="mode-row"
|
||||
></env-select-popover>
|
||||
</div>
|
||||
<div v-if="haveUICase">
|
||||
<div>{{ $t("ui.browser") }}:</div>
|
||||
<div>
|
||||
<el-select
|
||||
size="mini"
|
||||
v-model="runConfig.browser"
|
||||
style="width: 100%"
|
||||
class="mode-row"
|
||||
size="mini"
|
||||
v-model="runConfig.browser"
|
||||
style="width: 100%"
|
||||
class="mode-row"
|
||||
>
|
||||
<el-option
|
||||
v-for="b in browsers"
|
||||
:key="b.value"
|
||||
:value="b.value"
|
||||
:label="b.label"
|
||||
v-for="b in browsers"
|
||||
:key="b.value"
|
||||
:value="b.value"
|
||||
:label="b.label"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
@ -46,10 +48,10 @@
|
|||
<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"
|
||||
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>
|
||||
|
@ -59,51 +61,25 @@
|
|||
<div>
|
||||
<div class="mode-row">{{ $t("run_mode.other_config") }}:</div>
|
||||
<div>
|
||||
<!-- 串行 -->
|
||||
<!-- 资源池 -->
|
||||
<div
|
||||
class="mode-row"
|
||||
v-if="
|
||||
runConfig.mode === 'serial' &&
|
||||
class="mode-row"
|
||||
v-if="
|
||||
testType === 'API' &&
|
||||
haveOtherExecCase
|
||||
(haveOtherExecCase && !haveUICase)
|
||||
"
|
||||
>
|
||||
<span>{{ $t("run_mode.run_with_resource_pool") }}: </span>
|
||||
<el-select
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
style="width: 100%; margin-top: 8px"
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
style="width: 100%; margin-top: 8px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- 并行 -->
|
||||
<div
|
||||
class="mode-row"
|
||||
v-if="
|
||||
runConfig.mode === 'parallel' &&
|
||||
testType === 'API' &&
|
||||
haveOtherExecCase
|
||||
"
|
||||
>
|
||||
<span>{{ $t("run_mode.run_with_resource_pool") }}: </span>
|
||||
<el-select
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
style="width: 100%; margin-top: 8px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:disabled="!item.api"
|
||||
:value="item.id"
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
@ -112,8 +88,8 @@
|
|||
<!-- 失败重试 -->
|
||||
<div class="mode-row">
|
||||
<el-checkbox
|
||||
v-model="runConfig.retryEnable"
|
||||
class="radio-change ms-failure-div-right"
|
||||
v-model="runConfig.retryEnable"
|
||||
class="radio-change ms-failure-div-right"
|
||||
>
|
||||
{{ $t("run_mode.retry_on_failure") }}
|
||||
</el-checkbox>
|
||||
|
@ -121,19 +97,19 @@
|
|||
<el-tooltip placement="top" style="margin: 0 4px 0 2px">
|
||||
<div slot="content">{{ $t("run_mode.retry_message") }}</div>
|
||||
<i
|
||||
class="el-icon-question"
|
||||
style="cursor: pointer"
|
||||
class="el-icon-question"
|
||||
style="cursor: pointer"
|
||||
/> </el-tooltip
|
||||
><br />
|
||||
><br/>
|
||||
<span>
|
||||
{{ $t("run_mode.retry") }}
|
||||
<el-input-number
|
||||
:value="runConfig.retryNum"
|
||||
v-model="runConfig.retryNum"
|
||||
:min="1"
|
||||
:max="10000000"
|
||||
size="mini"
|
||||
style="width: 103px; margin-top: 8px"
|
||||
:value="runConfig.retryNum"
|
||||
v-model="runConfig.retryNum"
|
||||
:min="1"
|
||||
:max="10000000"
|
||||
size="mini"
|
||||
style="width: 103px; margin-top: 8px"
|
||||
/>
|
||||
|
||||
{{ $t("run_mode.retry_frequency") }}
|
||||
|
@ -143,14 +119,14 @@
|
|||
|
||||
<div class="mode-row" v-if="runConfig.mode === 'serial'">
|
||||
<el-checkbox v-model="runConfig.onSampleError" class="radio-change"
|
||||
>{{ $t("api_test.fail_to_stop") }}
|
||||
>{{ $t("api_test.fail_to_stop") }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="mode-row" v-if="haveUICase">
|
||||
<el-checkbox
|
||||
v-model="runConfig.headlessEnabled"
|
||||
class="radio-change"
|
||||
v-model="runConfig.headlessEnabled"
|
||||
class="radio-change"
|
||||
>
|
||||
{{ $t("ui.performance_mode") }}
|
||||
</el-checkbox>
|
||||
|
@ -164,23 +140,24 @@
|
|||
<el-button @click="close">{{ $t("commons.cancel") }}</el-button>
|
||||
<el-dropdown @command="handleCommand" style="margin-left: 5px">
|
||||
<el-button type="primary">
|
||||
{{ $t("api_test.run")
|
||||
{{
|
||||
$t("api_test.run")
|
||||
}}<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="run"
|
||||
>{{ $t("api_test.run") }}
|
||||
>{{ $t("api_test.run") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="runAndSave"
|
||||
>{{ $t("load_test.save_and_run") }}
|
||||
>{{ $t("load_test.save_and_run") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="save"
|
||||
>{{ $t("commons.save") }}
|
||||
>{{ $t("commons.save") }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<ms-dialog-footer v-else @cancel="close" @confirm="handleRunBatch" />
|
||||
<ms-dialog-footer v-else @cancel="close" @confirm="handleRunBatch"/>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
@ -220,7 +197,7 @@ export default {
|
|||
btnStyle: {
|
||||
width: "260px",
|
||||
},
|
||||
result: { loading: false },
|
||||
result: {loading: false},
|
||||
runModeVisible: false,
|
||||
testType: null,
|
||||
resourcePools: [],
|
||||
|
@ -233,7 +210,7 @@ export default {
|
|||
resourcePoolId: null,
|
||||
envMap: new Map(),
|
||||
environmentGroupId: "",
|
||||
environmentType: ENV_TYPE.JSON,
|
||||
environmentType: ENV_TYPE.DEFAULT,
|
||||
retryEnable: false,
|
||||
retryNum: 1,
|
||||
browser: "CHROME",
|
||||
|
@ -241,6 +218,8 @@ export default {
|
|||
},
|
||||
projectList: [],
|
||||
projectIds: new Set(),
|
||||
//环境是否保存过。未保存过的话展示的是”用例环境“
|
||||
isEnvSaved: true,
|
||||
options: [
|
||||
{
|
||||
value: "confirmAndRun",
|
||||
|
@ -279,6 +258,7 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//是否有其他用例(性能测试除外)
|
||||
haveOtherExecCase: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
@ -289,11 +269,22 @@ export default {
|
|||
this.defaultEnvMap = {};
|
||||
if (runModeConfig) {
|
||||
this.runConfig = JSON.parse(runModeConfig);
|
||||
if (!this.runConfig.envMap || JSON.stringify(this.runConfig.envMap) === "{}") {
|
||||
this.isEnvSaved = false;
|
||||
this.runConfig.environmentType = ENV_TYPE.DEFAULT;
|
||||
} else {
|
||||
this.isEnvSaved = true;
|
||||
this.runConfig.environmentType = ENV_TYPE.JSON;
|
||||
}
|
||||
this.runConfig.envMap = new Map();
|
||||
this.runConfig.testPlanDefaultEnvMap = {};
|
||||
this.runConfig.onSampleError =
|
||||
this.runConfig.onSampleError === "true" ||
|
||||
this.runConfig.onSampleError === true;
|
||||
this.runConfig.onSampleError === "true" ||
|
||||
this.runConfig.onSampleError === true;
|
||||
} else {
|
||||
this.isEnvSaved = false;
|
||||
//没保存过运行配置的测试计划,运行环境类型为default
|
||||
this.runConfig.environmentType = ENV_TYPE.DEFAULT;
|
||||
}
|
||||
this.runModeVisible = true;
|
||||
this.testType = testType;
|
||||
|
@ -348,7 +339,7 @@ export default {
|
|||
handleRunBatch() {
|
||||
if (this.runConfig.resourcePoolId == null && this.haveOtherExecCase) {
|
||||
this.$warning(
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool"));
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool"));
|
||||
return;
|
||||
}
|
||||
this.runConfig.testPlanDefaultEnvMap = this.defaultEnvMap;
|
||||
|
@ -408,7 +399,7 @@ export default {
|
|||
this.$refs.envSelectPopover.open();
|
||||
});
|
||||
} else if (this.type === "plan") {
|
||||
param = { id: this.planId };
|
||||
param = {id: this.planId};
|
||||
getPlanCaseEnv(param).then((res) => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
|
@ -418,7 +409,7 @@ export default {
|
|||
}
|
||||
}
|
||||
if (this.projectIds.size === 0) {
|
||||
param = { id: this.planId };
|
||||
param = {id: this.planId};
|
||||
getPlanCaseProjectIds(param).then((res) => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
|
@ -436,11 +427,11 @@ export default {
|
|||
},
|
||||
handleCommand(command) {
|
||||
if (
|
||||
this.runConfig.resourcePoolId == null &&
|
||||
this.haveOtherExecCase
|
||||
this.runConfig.resourcePoolId == null &&
|
||||
this.haveOtherExecCase
|
||||
) {
|
||||
this.$warning(
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -459,11 +450,12 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.env-container{
|
||||
.env-container {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
.env-container .title {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
|
@ -486,6 +478,7 @@ export default {
|
|||
.radio-change:deep(.el-radio__input.is-checked + .el-radio__label) {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
||||
.radio-change:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
v-loading="result.loading"
|
||||
:close-on-click-modal="false"
|
||||
width="60%"
|
||||
class="schedule-edit"
|
||||
:visible.sync="dialogVisible"
|
||||
:append-to-body="true"
|
||||
@close="close"
|
||||
v-loading="result.loading"
|
||||
:close-on-click-modal="false"
|
||||
width="60%"
|
||||
class="schedule-edit"
|
||||
:visible.sync="dialogVisible"
|
||||
:append-to-body="true"
|
||||
@close="close"
|
||||
>
|
||||
<template>
|
||||
<div>
|
||||
|
@ -17,32 +17,32 @@
|
|||
</div>
|
||||
<span>{{ $t("schedule.edit_timer_task") }}</span>
|
||||
<el-form
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
ref="from"
|
||||
style="padding-top: 10px; margin-left: 20px"
|
||||
class="ms-el-form-item__error"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
ref="from"
|
||||
style="padding-top: 10px; margin-left: 20px"
|
||||
class="ms-el-form-item__error"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('commons.schedule_cron_title')"
|
||||
prop="cronValue"
|
||||
style="height: 50px"
|
||||
:label="$t('commons.schedule_cron_title')"
|
||||
prop="cronValue"
|
||||
style="height: 50px"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="16">
|
||||
<el-input
|
||||
:disabled="isReadOnly"
|
||||
v-model="form.cronValue"
|
||||
class="inp"
|
||||
:placeholder="$t('schedule.please_input_cron_expression')"
|
||||
size="mini"
|
||||
:disabled="isReadOnly"
|
||||
v-model="form.cronValue"
|
||||
class="inp"
|
||||
:placeholder="$t('schedule.please_input_cron_expression')"
|
||||
size="mini"
|
||||
>
|
||||
<a
|
||||
:disabled="isReadOnly"
|
||||
type="primary"
|
||||
@click="showCronDialog"
|
||||
slot="suffix"
|
||||
class="head"
|
||||
:disabled="isReadOnly"
|
||||
type="primary"
|
||||
@click="showCronDialog"
|
||||
slot="suffix"
|
||||
class="head"
|
||||
>
|
||||
{{ $t("schedule.generate_expression") }}
|
||||
</a>
|
||||
|
@ -50,197 +50,198 @@
|
|||
|
||||
<span>{{ this.$t("commons.schedule_switch") }}</span>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
placement="bottom"
|
||||
:content="
|
||||
effect="dark"
|
||||
placement="bottom"
|
||||
:content="
|
||||
schedule.enable
|
||||
? $t('commons.close_schedule')
|
||||
: $t('commons.open_schedule')
|
||||
"
|
||||
>
|
||||
<el-switch
|
||||
v-model="schedule.enable"
|
||||
style="margin-left: 20px"
|
||||
v-model="schedule.enable"
|
||||
style="margin-left: 20px"
|
||||
></el-switch>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-button
|
||||
:disabled="isReadOnly"
|
||||
type="primary"
|
||||
@click="saveCron"
|
||||
size="mini"
|
||||
>{{ $t("commons.save") }}
|
||||
:disabled="isReadOnly"
|
||||
type="primary"
|
||||
@click="saveCron"
|
||||
size="mini"
|
||||
>{{ $t("commons.save") }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<crontab-result :ex="form.cronValue" ref="crontabResult" />
|
||||
<crontab-result :ex="form.cronValue" ref="crontabResult"/>
|
||||
</el-form>
|
||||
|
||||
<div class="el-step__icon is-text" style="margin-right: 10px">
|
||||
<div class="el-step__icon-inner">2</div>
|
||||
</div>
|
||||
<span>{{ $t("load_test.runtime_config") }}</span>
|
||||
<div class="ms-mode-div">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.title") }}:</span>
|
||||
<el-radio-group v-model="runConfig.mode" @change="changeMode">
|
||||
<el-radio label="serial">{{ $t("run_mode.serial") }}</el-radio>
|
||||
<el-radio label="parallel"
|
||||
<div v-if="haveUICase || haveOtherExecCase">
|
||||
<div class="el-step__icon is-text" style="margin-right: 10px">
|
||||
<div class="el-step__icon-inner">2</div>
|
||||
</div>
|
||||
<span>{{ $t("load_test.runtime_config") }}</span>
|
||||
<div class="ms-mode-div">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.title") }}:</span>
|
||||
<el-radio-group v-if="haveUICase || haveOtherExecCase" v-model="runConfig.mode" @change="changeMode">
|
||||
<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 style="margin-top: 10px">
|
||||
<span class="ms-mode-span">{{ $t("浏览器") }}:</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
v-model="runConfig.browser"
|
||||
style="margin-right: 30px; width: 100px"
|
||||
>
|
||||
<el-option
|
||||
v-for="b in browsers"
|
||||
:key="b.value"
|
||||
:value="b.value"
|
||||
:label="b.label"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="runConfig.mode === 'serial'">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div v-if="haveUICase" style="margin-top: 10px">
|
||||
<span class="ms-mode-span">{{ $t("浏览器") }}:</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
v-model="runConfig.browser"
|
||||
style="margin-right: 30px; width: 100px"
|
||||
>
|
||||
<el-option
|
||||
v-for="b in browsers"
|
||||
:key="b.value"
|
||||
:value="b.value"
|
||||
:label="b.label"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="(haveUICase || haveOtherExecCase) && runConfig.mode === 'serial'">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<span class="ms-mode-span"
|
||||
>{{ $t("run_mode.other_config") }}:</span
|
||||
>{{ $t("run_mode.other_config") }}:</span
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div v-if="testType === 'API'">
|
||||
<sapn>{{ $t("run_mode.run_with_resource_pool") }}: </sapn>
|
||||
<el-select
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div v-if="haveOtherExecCase && testType === 'API'">
|
||||
<sapn>{{ $t("run_mode.run_with_resource_pool") }}:</sapn>
|
||||
<el-select
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="runConfig.mode === 'parallel'">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="(haveUICase || haveOtherExecCase) && runConfig.mode === 'parallel'">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<span class="ms-mode-span"
|
||||
>{{ $t("run_mode.other_config") }}:</span
|
||||
>{{ $t("run_mode.other_config") }}:</span
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div v-if="testType === 'API'">
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div v-if="haveOtherExecCase && testType === 'API'">
|
||||
<span>
|
||||
{{ $t("run_mode.run_with_resource_pool") }} :
|
||||
</span>
|
||||
<el-select
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:disabled="!item.api"
|
||||
:value="item.id"
|
||||
<el-select
|
||||
v-model="runConfig.resourcePoolId"
|
||||
size="mini"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:disabled="!item.api"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 失败重试 -->
|
||||
<div class="ms-mode-div">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<span class="ms-mode-span"> </span>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-checkbox
|
||||
v-model="runConfig.retryEnable"
|
||||
class="ms-failure-div-right"
|
||||
>
|
||||
{{ $t("run_mode.retry_on_failure") }}
|
||||
</el-checkbox>
|
||||
<span v-if="runConfig.retryEnable">
|
||||
<!-- 失败重试 -->
|
||||
<div class="ms-mode-div">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<span class="ms-mode-span"> </span>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-checkbox
|
||||
v-model="runConfig.retryEnable"
|
||||
class="ms-failure-div-right"
|
||||
>
|
||||
{{ $t("run_mode.retry_on_failure") }}
|
||||
</el-checkbox>
|
||||
<span v-if="runConfig.retryEnable">
|
||||
<el-tooltip placement="top">
|
||||
<div slot="content">
|
||||
{{ $t("run_mode.retry_message") }}
|
||||
</div>
|
||||
<i class="el-icon-question" style="cursor: pointer" />
|
||||
<i class="el-icon-question" style="cursor: pointer"/>
|
||||
</el-tooltip>
|
||||
<span>
|
||||
{{ $t("run_mode.retry") }}
|
||||
<el-input-number
|
||||
:value="runConfig.retryNum"
|
||||
v-model="runConfig.retryNum"
|
||||
:min="1"
|
||||
:max="10000000"
|
||||
size="mini"
|
||||
:value="runConfig.retryNum"
|
||||
v-model="runConfig.retryNum"
|
||||
:min="1"
|
||||
:max="10000000"
|
||||
size="mini"
|
||||
/>
|
||||
|
||||
{{ $t("run_mode.retry_frequency") }}
|
||||
</span>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="ms-failure-div" v-if="runConfig.mode === 'serial'">
|
||||
<el-row>
|
||||
<el-col :span="18" :offset="3">
|
||||
<div>
|
||||
<el-checkbox v-model="runConfig.onSampleError"
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="ms-failure-div" v-if="runConfig.mode === 'serial'">
|
||||
<el-row>
|
||||
<el-col :span="18" :offset="3">
|
||||
<div>
|
||||
<el-checkbox v-model="runConfig.onSampleError"
|
||||
>{{ $t("api_test.fail_to_stop") }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div v-if="haveUICase">
|
||||
<el-row>
|
||||
<el-col :span="3"> </el-col>
|
||||
<el-col :span="18">
|
||||
<div style="margin-top: 10px">
|
||||
<el-checkbox v-model="runConfig.headlessEnabled">
|
||||
{{ $t("性能模式") }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="3"> </el-col>
|
||||
<el-col :span="18">
|
||||
<div style="margin-top: 10px">
|
||||
<el-checkbox v-model="runConfig.headlessEnabled">
|
||||
{{ $t("性能模式") }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
width="60%"
|
||||
:title="$t('schedule.generate_expression')"
|
||||
:visible.sync="showCron"
|
||||
:modal="false"
|
||||
width="60%"
|
||||
:title="$t('schedule.generate_expression')"
|
||||
:visible.sync="showCron"
|
||||
:modal="false"
|
||||
>
|
||||
<crontab
|
||||
@hide="showCron = false"
|
||||
@fill="crontabFill"
|
||||
:expression="schedule.value"
|
||||
ref="crontab"
|
||||
@hide="showCron = false"
|
||||
@fill="crontabFill"
|
||||
:expression="schedule.value"
|
||||
ref="crontab"
|
||||
/>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('schedule.task_notification')" name="second"
|
||||
v-permission="['PROJECT_MESSAGE:READ']">
|
||||
<ms-schedule-notification
|
||||
:test-id="testId"
|
||||
:schedule-receiver-options="scheduleReceiverOptions"
|
||||
:test-id="testId"
|
||||
:schedule-receiver-options="scheduleReceiverOptions"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
@ -250,21 +251,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
getCurrentUser,
|
||||
getCurrentWorkspaceId,
|
||||
} from "metersphere-frontend/src/utils/token";
|
||||
import {
|
||||
listenGoBack,
|
||||
removeGoBackListener,
|
||||
} from "metersphere-frontend/src/utils";
|
||||
import {getCurrentProjectID, getCurrentUser, getCurrentWorkspaceId,} from "metersphere-frontend/src/utils/token";
|
||||
import {listenGoBack, removeGoBackListener,} from "metersphere-frontend/src/utils";
|
||||
import Crontab from "metersphere-frontend/src/components/cron/Crontab";
|
||||
import CrontabResult from "metersphere-frontend/src/components/cron/CrontabResult";
|
||||
import { cronValidate } from "metersphere-frontend/src/utils/cron";
|
||||
import {cronValidate} from "metersphere-frontend/src/utils/cron";
|
||||
import MsScheduleNotification from "./ScheduleNotification";
|
||||
import ScheduleSwitch from "./ScheduleSwitch";
|
||||
import { ENV_TYPE } from "metersphere-frontend/src/utils/constants";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import MxNotification from "metersphere-frontend/src/components/MxNoticeTemplate";
|
||||
import {
|
||||
createSchedule,
|
||||
|
@ -272,14 +266,13 @@ import {
|
|||
updateSchedule,
|
||||
updateScheduleEnableByPrimyKey,
|
||||
} from "@/api/remote/plan/test-plan";
|
||||
import { saveNotice } from "@/api/notice";
|
||||
import { getProjectMember } from "@/api/user";
|
||||
import { getQuotaValidResourcePools } from "@/api/remote/resource-pool";
|
||||
import { getProjectConfig } from "@/api/project";
|
||||
import { getSystemBaseSetting } from "metersphere-frontend/src/api/system";
|
||||
import {saveNotice} from "@/api/notice";
|
||||
import {getProjectMember} from "@/api/user";
|
||||
import {getQuotaValidResourcePools} from "@/api/remote/resource-pool";
|
||||
import {getProjectConfig} from "@/api/project";
|
||||
|
||||
function defaultCustomValidate() {
|
||||
return { pass: true };
|
||||
return {pass: true};
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -308,6 +301,11 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//是否有其他用例(性能测试除外)
|
||||
haveOtherExecCase: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
@ -351,7 +349,7 @@ export default {
|
|||
activeName: "first",
|
||||
rules: {
|
||||
cronValue: [
|
||||
{ required: true, validator: validateCron, trigger: "blur" },
|
||||
{required: true, validator: validateCron, trigger: "blur"},
|
||||
],
|
||||
},
|
||||
resourcePools: [],
|
||||
|
@ -382,7 +380,7 @@ export default {
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
async checkPool(){
|
||||
async checkPool() {
|
||||
let hasPool = false;
|
||||
this.resourcePools.forEach(item => {
|
||||
if (item.id === this.runConfig.resourcePoolId) {
|
||||
|
@ -454,22 +452,22 @@ export default {
|
|||
async findSchedule() {
|
||||
let scheduleResourceID = this.testId;
|
||||
this.result = getPlanSchedule(scheduleResourceID, "TEST_PLAN_TEST").then(
|
||||
(response) => {
|
||||
if (response.data != null) {
|
||||
this.schedule = response.data;
|
||||
if (response.data.config) {
|
||||
this.runConfig = JSON.parse(response.data.config);
|
||||
if (this.runConfig.environmentType) {
|
||||
delete this.runConfig.environmentType;
|
||||
(response) => {
|
||||
if (response.data != null) {
|
||||
this.schedule = response.data;
|
||||
if (response.data.config) {
|
||||
this.runConfig = JSON.parse(response.data.config);
|
||||
if (this.runConfig.environmentType) {
|
||||
delete this.runConfig.environmentType;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.schedule = {
|
||||
value: "",
|
||||
enable: false,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
this.schedule = {
|
||||
value: "",
|
||||
enable: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
crontabFill(value, resultList) {
|
||||
|
@ -492,10 +490,10 @@ export default {
|
|||
},
|
||||
saveCron() {
|
||||
if (
|
||||
this.runConfig.resourcePoolId == null
|
||||
this.runConfig.resourcePoolId == null
|
||||
) {
|
||||
this.$warning(
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -525,10 +523,10 @@ export default {
|
|||
param.workspaceId = getCurrentWorkspaceId();
|
||||
}
|
||||
if (
|
||||
this.runConfig.resourcePoolId == null
|
||||
this.runConfig.resourcePoolId == null
|
||||
) {
|
||||
this.$warning(
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -636,7 +634,7 @@ export default {
|
|||
border-bottom: 1px solid var(--primary_color);
|
||||
color: var(--primary_color);
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||
Arial, sans-serif;
|
||||
Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,79 +1,89 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- {{ JSON.stringify(eventData) }}-->
|
||||
<el-radio-group
|
||||
v-model="radio"
|
||||
style="width: 100%"
|
||||
@change="radioChange"
|
||||
class="radio-change"
|
||||
v-model="radio"
|
||||
style="width: 100%"
|
||||
@change="radioChange"
|
||||
class="radio-change"
|
||||
>
|
||||
<el-radio v-show="!isEnvSaved" :label="ENV_TYPE.DEFAULT">{{
|
||||
$t("workspace.env_group.case_env")
|
||||
}}
|
||||
</el-radio>
|
||||
<el-radio :label="ENV_TYPE.JSON">{{
|
||||
$t("workspace.env_group.env_list")
|
||||
}}</el-radio>
|
||||
$t("workspace.env_group.env_list")
|
||||
}}
|
||||
</el-radio>
|
||||
<el-radio :label="ENV_TYPE.GROUP" v-if="showEnvGroup"
|
||||
>{{ $t("workspace.env_group.name")
|
||||
>{{
|
||||
$t("workspace.env_group.name")
|
||||
}}<i class="el-icon-tickets mode-span" @click="viewGroup"></i
|
||||
></el-radio>
|
||||
></el-radio>
|
||||
</el-radio-group>
|
||||
<div
|
||||
v-for="(pe, pIndex) in eventData"
|
||||
:key="pe.id"
|
||||
v-show="radio === ENV_TYPE.JSON"
|
||||
v-for="(pe, pIndex) in eventData"
|
||||
:key="pe.id"
|
||||
v-show="radio === ENV_TYPE.JSON"
|
||||
>
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="margin-top: 8px; background: #f5f6f7; border-radius: 4px"
|
||||
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)"
|
||||
@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)"
|
||||
@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 />
|
||||
><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"
|
||||
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>
|
||||
$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>
|
||||
$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
|
||||
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']"
|
||||
filterable
|
||||
:placeholder="$t('api_test.environment.select_environment')"
|
||||
style="margin-top: 8px; width: 100%"
|
||||
size="small"
|
||||
@change="chooseEnv"
|
||||
v-show="pe.showEnvSelect"
|
||||
v-model="pe['selectEnv']"
|
||||
filterable
|
||||
: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"
|
||||
v-for="(environment, index) in pe.envs"
|
||||
:key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
|
@ -82,57 +92,57 @@
|
|||
<div v-show="radio === ENV_TYPE.GROUP">
|
||||
<div>
|
||||
<el-select
|
||||
v-show="!hasOptionGroup"
|
||||
v-model="envGroupId"
|
||||
:placeholder="$t('workspace.env_group.select')"
|
||||
@change="chooseEnvGroup"
|
||||
style="margin-top: 8px; width: 100%"
|
||||
size="small"
|
||||
v-show="!hasOptionGroup"
|
||||
v-model="envGroupId"
|
||||
:placeholder="$t('workspace.env_group.select')"
|
||||
@change="chooseEnvGroup"
|
||||
style="margin-top: 8px; width: 100%"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="(group, index) in groups"
|
||||
:key="index"
|
||||
:label="group.name"
|
||||
:value="group.id"
|
||||
v-for="(group, index) in groups"
|
||||
:key="index"
|
||||
:label="group.name"
|
||||
:value="group.id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-show="hasOptionGroup"
|
||||
v-model="envGroupId"
|
||||
:placeholder="$t('workspace.env_group.select')"
|
||||
style="margin-top: 8px; width: 100%"
|
||||
@change="chooseEnvGroup"
|
||||
size="small"
|
||||
clearable
|
||||
v-show="hasOptionGroup"
|
||||
v-model="envGroupId"
|
||||
:placeholder="$t('workspace.env_group.select')"
|
||||
style="margin-top: 8px; width: 100%"
|
||||
@change="chooseEnvGroup"
|
||||
size="small"
|
||||
clearable
|
||||
>
|
||||
<el-option-group
|
||||
v-for="group in groups"
|
||||
:key="group.label"
|
||||
:label="group.label"
|
||||
v-for="group in groups"
|
||||
:key="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"
|
||||
v-for="item in group.options"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
:disabled="item.disabled"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-dialog
|
||||
:visible="visible"
|
||||
append-to-body
|
||||
:title="$t('workspace.env_group.name')"
|
||||
@close="visible = false"
|
||||
style="height: 800px"
|
||||
: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"
|
||||
style="overflow-y: auto"
|
||||
:screen-height="'350px'"
|
||||
:read-only="true"
|
||||
></environment-group>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -141,19 +151,16 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { ENV_TYPE } from "metersphere-frontend/src/utils/constants";
|
||||
import {
|
||||
environmentGetALL,
|
||||
getEnvironmentOptions,
|
||||
} from "metersphere-frontend/src/api/environment";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {environmentGetALL, getEnvironmentOptions,} from "metersphere-frontend/src/api/environment";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import EnvironmentGroup from "@/business/plan/env/EnvironmentGroupList";
|
||||
import { getEnvironmentByProjectId } from "@/api/remote/api/api-environment";
|
||||
import { parseEnvironment } from "metersphere-frontend/src/model/EnvironmentModel";
|
||||
import {getEnvironmentByProjectId} from "@/api/remote/api/api-environment";
|
||||
import {parseEnvironment} from "metersphere-frontend/src/model/EnvironmentModel";
|
||||
|
||||
export default {
|
||||
name: "EnvSelectPopover",
|
||||
components: { MsTag, EnvironmentGroup },
|
||||
components: {MsTag, EnvironmentGroup},
|
||||
data() {
|
||||
return {
|
||||
radio: this.environmentType,
|
||||
|
@ -189,6 +196,11 @@ export default {
|
|||
},
|
||||
projectIds: Set,
|
||||
projectList: Array,
|
||||
//环境是否保存过
|
||||
isEnvSaved: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
projectEnvMap: Object,
|
||||
envMap: Map,
|
||||
environmentType: String,
|
||||
|
@ -221,7 +233,7 @@ export default {
|
|||
envRadioChange(val, index) {
|
||||
this.eventData[index].envRadio = val;
|
||||
this.eventData[index].showEnvSelect =
|
||||
this.eventData[index].envRadio === "CUSTOMIZE_ENV";
|
||||
this.eventData[index].envRadio === "CUSTOMIZE_ENV";
|
||||
},
|
||||
viewGroup() {
|
||||
this.visible = true;
|
||||
|
@ -233,24 +245,24 @@ export default {
|
|||
this.groups = data ? data : [];
|
||||
});
|
||||
} else {
|
||||
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.$set(this.groups, 0, {
|
||||
label: this.$t("workspace.env_group.available_group"),
|
||||
options: this.notDisabledGroups,
|
||||
});
|
||||
this.$set(this.groups, 1, {
|
||||
label: this.$t("workspace.env_group.not_available_group"),
|
||||
options: this.disabledGroups,
|
||||
});
|
||||
}
|
||||
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.$set(this.groups, 0, {
|
||||
label: this.$t("workspace.env_group.available_group"),
|
||||
options: this.notDisabledGroups,
|
||||
});
|
||||
this.$set(this.groups, 1, {
|
||||
label: this.$t("workspace.env_group.not_available_group"),
|
||||
options: this.disabledGroups,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -291,11 +303,11 @@ export default {
|
|||
let envId = this.envMap.get(id);
|
||||
// 选中环境是否存在
|
||||
temp.selectEnv =
|
||||
envs.filter((e) => e.id === envId).length === 0 ? null : envId;
|
||||
envs.filter((e) => e.id === envId).length === 0 ? null : envId;
|
||||
}
|
||||
if (
|
||||
this.projectEnvMap &&
|
||||
Object.keys(this.projectEnvMap).length > 0
|
||||
this.projectEnvMap &&
|
||||
Object.keys(this.projectEnvMap).length > 0
|
||||
) {
|
||||
let projectEnvMapElement = this.projectEnvMap[d];
|
||||
if (projectEnvMapElement.length > 0) {
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
<template>
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
@close="close"
|
||||
:plan-id="planId"
|
||||
:is-saving="isSaving"
|
||||
ref="baseRelevance"
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
@close="close"
|
||||
:plan-id="planId"
|
||||
:is-saving="isSaving"
|
||||
ref="baseRelevance"
|
||||
>
|
||||
<template v-slot:aside>
|
||||
<ms-api-module
|
||||
class="node-tree"
|
||||
:relevance-project-id="projectId"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@protocolChange="handleProtocolChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:show-case-num="false"
|
||||
:is-read-only="true"
|
||||
:is-relevance="true"
|
||||
ref="nodeTree"
|
||||
class="node-tree"
|
||||
:relevance-project-id="projectId"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@protocolChange="handleProtocolChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:show-case-num="false"
|
||||
:is-read-only="true"
|
||||
:is-relevance="true"
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<relevance-api-list
|
||||
v-if="isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="true"
|
||||
:plan-id="planId"
|
||||
:versionFilters="versionFilters"
|
||||
:version-enable="versionEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiList"
|
||||
v-if="isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="true"
|
||||
:plan-id="planId"
|
||||
:versionFilters="versionFilters"
|
||||
:version-enable="versionEnable"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiList"
|
||||
>
|
||||
<template v-slot:version>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion($event, 'api')"
|
||||
margin-left="10"
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion($event, 'api')"
|
||||
margin-left="10"
|
||||
/>
|
||||
</template>
|
||||
</relevance-api-list>
|
||||
|
||||
<relevance-case-list
|
||||
v-if="!isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="true"
|
||||
:versionFilters="versionFilters"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiCaseList"
|
||||
v-if="!isApiListEnable"
|
||||
:current-protocol="currentProtocol"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:is-api-list-enable="isApiListEnable"
|
||||
:project-id="projectId"
|
||||
:is-test-plan="true"
|
||||
:versionFilters="versionFilters"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
@isApiListEnableChange="isApiListEnableChange"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiCaseList"
|
||||
>
|
||||
<template v-slot:version>
|
||||
<mx-version-select
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion($event, 'case')"
|
||||
margin-left="10"
|
||||
v-xpack
|
||||
:project-id="projectId"
|
||||
@changeVersion="changeVersion($event, 'case')"
|
||||
margin-left="10"
|
||||
/>
|
||||
</template>
|
||||
</relevance-case-list>
|
||||
|
@ -75,18 +75,12 @@
|
|||
<script>
|
||||
import TestCaseRelevanceBase from "../base/TestCaseRelevanceBase";
|
||||
import MxVersionSelect from "metersphere-frontend/src/components/version/MxVersionSelect";
|
||||
import {
|
||||
apiDefinitionListBatch,
|
||||
apiDefinitionRelevance,
|
||||
} from "@/api/remote/api/api-definition";
|
||||
import {
|
||||
apiTestCaseListBlobs,
|
||||
apiTestCaseRelevance,
|
||||
} from "@/api/remote/api/api-case";
|
||||
import {apiDefinitionListBatch, apiDefinitionRelevance,} from "@/api/remote/api/api-definition";
|
||||
import {apiTestCaseListBlobs, apiTestCaseRelevance,} from "@/api/remote/api/api-case";
|
||||
import RelevanceApiList from "@/business/plan/view/comonents/api/RelevanceApiList";
|
||||
import RelevanceCaseList from "@/business/plan/view/comonents/api/RelevanceCaseList";
|
||||
import MsApiModule from "@/business/plan/view/comonents/api/module/ApiModule";
|
||||
import { getVersionFilters } from "@/business/utils/sdk-utils";
|
||||
import {getVersionFilters} from "@/business/utils/sdk-utils";
|
||||
|
||||
export default {
|
||||
name: "TestCaseApiRelevance",
|
||||
|
@ -206,51 +200,44 @@ export default {
|
|||
//查找所有数据
|
||||
let params = this.$refs.apiList.getConditions();
|
||||
apiDefinitionListBatch(params)
|
||||
.then((response) => {
|
||||
let apis = response.data;
|
||||
environmentId = this.$refs.apiList.environmentId;
|
||||
selectIds = Array.from(apis).map((row) => row.id);
|
||||
let protocol = this.$refs.apiList.currentProtocol;
|
||||
this.postRelevance(
|
||||
apiDefinitionRelevance,
|
||||
environmentId,
|
||||
selectIds,
|
||||
protocol
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
.then((response) => {
|
||||
let apis = response.data;
|
||||
environmentId = this.$refs.apiList.environmentId;
|
||||
selectIds = Array.from(apis).map((row) => row.id);
|
||||
let protocol = this.$refs.apiList.currentProtocol;
|
||||
this.postRelevance(
|
||||
apiDefinitionRelevance,
|
||||
environmentId,
|
||||
selectIds,
|
||||
protocol
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
} else {
|
||||
let params = this.$refs.apiCaseList.getConditions();
|
||||
apiTestCaseListBlobs(params)
|
||||
.then((response) => {
|
||||
let apiCases = response.data;
|
||||
environmentId = this.$refs.apiCaseList.environmentId;
|
||||
selectIds = Array.from(apiCases).map((row) => row.id);
|
||||
let protocol = this.$refs.apiCaseList.currentProtocol;
|
||||
this.postRelevance(
|
||||
apiTestCaseRelevance,
|
||||
environmentId,
|
||||
selectIds,
|
||||
protocol
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
.then((response) => {
|
||||
let apiCases = response.data;
|
||||
environmentId = this.$refs.apiCaseList.environmentId;
|
||||
selectIds = Array.from(apiCases).map((row) => row.id);
|
||||
let protocol = this.$refs.apiCaseList.currentProtocol;
|
||||
this.postRelevance(
|
||||
apiTestCaseRelevance,
|
||||
environmentId,
|
||||
selectIds,
|
||||
protocol
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
postRelevance(relevanceList, environmentId, selectIds, protocol) {
|
||||
let param = {};
|
||||
if (protocol !== "DUBBO") {
|
||||
if (!environmentId) {
|
||||
this.isSaving = false;
|
||||
this.$warning(this.$t("api_test.environment.select_environment"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (selectIds.length < 1) {
|
||||
this.isSaving = false;
|
||||
this.$warning(this.$t("test_track.plan_view.please_choose_test_case"));
|
||||
|
@ -260,19 +247,19 @@ export default {
|
|||
param.selectIds = selectIds;
|
||||
param.environmentId = environmentId;
|
||||
relevanceList(param)
|
||||
.then(() => {
|
||||
this.$success(this.$t("plan.relevance_case_success"));
|
||||
this.$emit("refresh");
|
||||
this.refresh();
|
||||
this.isSaving = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
.then(() => {
|
||||
this.$success(this.$t("plan.relevance_case_success"));
|
||||
this.$emit("refresh");
|
||||
this.refresh();
|
||||
this.isSaving = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
},
|
||||
getVersionOptions() {
|
||||
getVersionFilters(this.projectId).then(
|
||||
(r) => (this.versionFilters = r.data)
|
||||
(r) => (this.versionFilters = r.data)
|
||||
);
|
||||
},
|
||||
changeVersion(currentVersion, type) {
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
<template>
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
@close="close"
|
||||
:plan-id="planId"
|
||||
ref="baseRelevance"
|
||||
:is-saving="isSaving"
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
@close="close"
|
||||
:plan-id="planId"
|
||||
ref="baseRelevance"
|
||||
:is-saving="isSaving"
|
||||
>
|
||||
<template v-slot:aside>
|
||||
<ms-api-scenario-module
|
||||
class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:show-case-num="false"
|
||||
:relevance-project-id="projectId"
|
||||
:is-read-only="true"
|
||||
ref="nodeTree"
|
||||
class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:show-case-num="false"
|
||||
:relevance-project-id="projectId"
|
||||
:is-read-only="true"
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<relevance-scenario-list
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
:project-id="projectId"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiScenarioList"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
:project-id="projectId"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiScenarioList"
|
||||
/>
|
||||
</test-case-relevance-base>
|
||||
</template>
|
||||
|
@ -35,15 +35,10 @@
|
|||
<script>
|
||||
import TestCaseRelevanceBase from "../base/TestCaseRelevanceBase";
|
||||
import RelevanceScenarioList from "./RelevanceScenarioList";
|
||||
import { ENV_TYPE } from "metersphere-frontend/src/utils/constants";
|
||||
import {
|
||||
getCurrentProjectID,
|
||||
hasLicense,
|
||||
strMapToObj,
|
||||
} from "@/business/utils/sdk-utils";
|
||||
import { getVersionFilters } from "@/business/utils/sdk-utils";
|
||||
import { testPlanAutoCheck } from "@/api/remote/plan/test-plan";
|
||||
import { scenarioRelevance } from "@/api/remote/plan/test-plan-scenario";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {getCurrentProjectID, getVersionFilters, hasLicense, strMapToObj,} from "@/business/utils/sdk-utils";
|
||||
import {testPlanAutoCheck} from "@/api/remote/plan/test-plan";
|
||||
import {scenarioRelevance} from "@/api/remote/plan/test-plan-scenario";
|
||||
import MsApiScenarioModule from "@/business/plan/view/comonents/api/module/ApiScenarioModule";
|
||||
|
||||
export default {
|
||||
|
@ -137,11 +132,6 @@ export default {
|
|||
},
|
||||
async saveCaseRelevance() {
|
||||
this.isSaving = true;
|
||||
const sign = await this.$refs.apiScenarioList.checkEnv();
|
||||
if (!sign) {
|
||||
this.isSaving = false;
|
||||
return false;
|
||||
}
|
||||
let selectIds = [];
|
||||
let selectRows = this.$refs.apiScenarioList.selectRows;
|
||||
const envMap = this.$refs.apiScenarioList.projectEnvMap;
|
||||
|
@ -157,15 +147,7 @@ export default {
|
|||
selectRows.forEach((row) => {
|
||||
selectIds.push(row.id);
|
||||
});
|
||||
if (envType === ENV_TYPE.JSON && (!envMap || envMap.size < 1)) {
|
||||
this.isSaving = false;
|
||||
this.$warning(this.$t("api_test.environment.select_environment"));
|
||||
return false;
|
||||
} else if (envType === ENV_TYPE.GROUP && !envGroupId) {
|
||||
this.isSaving = false;
|
||||
this.$warning(this.$t("api_test.environment.select_environment"));
|
||||
return false;
|
||||
}
|
||||
|
||||
let param = {};
|
||||
param.planId = this.planId;
|
||||
param.mapping = strMapToObj(map);
|
||||
|
@ -175,16 +157,16 @@ export default {
|
|||
param.ids = selectIds;
|
||||
param.condition = this.$refs.apiScenarioList.condition;
|
||||
scenarioRelevance(param)
|
||||
.then(() => {
|
||||
this.isSaving = false;
|
||||
this.$success(this.$t("plan.relevance_case_success"));
|
||||
this.$emit("refresh");
|
||||
this.refresh();
|
||||
this.autoCheckStatus();
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
.then(() => {
|
||||
this.isSaving = false;
|
||||
this.$success(this.$t("plan.relevance_case_success"));
|
||||
this.$emit("refresh");
|
||||
this.refresh();
|
||||
this.autoCheckStatus();
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
},
|
||||
autoCheckStatus() {
|
||||
// 检查执行结果,自动更新计划状态
|
||||
|
@ -199,7 +181,7 @@ export default {
|
|||
getVersionOptions() {
|
||||
if (hasLicense()) {
|
||||
getVersionFilters(getCurrentProjectID()).then(
|
||||
(r) => (this.versionFilters = r.data)
|
||||
(r) => (this.versionFilters = r.data)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
<ms-test-plan-common-component>
|
||||
<template v-slot:aside>
|
||||
<ms-api-module
|
||||
v-if="model === 'api'"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@protocolChange="handleProtocolChange"
|
||||
@refreshTable="refreshTable"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
:is-read-only="true"
|
||||
:redirectCharType="redirectCharType"
|
||||
ref="apiNodeTree">
|
||||
v-if="model === 'api'"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@protocolChange="handleProtocolChange"
|
||||
@refreshTable="refreshTable"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
:is-read-only="true"
|
||||
:redirectCharType="redirectCharType"
|
||||
ref="apiNodeTree">
|
||||
<template v-slot:header>
|
||||
<div class="model-change-radio">
|
||||
<el-radio v-model="model" label="api">{{ $t('commons.api_case') }}</el-radio>
|
||||
|
@ -22,14 +22,14 @@
|
|||
</ms-api-module>
|
||||
|
||||
<ms-api-scenario-module
|
||||
v-if="model === 'scenario'"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refreshTable"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:is-read-only="true"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
ref="scenarioNodeTree">
|
||||
v-if="model === 'scenario'"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refreshTable"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:is-read-only="true"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
ref="scenarioNodeTree">
|
||||
<template v-slot:header>
|
||||
<div class="model-change-radio">
|
||||
<el-radio v-model="model" label="api">{{ $t('commons.api_case') }}</el-radio>
|
||||
|
@ -43,62 +43,62 @@
|
|||
<template v-slot:main>
|
||||
<!--测试用例列表-->
|
||||
<test-plan-api-case-list
|
||||
v-if="model === 'api'"
|
||||
:current-protocol="currentProtocol"
|
||||
:currentRow="currentRow"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:is-case-relevance="true"
|
||||
:version-enable="versionEnable"
|
||||
:model="'plan'"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
:clickType="clickType"
|
||||
@refresh="refreshTree"
|
||||
@relevanceCase="openTestCaseRelevanceDialog"
|
||||
ref="apiCaseList"/>
|
||||
v-if="model === 'api'"
|
||||
:current-protocol="currentProtocol"
|
||||
:currentRow="currentRow"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:is-case-relevance="true"
|
||||
:version-enable="versionEnable"
|
||||
:model="'plan'"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
:clickType="clickType"
|
||||
@refresh="refreshTree"
|
||||
@relevanceCase="openTestCaseRelevanceDialog"
|
||||
ref="apiCaseList"/>
|
||||
|
||||
<ms-test-plan-api-scenario-list
|
||||
v-if="model === 'scenario'"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
:clickType="clickType"
|
||||
@refresh="refreshTree"
|
||||
@relevanceCase="openTestCaseRelevanceDialog"
|
||||
ref="apiScenarioList"/>
|
||||
v-if="model === 'scenario'"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
:plan-status="planStatus"
|
||||
:clickType="clickType"
|
||||
@refresh="refreshTree"
|
||||
@relevanceCase="openTestCaseRelevanceDialog"
|
||||
ref="apiScenarioList"/>
|
||||
|
||||
</template>
|
||||
|
||||
<test-case-api-relevance
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
:model="model"
|
||||
:version-enable="versionEnable"
|
||||
ref="apiCaseRelevance"/>
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
:model="model"
|
||||
:version-enable="versionEnable"
|
||||
ref="apiCaseRelevance"/>
|
||||
|
||||
<test-case-scenario-relevance
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
:model="model"
|
||||
:version-enable="versionEnable"
|
||||
ref="scenarioCaseRelevance"/>
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
:model="model"
|
||||
:version-enable="versionEnable"
|
||||
ref="scenarioCaseRelevance"/>
|
||||
|
||||
</ms-test-plan-common-component>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeTree from "metersphere-frontend/src/components/module/MsNodeTree";
|
||||
import MsTestPlanCommonComponent from "../base/TestPlanCommonComponent";
|
||||
import TestPlanApiCaseList from "./TestPlanApiCaseList";
|
||||
import TestCaseApiRelevance from "./TestCaseApiRelevance";
|
||||
import MsTestPlanApiScenarioList from "./TestPlanApiScenarioList";
|
||||
import TestCaseScenarioRelevance from "./TestCaseScenarioRelevance";
|
||||
import MsApiModule from "@/business/plan/view/comonents/api/module/ApiModule";
|
||||
import MsApiScenarioModule from "@/business/plan/view/comonents/api/module/ApiScenarioModule";
|
||||
import NodeTree from "metersphere-frontend/src/components/module/MsNodeTree";
|
||||
import MsTestPlanCommonComponent from "../base/TestPlanCommonComponent";
|
||||
import TestPlanApiCaseList from "./TestPlanApiCaseList";
|
||||
import TestCaseApiRelevance from "./TestCaseApiRelevance";
|
||||
import MsTestPlanApiScenarioList from "./TestPlanApiScenarioList";
|
||||
import TestCaseScenarioRelevance from "./TestCaseScenarioRelevance";
|
||||
import MsApiModule from "@/business/plan/view/comonents/api/module/ApiModule";
|
||||
import MsApiScenarioModule from "@/business/plan/view/comonents/api/module/ApiScenarioModule";
|
||||
|
||||
export default {
|
||||
name: "TestPlanApi",
|
||||
|
@ -140,19 +140,19 @@ export default {
|
|||
this.selectNodeIds = [];
|
||||
this.moduleOptions = {};
|
||||
},
|
||||
redirectCharType(){
|
||||
if(this.redirectCharType=='scenario'){
|
||||
redirectCharType() {
|
||||
if (this.redirectCharType == 'scenario') {
|
||||
this.model = 'scenario';
|
||||
}else{
|
||||
} else {
|
||||
this.model = 'api';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkRedirectCharType(){
|
||||
if(this.redirectCharType=='scenario'){
|
||||
checkRedirectCharType() {
|
||||
if (this.redirectCharType == 'scenario') {
|
||||
this.model = 'scenario';
|
||||
}else{
|
||||
} else {
|
||||
this.model = 'api';
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4,36 +4,36 @@
|
|||
<slot name="header"></slot>
|
||||
|
||||
<ms-node-tree
|
||||
v-if="refreshDataOver"
|
||||
v-loading="loading"
|
||||
:tree-nodes="data"
|
||||
:type="isReadOnly ? 'view' : 'edit'"
|
||||
:allLabel="$t('api_test.definition.api_all')"
|
||||
:default-label="$t('api_test.definition.unplanned_api')"
|
||||
:hide-opretor="true"
|
||||
local-suffix="api_definition"
|
||||
@refresh="list"
|
||||
@filter="filter"
|
||||
:show-case-num="showCaseNum"
|
||||
:delete-permission="['PROJECT_API_DEFINITION:READ+DELETE_API']"
|
||||
:add-permission="['PROJECT_API_DEFINITION:READ+CREATE_API']"
|
||||
:update-permission="['PROJECT_API_DEFINITION:READ+EDIT_API']"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
ref="nodeTree">
|
||||
v-if="refreshDataOver"
|
||||
v-loading="loading"
|
||||
:tree-nodes="data"
|
||||
:type="isReadOnly ? 'view' : 'edit'"
|
||||
:allLabel="$t('api_test.definition.api_all')"
|
||||
:default-label="$t('api_test.definition.unplanned_api')"
|
||||
:hide-opretor="true"
|
||||
local-suffix="api_definition"
|
||||
@refresh="list"
|
||||
@filter="filter"
|
||||
:show-case-num="showCaseNum"
|
||||
:delete-permission="['PROJECT_API_DEFINITION:READ+DELETE_API']"
|
||||
:add-permission="['PROJECT_API_DEFINITION:READ+CREATE_API']"
|
||||
:update-permission="['PROJECT_API_DEFINITION:READ+EDIT_API']"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
ref="nodeTree">
|
||||
|
||||
<template v-slot:header>
|
||||
<api-module-header
|
||||
:show-operator="showOperator"
|
||||
:condition="condition"
|
||||
:current-module="currentModule"
|
||||
:is-read-only="isReadOnly"
|
||||
:moduleOptions="data"
|
||||
:options="options"
|
||||
:total="total"
|
||||
:select-project-id="projectId"
|
||||
@refreshTable="$emit('refreshTable')"
|
||||
@schedule="$emit('schedule')"
|
||||
@refresh="refresh"/>
|
||||
:show-operator="showOperator"
|
||||
:condition="condition"
|
||||
:current-module="currentModule"
|
||||
:is-read-only="isReadOnly"
|
||||
:moduleOptions="data"
|
||||
:options="options"
|
||||
:total="total"
|
||||
:select-project-id="projectId"
|
||||
@refreshTable="$emit('refreshTable')"
|
||||
@schedule="$emit('schedule')"
|
||||
@refresh="refresh"/>
|
||||
</template>
|
||||
|
||||
</ms-node-tree>
|
||||
|
@ -124,6 +124,9 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initProtocol();
|
||||
},
|
||||
watch: {
|
||||
'condition.filterText'() {
|
||||
this.filter();
|
||||
|
@ -200,19 +203,19 @@ export default {
|
|||
this.loading = true;
|
||||
if (this.isPlanModel) {
|
||||
apiCaseModulePlanList(this.planId, this.condition.protocol)
|
||||
.then((response) => {
|
||||
this.getData(response);
|
||||
});
|
||||
.then((response) => {
|
||||
this.getData(response);
|
||||
});
|
||||
} else if (this.isRelevanceModel) {
|
||||
apiModuleProjectList(this.relevanceProjectId, this.condition.protocol)
|
||||
.then((response) => {
|
||||
this.getData(response);
|
||||
});
|
||||
.then((response) => {
|
||||
this.getData(response);
|
||||
});
|
||||
} else {
|
||||
apiModuleProjectList(getCurrentProjectID())
|
||||
.then((response) => {
|
||||
this.getData(response);
|
||||
});
|
||||
.then((response) => {
|
||||
this.getData(response);
|
||||
});
|
||||
}
|
||||
},
|
||||
nodeChange(node, nodeIds, pNodes) {
|
||||
|
@ -228,14 +231,14 @@ export default {
|
|||
this.loading = true;
|
||||
if (this.isPlanModel) {
|
||||
apiCaseModulePlanList(this.planId, this.condition.protocol)
|
||||
.then((response) => {
|
||||
this.getNohupReloadData(response, selectNodeId);
|
||||
});
|
||||
.then((response) => {
|
||||
this.getNohupReloadData(response, selectNodeId);
|
||||
});
|
||||
} else if (this.isRelevanceModel) {
|
||||
apiModuleProjectList(this.relevanceProjectId, this.condition.protocol)
|
||||
.then((response) => {
|
||||
this.getNohupReloadData(response, selectNodeId);
|
||||
});
|
||||
.then((response) => {
|
||||
this.getNohupReloadData(response, selectNodeId);
|
||||
});
|
||||
}
|
||||
},
|
||||
getData(response) {
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
<template>
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
@close="close"
|
||||
:plan-id="planId"
|
||||
:is-saving="isSaving"
|
||||
ref="baseRelevance"
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
@close="close"
|
||||
:plan-id="planId"
|
||||
:is-saving="isSaving"
|
||||
ref="baseRelevance"
|
||||
>
|
||||
<template v-slot:aside>
|
||||
<ui-scenario-module
|
||||
class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:relevance-project-id="projectId"
|
||||
:is-read-only="true"
|
||||
:show-case-num="false"
|
||||
ref="nodeTree"
|
||||
class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refreshTable="refresh"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:relevance-project-id="projectId"
|
||||
:is-read-only="true"
|
||||
:show-case-num="false"
|
||||
ref="nodeTree"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<relevance-ui-scenario-list
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
:project-id="projectId"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiScenarioList"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:trash-enable="trashEnable"
|
||||
:version-enable="versionEnable"
|
||||
:plan-id="planId"
|
||||
:project-id="projectId"
|
||||
@selectCountChange="setSelectCounts"
|
||||
ref="apiScenarioList"
|
||||
/>
|
||||
</test-case-relevance-base>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TestCaseRelevanceBase from "../base/TestCaseRelevanceBase";
|
||||
import { strMapToObj } from "metersphere-frontend/src/utils";
|
||||
import { ENV_TYPE } from "metersphere-frontend/src/utils/constants";
|
||||
import {strMapToObj} from "metersphere-frontend/src/utils";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import RelevanceUiScenarioList from "@/business/plan/view/comonents/ui/RelevanceUiScenarioList";
|
||||
import { testPlanAutoCheck } from "@/api/remote/plan/test-plan";
|
||||
import { testPlanUiScenarioRelevanceListIds } from "@/api/remote/ui/test-plan-ui-scenario-case";
|
||||
import {testPlanAutoCheck} from "@/api/remote/plan/test-plan";
|
||||
import {testPlanUiScenarioRelevanceListIds} from "@/api/remote/ui/test-plan-ui-scenario-case";
|
||||
import UiScenarioModule from "@/business/plan/view/comonents/ui/UiScenarioModule";
|
||||
import { uiAutomationRelevance } from "@/api/remote/ui/api-scenario";
|
||||
import {uiAutomationRelevance} from "@/api/remote/ui/api-scenario";
|
||||
|
||||
export default {
|
||||
name: "TestCaseUiScenarioRelevance",
|
||||
|
@ -163,12 +163,6 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!envMap || envMap.size == 0) {
|
||||
this.isSaving = false;
|
||||
this.$warning(this.$t("api_test.environment.select_environment"));
|
||||
return;
|
||||
}
|
||||
|
||||
let param = {};
|
||||
param.planId = this.planId;
|
||||
param.mapping = strMapToObj(map);
|
||||
|
@ -184,17 +178,17 @@ export default {
|
|||
}
|
||||
this.loading = true;
|
||||
uiAutomationRelevance(param)
|
||||
.then(() => {
|
||||
this.loading = false;
|
||||
this.isSaving = false;
|
||||
this.$success(this.$t("plan.relevance_case_success"));
|
||||
this.$emit("refresh");
|
||||
this.refresh();
|
||||
this.autoCheckStatus();
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
.then(() => {
|
||||
this.loading = false;
|
||||
this.isSaving = false;
|
||||
this.$success(this.$t("plan.relevance_case_success"));
|
||||
this.$emit("refresh");
|
||||
this.refresh();
|
||||
this.autoCheckStatus();
|
||||
})
|
||||
.catch(() => {
|
||||
this.isSaving = false;
|
||||
});
|
||||
},
|
||||
autoCheckStatus() {
|
||||
// 检查执行结果,自动更新计划状态
|
||||
|
|
Loading…
Reference in New Issue