fix(接口测试): 修改接口测试报告相关问题

This commit is contained in:
xinxin.wu 2024-03-27 13:58:57 +08:00 committed by 刘瑞斌
parent 64fcc5005a
commit 1299eef955
12 changed files with 208 additions and 87 deletions

View File

@ -3,7 +3,7 @@
<div class="relative mr-4">
<div class="absolute bottom-0 left-[30%] top-[35%] text-center">
<div class="text-[12px] text-[(var(--color-text-4))]">{{ t('report.detail.api.total') }}</div>
<div class="text-[18px] font-medium">{{ totalCount }}</div>
<div class="text-[18px] font-medium">{{ props.requestTotal }}</div>
</div>
<MsChart width="110px" height="110px" :options="props.options" />
</div>
@ -37,13 +37,8 @@
const props = defineProps<{
options: Record<string, any>;
legendData: LegendData[];
requestTotal: number;
}>();
const totalCount = computed(() => {
return props.legendData.reduce((prev, item) => {
return prev + item.count;
}, 0);
});
</script>
<style scoped lang="less">

View File

@ -3,17 +3,56 @@
<!-- 报告参数开始 -->
<div class="report-header flex items-center justify-between">
<span>
{{ detail.poolName || '-' }}
<a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.environmentName || '-' }}
<a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.creatUserName || '-' }}
<a-popover position="left" content-class="response-popover-content">
<span> {{ detail.environmentName || '-' }}</span>
<a-divider direction="vertical" :margin="4" class="!mx-2"></a-divider>
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.executeEnv') }}</div>
<span class="mx-1"> {{ detail.environmentName || '-' }}</span>
</div>
</template>
</a-popover>
<a-popover position="bottom" content-class="response-popover-content">
<span> {{ detail.poolName || '-' }}</span>
<a-divider direction="vertical" :margin="4" class="!mx-2"></a-divider>
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('project.taskCenter.resourcePool') }}</div>
<span class="mx-1"> {{ detail.poolName || '-' }}</span>
</div>
</template>
</a-popover>
<a-popover position="left" content-class="response-popover-content">
<span v-if="detail.runMode">
{{ detail.runMode === 'SERIAL' ? t('case.execute.serial') : t('case.execute.parallel') }}</span
>
<a-divider v-if="detail.runMode" direction="vertical" :margin="4" class="!mx-2"></a-divider>
<template #content>
<div class="items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.runMode') }}</div>
<div class="mx-1 mt-1">
{{ detail.runMode === 'SERIAL' ? t('case.execute.serial') : t('case.execute.parallel') }}</div
>
</div>
</template>
</a-popover>
<a-popover position="bottom" content-class="response-popover-content">
<span> {{ detail.creatUserName || '-' }}</span>
<template #content>
<div class="items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.reportCreator') }}</div>
<div class="mt-1"> {{ detail.creatUserName || '-' }}</div>
</div>
</template>
</a-popover>
</span>
<span>
<span class="text-[var(--color-text-4)]">{{ t('report.detail.api.executionTime') }}</span>
{{ dayjs(detail.startTime).format('YYYY-MM-DD HH:mm:ss') || '-' }}
{{ detail.startTime ? dayjs(detail.startTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
<span class="text-[var(--color-text-4)]">{{ t('report.detail.api.executionTimeTo') }}</span>
{{ dayjs(detail.endTime).format('YYYY-MM-DD HH:mm:ss') || '-' }}
{{ detail.endTime ? dayjs(detail.endTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
</span>
</div>
<!-- 报告参数结束 -->
@ -23,7 +62,11 @@
<div class="request-analyze min-h-[110px]">
<div class="block-title mb-4">{{ t('report.detail.api.requestAnalysis') }}</div>
<!-- 独立报告 -->
<SetReportChart :legend-data="legendData" :options="charOptions" />
<SetReportChart
:legend-data="legendData"
:options="charOptions"
:request-total="getIndicators(detail.requestTotal)"
/>
<!-- 集合报告 -->
<!-- </div> -->
</div>

View File

@ -75,7 +75,6 @@
tableData: any[];
pagination: MsPaginationI;
pageChange: (page: number) => Promise<void>;
showType: string; //
}>();
const emit = defineEmits<{

View File

@ -13,21 +13,12 @@
}>();
//
const scenarioStepMap = {
// [ScenarioStepType.QUOTE_API]: { label: 'apiScenario.quoteApi', color: 'rgb(var(--link-7))' },
// [ScenarioStepType.COPY_API]: { label: 'apiScenario.copyApi', color: 'rgb(var(--link-7))' },
// [ScenarioStepType.QUOTE_CASE]: { label: 'apiScenario.quoteCase', color: 'rgb(var(--success-7))' },
// [ScenarioStepType.COPY_CASE]: { label: 'apiScenario.copyCase', color: 'rgb(var(--success-7))' },
// [ScenarioStepType.QUOTE_SCENARIO]: { label: 'apiScenario.quoteScenario', color: 'rgb(var(--primary-7))' },
// [ScenarioStepType.COPY_SCENARIO]: { label: 'apiScenario.copyScenario', color: 'rgb(var(--primary-7))' },
// [ScenarioStepType.WAIT_TIME]: { label: 'apiScenario.waitTime', color: 'rgb(var(--warning-6))' },
[ScenarioStepType.LOOP_CONTROLLER]: { label: 'apiScenario.loopControl', color: 'rgba(167, 98, 191, 1)' },
[ScenarioStepType.IF_CONTROLLER]: { label: 'apiScenario.conditionControl', color: 'rgba(238, 80, 163, 1)' },
[ScenarioStepType.ONCE_ONLY_CONTROLLER]: { label: 'apiScenario.onlyOnceControl', color: 'rgba(211, 68, 0, 1)' },
[ScenarioStepType.SCRIPT]: { label: 'apiScenario.scriptOperation', color: 'rgba(20, 225, 198, 1)' },
// [ScenarioStepType.SCRIPT_OPERATION]: { label: 'apiScenario.scriptOperation', color: 'rgba(20, 225, 198, 1)' },
// [ScenarioStepType.CUSTOM_API]: { label: 'apiScenario.customApi', color: 'rgb(var(--link-4))' },
[ScenarioStepType.API_CASE]: { label: 'report.detail.api.apiCase', color: 'rgb(var(--link-4))' },
[ScenarioStepType.CUSTOM_REQUEST]: { label: 'report.detail.api.apiCase', color: 'rgb(var(--link-4))' },
[ScenarioStepType.CUSTOM_REQUEST]: { label: 'report.detail.api.customRequest', color: 'rgb(var(--link-4))' },
[ScenarioStepType.API]: { label: 'report.detail.api', color: 'rgb(var(--link-4))' },
};

View File

@ -75,7 +75,6 @@
tableData: any[];
pagination: MsPaginationI;
pageChange: (page: number) => Promise<void>;
showType: string; //
isShare?: boolean;
}>();

View File

@ -29,7 +29,7 @@
type="text"
class="one-text-line flex w-full text-[rgb(var(--primary-5))]"
@click="showReportDetail(record.id, rowIndex, record.integrated)"
>{{ characterLimit(record.name) }}-{{ dayjs(record.startTime).format('YYYY-MM-DD HH:mm:ss') }}</div
>{{ characterLimit(record.name) }}</div
>
</template>
<!-- 报告类型 -->

View File

@ -4,19 +4,73 @@
<div class="report-header flex items-center justify-between">
<!-- TODO 虚拟数据替换接口后边 -->
<span>
{{ detail.environmentName || '-' }}
<a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.poolName || '-' }}
<a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.requestDuration }}
<a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.creatUserName || '-' }}
<a-popover position="left" content-class="response-popover-content">
<span> {{ detail.environmentName || '-' }}</span>
<a-divider direction="vertical" :margin="4" class="!mx-2"></a-divider>
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.executeEnv') }}</div>
<span class="mx-1"> {{ detail.environmentName || '-' }}</span>
</div>
</template>
</a-popover>
<a-popover position="bottom" content-class="response-popover-content">
<span> {{ detail.poolName || '-' }}</span>
<a-divider direction="vertical" :margin="4" class="!mx-2"></a-divider>
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('project.taskCenter.resourcePool') }}</div>
<span class="mx-1"> {{ detail.poolName || '-' }}</span>
</div>
</template>
</a-popover>
<a-popover position="left" content-class="response-popover-content">
<span v-if="!detail.integrated">
{{ detail.waitingTime ? formatDuration(detail.waitingTime).split('-')[0] : '-' }}
<span>{{ detail.waitingTime ? formatDuration(detail.waitingTime).split('-')[1] : 'ms' }}</span>
<a-divider direction="vertical" :margin="4" class="!mx-2"></a-divider>
</span>
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.globalWaitingTime') }}</div>
{{ detail.waitingTime ? formatDuration(detail.waitingTime).split('-')[0] : '-' }}
<span class="mx-1">{{
detail.waitingTime ? formatDuration(detail.waitingTime).split('-')[1] : 'ms'
}}</span>
</div>
</template>
</a-popover>
<a-popover position="left" content-class="response-popover-content">
<span v-if="detail.runMode">
{{ detail.runMode === 'SERIAL' ? t('case.execute.serial') : t('case.execute.parallel') }}</span
>
<a-divider v-if="detail.runMode" direction="vertical" :margin="4" class="!mx-2"></a-divider>
<template #content>
<div class="items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.runMode') }}</div>
<div class="mt-1">
{{ detail.runMode === 'SERIAL' ? t('case.execute.serial') : t('case.execute.parallel') }}</div
>
</div>
</template>
</a-popover>
<a-popover position="bottom" content-class="response-popover-content">
<span> {{ detail.creatUserName || '-' }}</span>
<template #content>
<div class="items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('report.detail.api.reportCreator') }}</div>
<div class="mx-1 mt-1"> {{ detail.creatUserName || '-' }}</div>
</div>
</template>
</a-popover>
</span>
<span>
<span class="text-[var(--color-text-4)]">{{ t('report.detail.api.executionTime') }}</span>
{{ dayjs(detail.startTime).format('YYYY-MM-DD HH:mm:ss') || '-' }}
{{ detail.startTime ? dayjs(detail.startTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
<span class="text-[var(--color-text-4)]">{{ t('report.detail.api.executionTimeTo') }}</span>
{{ dayjs(detail.endTime).format('YYYY-MM-DD HH:mm:ss') || '-' }}
{{ detail.endTime ? dayjs(detail.endTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
</span>
</div>
<!-- 报告参数结束 -->
@ -28,7 +82,7 @@
<!-- 总数 -->
<div class="countItem">
<span class="mr-2 text-[var(--color-text-4)]"> {{ t('report.detail.stepTotal') }}</span>
{{ getTotal() || 0 }}
{{ detail.stepTotal || 0 }}
</div>
<!-- 通过 -->
<div class="countItem">
@ -113,7 +167,7 @@
<div class="relative mr-4">
<div class="absolute bottom-0 left-[30%] top-[35%] text-center">
<div class="text-[12px] text-[(var(--color-text-4))]">{{ t('report.detail.api.total') }}</div>
<div class="text-[18px] font-medium">{{ getTotal() }}</div>
<div class="text-[18px] font-medium">{{ getIndicators(detail.requestTotal) }}</div>
</div>
<MsChart width="110px" height="110px" :options="charOptions" />
</div>
@ -214,10 +268,6 @@
}
return '-';
});
function getTotal() {
const { errorCount, successCount, fakeErrorCount, pendingCount } = detail.value;
return errorCount + successCount + fakeErrorCount + pendingCount;
}
const legendData = ref<LegendData[]>([]);
const charOptions = ref({

View File

@ -30,8 +30,8 @@
>
{{ step.sort }}
</div>
<div class="step-node-content flex justify-between" @click.stop="showDetail(step)">
<div class="flex items-center">
<div class="step-node-content flex justify-between">
<div class="flex flex-1 items-center">
<!-- 步骤展开折叠按钮 -->
<a-tooltip
v-if="step.children?.length > 0"
@ -62,13 +62,12 @@
<icon-down class="text-[rgb(var(--primary-6))]" :style="{ 'font-size': '12px' }" />
</span>
</div>
<ConditionStatus
v-if="props.showType === 'API' && showCondition.includes(step.stepType)"
class="mx-1"
:status="step.stepType || ''"
/>
<div v-if="props.showType === 'API' && showCondition.includes(step.stepType)" class="flex-shrink-0">
<ConditionStatus class="mx-1" :status="step.stepType || ''" />
</div>
<a-tooltip :content="step.name">
<div class="step-name-container">
<div class="step-name-container w-full flex-grow" @click.stop="showDetail(step)">
<div class="one-line-text mx-[4px] max-w-[150px] text-[var(--color-text-1)]">
{{ step.name }}
</div>
@ -97,41 +96,43 @@
<div>{{ step.scriptIdentifier }}</div>
</template>
</a-popover>
<span class="statusCode mx-2">
<div class="mr-2"> {{ t('report.detail.api.statusCode') }}</div>
<a-popover position="left" content-class="response-popover-content">
<div class="one-line-text max-w-[200px]" :style="{ color: statusCodeColor(step.code) }">
{{ step.code || '-' }}
</div>
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.statusCode') }}</div>
<div :style="{ color: statusCodeColor(step.code) }">
{{ step.code || '-' }}
</div>
<div v-show="step.children && step.children.length > 0" class="flex">
<span class="statusCode mx-2">
<div class="mr-2"> {{ t('report.detail.api.statusCode') }}</div>
<a-popover position="left" content-class="response-popover-content">
<div class="one-line-text max-w-[200px]" :style="{ color: statusCodeColor(step.code) }">
{{ step.code || '-' }}
</div>
</template>
</a-popover>
</span>
<span class="resTime">
{{ t('report.detail.api.responseTime') }}
<span class="resTimeCount ml-2"
>{{ step.requestTime ? formatDuration(step.requestTime).split('-')[0] : '-'
}}{{ step.requestTime ? formatDuration(step.requestTime).split('-')[1] : 'ms' }}</span
></span
>
<a-popover position="left" content-class="response-popover-content">
<span class="resSize">
{{ t('report.detail.api.responseSize') }}
<span class="resTimeCount ml-2">{{ step.responseSize || 0 }} bytes</span></span
<template #content>
<div class="flex items-center gap-[8px] text-[14px]">
<div class="text-[var(--color-text-4)]">{{ t('apiTestDebug.statusCode') }}</div>
<div :style="{ color: statusCodeColor(step.code) }">
{{ step.code || '-' }}
</div>
</div>
</template>
</a-popover>
</span>
<span class="resTime">
{{ t('report.detail.api.responseTime') }}
<span class="resTimeCount ml-2"
>{{ step.requestTime ? formatDuration(step.requestTime).split('-')[0] : '-'
}}{{ step.requestTime ? formatDuration(step.requestTime).split('-')[1] : 'ms' }}</span
></span
>
<template #content>
<a-popover position="left" content-class="response-popover-content">
<span class="resSize">
{{ t('report.detail.api.responseSize') }}
<span class="resTimeCount ml-2">{{ step.responseSize || 0 }} bytes</span></span
>
</template>
</a-popover>
<template #content>
<span class="resSize">
{{ t('report.detail.api.responseSize') }}
<span class="resTimeCount ml-2">{{ step.responseSize || 0 }} bytes</span></span
>
</template>
</a-popover>
</div>
</div>
</div>
<div v-if="!step.fold" class="line"></div>

View File

@ -1,6 +1,6 @@
<template>
<div
class="tiled-wrap h-[calc(100vh - 374px)] p-4"
class="tiled-wrap p-4"
:class="{
'border border-solid border-[var(--color-text-n8)]': props.showType === 'API',
}"
@ -141,7 +141,7 @@
<style scoped lang="less">
.tiled-wrap {
height: calc(100vh - 424px);
min-height: calc(100vh - 424px);
border-radius: 4px;
}
</style>

View File

@ -58,6 +58,7 @@ export default {
'report.detail.api.resSuccess': 'Success',
'report.detail.api.resError': 'Error',
'report.detail.api.apiCase': 'Api Case',
'report.detail.api.customRequest': 'Custom request',
'report.detail.api': 'Api',
'report.detail.api.resBody': 'response body',
'report.detail.api.resHeader': 'headers',
@ -70,4 +71,8 @@ export default {
'report.detail.api.scriptErrorTip': 'Script error',
'report.detail.api.scenario': 'scenario',
'report.detail.api.request': 'request',
'report.detail.api.globalWaitingTime': 'Scenario global waiting time',
'report.detail.api.executeEnv': 'Running environment',
'report.detail.api.reportCreator': 'Report creator',
'report.detail.api.runMode': 'Run mode',
};

View File

@ -57,6 +57,7 @@ export default {
'report.detail.api.resSuccess': '成功',
'report.detail.api.resError': '失败',
'report.detail.api.apiCase': '接口用例',
'report.detail.api.customRequest': '自定义请求',
'report.detail.api': '接口定义',
'report.detail.api.resBody': '响应体',
'report.detail.api.resHeader': '响应头',
@ -69,4 +70,8 @@ export default {
'report.detail.api.scriptErrorTip': '脚本报错',
'report.detail.api.scenario': '场景',
'report.detail.api.request': '请求',
'report.detail.api.globalWaitingTime': '场景全局等待时间',
'report.detail.api.executeEnv': '运行环境',
'report.detail.api.reportCreator': '报告创建人',
'report.detail.api.runMode': '运行模式',
};

View File

@ -53,8 +53,11 @@
<template #operationTime="{ record }">
<span>{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template #operation="{ record }">
<MsButton class="!mr-0" @click="viewReport">{{ t('project.taskCenter.viewReport') }}</MsButton>
<template #operation="{ record, rowIndex }">
<MsButton class="!mr-0" @click="viewReport(record.id, rowIndex)">{{
t('project.taskCenter.viewReport')
}}</MsButton>
<span></span>
<a-divider v-if="['RUNNING', 'RERUNNING'].includes(record.status)" direction="vertical" />
<MsButton
v-if="['RUNNING', 'RERUNNING'].includes(record.status) && hasAnyPermission(permissionsMap[props.group].stop)"
@ -65,6 +68,22 @@
</template>
</ms-base-table>
</div>
<ReportDetailDrawer
v-model:visible="showDetailDrawer"
:report-id="activeDetailId"
:active-report-index="activeReportIndex"
:table-data="propsRes.data"
:page-change="propsEvent.pageChange"
:pagination="propsRes.msPagination!"
/>
<CaseReportDrawer
v-model:visible="showCaseDetailDrawer"
:report-id="activeDetailId"
:active-report-index="activeReportIndex"
:table-data="propsRes.data"
:page-change="propsEvent.pageChange"
:pagination="propsRes.msPagination!"
/>
</template>
<script setup lang="ts">
@ -77,6 +96,8 @@
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import ExecutionStatus from './executionStatus.vue';
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
import {
batchStopRealOrdApi,
@ -96,7 +117,6 @@
import { hasAnyPermission } from '@/utils/permission';
import { BatchApiParams } from '@/models/common';
import { RouteEnum } from '@/enums/routeEnum';
import { ExecutionMethodsLabel, TaskCenterEnum } from '@/enums/taskCenter';
import { TaskStatus } from './utils';
@ -339,8 +359,21 @@
}
}
function viewReport() {
openNewPage(RouteEnum.API_TEST_REPORT);
/**
* 报告详情 showReportDetail
*/
const activeDetailId = ref<string>('');
const activeReportIndex = ref<number>(0);
const showDetailDrawer = ref<boolean>(false);
const showCaseDetailDrawer = ref<boolean>(false);
function viewReport(id: string, rowIndex: number) {
if (props.moduleType === 'API_CASE') {
showCaseDetailDrawer.value = true;
} else {
showDetailDrawer.value = true;
}
activeDetailId.value = id;
activeReportIndex.value = rowIndex;
}
watch(