fix(接口管理): 用例执行渲染出响应数据

This commit is contained in:
teukkk 2024-03-19 21:03:17 +08:00 committed by Craftsman
parent d85c5d3ee5
commit 9b0a28ac9f
4 changed files with 100 additions and 64 deletions

View File

@ -234,26 +234,26 @@
</div>
</div>
</a-collapse-item>
<a-spin :loading="previewDetail.executeLoading" class="w-full">
<a-collapse-item
v-if="
previewDetail.responseDefinition &&
previewDetail.responseDefinition.length > 0 &&
props.detail.protocol === 'HTTP'
"
key="response"
>
<template #header>
<div class="flex items-center gap-[4px]">
<div v-if="activeDetailKey.includes('response')" class="down-icon">
<icon-down :size="10" class="block" />
</div>
<div v-else class="h-[16px] w-[16px] !rounded-full p-[4px]">
<icon-right :size="10" class="block" />
</div>
<div class="font-medium">{{ t('apiTestManagement.responseContent') }}</div>
<a-collapse-item
v-if="
previewDetail.responseDefinition &&
previewDetail.responseDefinition.length > 0 &&
props.detail.protocol === 'HTTP'
"
key="response"
>
<template #header>
<div class="flex items-center gap-[4px]">
<div v-if="activeDetailKey.includes('response')" class="down-icon">
<icon-down :size="10" class="block" />
</div>
</template>
<div v-else class="h-[16px] w-[16px] !rounded-full p-[4px]">
<icon-right :size="10" class="block" />
</div>
<div class="font-medium">{{ t('apiTestManagement.responseContent') }}</div>
</div>
</template>
<template v-if="!props.isCase">
<MsEditableTab
v-model:active-tab="activeResponse"
:tabs="previewDetail.responseDefinition?.map((e) => ({ ...e, closable: false })) || []"
@ -313,8 +313,23 @@
</div>
<MsFormTable :columns="responseHeaderColumns" :data="activeResponse?.headers || []" :selectable="false" />
</div>
</a-collapse-item>
</a-spin>
</template>
<a-spin v-else :loading="previewDetail.executeLoading" class="h-[calc(100%-45px)] w-full pb-[18px]">
<result
v-show="
previewDetail.protocol === 'HTTP' || previewDetail.response?.requestResults[0]?.responseResult.responseCode
"
v-model:active-tab="previewDetail.responseActiveTab"
:request-result="previewDetail.response?.requestResults[0]"
:console="previewDetail.response?.console"
:is-http-protocol="previewDetail.protocol === 'HTTP'"
:is-priority-local-exec="props.isPriorityLocalExec"
:request-url="previewDetail.url"
is-definition
@execute="emit('execute', props.isPriorityLocalExec ? 'localExec' : 'serverExec')"
/>
</a-spin>
</a-collapse-item>
</a-collapse>
</template>
@ -330,6 +345,7 @@
import MsFormTable, { FormTableColumn } from '@/components/pure/ms-form-table/index.vue';
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import { ResponseItem } from '@/views/api-test/components/requestComposition/response/edit.vue';
import result from '@/views/api-test/components/requestComposition/response/result.vue';
import { getPluginScript } from '@/api/modules/api-test/common';
import { useI18n } from '@/hooks/useI18n';
@ -343,6 +359,10 @@
isCase?: boolean; // case
detail: RequestParam;
protocols: ProtocolItem[];
isPriorityLocalExec?: boolean;
}>();
const emit = defineEmits<{
(e: 'execute', val: 'localExec' | 'serverExec'): void;
}>();
const { t } = useI18n();

View File

@ -4,7 +4,12 @@
<template #extra>
<div class="flex gap-[12px]">
<environmentSelect v-if="props.isDrawer" ref="environmentSelectRef" />
<execute v-model:detail="caseDetail" :environment-id="environmentId as string" />
<execute
ref="executeRef"
v-model:detail="caseDetail"
:environment-id="environmentId as string"
is-case-detail
/>
<a-dropdown position="br" :hide-on-select="false" @select="handleSelect">
<a-button v-if="!props.isDrawer">{{ t('common.operation') }}</a-button>
<template #content>
@ -45,7 +50,13 @@
<caseLevel :case-level="value as CaseLevel" />
</template>
</MsDetailCard>
<detailTab :detail="caseDetail" :protocols="protocols as ProtocolItem[]" is-case />
<detailTab
:detail="caseDetail"
:protocols="protocols as ProtocolItem[]"
:is-priority-local-exec="isPriorityLocalExec"
is-case
@execute="(val: 'localExec' | 'serverExec')=>executeRef?.execute(val)"
/>
</a-tab-pane>
<a-tab-pane key="reference" :title="t('apiTestManagement.reference')" class="px-[18px] py-[16px]">
<tab-case-dependency :source-id="caseDetail.id" />
@ -213,6 +224,9 @@
props.isDrawer ? currentEnvConfigByDrawer.value?.id : currentEnvConfigByInject?.value?.id
);
const executeRef = ref<InstanceType<typeof execute>>();
const isPriorityLocalExec = computed(() => executeRef.value?.isPriorityLocalExec ?? false);
defineExpose({
editCase,
share,
@ -248,4 +262,7 @@
color: rgb(var(--danger-6));
}
}
:deep(.monaco-editor) {
height: 212px !important;
}
</style>

