fix(接口测试): 去掉多余测试计划菜单和报告bug部分修复

This commit is contained in:
xinxin.wu 2024-03-25 11:44:23 +08:00 committed by Craftsman
parent e7e8d5a320
commit 01af00de0c
7 changed files with 85 additions and 30 deletions

View File

@ -8,11 +8,9 @@ const ShareRoute: AppRouteRecordRaw = {
name: ShareEnum.SHARE, name: ShareEnum.SHARE,
component: SHARE_LAYOUT, component: SHARE_LAYOUT,
meta: { meta: {
locale: 'menu.testPlan',
icon: 'icon-icon_test-tracking_filled',
hideChildrenInMenu: true,
roles: ['*'],
hideInMenu: true, hideInMenu: true,
roles: ['*'],
requiresAuth: true,
}, },
children: [ children: [
// 测试计划 // 测试计划

View File

@ -895,3 +895,23 @@ export function addLevelToTree<T>(tree: TreeNode<T>[], level = 0): TreeNode<T>[]
return newNode; return newNode;
}); });
} }
/**
*
* @param ms
*/
export function formatDuration(ms: number) {
// 将毫秒转换为秒
const seconds = ms / 1000;
// 如果小于1秒则直接返回毫秒
if (seconds < 1) return `${ms}-ms`;
// 如果小于60秒则返回秒
if (seconds < 60) return `${seconds}-sec`;
// 将秒转换为分钟
const minutes = seconds / 60;
// 如果小于60分钟则返回分钟
if (minutes < 60) return `${minutes.toFixed(1)}-min`;
// 将分钟转换为小时
const hours = minutes / 60;
// 返回小时
return `${hours.toFixed(1)}-hr`;
}

View File

@ -3,10 +3,10 @@
<!-- 展开折叠列表 --> <!-- 展开折叠列表 -->
<div class="tiledList"> <div class="tiledList">
<div v-for="item of props.menuList" :key="item.value" class="menu-list-wrapper"> <div v-for="item of props.menuList" :key="item.value" class="menu-list-wrapper">
<div class="menu-list"> <div v-if="isShowContent(item.value)" class="menu-list">
<div class="flex items-center"> <div class="flex items-center">
<MsButton <MsButton
v-if="expandIds.includes(item.value)" v-if="!expandIds.includes(item.value)"
type="icon" type="icon"
class="!mr-2 !rounded-full bg-[rgb(var(--primary-1))]" class="!mr-2 !rounded-full bg-[rgb(var(--primary-1))]"
size="small" size="small"
@ -28,28 +28,28 @@
</div> </div>
</div> </div>
<transition name="fade"> <transition name="fade">
<div v-show="expandIds.includes(item.value)" class="expandContent"> <div v-show="!expandIds.includes(item.value) && isShowContent(item.value)" class="expandContent">
<div v-if="item.value === ResponseComposition.BODY" class="res-item"> <div v-if="item.value === ResponseComposition.BODY" class="res-item">
<ResBody :request-result="props.requestResult" @copy="copyScript" /> <ResBody :request-result="props.requestResult" @copy="copyScript" />
</div> </div>
<div v-if="expandIds.includes(item.value) && item.value === ResponseComposition.CONSOLE" class="res-item"> <div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.CONSOLE" class="res-item">
<ResConsole :console="props.console?.trim()" /> <ResConsole :console="props.console?.trim()" />
</div> </div>
<div v-if="expandIds.includes(item.value) && item.value === ResponseComposition.HEADER" class="res-item"> <div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.HEADER" class="res-item">
<ResValueScript :active-tab="item.value" :request-result="props.requestResult" /> <ResValueScript :active-tab="item.value" :request-result="props.requestResult" />
</div> </div>
<div v-if="expandIds.includes(item.value) && item.value === ResponseComposition.REAL_REQUEST"> <div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.REAL_REQUEST">
<ResValueScript :active-tab="item.value" :request-result="props.requestResult" /> <ResValueScript :active-tab="item.value" :request-result="props.requestResult" />
</div> </div>
<div v-if="expandIds.includes(item.value) && item.value === ResponseComposition.EXTRACT"> <div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.EXTRACT">
<ResValueScript :active-tab="item.value" :request-result="props.requestResult" /> <ResValueScript :active-tab="item.value" :request-result="props.requestResult" />
</div> </div>
<div v-if="expandIds.includes(item.value) && item.value === ResponseComposition.ASSERTION"> <div v-if="!expandIds.includes(item.value) && item.value === ResponseComposition.ASSERTION">
<ResAssertion :request-result="props.requestResult" /> <ResAssertion :request-result="props.requestResult" />
</div> </div>
</div> </div>
</transition> </transition>
<a-divider type="dashed" :margin="0" class="!mb-4"></a-divider> <a-divider v-if="isShowContent(item.value)" type="dashed" :margin="0" class="!mb-4"></a-divider>
</div> </div>
</div> </div>
</div> </div>
@ -100,6 +100,32 @@
Message.warning(t('apiTestDebug.copyNotSupport')); Message.warning(t('apiTestDebug.copyNotSupport'));
} }
} }
const showBody = computed(() => props.requestResult?.responseResult.body);
const showHeaders = computed(() => props.requestResult?.responseResult.headers);
const showRealRequest = computed(
() => props.requestResult?.responseResult?.headers.trim() || props.requestResult?.url || props.requestResult?.body
);
const showExtract = computed(() => props.requestResult?.responseResult?.vars?.trim());
function isShowContent(key: keyof typeof ResponseComposition) {
switch (key) {
case ResponseComposition.BODY:
return showBody.value;
case ResponseComposition.HEADER:
return showHeaders.value;
case ResponseComposition.REAL_REQUEST:
return showRealRequest.value;
case ResponseComposition.CONSOLE:
return props?.console?.trim();
case ResponseComposition.EXTRACT:
return showExtract.value;
case ResponseComposition.ASSERTION:
return props.requestResult?.responseResult.assertions.length;
default:
break;
}
}
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -33,14 +33,16 @@
<div class="time-card-item flex h-full"> <div class="time-card-item flex h-full">
<MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" /> <MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
<span class="time-card-item-title">{{ t('report.detail.api.totalTime') }}</span> <span class="time-card-item-title">{{ t('report.detail.api.totalTime') }}</span>
<span class="count">{{ getTotalTime }}</span <span class="count">{{ getTotalTime.split('-')[0] || '-' }}</span
><span class="time-card-item-title">s</span> ><span class="time-card-item-title">{{ getTotalTime.split('-')[1] || 'ms' }}</span>
</div> </div>
<div class="time-card-item h-full"> <div class="time-card-item h-full">
<MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" /> <MsIcon type="icon-icon_time_outlined" class="mr-[4px] text-[var(--color-text-4)]" size="16" />
<span class="time-card-item-title"> {{ t('report.detail.api.requestTotalTime') }}</span> <span class="time-card-item-title"> {{ t('report.detail.api.requestTotalTime') }}</span>
<span class="count">{{ detail.requestDuration || '-' }}</span <span class="count">{{ formatDuration(detail.requestDuration).split('-')[0] || '-' }}</span
><span class="time-card-item-title">s</span> ><span class="time-card-item-title">{{
formatDuration(detail.requestDuration).split('-')[1] || 'ms'
}}</span>
</div> </div>
</div> </div>
@ -105,7 +107,7 @@
import TiledList from './tiledList.vue'; import TiledList from './tiledList.vue';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { addCommasToNumber } from '@/utils'; import { addCommasToNumber, formatDuration } from '@/utils';
import type { LegendData, ReportDetail } from '@/models/apiTest/report'; import type { LegendData, ReportDetail } from '@/models/apiTest/report';
@ -158,7 +160,7 @@
if (detail.value) { if (detail.value) {
const { endTime, startTime } = detail.value; const { endTime, startTime } = detail.value;
if (endTime && startTime && endTime !== 0 && startTime !== 0) { if (endTime && startTime && endTime !== 0 && startTime !== 0) {
return endTime - startTime; return formatDuration(endTime - startTime);
} }
return '-'; return '-';
} }

View File

@ -63,8 +63,8 @@
{{ t('report.detail.api.totalTime') }} {{ t('report.detail.api.totalTime') }}
</div> </div>
<div> <div>
<span class="ml-4 text-[18px] font-medium">{{ getTotalTime }}</span <span class="ml-4 text-[18px] font-medium">{{ getTotalTime.split('-')[0] || '-' }}</span>
>s <span class="ml-1 text-[var(--color-text-4)]">{{ getTotalTime.split('-')[1] || 'ms' }}</span>
</div> </div>
</div> </div>
<div class="timer-card mr-2"> <div class="timer-card mr-2">
@ -73,8 +73,12 @@
{{ t('report.detail.api.requestTotalTime') }} {{ t('report.detail.api.requestTotalTime') }}
</div> </div>
<div> <div>
<span class="ml-4 text-[18px] font-medium">{{ detail.requestDuration }}</span <span class="ml-4 text-[18px] font-medium">{{
>s formatDuration(detail.requestDuration).split('-')[0] || '-'
}}</span>
<span class="ml-1 text-[var(--color-text-4)]">{{
formatDuration(detail.requestDuration).split('-')[1] || 'ms'
}}</span>
</div> </div>
</div> </div>
<div class="timer-card min-w-[200px]"> <div class="timer-card min-w-[200px]">
@ -151,7 +155,7 @@
import TiledList from './tiledList.vue'; import TiledList from './tiledList.vue';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { addCommasToNumber } from '@/utils'; import { addCommasToNumber, formatDuration } from '@/utils';
import type { LegendData, ReportDetail } from '@/models/apiTest/report'; import type { LegendData, ReportDetail } from '@/models/apiTest/report';
@ -200,11 +204,13 @@
console: '', console: '',
}); });
const timeUnits = ['ms', 'sec', 'min', 'hr'];
const getTotalTime = computed(() => { const getTotalTime = computed(() => {
if (detail.value) { if (detail.value) {
const { endTime, startTime } = detail.value; const { endTime, startTime } = detail.value;
if (endTime && startTime && endTime !== 0 && startTime !== 0) { if (endTime && startTime && endTime !== 0 && startTime !== 0) {
return endTime - startTime; return formatDuration(endTime - startTime);
} }
return '-'; return '-';
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="flex h-full flex-col gap-[16px]"> <div class="flex h-full flex-col gap-[16px]">
<a-spin class="max-h-[calc(100%-46px)] w-full" :loading="loading"> <a-spin class="max-h-[calc(100vh - 454px)] w-full" :loading="loading">
<MsTree <MsTree
ref="treeRef" ref="treeRef"
v-model:selected-keys="selectedKeys" v-model:selected-keys="selectedKeys"
@ -8,7 +8,7 @@
:expand-all="props.expandAll" :expand-all="props.expandAll"
:field-names="{ title: 'name', key: 'stepId', children: 'children' }" :field-names="{ title: 'name', key: 'stepId', children: 'children' }"
:virtual-list-props="{ :virtual-list-props="{
height: `calc(100vh - 406px)`, height: `calc(100vh - 454px)`,
threshold: 20, threshold: 20,
fixedSize: true, fixedSize: true,
buffer: 15, buffer: 15,
@ -96,7 +96,10 @@
</span> </span>
<span class="resTime"> <span class="resTime">
{{ t('report.detail.api.responseTime') }} {{ t('report.detail.api.responseTime') }}
<span class="resTimeCount ml-2">{{ step.requestTime || 0 }}ms</span></span <span class="resTimeCount ml-2"
>{{ formatDuration(step.requestTime).split('-')[0]
}}{{ formatDuration(step.requestTime).split('-')[1] }}</span
></span
> >
<span class="resSize"> <span class="resSize">
{{ t('report.detail.api.responseSize') }} {{ t('report.detail.api.responseSize') }}
@ -143,7 +146,7 @@
import ConditionStatus from '@/views/api-test/report/component/conditionStatus.vue'; import ConditionStatus from '@/views/api-test/report/component/conditionStatus.vue';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { findNodeByKey, mapTree } from '@/utils'; import { findNodeByKey, formatDuration, mapTree } from '@/utils';
import type { ScenarioItemType } from '@/models/apiTest/report'; import type { ScenarioItemType } from '@/models/apiTest/report';
import { ScenarioStepType } from '@/enums/apiEnum'; import { ScenarioStepType } from '@/enums/apiEnum';

View File

@ -1,6 +1,6 @@
<template> <template>
<div <div
class="tiled-wrap p-4" class="tiled-wrap h-[calc(100vh - 374px)] p-4"
:class="{ :class="{
'border border-solid border-[var(--color-text-n8)]': props.showType === 'API', 'border border-solid border-[var(--color-text-n8)]': props.showType === 'API',
}" }"