feat(接口测试): 场景列表增加定时任务展示列

--story=1011684 --user=宋天阳 接口场景列表、UI场景列表 展示定时任务列
https://www.tapd.cn/55049933/s/1360916
This commit is contained in:
song-tianyang 2023-04-10 16:12:14 +08:00 committed by 建国
parent f34321b23c
commit e68cfc62e9
12 changed files with 516 additions and 270 deletions

View File

@ -0,0 +1,14 @@
package io.metersphere.api.dto;
import io.metersphere.base.domain.Schedule;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ScheduleDTO extends Schedule {
/**
* 定时任务下一次执行时间
*/
private Long scheduleExecuteTime;
}

View File

@ -1,9 +1,8 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.api.dto.ScheduleDTO;
import io.metersphere.api.dto.definition.ApiSwaggerUrlDTO;
import io.metersphere.dto.ScheduleDao;
import io.metersphere.dto.TaskInfoResult;
import io.metersphere.request.BaseQueryRequest;
import io.metersphere.request.QueryScheduleRequest;
import org.apache.ibatis.annotations.Param;
@ -12,16 +11,12 @@ import java.util.List;
public interface ExtScheduleMapper {
List<ScheduleDao> list(@Param("request") QueryScheduleRequest request);
long countTaskByProjectId(String workspaceId);
long countTaskByProjectIdAndCreateTimeRange(@Param("projectId")String projectId, @Param("startTime") long startTime, @Param("endTime") long endTime);
List<TaskInfoResult> findRunningTaskInfoByProjectID(@Param("projectId") String workspaceID, @Param("request") BaseQueryRequest request);
void insert(@Param("apiSwaggerUrlDTO") ApiSwaggerUrlDTO apiSwaggerUrlDTO);
ApiSwaggerUrlDTO select(String id);
ApiSwaggerUrlDTO select(String id);
int updateNameByResourceID(@Param("resourceId") String resourceId, @Param("name") String name);
List<ScheduleDTO> selectByResourceIds(@Param("ids") List<String> resourceIDs);
}

View File

@ -4,7 +4,8 @@
<insert id="insert" parameterType="io.metersphere.api.dto.definition.ApiSwaggerUrlDTO">
insert into swagger_url_project (id, `project_id`, `swagger_url`,
`schedule_id`)
values (#{apiSwaggerUrlDTO.id,jdbcType=VARCHAR}, #{apiSwaggerUrlDTO.projectId,jdbcType=VARCHAR}, #{apiSwaggerUrlDTO.swaggerUrl,jdbcType=VARCHAR},
values (#{apiSwaggerUrlDTO.id,jdbcType=VARCHAR}, #{apiSwaggerUrlDTO.projectId,jdbcType=VARCHAR},
#{apiSwaggerUrlDTO.swaggerUrl,jdbcType=VARCHAR},
#{apiSwaggerUrlDTO.scheduleId,jdbcType=VARCHAR})
</insert>
<select id="list" resultType="io.metersphere.dto.ScheduleDao">
@ -48,41 +49,49 @@
<select id="countTaskByProjectId" resultType="java.lang.Long">
SELECT COUNT(id) AS countNumber
FROM `schedule`
WHERE resource_id IN (
SELECT id FROM api_scenario WHERE project_id = #{0,jdbcType=VARCHAR} AND status != 'Trash' AND latest = 1
)
WHERE resource_id IN (SELECT id
FROM api_scenario
WHERE project_id = #{0,jdbcType=VARCHAR}
AND status != 'Trash'
AND latest = 1)
</select>
<select id="countTaskByProjectIdAndCreateTimeRange" resultType="java.lang.Long">
SELECT COUNT(id) AS countNumber
FROM `schedule`
WHERE resource_id IN (
SELECT scene.id
FROM api_scenario scene
WHERE scene.project_id = #{projectId,jdbcType=VARCHAR}
AND scene.status != 'Trash' AND latest = 1
)
WHERE resource_id IN (SELECT scene.id
FROM api_scenario scene
WHERE scene.project_id = #{projectId,jdbcType=VARCHAR}
AND scene.status != 'Trash'
AND latest = 1)
AND create_time BETWEEN #{startTime} AND #{endTime}
</select>
<select id="selectByResourceIds" resultType="io.metersphere.api.dto.ScheduleDTO">
SELECT * FROM `schedule`
WHERE resource_id IN
<foreach collection="ids" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</select>
<select id="findRunningTaskInfoByProjectID" resultType="io.metersphere.dto.TaskInfoResult">
SELECT sch.id AS taskID,
sch.`name` AS `name`,
sch.`value` AS rule,
sch.`enable` AS `taskStatus`,
sch.update_time AS updateTime,
sch.id AS taskID,
sch.`value` AS rule,
sch.`enable` AS `taskStatus`,
u.`name` AS creator,
sch.update_time AS updateTime,
sch.type AS taskType,
sch.`group` AS taskGroup,
sch.resource_id AS scenarioId
sch.`name` AS `name`,
sch.`value` AS rule,
sch.`enable` AS `taskStatus`,
sch.update_time AS updateTime,
sch.id AS taskID,
sch.`value` AS rule,
sch.`enable` AS `taskStatus`,
u.`name` AS creator,
sch.update_time AS updateTime,
sch.type AS taskType,
sch.`group` AS taskGroup,
sch.resource_id AS scenarioId
FROM (
schedule sch left join user u
ON sch.user_id = u.id
schedule sch left join user u
ON sch.user_id = u.id
)
WHERE sch.`enable` = true
AND sch.project_id = #{projectId,jdbcType=VARCHAR}
AND sch.project_id = #{projectId,jdbcType=VARCHAR}
<if test="request.filters != null and request.filters.size() > 0">
<foreach collection="request.filters.entrySet()" index="key" item="values">
@ -100,9 +109,13 @@
</if>
</select>
<select id="select" resultType="io.metersphere.api.dto.definition.ApiSwaggerUrlDTO">
select * from swagger_url_project where id=#{id}
select *
from swagger_url_project
where id = #{id}
</select>
<update id="updateNameByResourceID">
update schedule set name = #{name} where resource_id = #{resourceId}
update schedule
set name = #{name}
where resource_id = #{resourceId}
</update>
</mapper>

View File

@ -24,6 +24,7 @@ import io.metersphere.request.ResetOrderRequest;
import io.metersphere.service.ext.ExtApiTaskService;
import io.metersphere.service.scenario.ApiScenarioService;
import io.metersphere.task.dto.TaskRequestDTO;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
@ -34,7 +35,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -57,6 +57,12 @@ public class ApiScenarioController {
return PageUtils.setPageInfo(page, apiAutomationService.list(request));
}
@PostMapping("/scenario/schedule")
@RequiresPermissions("PROJECT_API_SCENARIO:READ")
public Map<String, ScheduleDTO> scenarioScheduleInfo(@RequestBody List<String> scenarioIds) {
return apiAutomationService.selectScheduleInfo(scenarioIds);
}
@PostMapping("/list")
@RequiresPermissions("PROJECT_API_SCENARIO:READ")
public List<ApiScenarioDTO> listAll(@RequestBody ApiScenarioRequest request) {

View File

@ -1,5 +1,6 @@
package io.metersphere.service.ext;
import io.metersphere.api.dto.ScheduleDTO;
import io.metersphere.api.dto.ScheduleRequest;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ScheduleMapper;
@ -22,6 +23,8 @@ import io.metersphere.sechedule.ApiScenarioTestJob;
import io.metersphere.sechedule.ScheduleManager;
import io.metersphere.sechedule.SwaggerUrlImportJob;
import io.metersphere.service.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobKey;
import org.quartz.SchedulerException;
@ -29,10 +32,10 @@ import org.quartz.TriggerKey;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import jakarta.annotation.Resource;
import java.util.stream.Collectors;
@Service
@ -233,4 +236,12 @@ public class ExtApiScheduleService {
}
}
public List<ScheduleDTO> selectByResourceIds(List<String> scenarioIds) {
if (CollectionUtils.isNotEmpty(scenarioIds)) {
return extScheduleMapper.selectByResourceIds(scenarioIds);
} else {
return new ArrayList<>();
}
}
}

View File

@ -9,7 +9,6 @@ import io.metersphere.api.dto.definition.ApiTestCaseInfo;
import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.unknown.MsJmeterElement;
import io.metersphere.api.dto.export.ScenarioToPerformanceInfoDTO;
import io.metersphere.api.dto.scenario.ApiScenarioParamDTO;
import io.metersphere.api.exec.scenario.ApiScenarioEnvService;
@ -71,6 +70,10 @@ import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONObject;
import org.mybatis.spring.SqlSessionUtils;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.TriggerBuilder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -2325,4 +2328,26 @@ public class ApiScenarioService {
}
public Map<String, ScheduleDTO> selectScheduleInfo(List<String> scenarioIds) {
if (CollectionUtils.isNotEmpty(scenarioIds)) {
List<ScheduleDTO> scheduleInfoList = scheduleService.selectByResourceIds(scenarioIds);
for (ScheduleDTO schedule : scheduleInfoList) {
schedule.setScheduleExecuteTime(this.getNextTriggerTime(schedule.getValue()));
}
return scheduleInfoList.stream().collect(Collectors.toMap(Schedule::getResourceId, item -> item));
} else {
return new HashMap<>();
}
}
//获取下次执行时间getFireTimeAfter也可以下下次...
private long getNextTriggerTime(String cron) {
if (!CronExpression.isValidExpression(cron)) {
return 0;
}
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("Calculate Date").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
Date time0 = trigger.getStartTime();
Date time1 = trigger.getFireTimeAfter(time0);
return time1 == null ? 0 : time1.getTime();
}
}

View File

@ -14,6 +14,11 @@ export function getScenarioList(currentPage, pageSize, condition) {
return post(url, condition);
}
export function getScheduleDetail(scenarioIds) {
let url = '/api/automation/scenario/schedule';
return post(url, scenarioIds);
}
export function getScenarioByTrash(condition) {
return post('/api/automation/list/all/trash', condition);
}

View File

@ -40,7 +40,7 @@
:fields-width="fieldsWidth"
v-if="this.trashEnable"
:label="$t('commons.delete_user')"
min-width="120"/>
min-width="120" />
<span v-for="item in fields" :key="item.key">
<ms-table-column
@ -81,7 +81,7 @@
:label="$t('api_test.automation.scenario_name')"
min-width="150px"
prop="name"
sortable/>
sortable />
<ms-table-column
:field="item"
@ -92,7 +92,7 @@
prop="level"
sortable>
<template v-slot:default="scope">
<priority-table-item :value="scope.row.level"/>
<priority-table-item :value="scope.row.level" />
</template>
</ms-table-column>
@ -105,7 +105,7 @@
prop="status"
min-width="120px">
<template v-slot:default="scope">
<plan-status-table-item :value="scope.row.status"/>
<plan-status-table-item :value="scope.row.status" />
</template>
</ms-table-column>
@ -117,20 +117,20 @@
min-width="120px"
prop="tags">
<template v-slot:default="scope">
<el-tooltip class="item" effect="dark" placement="top">
<div v-html="getTagToolTips(scope.row.tags)" slot="content"></div>
<div class="oneLine">
<ms-tag
v-for="(itemName, index) in scope.row.tags"
:key="index"
type="success"
effect="plain"
:show-tooltip="scope.row.tags.length === 1 && itemName.length * 12 <= 100"
:content="itemName"
style="margin-left: 0px; margin-right: 2px" />
</div>
</el-tooltip>
</template>
<el-tooltip class="item" effect="dark" placement="top">
<div v-html="getTagToolTips(scope.row.tags)" slot="content"></div>
<div class="oneLine">
<ms-tag
v-for="(itemName, index) in scope.row.tags"
:key="index"
type="success"
effect="plain"
:show-tooltip="scope.row.tags.length === 1 && itemName.length * 12 <= 100"
:content="itemName"
style="margin-left: 0px; margin-right: 2px" />
</div>
</el-tooltip>
</template>
</ms-table-column>
<ms-table-column
@ -151,7 +151,7 @@
:fields-width="fieldsWidth"
prop="principalName"
min-width="120px"
sortable/>
sortable />
<ms-table-column
:label="$t('api_test.automation.creator')"
:filters="userFilters"
@ -159,7 +159,7 @@
:fields-width="fieldsWidth"
prop="creatorName"
min-width="120px"
sortable="custom"/>
sortable="custom" />
<ms-table-column
:field="item"
:fields-width="fieldsWidth"
@ -176,25 +176,41 @@
<el-tag type="success" size="mini" effect="plain">
<span class="project-env" :title="k">{{ k }}</span>
</el-tag>
<br/>
<br />
</span>
<el-popover placement="top" width="350" trigger="click">
<div v-for="(k, v, index) in row.environmentMap" :key="index">
<span class="plan-case-env" :title="v">{{ v }}</span
>:
<el-tag type="success" size="mini" effect="plain">
<span class="project-env" style="margin: 0 0 0 5px" :title="k">{{ k }}
</span>
</el-tag>
<br/>
<el-tag type="success" size="mini" effect="plain">
<span class="project-env" style="margin: 0 0 0 5px" :title="k">{{ k }} </span>
</el-tag>
<br />
</div>
<el-link v-if="index === 1" slot="reference" type="info" :underline="false" icon="el-icon-more"/>
<el-link v-if="index === 1" slot="reference" type="info" :underline="false" icon="el-icon-more" />
</el-popover>
</span>
</div>
</template>
</ms-table-column>
<ms-table-column
:label="$t('commons.trigger_mode.schedule')"
:field="item"
:fields-width="fieldsWidth"
min-width="100px"
prop="schedule">
<template v-slot:default="scope">
<schedule-info-in-table
v-if="scope.row.scheduleObj"
@openSchedule="openSchedule(scope.row)"
@scheduleChange="scheduleStatusChange"
@refreshTable="nodeChange"
:scenario="scope.row"
:request="runRequest"
:schedule="scope.row.scheduleObj" />
<i v-else class="el-icon-loading" />
</template>
</ms-table-column>
<ms-table-column
:field="item"
:fields-width="fieldsWidth"
@ -223,7 +239,7 @@
:fields-width="fieldsWidth"
:label="$t('api_test.automation.step')"
prop="stepTotal"
min-width="80px"/>
min-width="80px" />
<ms-table-column
:label="$t('api_test.automation.last_result')"
:filters="resultFilters"
@ -234,7 +250,7 @@
min-width="130px">
<template v-slot:default="{ row }">
<el-link @click="showReport(row)" :disabled="!row.lastResult || row.lastResult === 'PENDING'">
<ms-api-report-status :status="row.lastResult"/>
<ms-api-report-status :status="row.lastResult" />
</el-link>
</template>
</ms-table-column>
@ -244,7 +260,7 @@
:fields-width="fieldsWidth"
:label="$t('api_test.automation.passing_rate')"
prop="passRate"
min-width="120px"/>
min-width="120px" />
</span>
<template v-slot:opt-before="scope">
@ -255,7 +271,7 @@
icon="el-icon-video-play"
class="run-button"
style="margin-right: 10px"
v-permission="['PROJECT_API_SCENARIO:READ+RUN']"/>
v-permission="['PROJECT_API_SCENARIO:READ+RUN']" />
<el-tooltip :content="$t('report.stop_btn')" placement="top" :enterable="false" v-else>
<el-button
v-if="!trashEnable"
@ -279,11 +295,11 @@
@openScenario="openScenario"
@showCaseRef="showScenarioRef"
v-if="!trashEnable"
style="display: contents"/>
style="display: contents" />
</template>
</ms-table>
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total"/>
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total" />
<div>
<!-- 执行结果 -->
@ -301,7 +317,7 @@
:scenarioId="scenarioId"
:infoDb="infoDb"
:report-id="reportId"
:currentProjectId="projectId"/>
:currentProjectId="projectId" />
</el-drawer>
<!-- 执行结果 -->
<el-drawer
@ -317,7 +333,7 @@
:infoDb="infoDb"
:show-cancel-button="false"
:report-id="showReportId"
:currentProjectId="projectId"/>
:currentProjectId="projectId" />
</el-drawer>
<!--测试计划-->
<el-drawer
@ -333,7 +349,7 @@
@cancel="cancel"
ref="testPlanList"
:scenario-condition="condition"
:row="selectRows"/>
:row="selectRows" />
</el-drawer>
</div>
@ -342,14 +358,14 @@
@batchEdit="batchEdit"
:typeArr="typeArr"
:value-arr="valueArr"
:dialog-title="$t('test_track.case.batch_edit_case')"/>
<batch-move @refresh="search" @moveSave="moveSave" ref="testBatchMove"/>
:dialog-title="$t('test_track.case.batch_edit_case')" />
<batch-move @refresh="search" @moveSave="moveSave" ref="testBatchMove" />
<ms-api-run-mode
:request="runRequest"
:project-id="projectId"
@close="search"
@handleRunBatch="handleRunBatch"
ref="apiBatchRun"/>
ref="apiBatchRun" />
<ms-run
:debug="true"
:environment="projectEnvMap"
@ -361,20 +377,20 @@
:run-data="debugData"
@runRefresh="runRefresh"
@errorRefresh="errorRefresh"
ref="runTest"/>
<ms-task-center ref="taskCenter" :show-menu="false"/>
<relationship-graph-drawer :graph-data="graphData" ref="relationshipGraph"/>
ref="runTest" />
<ms-task-center ref="taskCenter" :show-menu="false" />
<relationship-graph-drawer :graph-data="graphData" ref="relationshipGraph" />
<!-- 删除接口提示 -->
<scenario-delete-confirm ref="apiDeleteConfirmVersion" @handleDelete="_handleDelete"/>
<scenario-delete-confirm ref="apiDeleteConfirmVersion" @handleDelete="_handleDelete" />
<!-- 删除场景弹窗 -->
<api-delete-confirm
:has-ref="hasRef"
:show-scenario="showScenario"
@showCaseRef="showScenarioRef"
@handleDeleteCase="handleDeleteScenario"
ref="apiDeleteConfirm"/>
ref="apiDeleteConfirm" />
<!-- 引用场景弹窗 -->
<ms-show-reference ref="viewRef" @showCaseRef="showScenarioRef" @openScenario="openScenario"/>
<ms-show-reference ref="viewRef" @showCaseRef="showScenarioRef" @openScenario="openScenario" />
</el-card>
</template>
@ -395,6 +411,7 @@ import {
getScenarioList,
getScenarioVersions,
getScenarioWithBLOBsById,
getScheduleDetail,
listWithIds,
removeScenarioToGcByBatch,
runBatch,
@ -404,13 +421,13 @@ import {
scenarioRun,
updateScenarioEnv,
} from '@/api/scenario';
import {getMaintainer, getProject} from '@/api/project';
import {getProjectVersions, versionEnableByProjectId} from '@/api/xpack';
import {getCurrentProjectID, getCurrentUserId} from 'metersphere-frontend/src/utils/token';
import {downloadFile, getUUID, objToStrMap, strMapToObj} from 'metersphere-frontend/src/utils';
import {hasLicense, hasPermission} from 'metersphere-frontend/src/utils/permission';
import {API_SCENARIO_CONFIGS} from 'metersphere-frontend/src/components/search/search-components';
import {API_SCENARIO_LIST} from 'metersphere-frontend/src/utils/constants';
import { getMaintainer, getProject } from '@/api/project';
import { getProjectVersions, versionEnableByProjectId } from '@/api/xpack';
import { getCurrentProjectID, getCurrentUserId } from 'metersphere-frontend/src/utils/token';
import { downloadFile, getUUID, objToStrMap, strMapToObj } from 'metersphere-frontend/src/utils';
import { hasLicense, hasPermission } from 'metersphere-frontend/src/utils/permission';
import { API_SCENARIO_CONFIGS } from 'metersphere-frontend/src/components/search/search-components';
import { API_SCENARIO_LIST } from 'metersphere-frontend/src/utils/constants';
import {
buildBatchParam,
getCustomTableHeader,
@ -418,27 +435,29 @@ import {
getLastTableSortField,
getSelectDataCounts,
} from 'metersphere-frontend/src/utils/tableUtils';
import {API_SCENARIO_FILTERS} from 'metersphere-frontend/src/utils/table-constants';
import { API_SCENARIO_FILTERS } from 'metersphere-frontend/src/utils/table-constants';
import MsTable from 'metersphere-frontend/src/components/table/MsTable';
import MsTableColumn from 'metersphere-frontend/src/components/table/MsTableColumn';
import HeaderLabelOperate from 'metersphere-frontend/src/components/head/HeaderLabelOperate';
import {getGraphByCondition} from '@/api/graph';
import {API_SCENARIO_CONFIGS_TRASH, TYPE_TO_C} from '@/business/automation/scenario/Setting';
import { getGraphByCondition } from '@/api/graph';
import { API_SCENARIO_CONFIGS_TRASH, TYPE_TO_C } from '@/business/automation/scenario/Setting';
import MsTableSearchBar from 'metersphere-frontend/src/components/MsTableSearchBar';
import MsTableAdvSearchBar from 'metersphere-frontend/src/components/search/MsTableAdvSearchBar';
import ListItemDeleteConfirm from 'metersphere-frontend/src/components/ListItemDeleteConfirm';
import ScenarioDeleteConfirm from '@/business/automation/scenario/ScenarioDeleteConfirm';
import {$error} from 'metersphere-frontend/src/plugins/message';
import { $error } from 'metersphere-frontend/src/plugins/message';
import MsSearch from 'metersphere-frontend/src/components/search/MsSearch';
import {buildNodePath} from 'metersphere-frontend/src/model/NodeTree';
import {getEnvironmentByProjectId} from 'metersphere-frontend/src/api/environment';
import {REPORT_STATUS} from '@/business/commons/js/commons';
import {usePerformanceStore} from '@/store';
import {request} from 'metersphere-frontend/src/plugins/request';
import {parseEnvironment} from '@/business/environment/model/EnvironmentModel';
import { buildNodePath } from 'metersphere-frontend/src/model/NodeTree';
import { getEnvironmentByProjectId } from 'metersphere-frontend/src/api/environment';
import { REPORT_STATUS } from '@/business/commons/js/commons';
import { usePerformanceStore } from '@/store';
import { request } from 'metersphere-frontend/src/plugins/request';
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
import MsApiRunMode from '@/business/automation/scenario/common/ApiRunMode';
import ApiDeleteConfirm from '@/business/definition/components/list/ApiDeleteConfirm';
import MsShowReference from '@/business/definition/components/reference/ShowReference';
import scheduleInfoInTable from '@/business/automation/schedule/ScheduleInfoInTable.vue';
import { scheduleUpdate } from '@/api/schedule';
const performanceStore = usePerformanceStore();
export default {
@ -455,6 +474,7 @@ export default {
ApiDeleteConfirm,
MsShowReference,
ScenarioDeleteConfirm,
scheduleInfoInTable,
MsApiReportStatus: () => import('../report/ApiReportStatus'),
HeaderCustom: () => import('metersphere-frontend/src/components/head/HeaderCustom'),
BatchMove: () => import('@/business/commons/BatchMove'),
@ -657,8 +677,8 @@ export default {
},
],
typeArr: [
{id: 'level', name: this.$t('test_track.case.priority')},
{id: 'status', name: this.$t('test_track.plan.plan_status')},
{ id: 'level', name: this.$t('test_track.case.priority') },
{ id: 'status', name: this.$t('test_track.plan.plan_status') },
{
id: 'principal',
name: this.$t('api_test.definition.request.responsible'),
@ -669,14 +689,14 @@ export default {
id: 'projectEnv',
name: this.$t('api_test.definition.request.run_env'),
},
{id: 'tags', name: this.$t('commons.tag')},
{ id: 'tags', name: this.$t('commons.tag') },
],
valueArr: {
level: [
{name: 'P0', id: 'P0'},
{name: 'P1', id: 'P1'},
{name: 'P2', id: 'P2'},
{name: 'P3', id: 'P3'},
{ name: 'P0', id: 'P0' },
{ name: 'P1', id: 'P1' },
{ name: 'P2', id: 'P2' },
{ name: 'P3', id: 'P3' },
],
status: [
{
@ -717,10 +737,10 @@ export default {
if (!this.projectName || this.projectName === '') {
this.getProjectName();
}
this.condition.filters = {status: ['Prepare', 'Underway', 'Completed']};
this.condition.filters = { status: ['Prepare', 'Underway', 'Completed'] };
this.initEnvironment();
if (this.trashEnable) {
this.condition.filters = {status: ['Trash']};
this.condition.filters = { status: ['Trash'] };
this.condition.moduleIds = [];
this.operators = this.trashOperators;
this.buttons = this.trashButtons;
@ -735,7 +755,7 @@ export default {
}
if (this.trashEnable) {
this.condition.orders = [{name: 'delete_time', type: 'desc'}];
this.condition.orders = [{ name: 'delete_time', type: 'desc' }];
} else {
this.condition.orders = getLastTableSortField(this.tableHeaderKey);
}
@ -768,7 +788,7 @@ export default {
},
trashEnable() {
if (this.trashEnable) {
this.condition.filters = {status: ['Trash']};
this.condition.filters = { status: ['Trash'] };
this.condition.moduleIds = [];
this.operators = this.trashOperators;
this.buttons = this.trashButtons;
@ -797,7 +817,7 @@ export default {
moduleOptionsNew() {
let moduleOptions = [];
this.moduleOptions.forEach((node) => {
buildNodePath(node, {path: ''}, moduleOptions);
buildNodePath(node, { path: '' }, moduleOptions);
});
return moduleOptions;
},
@ -829,12 +849,12 @@ export default {
parseEnvironment(environment);
});
this.environmentsFilters = response.data.map((u) => {
return {text: u.name, value: u.id};
return { text: u.name, value: u.id };
});
});
}
},
search(projectId){
search(projectId) {
this.$EventBus.$emit('scenarioConditionBus', this.condition);
this.nodeChange(projectId);
},
@ -915,7 +935,9 @@ export default {
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
let ids = [];
this.tableData.forEach((item) => {
ids.push(item.id);
if (item.tags && item.tags.length > 0) {
item.tags = JSON.parse(item.tags);
}
@ -924,9 +946,59 @@ export default {
if (this.$refs.scenarioTable) {
this.$refs.scenarioTable.clearSelection();
}
this.selectSchedule(ids);
});
}
},
selectSchedule(ids) {
if (ids.length > 0) {
getScheduleDetail(ids).then((response) => {
if (response.data) {
let scheduleData = response.data;
this.tableData.forEach((scenario) => {
let scheduleInfo = this.getScheduleObject(scheduleData[scenario.id], scenario.id);
this.$set(scenario, 'scheduleObj', scheduleInfo);
});
}
});
}
},
scheduleStatusChange(schedule) {
let scheduleRequest = {
taskID: schedule.id,
enable: schedule.enable,
};
this.result = scheduleUpdate(scheduleRequest)
.then(() => {
schedule.scheduleStatus = schedule.enable ? 'OPEN' : 'SHUT';
this.$success(this.$t('commons.save_success'));
})
.catch(() => {
this.$success(this.$t('commons.save_failed'));
schedule.enable = !schedule.enable;
});
},
getScheduleObject(schedule, resourceId) {
if (schedule) {
return {
scheduleStatus: schedule.enable ? 'OPEN' : 'SHUT',
scheduleCorn: schedule.value,
scheduleExecuteTime: schedule.scheduleExecuteTime,
enable: schedule.enable,
id: schedule.id,
resourceId: schedule.resourceId,
};
} else {
return {
scheduleStatus: '',
scheduleCorn: '',
scheduleExecuteTime: '',
enable: false,
id: '',
resourceId: resourceId,
};
}
},
handleCommand(cmd) {
let table = this.$refs.scenarioTable;
switch (cmd) {
@ -1019,7 +1091,7 @@ export default {
getMaintainer().then((response) => {
option.push(...response.data);
this.userFilters = response.data.map((u) => {
return {text: u.name, value: u.id};
return { text: u.name, value: u.id };
});
});
},
@ -1030,11 +1102,11 @@ export default {
this.versionFilters = response.data
.filter((u) => u.id === currentVersion)
.map((u) => {
return {text: u.name, value: u.id};
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 };
});
}
});
@ -1125,7 +1197,7 @@ export default {
handleRunBatch(config) {
this.infoDb = false;
let run = {config: config};
let run = { config: config };
run.id = getUUID();
//
let ids = this.orderBySelectRows();
@ -1421,7 +1493,7 @@ export default {
this.search();
});
} else {
let param = {ids: [api.id]};
let param = { ids: [api.id] };
removeScenarioToGcByBatch(param).then(() => {
this.$success(this.$t('commons.delete_success'));
this.$refs.apiDeleteConfirmVersion.close();
@ -1460,7 +1532,7 @@ export default {
method: 'post',
data: param,
responseType: 'blob',
headers: {'Content-Type': 'application/json; charset=utf-8'},
headers: { 'Content-Type': 'application/json; charset=utf-8' },
};
request(config).then(
(response) => {

View File

@ -0,0 +1,78 @@
<template>
<div v-if="schedule">
<span v-if="schedule.scheduleStatus === 'OPEN'">
<el-tooltip placement="bottom-start" effect="light">
<div slot="content">
{{ $t('home.table.run_rule') }}: {{ schedule.scheduleCorn }}<br />
{{ $t('test_track.plan.next_run_time') }}<span>{{ schedule.scheduleExecuteTime | datetimeFormat }}</span>
</div>
<el-switch
@click.stop.native
v-model="schedule.enable"
inactive-color="#DCDFE6"
@change="scheduleChange"
:disabled="hasPermission">
</el-switch>
</el-tooltip>
</span>
<span v-else-if="schedule.scheduleStatus === 'SHUT'">
<el-switch
@click.stop.native
v-model="schedule.enable"
inactive-color="#DCDFE6"
@change="scheduleChange"
:disabled="hasPermission">
</el-switch>
</span>
<span v-else>
<el-link @click.stop="scheduleTask" :disabled="hasPermission" style="color: #783887">{{
$t('schedule.not_set')
}}</el-link>
</span>
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="refreshTable" :request="request" />
</div>
</template>
<script>
import { operationConfirm } from 'metersphere-frontend/src/utils';
import MsScheduleMaintain from '@/business/automation/schedule/ScheduleMaintain.vue';
export default {
name: 'ScheduleInfoInTable',
components: { MsScheduleMaintain },
props: {
schedule: Object,
hasPermission: Boolean,
scenario: Object,
request: {},
},
methods: {
scheduleTask() {
this.$emit('openSchedule');
this.$refs.scheduleMaintain.open(this.scenario);
},
refreshTable() {
this.$emit('refreshTable');
},
scheduleChange() {
let message = this.$t('api_test.home_page.running_task_list.confirm.close_title');
if (this.schedule.enable) {
message = this.$t('api_test.home_page.running_task_list.confirm.open_title');
}
operationConfirm(
this,
message,
() => {
this.$emit('scheduleChange', this.schedule);
},
() => {
this.schedule.enable = !this.schedule.enable;
}
);
},
},
};
</script>
<style scoped></style>

View File

@ -1,190 +1,220 @@
export const TEST_CASE_LIST = 'test_case_list';
export const TEST_CASE_LIST = "test_case_list";
export const CUSTOM_FIELD_LIST = new Set([
'name',
'scene',
'type',
'remark',
'system',
'createTime',
'updateTime'
"name",
"scene",
"type",
"remark",
"system",
"createTime",
"updateTime",
]);
export const ISSUE_TEMPLATE_LIST = new Set([
'name',
'platform',
'description',
'createTime',
'updateTime'
"name",
"platform",
"description",
"createTime",
"updateTime",
]);
export let CUSTOM_TABLE_HEADER = {
CUSTOM_FIELD: [
{id: 'name', key: '1', label: 'commons.name'},
{id: 'scene', key: '2', label: 'custom_field.scene'},
{id: 'type', key: '3', label: 'custom_field.attribute_type'},
{id: 'remark', key: '4', label: 'commons.remark'},
{id: 'system', key: '5', label: 'custom_field.system_field'},
{id: 'createTime', key: '6', label: 'commons.create_time'},
{id: 'updateTime', key: '7', label: 'commons.update_time'},
{ id: "name", key: "1", label: "commons.name" },
{ id: "scene", key: "2", label: "custom_field.scene" },
{ id: "type", key: "3", label: "custom_field.attribute_type" },
{ id: "remark", key: "4", label: "commons.remark" },
{ id: "system", key: "5", label: "custom_field.system_field" },
{ id: "createTime", key: "6", label: "commons.create_time" },
{ id: "updateTime", key: "7", label: "commons.update_time" },
],
//接口定义
API_DEFINITION: [
{id: 'num', key: '1', label: "ID"},
{id: 'name', key: '2', label: 'api_test.definition.api_name'},
{id: 'method', key: '3', label: 'api_test.definition.api_type'},
{id: 'userName', key: '4', label: 'api_test.definition.api_principal'},
{id: 'path', key: '5', label: 'api_test.definition.api_path'},
{id: 'tags', key: '6', label: 'commons.tag'},
{id: 'versionId', key: 'f', label: 'project.version.name', xpack: true},
{id: 'updateTime', key: '7', label: 'api_test.definition.api_last_time'},
{id: 'caseTotal', key: '8', label: 'api_test.definition.api_case_number'},
{id: 'caseStatus', key: '9', label: 'api_test.definition.api_case_status'},
{id: 'casePassingRate', key: 'a', label: 'api_test.definition.api_case_passing_rate'},
{id: 'status', key: 'b', label: 'api_test.definition.api_status'},
{id: 'createTime', key: 'c', label: 'commons.create_time'},
{id: 'description', key: 'e', label: 'commons.description'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "api_test.definition.api_name" },
{ id: "method", key: "3", label: "api_test.definition.api_type" },
{ id: "userName", key: "4", label: "api_test.definition.api_principal" },
{ id: "path", key: "5", label: "api_test.definition.api_path" },
{ id: "tags", key: "6", label: "commons.tag" },
{ id: "versionId", key: "f", label: "project.version.name", xpack: true },
{ id: "updateTime", key: "7", label: "api_test.definition.api_last_time" },
{ id: "caseTotal", key: "8", label: "api_test.definition.api_case_number" },
{
id: "caseStatus",
key: "9",
label: "api_test.definition.api_case_status",
},
{
id: "casePassingRate",
key: "a",
label: "api_test.definition.api_case_passing_rate",
},
{ id: "status", key: "b", label: "api_test.definition.api_status" },
{ id: "createTime", key: "c", label: "commons.create_time" },
{ id: "description", key: "e", label: "commons.description" },
],
//接口用例
API_CASE: [
{id: 'num', key: '1', label: "ID"},
{id: 'name', key: '2', label: 'test_track.case.name'},
{id: 'priority', key: '3', label: 'test_track.case.priority'},
{id: 'path', key: '4', label: 'api_test.definition.api_definition_path'},
{id: 'execResult', key: '5', label: 'test_track.plan_view.execute_result'},
{id: 'caseStatus', key: '6', label: 'commons.status'},
{id: 'tags', key: '7', label: 'commons.tag'},
{id: 'versionId', key: 'f', label: 'project.version.name', xpack: true},
{id: 'createUser', key: '8', label: 'api_test.creator'},
{id: 'updateTime', key: '9', label: 'api_test.definition.api_last_time'},
{id: 'createTime', key: 'a', label: 'commons.create_time'},
{id: 'passRate', key: 'b', label: 'commons.pass_rate'},
{id: 'environment', key: 'e', label: 'commons.environment'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "test_track.case.name" },
{ id: "priority", key: "3", label: "test_track.case.priority" },
{ id: "path", key: "4", label: "api_test.definition.api_definition_path" },
{
id: "execResult",
key: "5",
label: "test_track.plan_view.execute_result",
},
{ id: "caseStatus", key: "6", label: "commons.status" },
{ id: "tags", key: "7", label: "commons.tag" },
{ id: "versionId", key: "f", label: "project.version.name", xpack: true },
{ id: "createUser", key: "8", label: "api_test.creator" },
{ id: "updateTime", key: "9", label: "api_test.definition.api_last_time" },
{ id: "createTime", key: "a", label: "commons.create_time" },
{ id: "passRate", key: "b", label: "commons.pass_rate" },
{ id: "environment", key: "e", label: "commons.environment" },
],
//场景测试
API_SCENARIO: [
{id: 'num', key: '1', label: "ID"},
{id: 'name', key: '2', label: 'api_report.scenario_name'},
{id: 'level', key: '3', label: 'api_test.automation.case_level'},
{id: 'status', key: '4', label: 'test_track.plan.plan_status'},
{id: 'tags', key: '5', label: 'commons.tag'},
{id: 'versionId', key: 'f', label: 'project.version.name', xpack: true},
{id: 'creatorName', key: 'd', label: 'api_test.automation.creator'},
{id: 'principalName', key: '6', label: 'api_test.definition.api_principal'},
{id: 'environmentMap', key: 'e', label: 'commons.environment'},
{id: 'updateTime', key: '7', label: 'api_test.definition.api_last_time'},
{id: 'stepTotal', key: '8', label: 'api_test.automation.step'},
{id: 'lastResult', key: 'a', label: 'api_test.automation.last_result'},
{id: 'passRate', key: 'b', label: 'api_test.automation.passing_rate'},
{id: 'createTime', key: 'c', label: 'commons.create_time'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "api_report.scenario_name" },
{ id: "level", key: "3", label: "api_test.automation.case_level" },
{ id: "status", key: "4", label: "test_track.plan.plan_status" },
{ id: "tags", key: "5", label: "commons.tag" },
{ id: "versionId", key: "f", label: "project.version.name", xpack: true },
{ id: "creatorName", key: "d", label: "api_test.automation.creator" },
{
id: "principalName",
key: "6",
label: "api_test.definition.api_principal",
},
{ id: "environmentMap", key: "e", label: "commons.environment" },
{ id: "updateTime", key: "7", label: "api_test.definition.api_last_time" },
{ id: "stepTotal", key: "8", label: "api_test.automation.step" },
{ id: "lastResult", key: "a", label: "api_test.automation.last_result" },
{ id: "passRate", key: "b", label: "api_test.automation.passing_rate" },
{ id: "createTime", key: "c", label: "commons.create_time" },
{ id: "schedule", key: "g", label: "commons.trigger_mode.schedule" },
],
//场景测试
UI_SCENARIO: [
{id: 'num', key: '1', label: "ID"},
{id: 'name', key: '2', label: 'api_report.scenario_name'},
{id: 'level', key: '3', label: 'api_test.automation.case_level'},
{id: 'status', key: '4', label: 'test_track.plan.plan_status'},
{id: 'tags', key: '5', label: 'commons.tag'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "api_report.scenario_name" },
{ id: "level", key: "3", label: "api_test.automation.case_level" },
{ id: "status", key: "4", label: "test_track.plan.plan_status" },
{ id: "tags", key: "5", label: "commons.tag" },
// {id: 'versionId', key: 'f', label: 'project.version.name', xpack: true},
{id: 'creatorName', key: 'd', label: 'api_test.automation.creator'},
{id: 'principalName', key: '6', label: 'api_test.definition.api_principal'},
{id: 'environmentMap', key: 'e', label: 'commons.environment'},
{id: 'updateTime', key: '7', label: 'api_test.definition.api_last_time'},
{id: 'stepTotal', key: '8', label: 'api_test.automation.step'},
{id: 'lastResult', key: 'a', label: 'api_test.automation.last_result'},
{id: 'passRate', key: 'b', label: 'api_test.automation.passing_rate'},
{id: 'createTime', key: 'c', label: 'commons.create_time'},
{ id: "creatorName", key: "d", label: "api_test.automation.creator" },
{
id: "principalName",
key: "6",
label: "api_test.definition.api_principal",
},
{ id: "environmentMap", key: "e", label: "commons.environment" },
{ id: "updateTime", key: "7", label: "api_test.definition.api_last_time" },
{ id: "stepTotal", key: "8", label: "api_test.automation.step" },
{ id: "lastResult", key: "a", label: "api_test.automation.last_result" },
{ id: "passRate", key: "b", label: "api_test.automation.passing_rate" },
{ id: "createTime", key: "c", label: "commons.create_time" },
],
//自定义指令
UI_CUSTOM_COMMAND: [
{id: 'num', key: '1', label: "ID"},
{id: 'name', key: '2', label: 'ui.command_name_label'},
{id: 'tags', key: '5', label: 'commons.tag'},
{id: 'creatorName', key: 'd', label: 'api_test.automation.creator'},
{id: 'principalName', key: '6', label: 'api_test.definition.api_principal'},
{id: 'environmentMap', key: '8', label: 'commons.environment'},
{id: 'updateTime', key: '7', label: 'api_test.definition.api_last_time'},
{id: 'lastResult', key: 'a', label: 'ui.debug_result_label'},
{id: 'createTime', key: 'c', label: 'commons.create_time'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "ui.command_name_label" },
{ id: "tags", key: "5", label: "commons.tag" },
{ id: "creatorName", key: "d", label: "api_test.automation.creator" },
{
id: "principalName",
key: "6",
label: "api_test.definition.api_principal",
},
{ id: "environmentMap", key: "8", label: "commons.environment" },
{ id: "updateTime", key: "7", label: "api_test.definition.api_last_time" },
{ id: "lastResult", key: "a", label: "ui.debug_result_label" },
{ id: "createTime", key: "c", label: "commons.create_time" },
],
// 测试报告
TRACK_REPORT_TABLE: [
{id: 'name', key: '1', label: 'test_track.report.list.name'},
{id: 'testPlanName', key: '2', label: 'test_track.report.list.test_plan'},
{id: 'creator', key: '3', label: 'test_track.report.list.creator'},
{id: 'createTime', key: '4', label: 'test_track.report.list.create_time'},
{id: 'triggerMode', key: '5', label: 'test_track.report.list.trigger_mode'},
{id: 'status', key: '6', label: 'commons.status'},
{id: 'runTime', key: '7', label: 'test_track.report.list.run_time'},
{id: 'passRate', key: '8', label: 'test_track.report.list.pass_rate'},
{ id: "name", key: "1", label: "test_track.report.list.name" },
{ id: "testPlanName", key: "2", label: "test_track.report.list.test_plan" },
{ id: "creator", key: "3", label: "test_track.report.list.creator" },
{ id: "createTime", key: "4", label: "test_track.report.list.create_time" },
{
id: "triggerMode",
key: "5",
label: "test_track.report.list.trigger_mode",
},
{ id: "status", key: "6", label: "commons.status" },
{ id: "runTime", key: "7", label: "test_track.report.list.run_time" },
{ id: "passRate", key: "8", label: "test_track.report.list.pass_rate" },
],
// 场景变量
VARIABLE_LIST_TABLE: [
{id: 'num', key: '1', label: "ID"},
{id: 'name', key: '2', label: 'api_test.variable_name'},
{id: 'type', key: '3', label: 'test_track.case.type'},
{id: 'value', key: '4', label: 'api_test.value'},
{id: 'description', key: '5', label: 'commons.description'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "api_test.variable_name" },
{ id: "type", key: "3", label: "test_track.case.type" },
{ id: "value", key: "4", label: "api_test.value" },
{ id: "description", key: "5", label: "commons.description" },
],
//缺陷列表
ELEMENT_LIST: [
{id: 'num', key: '1', label: 'ID'},
{id: 'name', key: '2', label: '元素名称'},
{id: 'locationType', key: '3', label: '定位类型'},
{id: 'location', key: '4', label: '元素定位'},
{id: 'createUser', key: '5', label: '创建人'},
{id: 'createTime', key: '6', label: 'commons.create_time'},
{id: 'updateUser', key: '7', label: '更新人'},
{id: 'updateTime', key: '8', label: 'commons.update_time'},
{ id: "num", key: "1", label: "ID" },
{ id: "name", key: "2", label: "元素名称" },
{ id: "locationType", key: "3", label: "定位类型" },
{ id: "location", key: "4", label: "元素定位" },
{ id: "createUser", key: "5", label: "创建人" },
{ id: "createTime", key: "6", label: "commons.create_time" },
{ id: "updateUser", key: "7", label: "更新人" },
{ id: "updateTime", key: "8", label: "commons.update_time" },
],
//空间配额
QUOTA_WS_LIST: [
{id: 'workspaceName', key: 'a', label: 'commons.workspace'},
{id: 'api', key: 'b', label: 'quota.api'},
{id: 'performance', key: 'c', label: 'quota.performance'},
{id: 'maxThreads', key: 'd', label: 'quota.max_threads'},
{id: 'duration', key: 'e', label: 'quota.duration'},
{id: 'resourcePool', key: 'f', label: 'quota.resource_pool'},
{id: 'useDefault', key: 'j', label: 'quota.use_default'},
{id: 'vumTotal', key: 'h', label: 'quota.vum_total'},
{id: 'vumUsed', key: 'i', label: 'quota.vum_used'},
{id: 'member', key: 'g', label: 'quota.member'},
{id: 'project', key: 'k', label: 'quota.project'},
{ id: "workspaceName", key: "a", label: "commons.workspace" },
{ id: "api", key: "b", label: "quota.api" },
{ id: "performance", key: "c", label: "quota.performance" },
{ id: "maxThreads", key: "d", label: "quota.max_threads" },
{ id: "duration", key: "e", label: "quota.duration" },
{ id: "resourcePool", key: "f", label: "quota.resource_pool" },
{ id: "useDefault", key: "j", label: "quota.use_default" },
{ id: "vumTotal", key: "h", label: "quota.vum_total" },
{ id: "vumUsed", key: "i", label: "quota.vum_used" },
{ id: "member", key: "g", label: "quota.member" },
{ id: "project", key: "k", label: "quota.project" },
],
//项目配额
QUOTA_PJ_LIST: [
{id: 'projectName', key: 'a', label: 'commons.project'},
{id: 'api', key: 'b', label: 'quota.api'},
{id: 'performance', key: 'c', label: 'quota.performance'},
{id: 'maxThreads', key: 'd', label: 'quota.max_threads'},
{id: 'duration', key: 'e', label: 'quota.duration'},
{id: 'resourcePool', key: 'f', label: 'quota.resource_pool'},
{id: 'useDefault', key: 'j', label: 'quota.use_default'},
{id: 'vumTotal', key: 'h', label: 'quota.vum_total'},
{id: 'vumUsed', key: 'i', label: 'quota.vum_used'},
{id: 'member', key: 'g', label: 'quota.member'},
{ id: "projectName", key: "a", label: "commons.project" },
{ id: "api", key: "b", label: "quota.api" },
{ id: "performance", key: "c", label: "quota.performance" },
{ id: "maxThreads", key: "d", label: "quota.max_threads" },
{ id: "duration", key: "e", label: "quota.duration" },
{ id: "resourcePool", key: "f", label: "quota.resource_pool" },
{ id: "useDefault", key: "j", label: "quota.use_default" },
{ id: "vumTotal", key: "h", label: "quota.vum_total" },
{ id: "vumUsed", key: "i", label: "quota.vum_used" },
{ id: "member", key: "g", label: "quota.member" },
],
// 测试报告列表
PERFORMANCE_REPORT_TABLE: [
{id: 'testName', key: 'a', label: 'report.test_name'},
{id: 'name', key: 'b', label: 'commons.name'},
{id: 'versionId', key: 'c', label: 'project.version.name'},
{id: 'userName', key: 'd', label: 'report.user_name'},
{id: 'maxUsers', key: 'e', label: 'report.max_users'},
{id: 'avgResponseTime', key: 'f', label: 'report.response_time'},
{id: 'tps', key: 'g', label: 'TPS'},
{id: 'testStartTime', key: 'h', label: 'report.test_start_time'},
{id: 'testEndTime', key: 'i', label: 'report.test_end_time'},
{id: 'testDuration', key: 'j', label: 'report.test_execute_time'},
{id: 'triggerMode', key: 'k', label: 'test_track.report.list.trigger_mode'},
{id: 'status', key: 'l', label: 'commons.status'},
]
}
{ id: "testName", key: "a", label: "report.test_name" },
{ id: "name", key: "b", label: "commons.name" },
{ id: "versionId", key: "c", label: "project.version.name" },
{ id: "userName", key: "d", label: "report.user_name" },
{ id: "maxUsers", key: "e", label: "report.max_users" },
{ id: "avgResponseTime", key: "f", label: "report.response_time" },
{ id: "tps", key: "g", label: "TPS" },
{ id: "testStartTime", key: "h", label: "report.test_start_time" },
{ id: "testEndTime", key: "i", label: "report.test_end_time" },
{ id: "testDuration", key: "j", label: "report.test_execute_time" },
{
id: "triggerMode",
key: "k",
label: "test_track.report.list.trigger_mode",
},
{ id: "status", key: "l", label: "commons.status" },
],
};

View File

@ -73,7 +73,6 @@ public class TestPlanReportDataStruct extends TestPlanReportContent {
List<TestPlanApiDTO> runningCaseList =
apiAllCases.stream().filter(
dto -> StringUtils.equalsAnyIgnoreCase(dto.getExecResult(),
ApiReportStatus.PENDING.name(),
ApiReportStatus.RERUNNING.name(),
ApiReportStatus.RUNNING.name())).toList();
if (runningCaseList.size() > 0) {
@ -84,7 +83,6 @@ public class TestPlanReportDataStruct extends TestPlanReportContent {
List<TestPlanScenarioDTO> runningCaseList =
scenarioAllCases.stream().filter(
dto -> StringUtils.equalsAnyIgnoreCase(dto.getLastResult(),
ApiReportStatus.PENDING.name(),
ApiReportStatus.RERUNNING.name(),
ApiReportStatus.RUNNING.name())).toList();
if (runningCaseList.size() > 0) {
@ -95,8 +93,6 @@ public class TestPlanReportDataStruct extends TestPlanReportContent {
List<TestPlanLoadCaseDTO> runningCaseList =
loadAllCases.stream().filter(
dto -> StringUtils.equalsAnyIgnoreCase(dto.getStatus(),
PerformanceTestStatus.Starting.name(),
PerformanceTestStatus.Running.name(),
PerformanceTestStatus.Reporting.name())).toList();
if (runningCaseList.size() > 0) {
return true;
@ -106,7 +102,6 @@ public class TestPlanReportDataStruct extends TestPlanReportContent {
List<TestPlanUiScenarioDTO> runningCaseList =
uiAllCases.stream().filter(
dto -> StringUtils.equalsAnyIgnoreCase(dto.getLastResult(),
ApiReportStatus.PENDING.name(),
ApiReportStatus.RERUNNING.name(),
ApiReportStatus.RUNNING.name())).toList();
if (runningCaseList.size() > 0) {

View File

@ -2408,7 +2408,9 @@ public class TestPlanService {
TestPlanReportDataStruct testPlanReportDataStruct = new TestPlanReportDataStruct();
try {
testPlanReportDataStruct = this.generateReportStruct(testPlanWithBLOBs, testPlanReport, testPlanReportContent, false);
if (StringUtils.isBlank(testPlanReportContent.getApiBaseCount()) && !testPlanReportDataStruct.hasRunningCase()) {
if (StringUtils.isBlank(testPlanReportContent.getApiBaseCount())
&& !testPlanReportDataStruct.hasRunningCase()
&& StringUtils.equalsAnyIgnoreCase(testPlanReport.getStatus(), TestPlanReportStatus.FAILED.name(), TestPlanReportStatus.COMPLETED.name(), TestPlanReportStatus.SUCCESS.name())) {
//旧版本的测试计划报告没有重新统计过测试计划报告时且当不存在运行中的用例会将结果保存下来
testPlanReportService.updateReportStructInfo(testPlanReportContent, testPlanReportDataStruct);
}