View File

@ -7,10 +7,10 @@
@select="execute"
>
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
<template v-if="hasLocalExec" #icon>
<template #icon>
<icon-down />
</template>
<template v-if="hasLocalExec" #content>
<template #content>
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
</a-doption>
@ -28,15 +28,17 @@
import { localExecuteApiDebug } from '@/api/modules/api-test/common';
import { debugCase, runCase } from '@/api/modules/api-test/management';
import { getSocket } from '@/api/modules/project-management/commonScript';
import { getLocalConfig } from '@/api/modules/user/index';
import useAppStore from '@/store/modules/app';
import { getGenerateId } from '@/utils';
import { LocalConfig } from '@/models/user';
import { defaultResponse } from '@/views/api-test/components/config';
const props = defineProps<{
environmentId: string;
request?: (...args) => Record<string, any>;
isCaseDetail?: boolean;
}>();
const { t } = useI18n();
@ -46,31 +48,13 @@
required: true,
});
const hasLocalExec = ref(false); // api
const isPriorityLocalExec = ref(false); //
const localExecuteUrl = ref('');
const apiLocalExec = inject<Ref<LocalConfig>>('apiLocalExec');
const isPriorityLocalExec = ref(apiLocalExec?.value.enable || false); //
const localExecuteUrl = ref(apiLocalExec?.value.userUrl || '');
const reportId = ref('');
const websocket = ref<WebSocket>();
const temporaryResponseMap = {}; // websockettab
async function initLocalConfig() {
if (hasLocalExec.value) {
return;
}
try {
const res = await getLocalConfig(); // TODO:
const apiLocalExec = res.find((e) => e.type === 'API');
if (apiLocalExec) {
hasLocalExec.value = true;
isPriorityLocalExec.value = apiLocalExec.enable || false;
localExecuteUrl.value = apiLocalExec.userUrl || '';
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
/**
* 开启websocket监听接收执行结果
*/
@ -85,8 +69,7 @@
if (data.msgType === 'EXEC_RESULT') {
if (caseDetail.value.reportId === data.reportId) {
// tabtab
// TODO:
caseDetail.value.response = data.taskResult; //
caseDetail.value.response = data.taskResult; //
caseDetail.value.executeLoading = false;
} else {
// tab
@ -114,28 +97,28 @@
reportId: reportId.value,
};
debugSocket(executeType); // websocket
if ((caseDetail.value.id as string).startsWith('c')) {
//
res = await debugCase({
request: makeRequestParams?.request,
linkFileIds: makeRequestParams?.linkFileIds,
uploadFileIds: makeRequestParams?.uploadFileIds,
id: `case-${Date.now()}`,
projectId: appStore.currentProjectId,
...params,
});
} else {
if (!(caseDetail.value.id as string).startsWith('c') && executeType === 'serverExec') {
//
res = await runCase({
request: caseDetail.value.request,
request: props.isCaseDetail ? caseDetail.value.request : makeRequestParams?.request,
id: caseDetail.value.id as string,
projectId: caseDetail.value.projectId,
linkFileIds: caseDetail.value.linkFileIds,
uploadFileIds: caseDetail.value.uploadFileIds,
...params,
});
} else {
res = await debugCase({
request: props.isCaseDetail ? caseDetail.value.request : makeRequestParams?.request,
linkFileIds: makeRequestParams?.linkFileIds,
uploadFileIds: makeRequestParams?.uploadFileIds,
id: `case-${Date.now()}`,
projectId: appStore.currentProjectId,
...params,
});
}
if (executeType === 'localExec') {
await localExecuteApiDebug(localExecuteUrl.value, res); // TODO:
await localExecuteApiDebug(localExecuteUrl.value, res);
}
} catch (error) {
// eslint-disable-next-line no-console
@ -149,8 +132,9 @@
caseDetail.value.executeLoading = false;
}
onBeforeMount(() => {
initLocalConfig();
defineExpose({
isPriorityLocalExec,
execute,
});
</script>

View File

@ -70,6 +70,7 @@
// import MockTable from '@/views/api-test/management/components/management/mock/mockTable.vue';
import { getEnvironment, getEnvList, getProtocolList } from '@/api/modules/api-test/common';
import { getLocalConfig } from '@/api/modules/user/index';
import { useI18n } from '@/hooks/useI18n';
import router from '@/router';
import useAppStore from '@/store/modules/app';
@ -77,6 +78,7 @@
import { ProtocolItem } from '@/models/apiTest/common';
import { ModuleTreeNode } from '@/models/common';
import { EnvConfig } from '@/models/projectManagement/environmental';
import { LocalConfig } from '@/models/user';
import {
RequestAuthType,
RequestComposition,
@ -328,15 +330,28 @@
}
}
const apiLocalExec = ref<Record<string, any> | LocalConfig | undefined>({});
async function initLocalConfig() {
try {
const res = await getLocalConfig(); // TODO:
apiLocalExec.value = res.find((e) => e.type === 'API');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
onBeforeMount(() => {
initEnvList();
initProtocolList();
initLocalConfig();
});
/** 向孙组件提供属性 */
provide('currentEnvConfig', readonly(currentEnvConfig));
provide('defaultCaseParams', readonly(defaultCaseParams));
provide('protocols', readonly(protocols));
provide('apiLocalExec', readonly(apiLocalExec));
defineExpose({
newTab,