fix(接口测试): 去掉多余测试计划菜单和报告bug部分修复
This commit is contained in:
parent
e7e8d5a320
commit
01af00de0c
|
@ -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: [
|
||||||
// 测试计划
|
// 测试计划
|
||||||
|
|
|
@ -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`;
|
||||||
|
}
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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 '-';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 '-';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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',
|
||||||
}"
|
}"
|
||||||
|
|
Loading…
Reference in New Issue