fix(接口测试): 修复接口测试部分bug (#29807)

Co-authored-by: xinxin.wu <xinxin.wu@fit2cloud.com>
This commit is contained in:
MeterSphere Bot 2024-03-25 20:49:50 +08:00 committed by GitHub
parent 6300cdebfd
commit 4e8eec98ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 66 additions and 40 deletions

View File

@ -16,7 +16,7 @@
@cancel="handleDrawerCancel" @cancel="handleDrawerCancel"
> >
<div class="mb-4 flex items-center justify-between"> <div class="mb-4 flex items-center justify-between">
<a-button type="outline" @click="addCommonScript"> <a-button v-permission="['PROJECT_CUSTOM_FUNCTION:READ+ADD']" type="outline" @click="addCommonScript">
{{ t('project.commonScript.addPublicScript') }} {{ t('project.commonScript.addPublicScript') }}
</a-button> </a-button>
<a-input-search <a-input-search

View File

@ -1,12 +1,26 @@
import { Language, LanguageEnum } from '@/components/pure/ms-code-editor/types'; import { Language, LanguageEnum } from '@/components/pure/ms-code-editor/types';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { hasAnyPermission } from '@/utils/permission';
import type { CommonScriptMenu } from '@/models/projectManagement/commonScript'; import type { CommonScriptMenu } from '@/models/projectManagement/commonScript';
import { RequestConditionScriptLanguage } from '@/enums/apiEnum'; import { RequestConditionScriptLanguage } from '@/enums/apiEnum';
const { t } = useI18n(); const { t } = useI18n();
function getInsertCommonScript() {
if (hasAnyPermission(['PROJECT_CUSTOM_FUNCTION:READ'])) {
return [
{
title: t('project.processor.insertPublicScript'),
value: 'custom_function',
command: 'custom_function',
},
];
}
return [];
}
export const SCRIPT_MENU: CommonScriptMenu[] = [ export const SCRIPT_MENU: CommonScriptMenu[] = [
{ {
title: t('project.code_segment.importApiTest'), title: t('project.code_segment.importApiTest'),
@ -42,11 +56,7 @@ export const SCRIPT_MENU: CommonScriptMenu[] = [
title: t('project.processor.paramEnvironmentSetGlobalVariable'), title: t('project.processor.paramEnvironmentSetGlobalVariable'),
value: `vars.put(\${__metersphere_env_id}+"key","value");\nvars.put("key","value");`, value: `vars.put(\${__metersphere_env_id}+"key","value");\nvars.put("key","value");`,
}, },
{ ...getInsertCommonScript(),
title: t('project.processor.insertPublicScript'),
value: 'custom_function',
command: 'custom_function',
},
{ {
title: t('project.processor.terminationTest'), title: t('project.processor.terminationTest'),
value: 'ctx.getEngine().stopTest();', value: 'ctx.getEngine().stopTest();',

View File

@ -28,10 +28,11 @@
</span> </span>
</span> </span>
</MsTag> --> </MsTag> -->
<slot name="right"></slot>
<MsTag no-margin size="large" class="cursor-pointer" theme="outline" @click="handleRefresh"> <MsTag no-margin size="large" class="cursor-pointer" theme="outline" @click="handleRefresh">
<MsIcon class="text-[var(color-text-4)]" :size="16" type="icon-icon_reset_outlined" /> <MsIcon class="text-[var(color-text-4)]" :size="16" type="icon-icon_reset_outlined" />
</MsTag> </MsTag>
<slot name="right"></slot>
</div> </div>
</div> </div>
<FilterForm <FilterForm

View File

@ -1,5 +1,5 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { number } from 'echarts'; import { cloneDeep } from 'lodash-es';
import localforage from 'localforage'; import localforage from 'localforage';
import { getDetailEnv, getGlobalParamDetail } from '@/api/modules/project-management/envManagement'; import { getDetailEnv, getGlobalParamDetail } from '@/api/modules/project-management/envManagement';
@ -17,6 +17,7 @@ import {
export const ALL_PARAM = 'allParam'; export const ALL_PARAM = 'allParam';
export const NEW_ENV_PARAM = 'newEnvParam'; export const NEW_ENV_PARAM = 'newEnvParam';
export const NEW_ENV_GROUP = 'newEnvGroup'; export const NEW_ENV_GROUP = 'newEnvGroup';
// 环境默认配置项
const envParamsDefaultConfig: EnvConfig = { const envParamsDefaultConfig: EnvConfig = {
commonVariables: [], commonVariables: [],
httpConfig: [], httpConfig: [],
@ -70,6 +71,7 @@ const useProjectEnvStore = defineStore(
const backupEnvDetailInfo = ref<EnvDetailItem>({ const backupEnvDetailInfo = ref<EnvDetailItem>({
projectId: '', projectId: '',
name: '', name: '',
description: '',
config: envParamsDefaultConfig, config: envParamsDefaultConfig,
}); });
const allParamDetailInfo = ref<GlobalParams>(); // 全局参数详情 const allParamDetailInfo = ref<GlobalParams>(); // 全局参数详情
@ -106,14 +108,14 @@ const useProjectEnvStore = defineStore(
backupEnvDetailInfo.value = { backupEnvDetailInfo.value = {
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
name: '', name: '',
config: envParamsDefaultConfig, config: cloneDeep(envParamsDefaultConfig),
}; };
} else if (id === ALL_PARAM) { } else if (id === ALL_PARAM) {
allParamDetailInfo.value = await getGlobalParamDetail(appStore.currentProjectId); allParamDetailInfo.value = await getGlobalParamDetail(appStore.currentProjectId);
} else if (id !== ALL_PARAM && id) { } else if (id !== ALL_PARAM && id) {
const tmpObj = await getDetailEnv(id); const tmpObj = await getDetailEnv(id);
currentEnvDetailInfo.value = { ...tmpObj }; currentEnvDetailInfo.value = { ...tmpObj };
backupEnvDetailInfo.value = tmpObj; backupEnvDetailInfo.value = cloneDeep(tmpObj);
} }
} catch (e) { } catch (e) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console

View File

@ -207,7 +207,12 @@
{{ condition.commonScriptInfo?.name || '-' }} {{ condition.commonScriptInfo?.name || '-' }}
</div> </div>
<a-divider margin="8px" direction="vertical" /> <a-divider margin="8px" direction="vertical" />
<MsButton type="text" class="font-medium" @click="showQuoteDrawer = true"> <MsButton
v-permission="['PROJECT_CUSTOM_FUNCTION:READ']"
type="text"
class="font-medium"
@click="showQuoteDrawer = true"
>
{{ t('apiTestDebug.quote') }} {{ t('apiTestDebug.quote') }}
</MsButton> </MsButton>
</div> </div>

View File

@ -77,7 +77,7 @@
<a-spin <a-spin
v-else v-else
:loading="loading" :loading="loading"
:class="[props.isResponseModel ? 'h-[300px] w-full' : 'h-[calc(100%-35px)] w-full px-[18px] pb-[18px]']" :class="[props.isResponseModel ? 'h-full w-full' : 'h-[calc(100%-35px)] w-full px-[18px] pb-[18px]']"
> >
<result <result
v-model:active-tab="activeTab" v-model:active-tab="activeTab"
@ -256,7 +256,10 @@
stepDetailInfo.value = cloneDeep(res) as any; stepDetailInfo.value = cloneDeep(res) as any;
// TODO -- // TODO --
activeStepDetail.value = stepDetailInfo.value[activeIndex.value]; activeStepDetail.value = stepDetailInfo.value[activeIndex.value];
subRequestResults.value = stepDetailInfo.value[activeIndex.value].content.subRequestResults; if (stepDetailInfo.value.length) {
subRequestResults.value = stepDetailInfo.value[activeIndex.value].content.subRequestResults;
}
if (activeType.value === 'ResContent') { if (activeType.value === 'ResContent') {
activeStepDetailCopy.value = cloneDeep(activeStepDetail.value); activeStepDetailCopy.value = cloneDeep(activeStepDetail.value);
} else { } else {

View File

@ -35,7 +35,7 @@
<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="">
<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">

View File

@ -5,7 +5,7 @@
<span> <span>
{{ detail.poolName || '-' }} {{ detail.poolName || '-' }}
<a-divider direction="vertical" :margin="4"></a-divider> <a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.requestDuration || '-' }} {{ detail.environmentName || '-' }}
<a-divider direction="vertical" :margin="4"></a-divider> <a-divider direction="vertical" :margin="4"></a-divider>
{{ detail.creatUserName || '-' }} {{ detail.creatUserName || '-' }}
</span> </span>

View File

@ -29,7 +29,7 @@
type="text" type="text"
class="one-text-line flex w-full text-[rgb(var(--primary-5))]" class="one-text-line flex w-full text-[rgb(var(--primary-5))]"
@click="showReportDetail(record.id, rowIndex, record.integrated)" @click="showReportDetail(record.id, rowIndex, record.integrated)"
>{{ characterLimit(record.name) }}</div >{{ characterLimit(record.name) }}-{{ dayjs(record.startTime).format('YYYY-MM-DD HH:mm:ss') }}</div
> >
</template> </template>
<!-- 报告类型 --> <!-- 报告类型 -->
@ -185,7 +185,7 @@
title: 'report.name', title: 'report.name',
dataIndex: 'name', dataIndex: 'name',
slotName: 'name', slotName: 'name',
width: 200, width: 300,
showInTable: true, showInTable: true,
showTooltip: true, showTooltip: true,
editType: hasAnyPermission(['PROJECT_API_REPORT:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined, editType: hasAnyPermission(['PROJECT_API_REPORT:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined,

View File

@ -30,7 +30,7 @@
> >
{{ step.sort }} {{ step.sort }}
</div> </div>
<div class="step-node-content flex justify-between"> <div class="step-node-content flex justify-between" @click.stop="showDetail(step)">
<div class="flex items-center"> <div class="flex items-center">
<!-- 步骤展开折叠按钮 --> <!-- 步骤展开折叠按钮 -->
<a-tooltip <a-tooltip
@ -68,7 +68,7 @@
:status="step.stepType || ''" :status="step.stepType || ''"
/> />
<a-tooltip :content="step.name"> <a-tooltip :content="step.name">
<div class="step-name-container" @click.stop="showDetail(step)"> <div class="step-name-container">
<div class="one-line-text mx-[4px] max-w-[150px] text-[var(--color-text-1)]"> <div class="one-line-text mx-[4px] max-w-[150px] text-[var(--color-text-1)]">
{{ step.name }} {{ step.name }}
</div> </div>
@ -137,11 +137,11 @@
<div v-if="!step.fold" class="line"></div> <div v-if="!step.fold" class="line"></div>
</div> </div>
<!-- 折叠展开内容 --> <!-- 折叠展开内容 -->
<div v-if="showResContent(step)" class="mt-4 h-[210px] pl-2"> <div v-if="showResContent(step)" class="foldContent mt-4 pl-2">
<a-scrollbar <a-scrollbar
:style="{ :style="{
overflow: 'auto', overflow: 'auto',
height: '210px', height: 'calc(100vh - 540px)',
width: '100%', width: '100%',
}" }"
> >
@ -427,4 +427,7 @@
height: 1px; height: 1px;
background: var(--color-text-n8); background: var(--color-text-n8);
} }
:deep(.foldContent .arco-scrollbar-track-direction-vertical) {
left: -12px !important;
}
</style> </style>

View File

@ -1,5 +1,5 @@
<template> <template>
<assertion v-model:params="assertions" :is-definition="false" :assertion-config="assertionConfig" /> <assertion v-model:params="assertionConfig.assertions" :is-definition="false" :assertion-config="assertionConfig" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -7,7 +7,6 @@
import { AssertionConfig } from '@/models/apiTest/scenario'; import { AssertionConfig } from '@/models/apiTest/scenario';
const assertions = ref([]);
const assertionConfig = defineModel<AssertionConfig>('assertionConfig', { const assertionConfig = defineModel<AssertionConfig>('assertionConfig', {
required: true, required: true,
}); });

View File

@ -197,7 +197,13 @@
height: 200, height: 200,
}, },
}" }"
></a-tree-select> >
<template #tree-slot-title="node">
<div class="inline-flex w-full">
<div class="one-line-text w-[300px] text-[var(--color-text-1)]">{{ node.name }}</div>
</div>
</template>
</a-tree-select>
</a-form-item> </a-form-item>
<MsFormCreate <MsFormCreate
v-if="formRules.length" v-if="formRules.length"

View File

@ -74,8 +74,8 @@
<a-button <a-button
class="ml-3" class="ml-3"
type="primary" type="primary"
:disabled="isDisabled"
:loading="props.confirmLoading" :loading="props.confirmLoading"
:disabled="fileList.length < 1"
@click="saveConfirm" @click="saveConfirm"
>{{ t('caseManagement.featureCase.checkTemplate') }}</a-button >{{ t('caseManagement.featureCase.checkTemplate') }}</a-button
> >
@ -125,13 +125,6 @@
emit('close'); emit('close');
}; };
// const versionOptions = ref([
// {
// id: '1001',
// name: 'V1.0',
// },
// ]);
const fileTypeTip = computed(() => { const fileTypeTip = computed(() => {
return props.validateType === 'Excel' return props.validateType === 'Excel'
? t('caseManagement.featureCase.excelImportTip') ? t('caseManagement.featureCase.excelImportTip')
@ -140,8 +133,6 @@
const isRecover = ref<boolean>(false); const isRecover = ref<boolean>(false);
const isDisabled = ref<boolean>(false);
// excel|| xmind // excel|| xmind
async function downloadExcelTemplate() { async function downloadExcelTemplate() {
try { try {

View File

@ -54,7 +54,7 @@
<span>{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm:ss') }}</span> <span>{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template> </template>
<template #operation="{ record }"> <template #operation="{ record }">
<MsButton class="!mr-0">{{ t('project.taskCenter.viewReport') }}</MsButton> <MsButton class="!mr-0" @click="viewReport">{{ t('project.taskCenter.viewReport') }}</MsButton>
<a-divider v-if="['RUNNING', 'RERUNNING'].includes(record.status)" direction="vertical" /> <a-divider v-if="['RUNNING', 'RERUNNING'].includes(record.status)" direction="vertical" />
<MsButton <MsButton
v-if="['RUNNING', 'RERUNNING'].includes(record.status) && hasAnyPermission(permissionsMap[props.group].stop)" v-if="['RUNNING', 'RERUNNING'].includes(record.status) && hasAnyPermission(permissionsMap[props.group].stop)"
@ -91,10 +91,12 @@
} from '@/api/modules/project-management/taskCenter'; } from '@/api/modules/project-management/taskCenter';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import { characterLimit } from '@/utils'; import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission'; import { hasAnyPermission } from '@/utils/permission';
import { BatchApiParams } from '@/models/common'; import { BatchApiParams } from '@/models/common';
import { RouteEnum } from '@/enums/routeEnum';
import { ExecutionMethodsLabel, TaskCenterEnum } from '@/enums/taskCenter'; import { ExecutionMethodsLabel, TaskCenterEnum } from '@/enums/taskCenter';
import { TaskStatus } from './utils'; import { TaskStatus } from './utils';
@ -110,7 +112,7 @@
const keyword = ref<string>(''); const keyword = ref<string>('');
const statusFilterVisible = ref(false); const statusFilterVisible = ref(false);
const statusListFilters = ref<string[]>(Object.keys(TaskStatus[props.moduleType])); const statusListFilters = ref<string[]>(Object.keys(TaskStatus[props.moduleType]));
const { openNewPage } = useOpenNewPage();
const filterOptions = computed(() => { const filterOptions = computed(() => {
return statusListFilters.value.map((item) => { return statusListFilters.value.map((item) => {
return { return {
@ -330,12 +332,17 @@
const statusFilters = computed(() => { const statusFilters = computed(() => {
return Object.keys(TaskStatus[props.moduleType]); return Object.keys(TaskStatus[props.moduleType]);
}); });
function handleFilterHidden(val: boolean) { function handleFilterHidden(val: boolean) {
if (!val) { if (!val) {
initData(); initData();
} }
} }
function viewReport() {
openNewPage(RouteEnum.API_TEST_REPORT);
}
watch( watch(
() => props.moduleType, () => props.moduleType,
(val) => { (val) => {

View File

@ -95,7 +95,6 @@
dataIndex: 'value', dataIndex: 'value',
slotName: 'value', slotName: 'value',
showInTable: true, showInTable: true,
isTag: true,
width: 150, width: 150,
showDrag: true, showDrag: true,
}, },
@ -138,7 +137,7 @@
project: getScheduleProApiCaseList, project: getScheduleProApiCaseList,
}); });
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setProps } = useTable( const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
loadRealMap.value[props.group], loadRealMap.value[props.group],
{ {
columns, columns,
@ -148,8 +147,8 @@
showSetting: false, showSetting: false,
selectable: true, selectable: true,
heightUsed: 300, heightUsed: 300,
enableDrag: true, enableDrag: false,
showSelectAll: true, showSelectorAll: true,
} }
); );