@@ -88,16 +100,18 @@
import MsColorLine from '@/components/pure/ms-color-line/index.vue';
- import { statusConfig } from '@/config/testPlan';
+ import { defaultCount, statusConfig } from '@/config/testPlan';
import { useI18n } from '@/hooks/useI18n';
import { addCommasToNumber } from '@/utils';
- import type { countDetail, PlanReportDetail } from '@/models/testPlan/testPlanReport';
+ import type { AnalysisType, countDetail, PlanReportDetail } from '@/models/testPlan/testPlanReport';
const { t } = useI18n();
+
const props = defineProps<{
detail: PlanReportDetail;
status: keyof countDetail;
+ type: AnalysisType;
}>();
const defaultStatus = {
@@ -113,8 +127,15 @@
return statusConfig.find((e) => e.value === props.status) || defaultStatus;
});
+ const analysisTypeMap: Record = {
+ FUNCTIONAL: 'functionalCount',
+ API: 'apiCaseCount',
+ SCENARIO: 'apiScenarioCount',
+ };
+
const countDetailData = computed(() => {
- return props.detail.functionalCount;
+ const countKey = analysisTypeMap[props.type] as keyof PlanReportDetail;
+ return props.detail[countKey] ? (props.detail[countKey] as countDetail) : defaultCount;
});
const colorData = computed(() => {
diff --git a/frontend/src/views/test-plan/report/detail/component/planDetail.vue b/frontend/src/views/test-plan/report/detail/component/planDetail.vue
index 59c819ace6..e320711174 100644
--- a/frontend/src/views/test-plan/report/detail/component/planDetail.vue
+++ b/frontend/src/views/test-plan/report/detail/component/planDetail.vue
@@ -1,16 +1,5 @@
-
-
-
-
-
-
-
-
+
{{ t('report.detail.api.reportAnalysis') }}
@@ -30,16 +19,16 @@
/>
-
+
{{ t('report.detail.useCaseAnalysis') }}
+
{{ t('report.detail.apiUseCaseAnalysis') }}
-
-
-
-
+
+
+
+
@@ -96,10 +86,10 @@
{{ t('report.detail.scenarioUseCaseAnalysis') }}
-
- {{ t('report.detail.reportSummary') }}
-
-
-
-
-
-
- {{ t('common.save') }}
- {{ t('common.cancel') }}
-
-
+
();
const detail = ref({ ...cloneDeep(defaultReportDetail) });
- const showButton = ref(false);
+ const showButton = ref(false);
const richText = ref<{ summary: string; richTextTmpFileIds?: string[] }>({
summary: '',
});
@@ -373,13 +344,6 @@
});
}
- async function handleUploadImage(file: File) {
- const { data } = await editorUploadFile({
- fileList: [file],
- });
- return data;
- }
-
async function handleUpdateReportDetail() {
try {
await updateReportDetail({
@@ -395,10 +359,6 @@
console.log(error);
}
}
- function handleCancel() {
- richText.value = { summary: detail.value.summary };
- showButton.value = false;
- }
const reportAnalysisList = computed(() => [
{
@@ -471,10 +431,68 @@
});
});
- const summaryContent = ref(`
- 本次完成 测试计划名称,功能测试,接口测试;共 300条 用例,已执行 285 条,未执行 15 条,执行率为 95%,通过用例 270 条,通过率为 90%,达到/未达到通过阈值(通过阈值为85%),xxx计划满足/不满足发布要求。 (1)本次测试包含100条功能测试用例,执行了95条,未执行5条,执行率为95%,通过用例90条,通过率为90%。共发现缺陷0个。 (2)本次测试包含100条接口测试用例,执行了95条,未执行5条,执行率为95%,通过用例90条,通过率为90%。共发现缺陷0个。 (3)本次测试包含100条场景测试用例,执行了95条,未执行5条,执行率为95%,通过用例90条,通过率为90%。共发现缺陷0个
- `);
- // 一键总结 TODO 待联调
+ function getSummaryDetail(detailCount: countDetail) {
+ if (detailCount) {
+ const { success, error, fakeError, pending, block } = detailCount;
+ // 已执行用例
+ const hasExecutedCase = success + error + fakeError + block;
+ // 用例总数
+ const caseTotal = hasExecutedCase + pending;
+ // 执行率
+ const executedCount = (hasExecutedCase / caseTotal) * 100;
+ const apiExecutedRate = `${Number.isNaN(executedCount) ? 0 : executedCount.toFixed(2)}%`;
+ // 通过率
+ const successCount = (success / caseTotal) * 100;
+ const successRate = `${Number.isNaN(successCount) ? 0 : successCount.toFixed(2)}%`;
+ return {
+ hasExecutedCase,
+ caseTotal,
+ apiExecutedRate,
+ successRate,
+ pending,
+ success,
+ };
+ }
+ return {
+ hasExecutedCase: 0,
+ caseTotal: 0,
+ apiExecutedRate: 0,
+ successRate: 0,
+ pending: 0,
+ success: 0,
+ };
+ }
+
+ const summaryContent = computed(() => {
+ const { functionalCount, apiCaseCount, apiScenarioCount } = detail.value;
+ const functionalCaseDetail = getSummaryDetail(functionalCount);
+ const apiCaseDetail = getSummaryDetail(apiCaseCount);
+ const apiScenarioDetail = getSummaryDetail(apiScenarioCount);
+ const allCaseTotal = functionalCaseDetail.caseTotal + apiCaseDetail.caseTotal + apiScenarioDetail.caseTotal;
+ const allHasExecutedCase =
+ functionalCaseDetail.hasExecutedCase + apiCaseDetail.hasExecutedCase + apiScenarioDetail.hasExecutedCase;
+ const allPendingCase = functionalCaseDetail.pending + apiCaseDetail.pending + apiScenarioDetail.pending;
+ const allSuccessCase = functionalCaseDetail.success + apiCaseDetail.success + apiScenarioDetail.success;
+
+ const allExecutedCount = (allHasExecutedCase / allCaseTotal) * 100;
+ const allExecutedRate = `${Number.isNaN(allExecutedCount) ? 0 : allExecutedCount.toFixed(2)}%`;
+
+ // 通过率
+ const allSuccessCount = (allSuccessCase / allCaseTotal) * 100;
+ const allSuccessRate = `${Number.isNaN(allSuccessCount) ? 0 : allSuccessCount.toFixed(2)}%`;
+ // 接口用例通过率
+ return `本次完成 ${detail.value.name}的功能测试,接口测试;共 ${allCaseTotal}条 用例,已执行 ${allHasExecutedCase} 条,未执行 ${allPendingCase} 条,执行率为 ${allExecutedRate}%,通过用例 ${allSuccessCase} 条,通过率为 ${allSuccessRate},达到/未达到通过阈值(通过阈值为${detail.value.passThreshold}%),xxx计划满足/不满足发布要求。
+ (1)本次测试包含${functionalCaseDetail.caseTotal}条功能测试用例,执行了${functionalCaseDetail.hasExecutedCase}条,未执行${functionalCaseDetail.pending}条,执行率为${functionalCaseDetail.apiExecutedRate},通过用例${functionalCaseDetail.success}条,通过率为${functionalCaseDetail.successRate}。共发现缺陷0个。
+ (2)本次测试包含${apiCaseDetail.caseTotal}条接口测试用例,执行了${apiCaseDetail.hasExecutedCase}条,未执行${apiCaseDetail.pending}条,执行率为${apiCaseDetail.apiExecutedRate},通过用例${apiCaseDetail.success}条,通过率为${apiCaseDetail.successRate}。共发现缺陷0个。
+ (3)本次测试包含${apiScenarioDetail.caseTotal}条场景测试用例,执行了${apiScenarioDetail.hasExecutedCase}条,未执行${apiScenarioDetail.pending}条,执行率为${apiScenarioDetail.apiExecutedRate}%,通过用例${apiScenarioDetail.success}条,通过率为${apiScenarioDetail.successRate}。共发现缺陷0个
+ `;
+ });
+
+ function handleCancel() {
+ richText.value = { summary: detail.value.summary };
+ showButton.value = false;
+ }
+
function handleSummary() {
richText.value.summary = summaryContent.value;
}
diff --git a/frontend/src/views/test-plan/report/detail/component/planGroupDetail.vue b/frontend/src/views/test-plan/report/detail/component/planGroupDetail.vue
new file mode 100644
index 0000000000..54a9180f1f
--- /dev/null
+++ b/frontend/src/views/test-plan/report/detail/component/planGroupDetail.vue
@@ -0,0 +1,246 @@
+
+
+
+
+ {{ t('report.detail.api.reportAnalysis') }}
+
+
+
+ {{ t('report.detail.executionAnalysis') }}
+
+
+
+
+
+
+ {{ t('report.detail.api.reportDetail') }}
+
+
+
+
+ {{ t('msTable.columnSetting.drawer') }}
+
+
+
+
+
+ {{ t('msTable.columnSetting.newWindow') }}
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/test-plan/report/detail/component/reportHeader.vue b/frontend/src/views/test-plan/report/detail/component/reportHeader.vue
new file mode 100644
index 0000000000..7f16bb000f
--- /dev/null
+++ b/frontend/src/views/test-plan/report/detail/component/reportHeader.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/test-plan/report/detail/component/summary.vue b/frontend/src/views/test-plan/report/detail/component/summary.vue
new file mode 100644
index 0000000000..eb74f67cba
--- /dev/null
+++ b/frontend/src/views/test-plan/report/detail/component/summary.vue
@@ -0,0 +1,81 @@
+
+
+ {{ t('report.detail.reportSummary') }}
+
+
+
+
+
+
+ {{ t('common.save') }}
+ {{ t('common.cancel') }}
+
+
+
+
+
+
+
diff --git a/frontend/src/views/test-plan/report/detail/groupReportIndex.vue b/frontend/src/views/test-plan/report/detail/groupReportIndex.vue
new file mode 100644
index 0000000000..ad0e8e7787
--- /dev/null
+++ b/frontend/src/views/test-plan/report/detail/groupReportIndex.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/frontend/src/views/test-plan/report/locale/en-US.ts b/frontend/src/views/test-plan/report/locale/en-US.ts
index 7123c30791..0fa335d48a 100644
--- a/frontend/src/views/test-plan/report/locale/en-US.ts
+++ b/frontend/src/views/test-plan/report/locale/en-US.ts
@@ -40,4 +40,6 @@ export default {
'report.detail.apiCaseDetails': 'Api use case details',
'report.detail.scenarioCaseDetails': 'Scenario use case details',
'report.detail.oneClickSummary': 'One click report summary',
+ 'report.detail.testPlanTotal': 'Total plan',
+ 'report.detail.testPlanCaseTotal': 'Total use cases',
};
diff --git a/frontend/src/views/test-plan/report/locale/zh-CN.ts b/frontend/src/views/test-plan/report/locale/zh-CN.ts
index 3ad4e654fa..be588d4647 100644
--- a/frontend/src/views/test-plan/report/locale/zh-CN.ts
+++ b/frontend/src/views/test-plan/report/locale/zh-CN.ts
@@ -40,4 +40,8 @@ export default {
'report.detail.apiCaseDetails': '接口用例明细',
'report.detail.scenarioCaseDetails': '场景用例明细',
'report.detail.oneClickSummary': '一键填写报告总结',
+ 'report.detail.testReport': '测试报告',
+ 'report.detail.testPlanGroupReport': '测试组报告',
+ 'report.detail.testPlanTotal': '计划总数',
+ 'report.detail.testPlanCaseTotal': '用例总数',
};
diff --git a/frontend/src/views/test-plan/testPlan/components/planTable.vue b/frontend/src/views/test-plan/testPlan/components/planTable.vue
index d8a1bdcbef..04b050a5fc 100644
--- a/frontend/src/views/test-plan/testPlan/components/planTable.vue
+++ b/frontend/src/views/test-plan/testPlan/components/planTable.vue
@@ -39,6 +39,10 @@
:selectable="hasOperationPermission && showType !== testPlanTypeEnum.ALL"
filter-icon-align-left
:expanded-keys="expandedKeys"
+ :disabled-config="{
+ disabledChildren: true,
+ parentKey: 'parent',
+ }"
v-on="propsEvent"
@batch-action="handleTableBatch"
@filter-change="filterChange"
@@ -365,6 +369,7 @@
batchArchivedPlan,
batchCopyPlan,
batchDeletePlan,
+ batchEditTestPlan,
batchMovePlan,
deletePlan,
deleteScheduleTask,
@@ -383,7 +388,7 @@
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
- import { DragSortParams, ModuleTreeNode } from '@/models/common';
+ import { DragSortParams, ModuleTreeNode, TableQueryParams } from '@/models/common';
import type {
AddTestPlanParams,
BatchMoveParams,
@@ -993,9 +998,41 @@
}
/**
- * 打开关闭定时任务 TODO 待联调
+ * 打开关闭定时任务
*/
- function handleStatusTimingTask(enable: boolean) {}
+ async function handleStatusTimingTask(enable: boolean) {
+ const filterParams = {
+ ...propsRes.value.filter,
+ };
+ if (isArchived.value) {
+ filterParams.status = ['ARCHIVED'];
+ }
+ try {
+ const { selectedIds, selectAll, excludeIds } = batchParams.value;
+ const params: TableQueryParams = {
+ selectIds: selectedIds || [],
+ selectAll: !!selectAll,
+ excludeIds: excludeIds || [],
+ projectId: appStore.currentProjectId,
+ moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
+ condition: {
+ filter: filterParams,
+ keyword: keyword.value,
+ },
+ type: showType.value,
+ scheduleOpen: enable,
+ };
+ await batchEditTestPlan(params);
+ Message.success(
+ enable
+ ? t('testPlan.testPlanGroup.enableScheduleTaskSuccess')
+ : t('testPlan.testPlanGroup.closeScheduleTaskSuccess')
+ );
+ fetchData();
+ } catch (error) {
+ console.log(error);
+ }
+ }
/**
* 归档测试计划以及计划组
diff --git a/frontend/src/views/test-plan/testPlan/components/scheduledModal.vue b/frontend/src/views/test-plan/testPlan/components/scheduledModal.vue
index 3e2782bada..bd5bb5fc85 100644
--- a/frontend/src/views/test-plan/testPlan/components/scheduledModal.vue
+++ b/frontend/src/views/test-plan/testPlan/components/scheduledModal.vue
@@ -161,7 +161,7 @@
await configSchedule(params);
handleCancel();
emit('handleSuccess');
- Message.success(t('common.createSuccess'));
+ Message.success(props.taskConfig ? t('common.updateSuccess') : t('common.createSuccess'));
}
} catch (error) {
// eslint-disable-next-line no-console
diff --git a/frontend/src/views/test-plan/testPlan/locale/en-US.ts b/frontend/src/views/test-plan/testPlan/locale/en-US.ts
index 196e9aa7bf..13018acf53 100644
--- a/frontend/src/views/test-plan/testPlan/locale/en-US.ts
+++ b/frontend/src/views/test-plan/testPlan/locale/en-US.ts
@@ -134,4 +134,6 @@ export default {
'testPlan.testPlanGroup.batchArchivedGroup': 'Confirm archive: {count} test plan groups',
'testPlan.testPlanGroup.confirmBatchDeletePlanGroup': 'Are you sure to delete {count} test plan groups?',
'testPlan.testPlanGroup.deleteScheduleTaskSuccess': 'Delete the scheduled task successfully',
+ 'testPlan.testPlanGroup.enableScheduleTaskSuccess': 'Start the scheduled task successfully',
+ 'testPlan.testPlanGroup.closeScheduleTaskSuccess': 'Scheduled mission closed successfully',
};
diff --git a/frontend/src/views/test-plan/testPlan/locale/zh-CN.ts b/frontend/src/views/test-plan/testPlan/locale/zh-CN.ts
index 0bdb24dea9..0649f843f2 100644
--- a/frontend/src/views/test-plan/testPlan/locale/zh-CN.ts
+++ b/frontend/src/views/test-plan/testPlan/locale/zh-CN.ts
@@ -123,4 +123,6 @@ export default {
'testPlan.testPlanGroup.batchArchivedGroup': '确认归档:{count} 个测试计划组吗',
'testPlan.testPlanGroup.confirmBatchDeletePlanGroup': '确认删除 {count} 个测试计划组吗?',
'testPlan.testPlanGroup.deleteScheduleTaskSuccess': '删除定时任务成功',
+ 'testPlan.testPlanGroup.enableScheduleTaskSuccess': '开启定时任务成功',
+ 'testPlan.testPlanGroup.closeScheduleTaskSuccess': '关闭定时任务成功',
};
|