feat(测试跟踪): 支持区分默认环境和执行环境运行
https://www.tapd.cn/55049933/prong/stories/view/1155049933001010410 --user=郭雨琦
This commit is contained in:
parent
4dc898b8d5
commit
18f5ed8928
|
@ -322,18 +322,6 @@ public class TestPlanApiCaseService {
|
|||
*/
|
||||
public List<MsExecResponseDTO> run(BatchRunDefinitionRequest request) {
|
||||
if (request.getConfig() != null) {
|
||||
RunModeConfigDTO config = request.getConfig();
|
||||
if (config != null) {
|
||||
String envType = config.getEnvironmentType();
|
||||
String envGroupId = config.getEnvironmentGroupId();
|
||||
Map<String, String> envMap = config.getEnvMap();
|
||||
if ((StringUtils.equals(envType, EnvironmentType.JSON.toString()) && envMap != null && !envMap.isEmpty())) {
|
||||
setApiCaseEnv(null, request.getPlanIds(), envMap);
|
||||
} else if ((StringUtils.equals(envType, EnvironmentType.GROUP.toString()) && StringUtils.isNotBlank(envGroupId))) {
|
||||
Map<String, String> map = environmentGroupProjectService.getEnvMap(envGroupId);
|
||||
setApiCaseEnv(null, request.getPlanIds(), map);
|
||||
}
|
||||
}
|
||||
return testPlanApiCaseExecuteService.run(request);
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -1562,6 +1562,8 @@ const message = {
|
|||
config_environment: "Config Environment",
|
||||
copy_environment: "copy environment",
|
||||
environment: "Environment",
|
||||
default_environment:"Default environment",
|
||||
choose_new_environment:"Choose new environment",
|
||||
environment_type: "Environment Type",
|
||||
environment_json: "Environment Config",
|
||||
environment_group_id: "Environment Group ID",
|
||||
|
|
|
@ -1571,6 +1571,8 @@ const message = {
|
|||
config_environment: "配置环境",
|
||||
copy_environment: "复制环境",
|
||||
environment: "环境",
|
||||
default_environment:"默认环境",
|
||||
choose_new_environment:"选择新环境",
|
||||
environment_type: "环境类型",
|
||||
environment_json: "环境配置",
|
||||
environment_group_id: "环境组ID",
|
||||
|
|
|
@ -1568,6 +1568,8 @@ const message = {
|
|||
config_environment: "配置環境",
|
||||
copy_environment: "復製環境",
|
||||
environment: "環境",
|
||||
default_environment: "默認環境",
|
||||
choose_new_environment:"選擇新環境",
|
||||
environment_type: "環境类型",
|
||||
environment_json: "環境配置",
|
||||
environment_group_id: "環境組ID",
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.plan.dto;
|
||||
|
||||
public enum ExecutionWay {
|
||||
/**
|
||||
* 仅运行
|
||||
*/
|
||||
RUN,
|
||||
|
||||
/**
|
||||
* 仅保存
|
||||
*/
|
||||
SAVE,
|
||||
|
||||
/**
|
||||
* 运行保存
|
||||
*/
|
||||
RUN_SAVE
|
||||
}
|
|
@ -4,6 +4,7 @@ import io.metersphere.commons.constants.ReportTriggerMode;
|
|||
import io.metersphere.commons.constants.ScheduleGroup;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.HttpHeaderUtils;
|
||||
import io.metersphere.plan.dto.ExecutionWay;
|
||||
import io.metersphere.plan.service.TestPlanService;
|
||||
import io.metersphere.sechedule.MsScheduleJob;
|
||||
import io.metersphere.service.BaseUserService;
|
||||
|
@ -59,7 +60,7 @@ public class TestPlanTestJob extends MsScheduleJob {
|
|||
|
||||
// 定时任务指定调用微服务的user
|
||||
HttpHeaderUtils.runAsUser(baseUserService.getUserDTO(runUserId));
|
||||
testPlanService.run(runResourceId, runProjectId, runUserId, ReportTriggerMode.SCHEDULE.name(), null, config);
|
||||
testPlanService.run(runResourceId, runProjectId, runUserId, ReportTriggerMode.SCHEDULE.name(), null, ExecutionWay.RUN.name(), config);
|
||||
HttpHeaderUtils.clearUser();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,5 +34,8 @@ public class TestPlanRunRequest {
|
|||
//ui 测试
|
||||
private String browser;
|
||||
private boolean headlessEnabled;
|
||||
|
||||
//执行方式:仅保存,保存并执行,仅执行
|
||||
private String executionWay;
|
||||
}
|
||||
|
||||
|
|
|
@ -764,7 +764,7 @@ public class TestPlanService {
|
|||
return testPlanReportService.genTestPlanReportBySchedule(planReportId, planId, userId, triggerMode, runModeConfigDTO);
|
||||
}
|
||||
|
||||
public String run(String testPlanID, String projectID, String userId, String triggerMode, String planReportId, String apiRunConfig) {
|
||||
public String run(String testPlanId, String projectId, String userId, String triggerMode, String planReportId,String executionWay, String apiRunConfig) {
|
||||
RunModeConfigDTO runModeConfig = null;
|
||||
try {
|
||||
runModeConfig = JSON.parseObject(apiRunConfig, RunModeConfigDTO.class);
|
||||
|
@ -776,9 +776,10 @@ public class TestPlanService {
|
|||
}
|
||||
|
||||
//环境参数为空时,依据测试计划保存的环境执行
|
||||
if ((StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && StringUtils.isBlank(runModeConfig.getEnvironmentGroupId()))
|
||||
|| (!StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && MapUtils.isEmpty(runModeConfig.getEnvMap()))) {
|
||||
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanID);
|
||||
if (((StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && StringUtils.isBlank(runModeConfig.getEnvironmentGroupId()))
|
||||
|| (!StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && MapUtils.isEmpty(runModeConfig.getEnvMap())))
|
||||
&& !StringUtils.equals(executionWay,ExecutionWay.RUN.name())) {
|
||||
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
|
||||
if (StringUtils.isNotEmpty(testPlanWithBLOBs.getRunModeConfig())) {
|
||||
try {
|
||||
Map json = JSON.parseMap(testPlanWithBLOBs.getRunModeConfig());
|
||||
|
@ -788,7 +789,7 @@ public class TestPlanService {
|
|||
String envType = testPlanRunRequest.getEnvironmentType();
|
||||
Map<String, String> envMap = testPlanRunRequest.getEnvMap();
|
||||
String environmentGroupId = testPlanRunRequest.getEnvironmentGroupId();
|
||||
runModeConfig = getRunModeConfigDTO(testPlanRunRequest, envType, envMap, environmentGroupId, testPlanID);
|
||||
runModeConfig = getRunModeConfigDTO(testPlanRunRequest, envType, envMap, environmentGroupId, testPlanId);
|
||||
if (!testPlanRunRequest.isRunWithinResourcePool()) {
|
||||
runModeConfig.setResourcePoolId(null);
|
||||
}
|
||||
|
@ -803,9 +804,9 @@ public class TestPlanService {
|
|||
}
|
||||
|
||||
//创建测试报告,然后返回的ID重新赋值为resourceID,作为后续的参数
|
||||
TestPlanScheduleReportInfoDTO reportInfoDTO = this.genTestPlanReport(planReportId, testPlanID, userId, triggerMode, runModeConfig);
|
||||
TestPlanScheduleReportInfoDTO reportInfoDTO = this.genTestPlanReport(planReportId, testPlanId, userId, triggerMode, runModeConfig);
|
||||
//测试计划准备执行,取消测试计划的实际结束时间
|
||||
extTestPlanMapper.updateActualEndTimeIsNullById(testPlanID);
|
||||
extTestPlanMapper.updateActualEndTimeIsNullById(testPlanId);
|
||||
|
||||
LoggerUtil.info("预生成测试计划报告【" + reportInfoDTO.getTestPlanReport() != null ? reportInfoDTO.getTestPlanReport().getName() : StringUtils.EMPTY + "】计划报告ID[" + planReportId + "]");
|
||||
|
||||
|
@ -821,7 +822,7 @@ public class TestPlanService {
|
|||
if (reportInfoDTO.getPlanScenarioIdMap() != null) {
|
||||
//执行场景执行任务
|
||||
LoggerUtil.info("开始执行测试计划场景用例 " + planReportId);
|
||||
scenarioReportMap = this.executeScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
|
||||
scenarioReportMap = this.executeScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
|
||||
}
|
||||
|
||||
if (reportInfoDTO.getPerformanceIdMap() != null) {
|
||||
|
@ -833,7 +834,7 @@ public class TestPlanService {
|
|||
if (reportInfoDTO.getUiScenarioIdMap() != null) {
|
||||
//执行UI场景执行任务
|
||||
LoggerUtil.info("开始执行测试计划 UI 场景用例 " + planReportId);
|
||||
uiScenarioReportMap = this.executeUiScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, reportInfoDTO.getUiScenarioIdMap());
|
||||
uiScenarioReportMap = this.executeUiScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getUiScenarioIdMap());
|
||||
}
|
||||
|
||||
LoggerUtil.info("开始生成测试计划报告内容 " + planReportId);
|
||||
|
@ -1517,24 +1518,29 @@ public class TestPlanService {
|
|||
String environmentGroupId = testplanRunRequest.getEnvironmentGroupId();
|
||||
String testPlanId = testplanRunRequest.getTestPlanId();
|
||||
RunModeConfigDTO runModeConfig = getRunModeConfigDTO(testplanRunRequest, envType, envMap, environmentGroupId, testPlanId);
|
||||
if (!testplanRunRequest.isRunWithinResourcePool()) {
|
||||
runModeConfig.setResourcePoolId(null);
|
||||
}
|
||||
|
||||
String apiRunConfig = JSON.toJSONString(runModeConfig);
|
||||
return this.run(testPlanId, testplanRunRequest.getProjectId(),
|
||||
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(), testplanRunRequest.getReportId(), apiRunConfig);
|
||||
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(), testplanRunRequest.getReportId(),testplanRunRequest.getExecutionWay(), apiRunConfig);
|
||||
|
||||
}
|
||||
|
||||
private RunModeConfigDTO getRunModeConfigDTO(TestPlanRunRequest testplanRunRequest, String envType, Map<String, String> envMap, String environmentGroupId, String testPlanId) {
|
||||
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
|
||||
if (!testplanRunRequest.isRunWithinResourcePool()) {
|
||||
runModeConfig.setResourcePoolId(null);
|
||||
}
|
||||
runModeConfig.setEnvironmentType(testplanRunRequest.getEnvironmentType());
|
||||
if (StringUtils.equals(envType, "JSON") && !envMap.isEmpty()) {
|
||||
runModeConfig.setEnvMap(testplanRunRequest.getEnvMap());
|
||||
this.setPlanCaseEnv(testPlanId, runModeConfig);
|
||||
if (!StringUtils.equals(testplanRunRequest.getExecutionWay(),ExecutionWay.RUN.name())){
|
||||
this.setPlanCaseEnv(testPlanId, runModeConfig);
|
||||
}
|
||||
} else if (StringUtils.equals(envType, "GROUP") && StringUtils.isNotBlank(environmentGroupId)) {
|
||||
runModeConfig.setEnvironmentGroupId(testplanRunRequest.getEnvironmentGroupId());
|
||||
this.setPlanCaseEnv(testPlanId, runModeConfig);
|
||||
if (!StringUtils.equals(testplanRunRequest.getExecutionWay(),ExecutionWay.RUN.name())){
|
||||
this.setPlanCaseEnv(testPlanId, runModeConfig);
|
||||
}
|
||||
}
|
||||
runModeConfig.setMode(testplanRunRequest.getMode());
|
||||
runModeConfig.setResourcePoolId(testplanRunRequest.getResourcePoolId());
|
||||
|
@ -1827,6 +1833,19 @@ public class TestPlanService {
|
|||
public void updateRunModeConfig(TestPlanRunRequest testplanRunRequest) {
|
||||
String testPlanId = testplanRunRequest.getTestPlanId();
|
||||
updatePlan(testplanRunRequest, testPlanId);
|
||||
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
|
||||
if (!testplanRunRequest.isRunWithinResourcePool()) {
|
||||
runModeConfig.setResourcePoolId(null);
|
||||
}
|
||||
runModeConfig.setEnvironmentType(testplanRunRequest.getEnvironmentType());
|
||||
if (StringUtils.equals(testplanRunRequest.getEnvironmentType(), "JSON") && !testplanRunRequest.getEnvMap().isEmpty()) {
|
||||
runModeConfig.setEnvMap(testplanRunRequest.getEnvMap());
|
||||
this.setPlanCaseEnv(testPlanId, runModeConfig);
|
||||
} else if (StringUtils.equals(testplanRunRequest.getEnvironmentType(), "GROUP") && StringUtils.isNotBlank(testplanRunRequest.getEnvironmentGroupId())) {
|
||||
runModeConfig.setEnvironmentGroupId(testplanRunRequest.getEnvironmentGroupId());
|
||||
runModeConfig.setEnvMap(testplanRunRequest.getEnvMap());
|
||||
this.setPlanCaseEnv(testPlanId, runModeConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean haveUiCase(String planId) {
|
||||
|
|
|
@ -52,6 +52,10 @@ export function testPlanRunSave(param) {
|
|||
return post(BASE_URL + 'run/save', param);
|
||||
}
|
||||
|
||||
export function testPlanRun(param) {
|
||||
return post(BASE_URL + 'run', param);
|
||||
}
|
||||
|
||||
export function testPlanHaveUiCase(id) {
|
||||
return get(BASE_URL + `have/ui/case/${id}`);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,454 @@
|
|||
<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"
|
||||
>
|
||||
<div class="env-container">
|
||||
<div>
|
||||
<div>{{ $t("commons.environment") }}:</div>
|
||||
<env-select-popover :project-ids="projectIds"
|
||||
:project-list="projectList"
|
||||
:project-env-map="projectEnvListMap"
|
||||
:group-id="runConfig.environmentGroupId"
|
||||
@setProjectEnvMap="setProjectEnvMap"
|
||||
@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"
|
||||
>
|
||||
<el-option
|
||||
v-for="b in browsers"
|
||||
:key="b.value"
|
||||
:value="b.value"
|
||||
:label="b.label"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mode-row">{{ $t("run_mode.title") }}:</div>
|
||||
<div >
|
||||
<el-radio-group
|
||||
v-model="runConfig.mode"
|
||||
@change="changeMode"
|
||||
style="width: 100%"
|
||||
class="radio-change mode-row"
|
||||
>
|
||||
<el-radio label="serial">{{ $t("run_mode.serial") }}</el-radio>
|
||||
<el-radio label="parallel">{{ $t("run_mode.parallel") }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div >
|
||||
<div class="mode-row">{{ $t("run_mode.other_config") }}:</div>
|
||||
<div >
|
||||
<!-- 串行 -->
|
||||
<div
|
||||
class="mode-row"
|
||||
v-if="runConfig.mode === 'serial' && testType === 'API'"
|
||||
>
|
||||
<el-checkbox
|
||||
v-model="runConfig.runWithinResourcePool"
|
||||
style="padding-right: 10px"
|
||||
class="radio-change"
|
||||
>
|
||||
{{ $t("run_mode.run_with_resource_pool") }}
|
||||
</el-checkbox><br/>
|
||||
<el-select
|
||||
:disabled="!runConfig.runWithinResourcePool"
|
||||
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'"
|
||||
>
|
||||
<el-checkbox
|
||||
v-model="runConfig.runWithinResourcePool"
|
||||
style="padding-right: 10px"
|
||||
class="radio-change"
|
||||
>
|
||||
{{ $t("run_mode.run_with_resource_pool") }}
|
||||
</el-checkbox><br/>
|
||||
<el-select
|
||||
:disabled="!runConfig.runWithinResourcePool"
|
||||
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"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!-- 失败重试 -->
|
||||
<div class="mode-row" v-if="isHasLicense">
|
||||
<el-checkbox
|
||||
v-model="runConfig.retryEnable"
|
||||
class="radio-change ms-failure-div-right"
|
||||
>
|
||||
{{ $t("run_mode.retry_on_failure") }}
|
||||
</el-checkbox>
|
||||
<span v-if="runConfig.retryEnable">
|
||||
<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"/>
|
||||
</el-tooltip><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"
|
||||
/>
|
||||
|
||||
{{ $t("run_mode.retry_frequency") }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="mode-row" v-if="runConfig.mode === 'serial'">
|
||||
<el-checkbox v-model="runConfig.onSampleError" class="radio-change">{{
|
||||
$t("api_test.fail_to_stop")
|
||||
}}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="mode-row" v-if="haveUICase">
|
||||
<el-checkbox v-model="runConfig.headlessEnabled" class="radio-change">
|
||||
{{ $t("ui.performance_mode") }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-slot:footer>
|
||||
<div class="dialog-footer" v-if="showSave">
|
||||
<el-button @click="close">{{ $t("commons.cancel") }}</el-button>
|
||||
<el-dropdown @command="handleCommand" style="margin-left: 5px">
|
||||
<el-button type="primary">
|
||||
{{
|
||||
$t("commons.run")
|
||||
}}<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="run">{{
|
||||
$t("commons.run")
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="runAndSave">{{
|
||||
$t("load_test.save_and_run")
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="save">{{
|
||||
$t("commons.save")
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<ms-dialog-footer v-else @cancel="close" @confirm="handleRunBatch"/>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||
import {strMapToObj} from "metersphere-frontend/src/utils";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {getOwnerProjects} from "@/business/utils/sdk-utils";
|
||||
import {getQuotaValidResourcePools} from "@/api/remote/resource-pool";
|
||||
import EnvGroupPopover from "@/business/plan/env/EnvGroupPopover";
|
||||
import {getApiCaseEnv} from "@/api/remote/plan/test-plan-api-case";
|
||||
import {getApiScenarioEnv, getPlanCaseEnv} from "@/api/remote/plan/test-plan";
|
||||
import EnvGroupWithOption from "../env/EnvGroupWithOption";
|
||||
import EnvironmentGroup from "@/business/plan/env/EnvironmentGroupList";
|
||||
import EnvSelectPopover from "@/business/plan/env/EnvSelectPopover";
|
||||
|
||||
export default {
|
||||
name: "MsTestPlanRunModeWithEnv",
|
||||
components: {EnvGroupPopover, MsDialogFooter,MsTag,EnvGroupWithOption,EnvironmentGroup,EnvSelectPopover},
|
||||
computed: {
|
||||
ENV_TYPE() {
|
||||
return ENV_TYPE;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
btnStyle: {
|
||||
width: "260px",
|
||||
},
|
||||
result:{loading: false},
|
||||
runModeVisible: false,
|
||||
testType: null,
|
||||
resourcePools: [],
|
||||
projectEnvListMap: {},
|
||||
runConfig: {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
onSampleError: false,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
envMap: new Map(),
|
||||
environmentGroupId: "",
|
||||
environmentType: ENV_TYPE.JSON,
|
||||
retryEnable: false,
|
||||
retryNum: 1,
|
||||
browser: "CHROME",
|
||||
},
|
||||
isHasLicense: hasLicense(),
|
||||
projectList: [],
|
||||
projectIds: new Set(),
|
||||
options: [
|
||||
{
|
||||
value: "confirmAndRun",
|
||||
label: this.$t("load_test.save_and_run"),
|
||||
},
|
||||
{
|
||||
value: "save",
|
||||
label: this.$t("commons.save"),
|
||||
},
|
||||
],
|
||||
value: "confirmAndRun",
|
||||
browsers: [
|
||||
{
|
||||
label: this.$t("chrome"),
|
||||
value: "CHROME",
|
||||
},
|
||||
{
|
||||
label: this.$t("firefox"),
|
||||
value: "FIREFOX",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
planCaseIds: {
|
||||
type: Array,
|
||||
},
|
||||
type: String,
|
||||
planId: String,
|
||||
showSave: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//是否含有ui场景 有 ui 场景就要展示 浏览器选项,性能模式
|
||||
haveUICase: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open(testType, runModeConfig) {
|
||||
if (runModeConfig) {
|
||||
this.runConfig = JSON.parse(runModeConfig);
|
||||
this.runConfig.envMap = new Map();
|
||||
this.runConfig.onSampleError = this.runConfig.onSampleError === 'true' || this.runConfig.onSampleError === true;
|
||||
this.runConfig.runWithinResourcePool = this.runConfig.runWithinResourcePool === 'true' || this.runConfig.runWithinResourcePool === true;
|
||||
}
|
||||
this.runModeVisible = true;
|
||||
this.testType = testType;
|
||||
this.getResourcePools();
|
||||
this.getWsProjects();
|
||||
this.showPopover();
|
||||
},
|
||||
changeMode() {
|
||||
this.runConfig.onSampleError = false;
|
||||
this.runConfig.runWithinResourcePool = false;
|
||||
this.runConfig.resourcePoolId = null;
|
||||
},
|
||||
close() {
|
||||
this.runConfig = {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
onSampleError: false,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
envMap: new Map(),
|
||||
environmentGroupId: "",
|
||||
environmentType: ENV_TYPE.JSON,
|
||||
browser: "CHROME",
|
||||
};
|
||||
this.runModeVisible = false;
|
||||
this.$emit("close");
|
||||
},
|
||||
handleRunBatch() {
|
||||
this.$emit("handleRunBatch", this.runConfig);
|
||||
this.close();
|
||||
},
|
||||
getResourcePools() {
|
||||
getQuotaValidResourcePools()
|
||||
.then((response) => {
|
||||
this.resourcePools = response.data;
|
||||
});
|
||||
},
|
||||
setProjectEnvMap(projectEnvMap) {
|
||||
this.runConfig.envMap = projectEnvMap;
|
||||
},
|
||||
setEnvGroup(id) {
|
||||
this.runConfig.environmentGroupId = id;
|
||||
},
|
||||
getWsProjects() {
|
||||
getOwnerProjects()
|
||||
.then((res) => {
|
||||
this.projectList = res.data;
|
||||
});
|
||||
},
|
||||
showPopover() {
|
||||
this.projectIds.clear();
|
||||
let param = undefined;
|
||||
if (this.type === "apiCase") {
|
||||
param = this.planCaseIds;
|
||||
getApiCaseEnv(param).then((res) => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.projectEnvListMap = data;
|
||||
for (let d in data) {
|
||||
this.projectIds.add(d);
|
||||
}
|
||||
}
|
||||
this.$refs.envSelectPopover.open();
|
||||
});
|
||||
} else if (this.type === "apiScenario") {
|
||||
param = this.planCaseIds;
|
||||
getApiScenarioEnv(param).then((res) => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.projectEnvListMap = data;
|
||||
for (let d in data) {
|
||||
this.projectIds.add(d);
|
||||
}
|
||||
}
|
||||
this.$refs.envSelectPopover.open();
|
||||
});
|
||||
} else if (this.type === "plan") {
|
||||
param = {id: this.planId};
|
||||
getPlanCaseEnv(param).then((res) => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.projectEnvListMap = data;
|
||||
for (let d in data) {
|
||||
this.projectIds.add(d);
|
||||
}
|
||||
}
|
||||
this.$refs.envSelectPopover.open();
|
||||
});
|
||||
}
|
||||
},
|
||||
handleCommand(command) {
|
||||
if (
|
||||
this.runConfig.runWithinResourcePool &&
|
||||
this.runConfig.resourcePoolId == null
|
||||
) {
|
||||
this.$warning(
|
||||
this.$t("workspace.env_group.please_select_run_within_resource_pool")
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.runConfig.envMap =strMapToObj(this.runConfig.envMap)
|
||||
if (command === "runAndSave") {
|
||||
this.runConfig.executionWay = "runAndSave";
|
||||
} else if(command === "save"){
|
||||
this.runConfig.executionWay = "save";
|
||||
} else {
|
||||
this.runConfig.executionWay = "run";
|
||||
}
|
||||
this.handleRunBatch();
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.env-container .title {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.env-container .content {
|
||||
width: 163px;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 10px 5px 10px;
|
||||
}
|
||||
|
||||
:deep(.content .el-popover__reference) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mode-row {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.other-title {
|
||||
height: 100%;
|
||||
margin-top: 25px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.other-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.other-row {
|
||||
height: 125px;
|
||||
}
|
||||
.project-name {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 150px;
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.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;
|
||||
}
|
||||
</style>
|
|
@ -315,7 +315,7 @@
|
|||
<ms-test-plan-schedule-maintain ref="scheduleMaintain" @refreshTable="initTableData" :plan-case-ids="[]"
|
||||
:type="'plan'" :have-u-i-case="haveUICase"/>
|
||||
<ms-test-plan-schedule-batch-switch ref="scheduleBatchSwitch" @refresh="refresh"/>
|
||||
<plan-run-mode-with-env @handleRunBatch="_handleRun" ref="runMode" :plan-case-ids="[]" :type="'plan'"
|
||||
<ms-test-plan-run-mode-with-env @handleRunBatch="_handleRun" ref="runMode" :plan-case-ids="[]" :type="'plan'"
|
||||
:plan-id="currentPlanId" :show-save="true" :have-u-i-case="haveUICase"/>
|
||||
<test-plan-report-review ref="testCaseReportView"/>
|
||||
<ms-task-center ref="taskCenter" :show-menu="false"/>
|
||||
|
@ -366,13 +366,13 @@ import MsTestPlanScheduleMaintain from "@/business/plan/components/ScheduleMaint
|
|||
import {getCurrentProjectID, getCurrentUser, getCurrentUserId} from "metersphere-frontend/src/utils/token";
|
||||
import {hasLicense, hasPermission} from "metersphere-frontend/src/utils/permission";
|
||||
import {operationConfirm} from "metersphere-frontend/src/utils";
|
||||
import PlanRunModeWithEnv from "@/business/plan/common/PlanRunModeWithEnv";
|
||||
import MsTestPlanRunModeWithEnv from "@/business/plan/common/TestPlanRunModeWithEnv";
|
||||
import MsTaskCenter from "metersphere-frontend/src/components/task/TaskCenter";
|
||||
import {
|
||||
getPlanStageOption, testPlanCopy, testPlanDelete, testPlanEdit,
|
||||
testPlanEditFollows,
|
||||
testPlanEditRunConfig, testPlanGetEnableScheduleCount, testPlanGetFollow, testPlanGetPrincipal, testPlanHaveExecCase,
|
||||
testPlanHaveUiCase, testPlanList, testPlanRunBatch,
|
||||
testPlanHaveUiCase, testPlanList, testPlanRun, testPlanRunBatch,
|
||||
testPlanRunSave, testPlanUpdateScheduleEnable
|
||||
} from "@/api/remote/plan/test-plan";
|
||||
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
||||
|
@ -397,7 +397,7 @@ export default {
|
|||
MsTestPlanScheduleMaintain,
|
||||
MsTableOperator, MsTableOperatorButton,
|
||||
MsDialogFooter, MsTableHeader,
|
||||
MsTablePagination, PlanRunModeWithEnv, MsTaskCenter,
|
||||
MsTablePagination, MsTestPlanRunModeWithEnv, MsTaskCenter,
|
||||
MsTableColumn,
|
||||
MsTable,
|
||||
MsTestPlanScheduleBatchSwitch
|
||||
|
@ -829,7 +829,8 @@ export default {
|
|||
param.retryNum = config.retryNum;
|
||||
param.browser = config.browser;
|
||||
param.headlessEnabled = config.headlessEnabled;
|
||||
if (config.isRun === true) {
|
||||
if (config.executionWay === "runAndSave") {
|
||||
param.executionWay = "RUN_SAVE"
|
||||
this.$refs.taskCenter.open();
|
||||
this.cardLoading = true;
|
||||
testPlanRunSave(param)
|
||||
|
@ -838,7 +839,8 @@ export default {
|
|||
this.$success(this.$t('commons.run_success'));
|
||||
});
|
||||
|
||||
} else {
|
||||
} else if (config.executionWay === "save") {
|
||||
param.executionWay = "SAVE"
|
||||
this.cardLoading = true;
|
||||
testPlanEditRunConfig(param)
|
||||
.then(() => {
|
||||
|
@ -846,6 +848,15 @@ export default {
|
|||
this.initTableData();
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
});
|
||||
} else {
|
||||
param.executionWay = "RUN"
|
||||
this.$refs.taskCenter.open();
|
||||
this.cardLoading = true;
|
||||
testPlanRun(param)
|
||||
.then(() => {
|
||||
this.cardLoading = false;
|
||||
this.$success(this.$t('commons.run_success'));
|
||||
});
|
||||
}
|
||||
},
|
||||
saveFollow(row) {
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-radio-group v-model="radio" style="width: 100%" @change="radioChange" class="radio-change">
|
||||
<el-radio :label="ENV_TYPE.JSON">{{ $t('workspace.env_group.env_list') }}</el-radio>
|
||||
<el-radio :label="ENV_TYPE.GROUP">{{ $t('workspace.env_group.name') }}<i class="el-icon-tickets mode-span" @click="viewGroup"></i></el-radio>
|
||||
</el-radio-group>
|
||||
<div 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;">
|
||||
<i @click="expandCard(pIndex)" v-if="pe.expendStatus==='close'" class="el-icon-caret-right" style="color: var(--primary_color)"/>
|
||||
<i @click="expandCard(pIndex)" v-else class="el-icon-caret-bottom" style="color: var(--primary_color)"/>
|
||||
<span class="project-name" :title="getProjectName(pe.id)">
|
||||
{{ getProjectName(pe.id) }}
|
||||
</span><br/>
|
||||
<div v-if="pe.expendStatus==='open'">
|
||||
<el-radio-group v-model="pe.envRadio" style="width: 100%;" @change="envRadioChange(pe.envRadio,pIndex)" class="radio-change">
|
||||
<el-radio label="DEFAULT_ENV" style="margin-top: 7px">{{$t('api_test.environment.default_environment') }}</el-radio>
|
||||
<el-radio label="CUSTOMIZE_ENV" style="margin-top: 7px">{{$t('api_test.environment.choose_new_environment')}}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tag v-show="!pe.showEnvSelect" v-for="(itemName,index) in selectedEnvName.get(pe.id)" :key="index" size="mini"
|
||||
style="margin-left: 0; margin-right: 2px;margin-top: 8px">{{ itemName }}</el-tag>
|
||||
<el-select v-show="pe.showEnvSelect" v-model="pe['selectEnv']" :placeholder="$t('api_test.environment.select_environment')"
|
||||
style="margin-top: 8px;width: 100%;" size="small" @change="chooseEnv">
|
||||
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
||||
:label="environment.name"
|
||||
:value="environment.id"/>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
|
||||
</div>
|
||||
<div v-show="radio === ENV_TYPE.GROUP">
|
||||
<div>
|
||||
<el-select v-model="groupId" :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"/>
|
||||
</el-select>
|
||||
|
||||
</div>
|
||||
<el-dialog :visible="visible" append-to-body :title="$t('workspace.env_group.name')" @close="visible = false"
|
||||
style="height: 800px;">
|
||||
<template>
|
||||
<environment-group style="overflow-y: auto;"
|
||||
:screen-height="'350px'"
|
||||
:read-only="true"
|
||||
></environment-group>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants";
|
||||
import {environmentGetALl} from "metersphere-frontend/src/api/environment";
|
||||
import MsTag from "metersphere-frontend/src/components/MsTag";
|
||||
import EnvironmentGroup from "@/business/plan/env/EnvironmentGroupList";
|
||||
import {getEnvironmentByProjectId} from "@/api/remote/api/api-environment";
|
||||
import {parseEnvironment} from "metersphere-frontend/src/model/EnvironmentModel";
|
||||
|
||||
export default {
|
||||
name: "EnvSelectPopover",
|
||||
components: {MsTag,EnvironmentGroup},
|
||||
data(){
|
||||
return {
|
||||
radio:ENV_TYPE.JSON,
|
||||
visible: false,
|
||||
groups:[],
|
||||
selectedEnvName:new Map(),
|
||||
showEnvName:false,
|
||||
eventData:[],
|
||||
evnList:[],
|
||||
selectEnvMap:new Map(),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ENV_TYPE() {
|
||||
return ENV_TYPE;
|
||||
}
|
||||
},
|
||||
props:{
|
||||
projectIds: Set,
|
||||
projectList:Array,
|
||||
projectEnvMap:Object,
|
||||
envMap: Map,
|
||||
groupId: {
|
||||
type: String,
|
||||
default() {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open(){
|
||||
this.initDefaultEnv();
|
||||
this.getgroups();
|
||||
},
|
||||
radioChange(val){
|
||||
this.radio = val;
|
||||
},
|
||||
getProjectName(id) {
|
||||
const project = this.projectList.find(p => p.id === id);
|
||||
return project ? project.name : "";
|
||||
},
|
||||
envRadioChange(val,index){
|
||||
this.eventData[index].envRadio = val
|
||||
this.eventData[index].showEnvSelect = this.eventData[index].envRadio === "CUSTOMIZE_ENV";
|
||||
},
|
||||
viewGroup() {
|
||||
this.visible = true;
|
||||
},
|
||||
getgroups(){
|
||||
environmentGetALl().then(res => {
|
||||
let data = res.data;
|
||||
this.groups = data ? data : [];
|
||||
})
|
||||
},
|
||||
chooseEnv(val){
|
||||
let filter = this.evnList.filter(e => e.id === val);
|
||||
this.selectEnvMap.set(filter[0].projectId,val);
|
||||
this.$emit('setProjectEnvMap', this.selectEnvMap);
|
||||
},
|
||||
chooseEnvGroup(envGroupId){
|
||||
this.$emit("setEnvGroup", envGroupId);
|
||||
},
|
||||
initDefaultEnv(){
|
||||
this.selectedEnvName = new Map();
|
||||
this.evnList = [];
|
||||
this.projectIds.forEach(d => {
|
||||
let item = {id: d, envs: [], selectEnv: "",envRadio:"DEFAULT_ENV",showEnvSelect:false,expendStatus:"open"};
|
||||
this.eventData.push(item);
|
||||
getEnvironmentByProjectId(d)
|
||||
.then(res => {
|
||||
let envs = res.data;
|
||||
envs.forEach(environment => {
|
||||
parseEnvironment(environment);
|
||||
});
|
||||
// 固定环境列表渲染顺序
|
||||
let temp = this.eventData.find(dt => dt.id === d);
|
||||
temp.envs = envs;
|
||||
envs.forEach(t=>{
|
||||
this.evnList.push(t);
|
||||
})
|
||||
if (this.envMap && this.envMap.size > 0) {
|
||||
let envId = this.envMap.get(id);
|
||||
// 选中环境是否存在
|
||||
temp.selectEnv = envs.filter(e => e.id === envId).length === 0 ? null : envId;
|
||||
}
|
||||
if (this.projectEnvMap) {
|
||||
let projectEnvMapElement = this.projectEnvMap[d];
|
||||
if (projectEnvMapElement.length>0) {
|
||||
projectEnvMapElement.forEach(envId => {
|
||||
let filter = envs.filter(e => e.id === envId);
|
||||
if (!this.selectedEnvName.has(d)) {
|
||||
let name = [];
|
||||
name.push(filter[0].name)
|
||||
this.selectedEnvName.set(d,name);
|
||||
} else {
|
||||
this.selectedEnvName.get(d).push(filter[0].name);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
expandCard(index){
|
||||
if (this.eventData[index].expendStatus === "open") {
|
||||
this.eventData[index].expendStatus = "close"
|
||||
}else {
|
||||
this.eventData[index].expendStatus = "open"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mode-span{
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.radio-change:deep(.el-radio__input.is-checked + .el-radio__label) {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue