fix(测试计划): 修复测试计划报告bug&报告明细展示问题&状态等问题
This commit is contained in:
parent
ae5ea6394e
commit
4b14f649a9
|
@ -579,11 +579,20 @@
|
|||
function writeAssociateCases(param: AssociateCaseRequest) {
|
||||
selectedAssociateCasesParams.value = { ...param };
|
||||
const node: PlanMinderNode = window.minder.getSelectedNode();
|
||||
let associateType: string = '';
|
||||
// TODO 类型对应的上 但是node保存的时候节点好像不太对
|
||||
if (node.data.type === PlanMinderCollectionType.SCENARIO) {
|
||||
associateType = PlanMinderAssociateType.SCENARIO_CASE;
|
||||
} else {
|
||||
associateType =
|
||||
node.data.type === PlanMinderCollectionType.API && param.associateApiType
|
||||
? param.associateApiType
|
||||
: node.data.type;
|
||||
}
|
||||
node.data.associateDTOS = [
|
||||
{
|
||||
ids: param.selectIds,
|
||||
associateType:
|
||||
node.data.type === PlanMinderCollectionType.SCENARIO ? PlanMinderAssociateType.SCENARIO_CASE : node.data.type,
|
||||
associateType,
|
||||
},
|
||||
];
|
||||
caseAssociateVisible.value = false;
|
||||
|
|
|
@ -37,6 +37,7 @@ export interface AssociateCaseRequest extends BatchApiParams {
|
|||
apiScenarioSelectIds?: string[];
|
||||
totalCount?: number;
|
||||
testPlanId?: string;
|
||||
associateApiType?: string;
|
||||
}
|
||||
|
||||
export type AssociateCaseRequestType = Pick<AssociateCaseRequest, 'functionalSelectIds' | 'testPlanId'>;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
size="160px"
|
||||
:legend-data="legendData"
|
||||
:options="executeCharOptions"
|
||||
:request-total="getIndicators(detail.caseTotal) || 0"
|
||||
:request-total="getIndicators(getTotal) || 0"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -97,6 +97,12 @@
|
|||
}) as unknown as LegendData[];
|
||||
}
|
||||
|
||||
const getTotal = computed(() => {
|
||||
const { executeCount } = props.detail;
|
||||
const { success, error, fakeError, pending, block } = executeCount;
|
||||
return success + error + fakeError + pending + block;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.detail) {
|
||||
initExecuteOptions();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<MsButton class="!mx-0" @click="openReport(record)">{{ t('report.detail.testPlanGroup.viewReport') }}</MsButton>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
<ReportDrawer v-model:visible="reportVisible" :report-id="reportId" />
|
||||
<ReportDrawer v-model:visible="reportVisible" :report-id="independentReportId" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -133,12 +133,15 @@
|
|||
|
||||
const reportVisible = ref(false);
|
||||
|
||||
const independentReportId = ref<string>('');
|
||||
|
||||
function openReport(record: PlanReportDetail) {
|
||||
independentReportId.value = record.id;
|
||||
if (props.currentMode === 'drawer') {
|
||||
reportVisible.value = true;
|
||||
} else {
|
||||
openNewPage(RouteEnum.TEST_PLAN_REPORT_DETAIL, {
|
||||
reportId: record.id,
|
||||
id: record.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { characterLimit } from '@/utils';
|
||||
|
||||
import type { TestPlanDetail, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||
import type { CreateTask, TestPlanDetail, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
@ -56,6 +56,7 @@
|
|||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
record: TestPlanItem | TestPlanDetail | undefined; // 表record
|
||||
scheduleConfig?: CreateTask;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -98,7 +99,9 @@
|
|||
case 'ARCHIVED':
|
||||
return t('testPlan.testPlanIndex.deleteArchivedPlan');
|
||||
case 'UNDERWAY':
|
||||
return t('testPlan.testPlanIndex.deleteRunningPlan');
|
||||
return props.scheduleConfig && props.scheduleConfig.enable
|
||||
? t('testPlan.testPlanIndex.deleteRunningSchedulePlan')
|
||||
: t('testPlan.testPlanIndex.deleteRunningPlan');
|
||||
case 'COMPLETED':
|
||||
return t('testPlan.testPlanIndex.deleteCompletedPlan');
|
||||
default:
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
@batch-action="handleTableBatch"
|
||||
@filter-change="filterChange"
|
||||
@drag-change="handleDragChange"
|
||||
@sorter-change="saveSort"
|
||||
>
|
||||
<!-- TODO: 快捷创建暂时不上 -->
|
||||
<!-- <template v-if="hasAnyPermission(['PROJECT_TEST_PLAN:READ+ADD'])" #quickCreate>
|
||||
|
@ -159,30 +160,32 @@
|
|||
</template>
|
||||
<template #planStartToEndTime="{ record }">
|
||||
<div>
|
||||
{{ record.plannedStartTime ? dayjs(record.plannedStartTime) : '-' }} {{ t('common.to') }}
|
||||
{{ record.plannedStartTime ? dayjs(record.plannedStartTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
|
||||
{{ t('common.to') }}
|
||||
<a-tooltip
|
||||
class="ms-tooltip-red"
|
||||
:content="t('testPlan.planStartToEndTimeTip')"
|
||||
:disabled="record.execStatus !== LastExecuteResults.ERROR"
|
||||
>
|
||||
<span :class="[`${record.execStatus === LastExecuteResults.ERROR ? 'text-[rgb(var(--danger-6))' : ''}`]">
|
||||
{{ record?.plannedEndTime ? dayjs(record.plannedEndTime) : '-' }}
|
||||
{{ record?.plannedEndTime ? dayjs(record.plannedEndTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #actualStartToEndTime="{ record }">
|
||||
{{ record?.actualStartTime ? dayjs(record.actualStartTime) : '-' }}{{ t('common.to')
|
||||
}}{{ record.actualEndTime ? dayjs(record.actualEndTime) : '-' }}
|
||||
{{ record?.actualStartTime ? dayjs(record.actualStartTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
|
||||
{{ t('common.to') }} {{ record.actualEndTime ? dayjs(record.actualEndTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
|
||||
</template>
|
||||
|
||||
<template #passRate="{ record }">
|
||||
<div class="mr-[8px] w-[100px]">
|
||||
<div v-if="record.type === testPlanTypeEnum.TEST_PLAN" class="mr-[8px] w-[100px]">
|
||||
<StatusProgress :status-detail="defaultCountDetailMap[record.id]" height="5px" />
|
||||
</div>
|
||||
<div class="text-[var(--color-text-1)]">
|
||||
<div v-if="record.type === testPlanTypeEnum.TEST_PLAN" class="text-[var(--color-text-1)]">
|
||||
{{ `${defaultCountDetailMap[record.id]?.passRate ? defaultCountDetailMap[record.id].passRate : '-'}%` }}
|
||||
</div>
|
||||
<span v-else> - </span>
|
||||
</template>
|
||||
<template #passRateTitleSlot="{ columnConfig }">
|
||||
<div class="flex items-center text-[var(--color-text-3)]">
|
||||
|
@ -196,8 +199,13 @@
|
|||
</div>
|
||||
</template>
|
||||
<template #functionalCaseCount="{ record }">
|
||||
<a-popover position="bottom" content-class="p-[16px]" :disabled="getFunctionalCount(record.id) < 1">
|
||||
<div>{{ getFunctionalCount(record.id) }}</div>
|
||||
<a-popover
|
||||
v-if="record.type === testPlanTypeEnum.TEST_PLAN"
|
||||
position="bottom"
|
||||
content-class="p-[16px]"
|
||||
:disabled="getFunctionalCount(record.id) < 1"
|
||||
>
|
||||
<div v-if="record.type === testPlanTypeEnum.TEST_PLAN">{{ getFunctionalCount(record.id) }}</div>
|
||||
<template #content>
|
||||
<table class="min-w-[140px] max-w-[176px]">
|
||||
<tr>
|
||||
|
@ -235,14 +243,22 @@
|
|||
</table>
|
||||
</template>
|
||||
</a-popover>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #operation="{ record }">
|
||||
<div class="flex items-center">
|
||||
<MsButton v-if="isShowExecuteButton(record)" class="!mx-0" @click="executePlan(record)">{{
|
||||
t('testPlan.testPlanIndex.execution')
|
||||
}}</MsButton>
|
||||
<a-divider v-if="isShowExecuteButton(record)" direction="vertical" :margin="8"></a-divider>
|
||||
<MsButton
|
||||
v-if="isShowExecuteButton(record, ['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
class="!mx-0"
|
||||
@click="executePlan(record)"
|
||||
>{{ t('testPlan.testPlanIndex.execution') }}</MsButton
|
||||
>
|
||||
<a-divider
|
||||
v-if="isShowExecuteButton(record, ['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
direction="vertical"
|
||||
:margin="8"
|
||||
></a-divider>
|
||||
|
||||
<MsButton
|
||||
v-if="hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']) && record.status !== 'ARCHIVED'"
|
||||
|
@ -256,10 +272,17 @@
|
|||
:margin="8"
|
||||
></a-divider>
|
||||
|
||||
<MsButton v-if="!isShowExecuteButton(record)" class="!mx-0" @click="copyTestPlanOrGroup(record.id)">{{
|
||||
t('common.copy')
|
||||
}}</MsButton>
|
||||
<a-divider v-if="!isShowExecuteButton(record)" direction="vertical" :margin="8"></a-divider>
|
||||
<MsButton
|
||||
v-if="!isShowExecuteButton(record, ['PROJECT_TEST_PLAN:READ+ADD'])"
|
||||
class="!mx-0"
|
||||
@click="copyTestPlanOrGroup(record.id)"
|
||||
>{{ t('common.copy') }}</MsButton
|
||||
>
|
||||
<a-divider
|
||||
v-if="!isShowExecuteButton(record, ['PROJECT_TEST_PLAN:READ+ADD'])"
|
||||
direction="vertical"
|
||||
:margin="8"
|
||||
></a-divider>
|
||||
<MsTableMoreAction :list="getMoreActions(record)" @select="handleMoreActionSelect($event, record)" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -308,7 +331,12 @@
|
|||
:task-config="taskForm"
|
||||
@handle-success="fetchData()"
|
||||
/>
|
||||
<ActionModal v-model:visible="showStatusDeleteModal" :record="activeRecord" @success="fetchData()" />
|
||||
<ActionModal
|
||||
v-model:visible="showStatusDeleteModal"
|
||||
:record="activeRecord"
|
||||
:schedule-config="defaultCountDetailMap[activeRecord?.id || 'none']?.scheduleConfig"
|
||||
@success="fetchData()"
|
||||
/>
|
||||
<BatchEditModal
|
||||
v-model:visible="showEditModel"
|
||||
:batch-params="batchParams"
|
||||
|
@ -501,6 +529,7 @@
|
|||
dataIndex: 'moduleId',
|
||||
showInTable: true,
|
||||
showDrag: true,
|
||||
showTooltip: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
|
@ -514,6 +543,7 @@
|
|||
},
|
||||
width: 200,
|
||||
showDrag: true,
|
||||
showTooltip: true,
|
||||
},
|
||||
{
|
||||
title: 'testPlan.testPlanIndex.planStartToEndTime',
|
||||
|
@ -523,7 +553,8 @@
|
|||
sortDirections: ['ascend', 'descend'],
|
||||
sorter: true,
|
||||
},
|
||||
width: 200,
|
||||
width: 370,
|
||||
showTooltip: true,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
|
@ -534,7 +565,8 @@
|
|||
sortDirections: ['ascend', 'descend'],
|
||||
sorter: true,
|
||||
},
|
||||
width: 200,
|
||||
showTooltip: true,
|
||||
width: 370,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
|
@ -668,19 +700,19 @@
|
|||
{
|
||||
label: 'testPlan.testPlanIndex.createScheduledTask',
|
||||
eventTag: 'createScheduledTask',
|
||||
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||
permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
||||
},
|
||||
];
|
||||
const updateAndDeleteScheduledActions: ActionsItem[] = [
|
||||
{
|
||||
label: 'testPlan.testPlanIndex.updateScheduledTask',
|
||||
eventTag: 'updateScheduledTask',
|
||||
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||
permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
||||
},
|
||||
{
|
||||
label: 'testPlan.testPlanIndex.deleteScheduledTask',
|
||||
eventTag: 'deleteScheduledTask',
|
||||
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||
permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -695,11 +727,11 @@
|
|||
return defaultCountDetailMap.value[id].scheduleConfig.enable;
|
||||
}
|
||||
|
||||
function isShowExecuteButton(record: TestPlanItem) {
|
||||
function isShowExecuteButton(record: TestPlanItem, permission: string[]) {
|
||||
return (
|
||||
((record.type === testPlanTypeEnum.TEST_PLAN && getFunctionalCount(record.id) > 0) ||
|
||||
(record.type === testPlanTypeEnum.GROUP && record.childrenCount)) &&
|
||||
hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE']) &&
|
||||
hasAnyPermission(permission) &&
|
||||
record.status !== 'ARCHIVED'
|
||||
);
|
||||
}
|
||||
|
@ -708,7 +740,7 @@
|
|||
const { status: planStatus } = record;
|
||||
|
||||
// 有用例数量才可以执行 否则不展示执行
|
||||
const copyAction = isShowExecuteButton(record) ? copyActions : [];
|
||||
const copyAction = isShowExecuteButton(record, ['PROJECT_TEST_PLAN:READ+ADD']) ? copyActions : [];
|
||||
|
||||
let scheduledTaskAction: ActionsItem[] = [];
|
||||
if (planStatus !== 'ARCHIVED' && record.groupId && record.groupId === 'NONE') {
|
||||
|
@ -825,6 +857,11 @@
|
|||
setLoadListParams(await initTableParams());
|
||||
loadList();
|
||||
}
|
||||
// 排序
|
||||
const sort = ref<{ [key: string]: string }>({});
|
||||
function saveSort(sortObj: { [key: string]: string }) {
|
||||
sort.value = sortObj;
|
||||
}
|
||||
|
||||
// 获取父组件模块数量
|
||||
async function emitTableParams(isInit = false) {
|
||||
|
@ -871,7 +908,7 @@
|
|||
projectId: appStore.currentProjectId,
|
||||
executeIds: [],
|
||||
runMode: 'SERIAL',
|
||||
executionSource: 'JENKINS',
|
||||
executionSource: 'MANUAL',
|
||||
};
|
||||
|
||||
const executeForm = ref<BatchExecutePlan>(cloneDeep(initExecuteForm));
|
||||
|
@ -913,7 +950,7 @@
|
|||
const params: ExecutePlan = {
|
||||
executeId: id,
|
||||
runMode: 'SERIAL',
|
||||
executionSource: 'JENKINS',
|
||||
executionSource: 'MANUAL',
|
||||
};
|
||||
await executeSinglePlan(params);
|
||||
Message.success(t('case.detail.execute.success'));
|
||||
|
@ -1331,7 +1368,8 @@
|
|||
() => showType.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
tableProps.value.draggableCondition = hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']) && val === 'ALL';
|
||||
tableProps.value.draggableCondition =
|
||||
hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']) && val !== 'TEST_PLAN' && !Object.keys(sort.value).length;
|
||||
setPagination({
|
||||
current: 1,
|
||||
});
|
||||
|
@ -1342,6 +1380,21 @@
|
|||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => sort.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
tableProps.value.draggableCondition =
|
||||
hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']) &&
|
||||
showType.value !== 'GROUP' &&
|
||||
!Object.keys(sort.value).length;
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.activeFolder,
|
||||
(val) => {
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
{{ detailCount.errorCount }}
|
||||
</td>
|
||||
</tr>
|
||||
<!-- TODO 这个版本暂时不上 -->
|
||||
<!-- <tr>
|
||||
<tr>
|
||||
<td class="popover-label-td">
|
||||
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--warning-6))]"></div>
|
||||
<div>{{ t('common.fakeError') }}</div>
|
||||
|
@ -41,7 +40,7 @@
|
|||
<td class="popover-value-td">
|
||||
{{ detailCount.fakeErrorCount }}
|
||||
</td>
|
||||
</tr> -->
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="popover-label-td">
|
||||
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[var(--color-fill-p-3)]"></div>
|
||||
|
|
|
@ -73,12 +73,15 @@ export default {
|
|||
'The plan is not executed, the data cannot be recovered after deletion, please operate carefully!',
|
||||
'testPlan.testPlanIndex.deleteRunningPlan':
|
||||
'Scheduled tasks are stopped and deleted. Exercise caution when performing this operation',
|
||||
'testPlan.testPlanIndex.deleteRunningSchedulePlan':
|
||||
'Scheduled tasks are stopped and deleted. Exercise caution when performing this operation.',
|
||||
'testPlan.testPlanIndex.deleteCompletedPlan':
|
||||
'The proposed plan is completed, the option is archived, and the use case information and execution results are retained;If you continue to delete, the data will not be restored, please be careful!',
|
||||
'testPlan.testPlanIndex.confirmArchivePlan':
|
||||
'After filing, implement information no longer update and editing, data unrecoverable, please careful operation!',
|
||||
'testPlan.testPlanIndex.passRateTitleTip': 'Passed use cases/all use cases *100%',
|
||||
'testPlan.planForm.namePlaceholder': 'Please enter the name of the test plan',
|
||||
'testPlan.planForm.nameGroupPlaceholder': 'Please enter a plan group name',
|
||||
'testPlan.planForm.nameRequired': 'Test plan name cannot be empty',
|
||||
'testPlan.planForm.testPlanGroupRequired': 'Plan group cannot be empty',
|
||||
'testPlan.planForm.planStartAndEndTime': 'Planned start and end time',
|
||||
|
|
|
@ -68,12 +68,15 @@ export default {
|
|||
'testPlan.testPlanIndex.deleteArchivedPlan': '计划 已归档,删除后数据不可恢复,请谨慎操作!',
|
||||
'testPlan.testPlanIndex.deletePendingPlan': '计划 未执行,删除后数据不可恢复,请谨慎操作!',
|
||||
'testPlan.testPlanIndex.deleteRunningPlan': '计划 进行中,删除后,终止执行且不可恢复,请谨慎操作!',
|
||||
'testPlan.testPlanIndex.deleteRunningSchedulePlan':
|
||||
'计划 进行中,删除后,终止执行且不可恢复,定时任务停止并删除,请谨慎操作!',
|
||||
'testPlan.testPlanIndex.deleteCompletedPlan':
|
||||
'建议计划 已完成 ,选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,请谨慎操作!',
|
||||
'testPlan.testPlanIndex.confirmArchivePlan': '归档后,执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
|
||||
'testPlan.testPlanIndex.passRateTitleTip': '已通过用例/全部用例*100%',
|
||||
'testPlan.testPlanIndex.batchEdit': '批量编辑 (已选 { number } 项数据)',
|
||||
'testPlan.planForm.namePlaceholder': '请输入测试计划名称',
|
||||
'testPlan.planForm.nameGroupPlaceholder': '请输入计划组名称',
|
||||
'testPlan.planForm.nameRequired': '测试计划名称不能为空',
|
||||
'testPlan.planForm.testPlanGroupRequired': '计划组不能为空',
|
||||
'testPlan.planForm.planStartAndEndTime': '计划起止时间',
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<a-form-item
|
||||
field="name"
|
||||
:label="t('testPlan.testPlanGroup.name')"
|
||||
:rules="[{ required: true, message: t('apiTestDebug.requestNameRequired') }]"
|
||||
:rules="[{ required: true, message: t('testPlan.planForm.nameGroupPlaceholder') }]"
|
||||
asterisk-position="end"
|
||||
>
|
||||
<a-input
|
||||
|
|
Loading…
Reference in New Issue