fix(测试计划): 修复测试计划以及用例管理bugs
This commit is contained in:
parent
b47d8c60ed
commit
4165947b4a
|
@ -134,7 +134,6 @@
|
|||
width: 200,
|
||||
showDrag: true,
|
||||
},
|
||||
|
||||
{
|
||||
title: 'common.tag',
|
||||
dataIndex: 'tags',
|
||||
|
|
|
@ -169,6 +169,14 @@
|
|||
width: 150,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'common.tag',
|
||||
dataIndex: 'tags',
|
||||
isTag: true,
|
||||
isStringTag: true,
|
||||
width: 400,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'caseManagement.featureCase.tableColumnCreateUser',
|
||||
slotName: 'createUserName',
|
||||
|
@ -227,12 +235,6 @@
|
|||
return {
|
||||
...record,
|
||||
caseLevel: getCaseLevel(record),
|
||||
tags: (record.tags || []).map((item: string, i: number) => {
|
||||
return {
|
||||
id: `${record.id}-${i}`,
|
||||
name: item,
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
|
@ -374,7 +374,7 @@
|
|||
case CaseLinkEnum.FUNCTIONAL:
|
||||
return t('common.searchByIdName');
|
||||
case CaseLinkEnum.API:
|
||||
return t('apiTestManagement.searchPlaceholder');
|
||||
return t('ms.case.associate.apiSearchPlaceholder');
|
||||
case CaseLinkEnum.SCENARIO:
|
||||
return t('common.searchByIdName');
|
||||
default:
|
||||
|
|
|
@ -21,4 +21,5 @@ export default {
|
|||
'ms.case.associate.gotIt': 'I got it',
|
||||
'ms.case.associate.switchProject': 'Switch project?',
|
||||
'ms.case.associate.switchProjectPopTip': 'After switching, the selected data will be cleared',
|
||||
'ms.case.associate.apiSearchPlaceholder': 'Support ID/ name/tag/ path search',
|
||||
};
|
||||
|
|
|
@ -21,4 +21,5 @@ export default {
|
|||
'ms.case.associate.gotIt': '知道了',
|
||||
'ms.case.associate.switchProject': '切换项目?',
|
||||
'ms.case.associate.switchProjectPopTip': '切换后,已选数据将清空',
|
||||
'ms.case.associate.apiSearchPlaceholder': '支持 ID/名称/标签/路径搜索',
|
||||
};
|
||||
|
|
|
@ -285,24 +285,25 @@
|
|||
return customFieldToColumns(res);
|
||||
};
|
||||
|
||||
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps } = useTable(
|
||||
getRecycleList,
|
||||
{
|
||||
tableKey: TableKeyEnum.BUG_MANAGEMENT_RECYCLE,
|
||||
selectable: true,
|
||||
noDisable: true,
|
||||
showSetting: true,
|
||||
scroll: { x: '1900px' },
|
||||
heightUsed: 256,
|
||||
},
|
||||
(record: TableData) => ({
|
||||
...record,
|
||||
handleUser: record.handleUserName,
|
||||
createUser: record.createUserName,
|
||||
updateUser: record.updateUserName,
|
||||
...customFieldDataToTableData(record.customFields, customFields.value),
|
||||
})
|
||||
);
|
||||
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps, resetSelector, resetFilterParams } =
|
||||
useTable(
|
||||
getRecycleList,
|
||||
{
|
||||
tableKey: TableKeyEnum.BUG_MANAGEMENT_RECYCLE,
|
||||
selectable: true,
|
||||
noDisable: true,
|
||||
showSetting: true,
|
||||
scroll: { x: '1900px' },
|
||||
heightUsed: 256,
|
||||
},
|
||||
(record: TableData) => ({
|
||||
...record,
|
||||
handleUser: record.handleUserName,
|
||||
createUser: record.createUserName,
|
||||
updateUser: record.updateUserName,
|
||||
...customFieldDataToTableData(record.customFields, customFields.value),
|
||||
})
|
||||
);
|
||||
|
||||
const tableAction = {
|
||||
baseAction: [
|
||||
|
@ -354,6 +355,8 @@
|
|||
try {
|
||||
await recoverSingleByRecycle(record.id);
|
||||
Message.success(t('bugManagement.recycle.recoverSuccess'));
|
||||
resetSelector();
|
||||
resetFilterParams();
|
||||
fetchData();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -370,6 +373,8 @@
|
|||
appStore.hideLoading();
|
||||
Message.success(t('bugManagement.recycle.recoverSuccess'));
|
||||
keyword.value = '';
|
||||
resetSelector();
|
||||
resetFilterParams();
|
||||
fetchData();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -386,6 +391,8 @@
|
|||
try {
|
||||
await deleteSingleByRecycle(record.id);
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
resetSelector();
|
||||
resetFilterParams();
|
||||
fetchData();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -405,6 +412,8 @@
|
|||
await deleteBatchByRecycle(tmpObj);
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
keyword.value = '';
|
||||
resetSelector();
|
||||
resetFilterParams();
|
||||
fetchData();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<MsDetailDrawer
|
||||
ref="detailDrawerRef"
|
||||
v-model:visible="showDrawerVisible"
|
||||
:width="880"
|
||||
:width="860"
|
||||
:footer="false"
|
||||
:mask="false"
|
||||
:title="t('caseManagement.featureCase.caseDetailTitle', { id: detailInfo?.num, name: detailInfo?.name })"
|
||||
|
@ -89,14 +89,16 @@
|
|||
</template>
|
||||
<template #default="{ detail, loading }">
|
||||
<div ref="wrapperRef" class="bg-white">
|
||||
<div class="header relative h-[48px] pl-2">
|
||||
<MsTab
|
||||
v-model:active-key="activeTab"
|
||||
:content-tab-list="tabSetting"
|
||||
:get-text-func="getTotal"
|
||||
class="no-content relative border-b"
|
||||
@change="clickMenu"
|
||||
/>
|
||||
<div class="header relative h-[48px] border-b pl-2">
|
||||
<div class="max-w-[calc(100%-72px)]"
|
||||
><MsTab
|
||||
v-model:active-key="activeTab"
|
||||
:content-tab-list="tabSetting"
|
||||
:get-text-func="getTotal"
|
||||
class="no-content relative"
|
||||
@change="clickMenu"
|
||||
/></div>
|
||||
|
||||
<span class="display-setting h-full text-[var(--color-text-2)]" @click="showMenuSetting">{{
|
||||
t('caseManagement.featureCase.detailDisplaySetting')
|
||||
}}</span>
|
||||
|
|
|
@ -331,7 +331,7 @@
|
|||
]);
|
||||
|
||||
const featureCaseStore = useFeatureCaseStore();
|
||||
const modelId = computed(() => featureCaseStore.moduleId[0]);
|
||||
const modelId = computed(() => featureCaseStore.moduleId[0] || 'root');
|
||||
|
||||
const initForm: DetailCase = {
|
||||
id: '',
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
<div class="one-line-text max-w-[200px]">{{ characterLimit(record.handleUserName) || '-' }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template #createUserName="{ record }">
|
||||
<a-tooltip :content="record.handleUserName">
|
||||
<div class="one-line-text">{{ record.createUserName || '-' }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
||||
<template #operation="{ record }">
|
||||
<MsButton v-permission="['FUNCTIONAL_CASE:READ+UPDATE']" @click="cancelLink(record.id)">{{
|
||||
|
|
|
@ -27,21 +27,19 @@
|
|||
></a-input-search>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ms-base-table
|
||||
ref="tableRef"
|
||||
v-bind="propsRes"
|
||||
:action-config="{
|
||||
baseAction: [],
|
||||
moreAction: [],
|
||||
}"
|
||||
v-on="propsEvent"
|
||||
>
|
||||
<template #name="{ record }">
|
||||
<BugNamePopover :name="record.name" :content="record.content" />
|
||||
</template>
|
||||
</ms-base-table>
|
||||
</div>
|
||||
<ms-base-table
|
||||
ref="tableRef"
|
||||
v-bind="propsRes"
|
||||
:action-config="{
|
||||
baseAction: [],
|
||||
moreAction: [],
|
||||
}"
|
||||
v-on="propsEvent"
|
||||
>
|
||||
<template #name="{ record }">
|
||||
<BugNamePopover :name="record.name" :content="record.content" />
|
||||
</template>
|
||||
</ms-base-table>
|
||||
</MsDrawer>
|
||||
</template>
|
||||
|
||||
|
@ -87,7 +85,6 @@
|
|||
width: 150,
|
||||
showInTable: true,
|
||||
showTooltip: true,
|
||||
ellipsis: true,
|
||||
showDrag: false,
|
||||
},
|
||||
{
|
||||
|
@ -105,7 +102,6 @@
|
|||
showInTable: true,
|
||||
showTooltip: true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
showDrag: false,
|
||||
},
|
||||
{
|
||||
|
@ -124,7 +120,6 @@
|
|||
showInTable: true,
|
||||
showTooltip: true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
showDrag: false,
|
||||
},
|
||||
{
|
||||
|
@ -134,7 +129,6 @@
|
|||
showInTable: true,
|
||||
showTooltip: true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: 'caseManagement.featureCase.tableColumnCreateTime',
|
||||
|
|
|
@ -78,7 +78,12 @@
|
|||
</template>
|
||||
<template #handleUserName="{ record }">
|
||||
<a-tooltip :content="record.handleUserName">
|
||||
<div class="one-line-text max-w-[200px]">{{ characterLimit(record.handleUserName) || '-' }}</div>
|
||||
<div class="one-line-text">{{ record.handleUserName || '-' }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template #createUserName="{ record }">
|
||||
<a-tooltip :content="record.handleUserName">
|
||||
<div class="one-line-text">{{ record.createUserName || '-' }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template #testPlanName="{ record }">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
:max-length="255"
|
||||
/>
|
||||
<a-dropdown-button
|
||||
v-if="hasAllPermission(['FUNCTIONAL_CASE:READ+ADD', 'FUNCTIONAL_CASE:READ+IMPORT'])"
|
||||
v-if="hasAllPermission(['FUNCTIONAL_CASE:READ+IMPORT', 'FUNCTIONAL_CASE:READ+ADD'])"
|
||||
class="ml-2"
|
||||
type="primary"
|
||||
@click="handleSelect('newCase')"
|
||||
|
@ -31,14 +31,33 @@
|
|||
</a-doption>
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
<a-button
|
||||
v-else-if="
|
||||
!hasAnyPermission(['FUNCTIONAL_CASE:READ+ADD']) && hasAnyPermission(['FUNCTIONAL_CASE:READ+IMPORT'])
|
||||
"
|
||||
class="ml-2"
|
||||
type="primary"
|
||||
@click="handleSelect('import', 'Excel')"
|
||||
>
|
||||
{{ t('caseManagement.featureCase.importExcel') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-else
|
||||
v-permission="['FUNCTIONAL_CASE:READ+ADD']"
|
||||
class="ml-2"
|
||||
type="primary"
|
||||
@click="handleSelect('newCase')"
|
||||
>
|
||||
{{ t('common.newCreate') }}
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<div class="case h-[38px]">
|
||||
<div class="flex items-center" :class="getActiveClass('all')" @click="setActiveFolder('all')">
|
||||
<MsIcon type="icon-icon_folder_filled1" class="folder-icon" />
|
||||
<div class="folder-name mx-[4px]">{{ t('caseManagement.featureCase.allCase') }}</div>
|
||||
<div class="folder-count">({{ modulesCount.all || 0 }})</div></div
|
||||
>
|
||||
<div class="folder-count">({{ modulesCount.all || 0 }})</div>
|
||||
</div>
|
||||
<div class="ml-auto flex items-center">
|
||||
<a-tooltip :content="isExpandAll ? t('common.expandAllSubModule') : t('common.collapseAllSubModule')">
|
||||
<MsButton type="icon" status="secondary" class="!mr-0 p-[4px]" @click="expandHandler">
|
||||
|
@ -82,7 +101,7 @@
|
|||
@case-node-select="caseNodeSelect"
|
||||
@init="setRootModules"
|
||||
@drag-update="dragUpdate"
|
||||
></FeatureCaseTree>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
|
@ -110,7 +129,7 @@
|
|||
:module-name="activeFolderName"
|
||||
@init="initModulesCount"
|
||||
@import="importCase"
|
||||
></CaseTable>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</MsSplitBox>
|
||||
|
@ -435,7 +454,7 @@
|
|||
.case {
|
||||
padding: 8px 4px;
|
||||
border-radius: var(--border-radius-small);
|
||||
@apply flex cursor-pointer items-center justify-between;
|
||||
@apply flex cursor-pointer items-center justify-between;
|
||||
&:hover {
|
||||
background-color: rgb(var(--primary-1));
|
||||
}
|
||||
|
@ -471,7 +490,7 @@
|
|||
}
|
||||
}
|
||||
.recycle {
|
||||
@apply absolute bottom-0 bg-white pb-4;
|
||||
@apply absolute bottom-0 bg-white pb-4;
|
||||
:deep(.arco-divider-horizontal) {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ export default {
|
|||
'caseManagement.featureCase.tabShowSetting': 'tab display setting',
|
||||
'caseManagement.featureCase.closeModuleTab': 'Close: in the drawer not show related modules',
|
||||
'caseManagement.featureCase.enableModuleTab': 'Open: Display the relevant modules in the drawer',
|
||||
'caseManagement.featureCase.recoverDefault': 'Restore default',
|
||||
'caseManagement.featureCase.recoverDefault': 'Undo modify',
|
||||
'caseManagement.featureCase.detail': 'details',
|
||||
'caseManagement.featureCase.nonClosableTab': 'These attributes cannot be turned off',
|
||||
'caseManagement.featureCase.case': 'case',
|
||||
|
|
|
@ -134,7 +134,7 @@ export default {
|
|||
'caseManagement.featureCase.tabShowSetting': 'tab 显示设置',
|
||||
'caseManagement.featureCase.closeModuleTab': '关闭: 在抽屉内不展示相关模块',
|
||||
'caseManagement.featureCase.enableModuleTab': '开启: 在抽屉内展示相关模块',
|
||||
'caseManagement.featureCase.recoverDefault': '恢复默认',
|
||||
'caseManagement.featureCase.recoverDefault': '撤销修改',
|
||||
'caseManagement.featureCase.detail': '详情',
|
||||
'caseManagement.featureCase.nonClosableTab': '以上属性不可关闭',
|
||||
'caseManagement.featureCase.case': '用例',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<MsBaseTable v-bind="currentCaseTable.propsRes.value" v-on="currentCaseTable.propsEvent.value">
|
||||
<template #num="{ record }">
|
||||
<MsButton type="text" @click="showReport(record)">{{ record.num }}</MsButton>
|
||||
<MsButton type="text" @click="toDetail(record)">{{ record.num }}</MsButton>
|
||||
</template>
|
||||
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL]="{ filterContent }">
|
||||
<caseLevel :case-level="filterContent.value" />
|
||||
|
@ -14,7 +14,12 @@
|
|||
</template>
|
||||
|
||||
<template #lastExecResult="{ record }">
|
||||
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="record.executeResult" />
|
||||
<ExecutionStatus
|
||||
:module-type="ReportEnum.API_REPORT"
|
||||
:status="record.executeResult"
|
||||
:class="[!record.executeResult ? '' : 'cursor-pointer']"
|
||||
@click="showReport(record)"
|
||||
/>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
<CaseAndScenarioReportDrawer
|
||||
|
@ -44,13 +49,18 @@
|
|||
reportScenarioDetail,
|
||||
reportStepDetail,
|
||||
} from '@/api/modules/test-plan/report';
|
||||
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
||||
|
||||
import { ApiOrScenarioCaseItem } from '@/models/testPlan/report';
|
||||
import type { PlanDetailApiCaseItem } from '@/models/testPlan/testPlan';
|
||||
import { ReportEnum } from '@/enums/reportEnum';
|
||||
import { ApiTestRouteEnum } from '@/enums/routeEnum';
|
||||
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||
|
||||
import { casePriorityOptions, lastReportStatusListOptions } from '@/views/api-test/components/config';
|
||||
|
||||
const { openNewPage } = useOpenNewPage();
|
||||
|
||||
const props = defineProps<{
|
||||
reportId: string;
|
||||
shareId?: string;
|
||||
|
@ -153,10 +163,26 @@
|
|||
const apiReportId = ref<string>('');
|
||||
|
||||
function showReport(record: ApiOrScenarioCaseItem) {
|
||||
if (!record.executeResult || record.executeResult === 'STOPPED') return;
|
||||
reportVisible.value = true;
|
||||
apiReportId.value = record.reportId;
|
||||
}
|
||||
|
||||
// 去接口用例详情页面
|
||||
function toDetail(record: PlanDetailApiCaseItem) {
|
||||
if (props.activeTab === 'scenarioCase') {
|
||||
openNewPage(ApiTestRouteEnum.API_TEST_SCENARIO, {
|
||||
id: record.id,
|
||||
pId: record.projectId,
|
||||
});
|
||||
} else {
|
||||
openNewPage(ApiTestRouteEnum.API_TEST_MANAGEMENT, {
|
||||
cId: record.id,
|
||||
pId: record.projectId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.activeTab,
|
||||
() => {
|
||||
|
|
|
@ -79,6 +79,13 @@
|
|||
return data;
|
||||
}
|
||||
|
||||
function getResultText(isPass: boolean, text: string) {
|
||||
const successColor = 'rgb(76, 217, 100)';
|
||||
const errorColor = 'rgb(255, 59, 48)';
|
||||
const color = isPass ? successColor : errorColor;
|
||||
return `<strong><span style="color: ${color}" color="${color}" fontsize="">${text}</span></strong>`;
|
||||
}
|
||||
|
||||
const summaryContent = computed(() => {
|
||||
const { functionalCount, apiCaseCount, apiScenarioCount } = props.detail;
|
||||
const functionalCaseDetail = getSummaryDetail(functionalCount);
|
||||
|
@ -91,17 +98,30 @@
|
|||
|
||||
// 通过率
|
||||
const allSuccessCount = (allSuccessCase / allCaseTotal) * 100;
|
||||
const allSuccessRate = `${Number.isNaN(allSuccessCount) ? 0 : allSuccessCount.toFixed(2)}%`;
|
||||
// TODO 待联调
|
||||
const allSuccessRate = `${Number.isNaN(allSuccessCount) ? 0 : allSuccessCount.toFixed(2)}`;
|
||||
|
||||
if (props.isPlanGroup) {
|
||||
return `<p style=""><span color="" fontsize=""> <strong>${props.detail.testPlanName}</strong>包含 ${props.detail.planCount}个子计划。
|
||||
其中 ${props.detail.passCountOfPlan} 个子计划通过, ${props.detail.failCountOfPlan} 个子计划不通过。</span></p>`;
|
||||
}
|
||||
const functionalCasText = `(1)本次测试包含${functionalCaseDetail.caseTotal}条功能测试用例,执行了${functionalCaseDetail.hasExecutedCase}条,未执行${functionalCaseDetail.pending}条,执行率为${functionalCaseDetail.apiExecutedRate},通过用例${functionalCaseDetail.success}条,通过率为${functionalCaseDetail.successRate}。共发现缺陷${props.detail.functionalBugCount}个。<br>`;
|
||||
const functionCaseDesc = functionalCaseDetail.caseTotal ? `${functionalCasText}` : ``;
|
||||
|
||||
const apiCaseText = `(2)本次测试包含${apiCaseDetail.caseTotal}条接口测试用例,执行了${apiCaseDetail.hasExecutedCase}条,未执行${apiCaseDetail.pending}条,执行率为${apiCaseDetail.apiExecutedRate},通过用例${apiCaseDetail.success}条,通过率为${apiCaseDetail.successRate}。共发现缺陷 ${props.detail.apiBugCount} 个。<br>`;
|
||||
const apiCaseDesc = apiCaseDetail.caseTotal ? `${apiCaseText}` : ``;
|
||||
|
||||
const scenarioCaseText = `(3)本次测试包含${apiScenarioDetail.caseTotal}条场景测试用例,执行了${apiScenarioDetail.hasExecutedCase}条,未执行${apiScenarioDetail.pending}条,执行率为${apiScenarioDetail.apiExecutedRate}%,通过用例${apiScenarioDetail.success}条,通过率为${apiScenarioDetail.successRate}。共发现缺陷${props.detail.scenarioBugCount}个`;
|
||||
const scenarioCaseDesc = apiScenarioDetail.caseTotal ? `${scenarioCaseText}` : ``;
|
||||
|
||||
const isPass = Number(allSuccessRate) >= Number(props.detail.passThreshold);
|
||||
|
||||
const isAchieveText = getResultText(isPass, isPass ? '达到' : '未达到');
|
||||
const isMeetText = getResultText(isPass, isPass ? '满足' : '不满足');
|
||||
// 接口用例通过率
|
||||
return `<p style=""><span color="" fontsize=""> <strong>${props.detail.testPlanName}</strong> 包含功能测试、接口用例、场景用例, 共 ${allCaseTotal}条用例,已执行 ${allHasExecutedCase} 条,通过用例 ${allSuccessCase} 条,通过率为 ${allSuccessRate},达到/未达到通过阈值(通过阈值为${props.detail.passThreshold}%),<strong>${props.detail.testPlanName}</strong> 计划满足/不满足发布要求。<br>
|
||||
(1)本次测试包含${functionalCaseDetail.caseTotal}条功能测试用例,执行了${functionalCaseDetail.hasExecutedCase}条,未执行${functionalCaseDetail.pending}条,执行率为${functionalCaseDetail.apiExecutedRate},通过用例${functionalCaseDetail.success}条,通过率为${functionalCaseDetail.successRate}。共发现缺陷${props.detail.functionalBugCount}个。<br>
|
||||
(2)本次测试包含${apiCaseDetail.caseTotal}条接口测试用例,执行了${apiCaseDetail.hasExecutedCase}条,未执行${apiCaseDetail.pending}条,执行率为${apiCaseDetail.apiExecutedRate},通过用例${apiCaseDetail.success}条,通过率为${apiCaseDetail.successRate}。共发现缺陷 ${props.detail.apiBugCount} 个。<br>
|
||||
(3)本次测试包含${apiScenarioDetail.caseTotal}条场景测试用例,执行了${apiScenarioDetail.hasExecutedCase}条,未执行${apiScenarioDetail.pending}条,执行率为${apiScenarioDetail.apiExecutedRate}%,通过用例${apiScenarioDetail.success}条,通过率为${apiScenarioDetail.successRate}。共发现缺陷${props.detail.scenarioBugCount}个</span></p>
|
||||
return `<p style=""><span color="" fontsize=""> <strong>${props.detail.testPlanName}</strong> 包含功能测试、接口用例、场景用例, 共 ${allCaseTotal}条用例,已执行 ${allHasExecutedCase} 条,通过用例 ${allSuccessCase} 条,通过率为 ${allSuccessRate}%,${isAchieveText}通过阈值(通过阈值为${props.detail.passThreshold}%),<strong>${props.detail.testPlanName}</strong> 计划${isMeetText}发布要求。<br>
|
||||
${functionCaseDesc}
|
||||
${apiCaseDesc}
|
||||
${scenarioCaseDesc}</span></p>
|
||||
`;
|
||||
});
|
||||
|
||||
|
|
|
@ -92,10 +92,12 @@
|
|||
}
|
||||
|
||||
const contentTip = computed(() => {
|
||||
if (props.record?.type === testPlanTypeEnum.GROUP) {
|
||||
return t('testPlan.testPlanGroup.planGroupDeleteContent');
|
||||
}
|
||||
let deleteMessage;
|
||||
const planType =
|
||||
props.record?.type === testPlanTypeEnum.GROUP
|
||||
? `${t('testPlan.testPlanIndex.testPlanGroup')}`
|
||||
: `${t('testPlan.testPlanIndex.plan')}`;
|
||||
|
||||
switch (props.record && props.record.status) {
|
||||
case 'ARCHIVED':
|
||||
deleteMessage = t('testPlan.testPlanIndex.deleteArchivedPlan');
|
||||
|
@ -104,13 +106,13 @@
|
|||
deleteMessage = t('testPlan.testPlanIndex.deleteRunningPlan');
|
||||
break;
|
||||
case 'COMPLETED':
|
||||
deleteMessage = t('testPlan.testPlanIndex.deleteCompletedPlan');
|
||||
deleteMessage = t('testPlan.testPlanGroup.planGroupDeleteContent');
|
||||
break;
|
||||
default:
|
||||
deleteMessage = t('testPlan.testPlanIndex.deletePendingPlan');
|
||||
}
|
||||
const scheduledMessage = props.scheduleConfig ? t('testPlan.testPlanIndex.scheduledTask') : '';
|
||||
return `${deleteMessage}${scheduledMessage}${t('testPlan.testPlanIndex.operateWithCaution')}`;
|
||||
return `${planType}${deleteMessage}${scheduledMessage}${t('testPlan.testPlanIndex.operateWithCaution')}`;
|
||||
});
|
||||
|
||||
const showArchive = computed(() => {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
ref="tableRef"
|
||||
class="mt-4"
|
||||
:action-config="testPlanBatchActions"
|
||||
:selectable="hasOperationPermission && showType !== testPlanTypeEnum.ALL"
|
||||
:selectable="hasOperationPermission && showType !== testPlanTypeEnum.ALL && !isArchived"
|
||||
filter-icon-align-left
|
||||
:expanded-keys="expandedKeys"
|
||||
:disabled-config="{
|
||||
|
@ -1287,7 +1287,7 @@
|
|||
}
|
||||
planType.value = record.type;
|
||||
planSourceId.value = record.id;
|
||||
taskForm.value = defaultCountDetailMap.value[record.id]?.scheduleConfig;
|
||||
taskForm.value = cloneDeep(defaultCountDetailMap.value[record.id]?.scheduleConfig);
|
||||
showScheduledTaskModal.value = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,4 @@ export const planStatusOptions: { value: planStatusType; label: string }[] = [
|
|||
value: 'COMPLETED',
|
||||
label: t('caseManagement.caseReview.unStart'),
|
||||
},
|
||||
{
|
||||
value: 'ARCHIVED',
|
||||
label: t('caseManagement.caseReview.going'),
|
||||
},
|
||||
];
|
||||
|
|
|
@ -66,10 +66,10 @@ export default {
|
|||
'testPlan.testPlanIndex.apiScenarioCase': 'Scenario use cases',
|
||||
'testPlan.testPlanIndex.scheduledTask': 'stop and delete scheduled tasks, ',
|
||||
'testPlan.testPlanIndex.operateWithCaution': 'please operate with caution!',
|
||||
'testPlan.testPlanIndex.deleteArchivedPlan': 'After the program has been archived, delete data unrecoverable,',
|
||||
'testPlan.testPlanIndex.deletePendingPlan': 'The plan is not executed, the data cannot be recovered after deletion,',
|
||||
'testPlan.testPlanIndex.deleteArchivedPlan': 'Archived. Data cannot be recovered after deletion.',
|
||||
'testPlan.testPlanIndex.deletePendingPlan': 'Not executed. Data cannot be recovered after deletion.',
|
||||
'testPlan.testPlanIndex.deleteRunningPlan':
|
||||
'The plan is in progress. After deletion, the execution will be terminated and cannot be restored,',
|
||||
'In progress. After deletion, execution terminates and cannot be recovered.',
|
||||
'testPlan.testPlanIndex.deleteCompletedPlan':
|
||||
'Suggest that completed plans, choose archiving, and retain use case information and execution results; If the deletion continues, the data will not be restored,',
|
||||
'testPlan.testPlanIndex.confirmArchivePlan':
|
||||
|
@ -134,7 +134,7 @@ export default {
|
|||
'testPlan.testPlanGroup.planGroupArchiveContent':
|
||||
'After archived, plan and carry out information no longer update and edit data unrecoverable, please careful operation.',
|
||||
'testPlan.testPlanGroup.planGroupDeleteContent':
|
||||
'Planning groups choose file has been completed and the case information, and the results will be retained, If you continue to delete, the data will not be recovered, please be careful!',
|
||||
'It is recommended to select the archive, and the use case information and execution results will be retained;The data will not be restored if continue to delete,',
|
||||
'testPlan.testPlanGroup.selectTestPlanGroupPlaceHolder': 'Please select the Plan group',
|
||||
'testPlan.testPlanGroup.batchArchivedGroup': 'Confirm archive: {count} test plan groups',
|
||||
'testPlan.testPlanGroup.confirmBatchDeletePlanGroup': 'Are you sure to delete {count} test plan groups?',
|
||||
|
|
|
@ -64,9 +64,9 @@ export default {
|
|||
'testPlan.testPlanIndex.apiScenarioCase': '场景用例',
|
||||
'testPlan.testPlanIndex.scheduledTask': '定时任务停止并删除,',
|
||||
'testPlan.testPlanIndex.operateWithCaution': '请谨慎操作!',
|
||||
'testPlan.testPlanIndex.deleteArchivedPlan': '计划 已归档,删除后数据不可恢复,',
|
||||
'testPlan.testPlanIndex.deletePendingPlan': '计划 未执行,删除后数据不可恢复,',
|
||||
'testPlan.testPlanIndex.deleteRunningPlan': '计划 进行中,删除后,终止执行且不可恢复,',
|
||||
'testPlan.testPlanIndex.deleteArchivedPlan': ' 已归档,删除后数据不可恢复,',
|
||||
'testPlan.testPlanIndex.deletePendingPlan': ' 未执行,删除后数据不可恢复,',
|
||||
'testPlan.testPlanIndex.deleteRunningPlan': ' 进行中,删除后,终止执行且不可恢复,',
|
||||
'testPlan.testPlanIndex.deleteCompletedPlan':
|
||||
'建议计划 已完成 ,选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,',
|
||||
'testPlan.testPlanIndex.confirmArchivePlan': '归档后,执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
|
||||
|
@ -124,7 +124,7 @@ export default {
|
|||
'testPlan.testPlanGroup.planGroupArchiveContent':
|
||||
'归档后,计划执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
|
||||
'testPlan.testPlanGroup.planGroupDeleteContent':
|
||||
'计划组 已完成 选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,请谨慎操作!',
|
||||
' 已完成 建议选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,',
|
||||
'testPlan.testPlanGroup.module': '模块',
|
||||
'testPlan.testPlanGroup.selectTestPlanGroupPlaceHolder': '请选择计划组',
|
||||
'testPlan.testPlanGroup.batchArchivedGroup': '确认归档:{count} 个测试计划组吗',
|
||||
|
|
Loading…
Reference in New Issue