feat(接口场景): 场景执行优化&部分问题修复
This commit is contained in:
parent
f195c3595b
commit
0be3be4a28
|
@ -149,7 +149,7 @@
|
|||
import { ExecuteAssertionConfig } from '@/models/apiTest/common';
|
||||
import { ResponseAssertionType, ResponseBodyAssertionType } from '@/enums/apiEnum';
|
||||
|
||||
import { ExecuteAssertion, MsAssertionItem } from './type';
|
||||
import { MsAssertionItem } from './type';
|
||||
|
||||
defineOptions({
|
||||
name: 'MsAssertion',
|
||||
|
|
|
@ -247,6 +247,7 @@ export enum ScenarioExecuteStatus {
|
|||
EXECUTING = 'EXECUTING',
|
||||
FAILED = 'FAILED',
|
||||
STOP = 'STOP',
|
||||
UN_EXECUTE = 'UN_EXECUTE',
|
||||
}
|
||||
// 场景步骤类型
|
||||
export enum ScenarioStepType {
|
||||
|
|
|
@ -43,23 +43,6 @@ export interface ApiScenarioGetModuleParams {
|
|||
refId?: string;
|
||||
}
|
||||
|
||||
// 场景修改参数
|
||||
export interface ApiScenarioUpdateDTO {
|
||||
id: string | number;
|
||||
name?: string;
|
||||
priority?: string;
|
||||
status?: ApiScenarioStatus;
|
||||
moduleId?: string | number;
|
||||
description?: string;
|
||||
tags?: string[];
|
||||
grouped?: boolean;
|
||||
environmentId?: string;
|
||||
uploadFileIds?: string[];
|
||||
linkFileIds?: string[];
|
||||
deleteFileIds?: string[];
|
||||
unLinkFileIds?: string[];
|
||||
}
|
||||
|
||||
// 场景详情
|
||||
export interface ApiScenarioTableItem {
|
||||
id: string;
|
||||
|
@ -408,3 +391,19 @@ export interface ApiScenarioDebugRequest {
|
|||
linkFileIds: string[];
|
||||
frontendDebug?: boolean;
|
||||
}
|
||||
|
||||
// 场景修改参数
|
||||
export interface ApiScenarioUpdateDTO extends Partial<Scenario> {
|
||||
id: string | number;
|
||||
name?: string;
|
||||
status?: ApiScenarioStatus;
|
||||
moduleId?: string | number;
|
||||
description?: string;
|
||||
tags?: string[];
|
||||
grouped?: boolean;
|
||||
environmentId?: string;
|
||||
uploadFileIds?: string[];
|
||||
linkFileIds?: string[];
|
||||
deleteFileIds?: string[];
|
||||
unLinkFileIds?: string[];
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@
|
|||
<postcondition
|
||||
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
|
||||
v-model:config="requestVModel.children[0].postProcessorConfig"
|
||||
:response="requestVModel.response?.requestResults[0]?.responseResult.body"
|
||||
:response="props.stepResponses?.[requestVModel.stepId].responseResult.body"
|
||||
:layout="activeLayout"
|
||||
:disabled="!isEditableApi"
|
||||
:second-box-height="secondBoxHeight"
|
||||
|
@ -227,6 +227,7 @@
|
|||
<assertion
|
||||
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
|
||||
v-model:params="requestVModel.children[0].assertionConfig.assertions"
|
||||
:response="props.stepResponses?.[requestVModel.stepId].responseResult.body"
|
||||
is-definition
|
||||
:disabled="!isEditableApi"
|
||||
:assertion-config="requestVModel.children[0].assertionConfig"
|
||||
|
|
|
@ -362,7 +362,7 @@
|
|||
...props.request,
|
||||
response: {
|
||||
requestResults: [props.stepResponses?.[props.request?.stepId] || defaultResponse.requestResults[0]],
|
||||
console: props.stepResponses?.[props.request?.stepId].console || '',
|
||||
console: props.stepResponses?.[props.request?.stepId]?.console || '',
|
||||
},
|
||||
};
|
||||
if (isQuote.value || isCopyNeedInit.value) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MsTag :self-style="status.style" :size="props.size"> {{ status.text }}</MsTag>
|
||||
<MsTag v-if="status" :self-style="status.style" :size="props.size"> {{ status.text }}</MsTag>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -10,7 +10,7 @@
|
|||
import { ScenarioExecuteStatus } from '@/enums/apiEnum';
|
||||
|
||||
const props = defineProps<{
|
||||
status: ScenarioExecuteStatus;
|
||||
status?: ScenarioExecuteStatus;
|
||||
size?: Size;
|
||||
}>();
|
||||
|
||||
|
@ -37,16 +37,23 @@
|
|||
color: 'rgb(var(--success-6))',
|
||||
text: 'common.success',
|
||||
},
|
||||
[ScenarioExecuteStatus.UN_EXECUTE]: {
|
||||
bgColor: 'var(--color-text-4)',
|
||||
color: 'var(--color-text-n9)',
|
||||
text: 'apiScenario.unExecute',
|
||||
},
|
||||
};
|
||||
const status = computed(() => {
|
||||
const config = statusMap[props.status];
|
||||
return {
|
||||
style: {
|
||||
backgroundColor: config?.bgColor,
|
||||
color: config?.color,
|
||||
},
|
||||
text: t(config?.text),
|
||||
};
|
||||
if (props.status) {
|
||||
const config = statusMap[props.status];
|
||||
return {
|
||||
style: {
|
||||
backgroundColor: config?.bgColor,
|
||||
color: config?.color,
|
||||
},
|
||||
text: t(config?.text),
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export const defaultLoopController = {
|
|||
variable: '', // 变量名
|
||||
},
|
||||
msCountController: {
|
||||
loops: 0, // 循环次数
|
||||
loops: 1, // 循环次数
|
||||
loopTime: 0, // 循环间隔时间
|
||||
},
|
||||
whileController: {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
/>
|
||||
<a-tooltip
|
||||
v-if="innerData.loopType === ScenarioStepLoopTypeEnum.LOOP_COUNT"
|
||||
:content="innerData.msCountController.loops.toString()"
|
||||
:content="innerData.msCountController.loops?.toString()"
|
||||
:disabled="!innerData.msCountController.loops"
|
||||
>
|
||||
<a-input-number
|
||||
|
@ -18,7 +18,7 @@
|
|||
class="w-[80px] px-[8px]"
|
||||
size="mini"
|
||||
:step="1"
|
||||
:min="0"
|
||||
:min="1"
|
||||
hide-button
|
||||
:precision="0"
|
||||
model-event="input"
|
||||
|
@ -118,7 +118,10 @@
|
|||
>
|
||||
</a-input>
|
||||
</a-tooltip>
|
||||
<a-tooltip :content="innerData.whileController.timeout.toString()" :disabled="!innerData.whileController.timeout">
|
||||
<a-tooltip
|
||||
:content="innerData.whileController.timeout?.toString()"
|
||||
:disabled="!innerData.whileController.timeout"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:model-value="innerData.whileController.timeout"
|
||||
class="w-[100px] px-[8px]"
|
||||
|
@ -138,7 +141,7 @@
|
|||
</template>
|
||||
<a-tooltip
|
||||
v-if="innerData.loopType !== ScenarioStepLoopTypeEnum.WHILE"
|
||||
:content="innerData.forEachController.loopTime.toString()"
|
||||
:content="innerData.forEachController.loopTime?.toString()"
|
||||
:disabled="!innerData.forEachController.loopTime"
|
||||
>
|
||||
<a-input-number
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="flex items-center gap-[4px]" draggable="false">
|
||||
<a-tooltip :content="innerData.delay.toString()" :disabled="!innerData.delay">
|
||||
<a-tooltip :content="innerData.delay?.toString()" :disabled="!innerData.delay">
|
||||
<a-input-number
|
||||
v-model:model-value="innerData.delay"
|
||||
class="max-w-[500px] px-[8px]"
|
||||
|
|
|
@ -177,13 +177,15 @@
|
|||
</template>
|
||||
<template #extraEnd="step">
|
||||
<a-popover
|
||||
v-if="step.executeStatus && checkStepIsApi(step)"
|
||||
v-if="
|
||||
getExecuteStatus(step) === ScenarioExecuteStatus.SUCCESS ||
|
||||
getExecuteStatus(step) === ScenarioExecuteStatus.FAILED
|
||||
"
|
||||
position="br"
|
||||
content-class="scenario-step-response-popover"
|
||||
:disabled="![ScenarioExecuteStatus.SUCCESS, ScenarioExecuteStatus.FAILED].includes(step.executeStatus)"
|
||||
@popup-visible-change="handleResponsePopoverVisibleChange($event, step)"
|
||||
>
|
||||
<executeStatus :status="getExecuteStatus(step) || step.executeStatus" size="small" />
|
||||
<executeStatus :status="getExecuteStatus(step)" size="small" />
|
||||
<template #content>
|
||||
<responseResult
|
||||
:active-tab="ResponseComposition.BODY"
|
||||
|
@ -204,11 +206,7 @@
|
|||
</responseResult>
|
||||
</template>
|
||||
</a-popover>
|
||||
<executeStatus
|
||||
v-else-if="step.executeStatus"
|
||||
:status="getExecuteStatus(step) || step.executeStatus"
|
||||
size="small"
|
||||
/>
|
||||
<executeStatus v-else-if="step.executeStatus" :status="getExecuteStatus(step)" size="small" />
|
||||
</template>
|
||||
<template v-if="steps.length === 0 && stepKeyword.trim() !== ''" #empty>
|
||||
<div
|
||||
|
@ -793,6 +791,12 @@
|
|||
scenarioConfig: scenario.value.scenarioConfig,
|
||||
frontendDebug: executeType === 'localExec',
|
||||
...executeParams,
|
||||
steps: mapTree(executeParams.steps, (node) => {
|
||||
return {
|
||||
...node,
|
||||
parent: null, // 原树形结构存在循环引用,这里要去掉以免 axios 序列化失败
|
||||
};
|
||||
}),
|
||||
});
|
||||
if (executeType === 'localExec' && localExecuteUrl) {
|
||||
await localExecuteApiDebug(localExecuteUrl, res);
|
||||
|
|
|
@ -223,6 +223,12 @@
|
|||
if (activeScenarioTab.value.isNew) {
|
||||
const res = await addScenario({
|
||||
...activeScenarioTab.value,
|
||||
steps: mapTree(activeScenarioTab.value.steps, (node) => {
|
||||
return {
|
||||
...node,
|
||||
parent: null, // 原树形结构存在循环引用,这里要去掉以免 axios 序列化失败
|
||||
};
|
||||
}),
|
||||
projectId: appStore.currentProjectId,
|
||||
environmentId: currentEnvConfig.value?.id || '',
|
||||
});
|
||||
|
@ -246,6 +252,12 @@
|
|||
await updateScenario({
|
||||
...activeScenarioTab.value,
|
||||
environmentId: currentEnvConfig.value?.id || '',
|
||||
steps: mapTree(activeScenarioTab.value.steps, (node) => {
|
||||
return {
|
||||
...node,
|
||||
parent: null, // 原树形结构存在循环引用,这里要去掉以免 axios 序列化失败
|
||||
};
|
||||
}),
|
||||
});
|
||||
}
|
||||
Message.success(activeScenarioTab.value.isNew ? t('common.createSuccess') : t('common.saveSuccess'));
|
||||
|
@ -394,6 +406,7 @@
|
|||
});
|
||||
}
|
||||
if (executeType === 'localExec' && localExecuteUrl) {
|
||||
// 本地执行需要调 debug 接口获取响应结果,然后再调本地执行接口
|
||||
await localExecuteApiDebug(localExecuteUrl, res);
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
@ -137,6 +137,7 @@ export default {
|
|||
'apiScenario.saveAsApi': '保存为新接口',
|
||||
'apiScenario.scenarioLevel': '场景等级',
|
||||
'apiScenario.running': '执行中',
|
||||
'apiScenario.unExecute': '未执行',
|
||||
'apiScenario.response': '响应内容',
|
||||
// 执行历史
|
||||
'apiScenario.executeHistory.searchPlaceholder': '通过ID或名称搜索',
|
||||
|
|
Loading…
Reference in New Issue