feat(测试计划): 测试计划详情-接口用例&接口场景-执行

This commit is contained in:
teukkk 2024-06-12 15:07:58 +08:00 committed by Craftsman
parent d89b550c50
commit 39febe26dd
8 changed files with 139 additions and 9 deletions

View File

@ -12,6 +12,8 @@ import {
BatchDisassociateCaseUrl,
BatchEditTestPlanUrl,
batchMovePlanUrl,
BatchRunApiCaseUrl,
BatchRunApiScenarioUrl,
BatchRunCaseUrl,
BatchUpdateApiCaseExecutorUrl,
BatchUpdateApiScenarioExecutorUrl,
@ -51,6 +53,8 @@ import {
planDetailBugPageUrl,
PlanDetailExecuteHistoryUrl,
planPassRateUrl,
RunApiCaseUrl,
RunApiScenarioUrl,
RunFeatureCaseUrl,
SortApiCaseUrl,
SortApiScenarioUrl,
@ -296,6 +300,10 @@ export const sortApiCase = (data: SortApiCaseParams) => {
export function disassociateApiCase(data: DisassociateCaseParams) {
return MSR.post({ url: DisassociateApiCaseUrl, data });
}
// 计划详情-接口用例列表-执行
export function runApiCase(id: string, reportId?: string) {
return MSR.get({ url: `${RunApiCaseUrl}/${id}`, params: reportId });
}
// 计划详情-接口用例列表-批量取消关联用例
export function batchDisassociateApiCase(data: BatchApiCaseParams) {
return MSR.post({ url: BatchDisassociateApiCaseUrl, data });
@ -304,6 +312,10 @@ export function batchDisassociateApiCase(data: BatchApiCaseParams) {
export function batchUpdateApiCaseExecutor(data: BatchUpdateApiCaseExecutorParams) {
return MSR.post({ url: BatchUpdateApiCaseExecutorUrl, data });
}
// 计划详情-接口用例列表-批量执行
export function batchRunApiCase(data: BatchApiCaseParams) {
return MSR.post({ url: BatchRunApiCaseUrl, data });
}
// 计划详情-接口场景列表
export function getPlanDetailApiScenarioList(data: PlanDetailApiScenarioQueryParams) {
return MSR.post<CommonList<PlanDetailApiScenarioItem>>({ url: GetPlanDetailApiScenarioListUrl, data });
@ -320,6 +332,10 @@ export function getApiScenarioModuleCount(data: PlanDetailApiScenarioQueryParams
export const sortApiScenario = (data: SortApiCaseParams) => {
return MSR.post({ url: SortApiScenarioUrl, data });
};
// 计划详情-接口场景列表-执行
export function runApiScenario(id: string, reportId?: string) {
return MSR.get({ url: `${RunApiScenarioUrl}/${id}`, params: reportId });
}
// 计划详情-接口场景列表-取消关联用例
export function disassociateApiScenario(data: DisassociateCaseParams) {
return MSR.post({ url: DisassociateApiScenarioUrl, data });
@ -332,6 +348,10 @@ export function batchDisassociateApiScenario(data: BatchApiCaseParams) {
export function batchUpdateApiScenarioExecutor(data: BatchUpdateApiCaseExecutorParams) {
return MSR.post({ url: BatchUpdateApiScenarioExecutorUrl, data });
}
// 计划详情-接口场景列表-批量执行
export function batchRunApiScenario(data: BatchApiCaseParams) {
return MSR.post({ url: BatchRunApiScenarioUrl, data });
}
// 计划详情-执行历史 TODO 联调
export function getPlanDetailExecuteHistory(data: PlanDetailFeatureCaseListQueryParams) {
return MSR.post<CommonList<PlanDetailExecuteHistoryItem>>({ url: PlanDetailExecuteHistoryUrl, data });

View File

@ -107,12 +107,16 @@ export const GetApiCaseModuleUrl = '/test-plan/api/case/tree';
export const GetApiCaseModuleCountUrl = '/test-plan/api/case/module/count';
// 计划详情-接口用例列表-拖拽排序
export const SortApiCaseUrl = '/test-plan/api/case/sort';
// 计划详情-接口用例列表-执行
export const RunApiCaseUrl = '/test-plan/api/case/run';
// 计划详情-接口用例列表-取消关联用例
export const DisassociateApiCaseUrl = '/test-plan/api/case/disassociate';
// 计划详情-接口用例列表-批量取消关联用例
export const BatchDisassociateApiCaseUrl = '/test-plan/api/case/batch/disassociate';
// 计划详情-接口用例列表-批量更新执行人
export const BatchUpdateApiCaseExecutorUrl = '/test-plan/api/case/batch/update/executor';
// 计划详情-接口用例列表-批量执行
export const BatchRunApiCaseUrl = '/test-plan/api/case/batch/run';
// 计划详情-接口场景列表
export const GetPlanDetailApiScenarioListUrl = '/test-plan/api/scenario/page';
@ -122,12 +126,16 @@ export const GetApiScenarioModuleUrl = '/test-plan/api/scenario/tree';
export const GetApiScenarioModuleCountUrl = '/test-plan/api/scenario/module/count';
// 计划详情-接口场景列表-拖拽排序
export const SortApiScenarioUrl = '/test-plan/api/scenario/sort';
// 计划详情-接口场景列表-执行
export const RunApiScenarioUrl = '/test-plan/api/scenario/run';
// 计划详情-接口场景列表-取消关联用例
export const DisassociateApiScenarioUrl = '/test-plan/api/scenario/disassociate';
// 计划详情-接口场景列表-批量取消关联用例
export const BatchDisassociateApiScenarioUrl = '/test-plan/api/scenario/batch/disassociate';
// 计划详情-接口场景列表-批量更新执行人
export const BatchUpdateApiScenarioExecutorUrl = '/test-plan/api/scenario/batch/update/executor';
// 计划详情-接口场景列表-批量执行
export const BatchRunApiScenarioUrl = '/test-plan/api/scenario/batch/run';
// 测试规划脑图
export const GetPlanMinderUrl = '/test-plan/mind/data';

View File

@ -56,6 +56,7 @@ export default {
'common.operationFailed': 'Operation failed',
'common.removeSuccess': 'Remove success',
'common.removeFailed': 'Remove failed',
'common.executionSuccess': 'Execution success',
'common.admin': 'Admin',
'common.revokeDelete': 'Revoke delete',
'common.revokeDeleteSuccess': 'Revoke delete success',

View File

@ -57,6 +57,7 @@ export default {
'common.operationFailed': '操作失败',
'common.removeSuccess': '移除成功',
'common.removeFailed': '移除失败',
'common.executionSuccess': '执行成功',
'common.admin': '管理员',
'common.revokeDelete': '撤销删除',
'common.revokeDeleteSuccess': '已撤销删除',

View File

@ -287,6 +287,7 @@ export interface PlanDetailApiCaseItem {
executeUser: string;
executeUserName: string;
priority: string;
protocol: string;
path: string;
projectId: string;
projectName: string;

View File

@ -9,7 +9,7 @@
show-full-screen
>
<template #tbutton>
<a-dropdown position="br" @select="shareHandler">
<a-dropdown v-if="!props.doNotShowShare" position="br" @select="shareHandler">
<MsButton
v-permission="['PROJECT_API_REPORT:READ+SHARE']"
type="icon"
@ -53,6 +53,7 @@
const props = defineProps<{
reportId: string;
isScenario?: boolean;
doNotShowShare?: boolean; //
}>();
const appStore = useAppStore();

View File

@ -23,6 +23,9 @@
@selected-change="handleTableSelect"
@filter-change="getModuleCount"
>
<template #protocol="{ record }">
<ApiMethodName :method="record.protocol" />
</template>
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL]="{ filterContent }">
<CaseLevel :case-level="filterContent.value" />
</template>
@ -46,7 +49,12 @@
<apiStatus :status="record.status" />
</template>
<template v-if="props.canEdit" #operation="{ record }">
<MsButton v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']" type="text" class="!mr-0">
<MsButton
v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']"
type="text"
class="!mr-0"
@click="handleRun(record)"
>
{{ t('common.execute') }}
</MsButton>
<a-divider v-permission="['PROJECT_TEST_PLAN:READ+ASSOCIATION']" direction="vertical" :margin="8"></a-divider>
@ -64,7 +72,7 @@
</MsPopconfirm>
</template>
</MsBaseTable>
<ReportDrawer v-model:visible="reportVisible" :report-id="reportId" />
<CaseAndScenarioReportDrawer v-model:visible="reportVisible" :report-id="reportId" do-not-show-share />
<!-- 批量修改执行人 -->
<BatchUpdateExecutorModal
v-model:visible="batchUpdateExecutorModalVisible"
@ -93,15 +101,18 @@
import useTable from '@/components/pure/ms-table/useTable';
import CaseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
import ApiMethodName from '@/views/api-test/components/apiMethodName.vue';
import apiStatus from '@/views/api-test/components/apiStatus.vue';
import CaseAndScenarioReportDrawer from '@/views/api-test/components/caseAndScenarioReportDrawer.vue';
import BatchUpdateExecutorModal from '@/views/test-plan/testPlan/components/batchUpdateExecutorModal.vue';
import ReportDrawer from '@/views/test-plan/testPlan/detail/reportDrawer.vue';
import {
batchDisassociateApiCase,
batchRunApiCase,
batchUpdateApiCaseExecutor,
disassociateApiCase,
getPlanDetailApiCaseList,
runApiCase,
sortApiCase,
} from '@/api/modules/test-plan/testPlan';
import { useI18n } from '@/hooks/useI18n';
@ -176,6 +187,13 @@
showTooltip: true,
columnSelectorDisabled: true,
},
{
title: 'apiTestManagement.protocol',
dataIndex: 'protocol',
slotName: 'protocol',
width: 150,
showDrag: true,
},
{
title: 'case.caseLevel',
dataIndex: 'priority',
@ -271,7 +289,7 @@
selectable: hasOperationPermission.value,
});
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setLoading } = useTable(
getPlanDetailApiCaseList,
tableProps.value,
(record) => {
@ -455,6 +473,44 @@
}
}
//
async function handleRun(record: PlanDetailApiCaseItem) {
try {
setLoading(true);
await runApiCase(record.id);
Message.success(t('common.executionSuccess'));
resetSelectorAndCaseList();
emit('refresh');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
setLoading(false);
}
}
//
async function handleBatchRun() {
try {
setLoading(true);
const tableParams = await getTableParams(true);
await batchRunApiCase({
selectIds: tableSelected.value as string[],
selectAll: batchParams.value.selectAll,
excludeIds: batchParams.value?.excludeIds || [],
...tableParams,
});
Message.success(t('common.executionSuccess'));
resetSelectorAndCaseList();
emit('refresh');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
setLoading(false);
}
}
//
function handleBatchDisassociateCase() {
openModal({
@ -498,6 +554,7 @@
const tableParams = await getTableParams(true);
switch (event.eventTag) {
case 'execute':
handleBatchRun();
break;
case 'disassociate':
handleBatchDisassociateCase();

View File

@ -49,7 +49,7 @@
<apiStatus :status="record.status" />
</template>
<template v-if="props.canEdit" #operation="{ record }">
<MsButton v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']" type="text" class="!mr-0">
<MsButton v-permission="['PROJECT_TEST_PLAN:READ+EXECUTE']" type="text" class="!mr-0" @click="handleRun">
{{ t('common.execute') }}
</MsButton>
<a-divider v-permission="['PROJECT_TEST_PLAN:READ+ASSOCIATION']" direction="vertical" :margin="8"></a-divider>
@ -67,7 +67,7 @@
</MsPopconfirm>
</template>
</MsBaseTable>
<ReportDrawer v-model:visible="reportVisible" :report-id="reportId" />
<CaseAndScenarioReportDrawer v-model:visible="reportVisible" :report-id="reportId" do-not-show-share />
<!-- 批量修改执行人 -->
<BatchUpdateExecutorModal
v-model:visible="batchUpdateExecutorModalVisible"
@ -97,14 +97,16 @@
import CaseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
import apiStatus from '@/views/api-test/components/apiStatus.vue';
import CaseAndScenarioReportDrawer from '@/views/api-test/components/caseAndScenarioReportDrawer.vue';
import BatchUpdateExecutorModal from '@/views/test-plan/testPlan/components/batchUpdateExecutorModal.vue';
import ReportDrawer from '@/views/test-plan/testPlan/detail/reportDrawer.vue';
import {
batchDisassociateApiScenario,
batchRunApiScenario,
batchUpdateApiScenarioExecutor,
disassociateApiScenario,
getPlanDetailApiScenarioList,
runApiScenario,
sortApiScenario,
} from '@/api/modules/test-plan/testPlan';
import { useI18n } from '@/hooks/useI18n';
@ -270,7 +272,7 @@
selectable: hasOperationPermission.value,
});
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setLoading } = useTable(
getPlanDetailApiScenarioList,
tableProps.value,
(record) => {
@ -456,6 +458,44 @@
}
}
//
async function handleRun(record: PlanDetailApiScenarioItem) {
try {
setLoading(true);
await runApiScenario(record.id);
Message.success(t('common.executionSuccess'));
resetSelectorAndCaseList();
emit('refresh');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
setLoading(false);
}
}
//
async function handleBatchRun() {
try {
setLoading(true);
const tableParams = await getTableParams(true);
await batchRunApiScenario({
selectIds: tableSelected.value as string[],
selectAll: batchParams.value.selectAll,
excludeIds: batchParams.value?.excludeIds || [],
...tableParams,
});
Message.success(t('common.executionSuccess'));
resetSelectorAndCaseList();
emit('refresh');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
setLoading(false);
}
}
//
function handleBatchDisassociateCase() {
openModal({
@ -499,6 +539,7 @@
const tableParams = await getTableParams(true);
switch (event.eventTag) {
case 'execute':
handleBatchRun();
break;
case 'disassociate':
handleBatchDisassociateCase();