feat(接口测试): 场景脚本断言&响应内容&样式调整
This commit is contained in:
parent
de429a90fb
commit
5c9162f898
|
@ -2,6 +2,7 @@
|
||||||
<div class="ms-detail-card">
|
<div class="ms-detail-card">
|
||||||
<div class="ms-detail-card-title">
|
<div class="ms-detail-card-title">
|
||||||
<div class="flex flex-1 items-center gap-[8px]">
|
<div class="flex flex-1 items-center gap-[8px]">
|
||||||
|
<slot name="titlePrefix"></slot>
|
||||||
<a-tooltip :content="t(props.title)">
|
<a-tooltip :content="t(props.title)">
|
||||||
<div class="one-line-text max-w-[300px] font-medium text-[var(--color-text-1)]">
|
<div class="one-line-text max-w-[300px] font-medium text-[var(--color-text-1)]">
|
||||||
{{ t(props.title) }}
|
{{ t(props.title) }}
|
||||||
|
|
|
@ -233,8 +233,6 @@ export interface ExecuteConditionProcessorCommon {
|
||||||
beforeStepScript: boolean; // 是否是步骤内前置脚本前
|
beforeStepScript: boolean; // 是否是步骤内前置脚本前
|
||||||
assertionType?: RequestConditionProcessor;
|
assertionType?: RequestConditionProcessor;
|
||||||
}
|
}
|
||||||
// 执行请求-前后置操作-脚本处理器
|
|
||||||
export type ScriptProcessor = ScriptCommonConfig & ExecuteConditionProcessorCommon;
|
|
||||||
// 执行请求-前后置操作-SQL脚本处理器
|
// 执行请求-前后置操作-SQL脚本处理器
|
||||||
export interface SQLProcessor extends ExecuteConditionProcessorCommon {
|
export interface SQLProcessor extends ExecuteConditionProcessorCommon {
|
||||||
name: string; // 描述
|
name: string; // 描述
|
||||||
|
@ -278,16 +276,6 @@ export interface XPathExtract extends ExpressionCommonConfig {
|
||||||
export interface ExtractProcessor extends ExecuteConditionProcessorCommon {
|
export interface ExtractProcessor extends ExecuteConditionProcessorCommon {
|
||||||
extractors: (RegexExtract | JSONPathExtract | XPathExtract)[];
|
extractors: (RegexExtract | JSONPathExtract | XPathExtract)[];
|
||||||
}
|
}
|
||||||
// 执行请求-前后置操作配置
|
|
||||||
export type ExecuteConditionProcessor = Partial<
|
|
||||||
ScriptProcessor & SQLProcessor & TimeWaitingProcessor & ExtractProcessor
|
|
||||||
> &
|
|
||||||
ExecuteConditionProcessorCommon;
|
|
||||||
export interface ExecuteConditionConfig {
|
|
||||||
enableGlobal?: boolean; // 是否启用全局前/后置 默认为 true
|
|
||||||
processors: ExecuteConditionProcessor[];
|
|
||||||
activeItemId?: number;
|
|
||||||
}
|
|
||||||
// 执行请求-断言配置子项
|
// 执行请求-断言配置子项
|
||||||
export type ExecuteAssertionItem = ResponseAssertionCommon &
|
export type ExecuteAssertionItem = ResponseAssertionCommon &
|
||||||
ResponseCodeAssertion &
|
ResponseCodeAssertion &
|
||||||
|
@ -301,6 +289,24 @@ export interface ExecuteAssertionConfig {
|
||||||
enableGlobal?: boolean; // 是否启用全局断言,部分地方没有
|
enableGlobal?: boolean; // 是否启用全局断言,部分地方没有
|
||||||
assertions: ExecuteAssertionItem[];
|
assertions: ExecuteAssertionItem[];
|
||||||
}
|
}
|
||||||
|
// 执行请求-前后置操作-脚本处理器
|
||||||
|
export interface ScriptProcessorChild {
|
||||||
|
polymorphicName: string; // 协议多态名称,写死MsCommonElement
|
||||||
|
assertionConfig: ExecuteAssertionConfig;
|
||||||
|
}
|
||||||
|
export interface ScriptProcessor extends ScriptCommonConfig, ExecuteConditionProcessorCommon {
|
||||||
|
children: ScriptProcessorChild[]; // 协议共有的子项配置
|
||||||
|
}
|
||||||
|
// 执行请求-前后置操作配置
|
||||||
|
export type ExecuteConditionProcessor = Partial<
|
||||||
|
ScriptProcessor & SQLProcessor & TimeWaitingProcessor & ExtractProcessor
|
||||||
|
> &
|
||||||
|
ExecuteConditionProcessorCommon;
|
||||||
|
export interface ExecuteConditionConfig {
|
||||||
|
enableGlobal?: boolean; // 是否启用全局前/后置 默认为 true
|
||||||
|
processors: ExecuteConditionProcessor[];
|
||||||
|
activeItemId?: number;
|
||||||
|
}
|
||||||
// 执行请求-共用配置子项
|
// 执行请求-共用配置子项
|
||||||
export interface ExecuteCommonChild {
|
export interface ExecuteCommonChild {
|
||||||
polymorphicName: string; // 协议多态名称,写死MsCommonElement
|
polymorphicName: string; // 协议多态名称,写死MsCommonElement
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="ms-params-popover-title">
|
<div class="ms-params-popover-title">
|
||||||
{{ t('apiTestDebug.paramName') }}
|
{{ t(columnConfig.title as string) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-params-popover-value">
|
<div class="ms-params-popover-value">
|
||||||
{{ record[columnConfig.dataIndex as string] }}
|
{{ record[columnConfig.dataIndex as string] }}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="props.requestResult?.responseResult?.responseCode"
|
v-if="props.requestResult?.responseResult?.responseCode"
|
||||||
class="flex items-center justify-between gap-[24px] text-[14px]"
|
class="flex items-center justify-between gap-[16px] text-[14px]"
|
||||||
>
|
>
|
||||||
<a-tooltip :content="props.requestResult.fakeErrorCode" :disabled="!props.requestResult.fakeErrorCode">
|
<a-tooltip :content="props.requestResult.fakeErrorCode" :disabled="!props.requestResult.fakeErrorCode">
|
||||||
<executeStatus :status="finalStatus" size="small" class="ml-[4px]" />
|
<executeStatus :status="finalStatus" size="small" class="ml-[4px]" />
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-show="props.requestResult?.responseResult.responseCode" class="h-full">
|
<div v-show="props.requestResult?.responseResult.responseCode" class="h-full">
|
||||||
<a-tabs v-model:active-key="activeTab" class="no-content border-b border-[var(--color-text-n8)]">
|
<div class="flex items-center" :class="$slots.tabRight ? 'border-b border-[var(--color-text-n8)]' : ''">
|
||||||
<a-tab-pane v-for="item of responseCompositionTabList" :key="item.value" :title="item.label" />
|
<a-tabs v-model:active-key="activeTab" class="no-content flex-1">
|
||||||
</a-tabs>
|
<a-tab-pane v-for="item of responseCompositionTabList" :key="item.value" :title="item.label" />
|
||||||
|
</a-tabs>
|
||||||
|
<slot name="tabRight"></slot>
|
||||||
|
</div>
|
||||||
<div class="response-container">
|
<div class="response-container">
|
||||||
<ResBody
|
<ResBody
|
||||||
v-if="activeTab === ResponseComposition.BODY"
|
v-if="activeTab === ResponseComposition.BODY"
|
||||||
|
@ -138,7 +141,7 @@
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.response-container {
|
.response-container {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
height: calc(100% - 48px);
|
height: calc(100% - 58px);
|
||||||
}
|
}
|
||||||
:deep(.arco-table-th) {
|
:deep(.arco-table-th) {
|
||||||
background-color: var(--color-text-n9);
|
background-color: var(--color-text-n9);
|
||||||
|
|
|
@ -360,7 +360,6 @@
|
||||||
import { TabErrorMessage } from '@/views/api-test/components/requestComposition/index.vue';
|
import { TabErrorMessage } from '@/views/api-test/components/requestComposition/index.vue';
|
||||||
import postcondition from '@/views/api-test/components/requestComposition/postcondition.vue';
|
import postcondition from '@/views/api-test/components/requestComposition/postcondition.vue';
|
||||||
import precondition from '@/views/api-test/components/requestComposition/precondition.vue';
|
import precondition from '@/views/api-test/components/requestComposition/precondition.vue';
|
||||||
import response from '@/views/api-test/components/requestComposition/response/index.vue';
|
|
||||||
import setting from '@/views/api-test/components/requestComposition/setting.vue';
|
import setting from '@/views/api-test/components/requestComposition/setting.vue';
|
||||||
|
|
||||||
import { getPluginScript, getProtocolList } from '@/api/modules/api-test/common';
|
import { getPluginScript, getProtocolList } from '@/api/modules/api-test/common';
|
||||||
|
@ -416,6 +415,9 @@
|
||||||
const httpBody = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/body.vue'));
|
const httpBody = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/body.vue'));
|
||||||
const httpQuery = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/query.vue'));
|
const httpQuery = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/query.vue'));
|
||||||
const httpRest = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/rest.vue'));
|
const httpRest = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/rest.vue'));
|
||||||
|
const response = defineAsyncComponent(
|
||||||
|
() => import('@/views/api-test/components/requestComposition/response/index.vue')
|
||||||
|
);
|
||||||
// const addDependencyDrawer = defineAsyncComponent(
|
// const addDependencyDrawer = defineAsyncComponent(
|
||||||
// () => import('@/views/api-test/management/components/addDependencyDrawer.vue')
|
// () => import('@/views/api-test/management/components/addDependencyDrawer.vue')
|
||||||
// );
|
// );
|
||||||
|
|
|
@ -21,31 +21,17 @@
|
||||||
<div class="flex h-full flex-col">
|
<div class="flex h-full flex-col">
|
||||||
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
||||||
<div class="flex-1 overflow-y-hidden">
|
<div class="flex-1 overflow-y-hidden">
|
||||||
<div v-if="step.stepType === ScenarioStepType.SCRIPT" class="flex h-full flex-col p-[8px]">
|
<div class="response-result">
|
||||||
<div class="mb-[8px] flex gap-[8px] text-[14px] font-medium text-[var(--color-text-1)]">
|
|
||||||
{{ t('apiScenario.executionResult') }}
|
|
||||||
<div class="one-line-text text-[var(--color-text-4)]">({{ step.name }})</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 bg-[var(--color-text-n9)] p-[12px]">
|
|
||||||
<pre class="response-header-pre">{{ currentResponse?.console }}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="response-result">
|
|
||||||
<responseResult
|
<responseResult
|
||||||
:active-tab="ResponseComposition.BODY"
|
:active-tab="ResponseComposition.BODY"
|
||||||
:request-result="currentResponse"
|
:request-result="currentResponse"
|
||||||
:console="currentResponse?.console"
|
:console="currentResponse?.console"
|
||||||
:show-empty="false"
|
:show-empty="false"
|
||||||
:is-edit="false"
|
:is-priority-local-exec="false"
|
||||||
is-definition
|
is-definition
|
||||||
>
|
>
|
||||||
<template #titleLeft>
|
<template #tabRight>
|
||||||
<div class="flex items-center text-[14px]">
|
<responseCodeTimeSize :request-result="currentResponse" />
|
||||||
<div class="font-medium text-[var(--color-text-1)]">{{ t('apiScenario.response') }}</div>
|
|
||||||
<a-tooltip :content="props.step.name">
|
|
||||||
<div class="one-line-text">({{ props.step.name }})</div>
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</responseResult>
|
</responseResult>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,8 +52,6 @@
|
||||||
import executeStatus from './executeStatus.vue';
|
import executeStatus from './executeStatus.vue';
|
||||||
import loopPagination from './loopPagination.vue';
|
import loopPagination from './loopPagination.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
|
|
||||||
import { RequestResult } from '@/models/apiTest/common';
|
import { RequestResult } from '@/models/apiTest/common';
|
||||||
import { ScenarioStepItem } from '@/models/apiTest/scenario';
|
import { ScenarioStepItem } from '@/models/apiTest/scenario';
|
||||||
import {
|
import {
|
||||||
|
@ -78,7 +62,10 @@
|
||||||
} from '@/enums/apiEnum';
|
} from '@/enums/apiEnum';
|
||||||
|
|
||||||
const responseResult = defineAsyncComponent(
|
const responseResult = defineAsyncComponent(
|
||||||
() => import('@/views/api-test/components/requestComposition/response/index.vue')
|
() => import('@/views/api-test/components/requestComposition/response/result.vue')
|
||||||
|
);
|
||||||
|
const responseCodeTimeSize = defineAsyncComponent(
|
||||||
|
() => import('@/views/api-test/components/requestComposition/response/responseCodeTimeSize.vue')
|
||||||
);
|
);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -88,8 +75,6 @@
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits(['visibleChange']);
|
const emit = defineEmits(['visibleChange']);
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const currentLoop = ref(1);
|
const currentLoop = ref(1);
|
||||||
const currentResponse = computed(() => props.stepResponses?.[props.step.uniqueId]?.[currentLoop.value - 1]);
|
const currentResponse = computed(() => props.stepResponses?.[props.step.uniqueId]?.[currentLoop.value - 1]);
|
||||||
const loopTotal = computed(() => props.stepResponses?.[props.step.uniqueId]?.length || 0);
|
const loopTotal = computed(() => props.stepResponses?.[props.step.uniqueId]?.length || 0);
|
||||||
|
@ -119,10 +104,11 @@
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.scenario-step-response-popover {
|
.scenario-step-response-popover {
|
||||||
width: 540px;
|
padding: 8px 16px;
|
||||||
height: 500px;
|
width: 640px;
|
||||||
|
height: 440px;
|
||||||
.arco-popover-content {
|
.arco-popover-content {
|
||||||
@apply h-full;
|
@apply mt-0 h-full;
|
||||||
.response-header-pre {
|
.response-header-pre {
|
||||||
@apply h-full overflow-auto bg-white;
|
@apply h-full overflow-auto bg-white;
|
||||||
.ms-scroll-bar();
|
.ms-scroll-bar();
|
||||||
|
@ -133,6 +119,9 @@
|
||||||
.response-result {
|
.response-result {
|
||||||
@apply h-full overflow-auto bg-white;
|
@apply h-full overflow-auto bg-white;
|
||||||
.ms-scroll-bar();
|
.ms-scroll-bar();
|
||||||
|
.arco-tabs-tab:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
.response {
|
.response {
|
||||||
.response-head {
|
.response-head {
|
||||||
background-color: var(--color-text-n9);
|
background-color: var(--color-text-n9);
|
||||||
|
|
|
@ -10,36 +10,71 @@
|
||||||
@cancel="handleDrawerCancel"
|
@cancel="handleDrawerCancel"
|
||||||
>
|
>
|
||||||
<div class="scenario-script-drawer-content">
|
<div class="scenario-script-drawer-content">
|
||||||
<div class="ml-[16px] mt-[10px]">
|
<MsTab
|
||||||
<!-- <stepTypeVue v-if="props.step" :step="props.step" /> -->
|
v-model:active-key="activeTab"
|
||||||
{{ t('apiScenario.scriptOperationName') }}
|
:content-tab-list="contentTabList"
|
||||||
</div>
|
:get-text-func="() => ''"
|
||||||
<div class="ml-[16px] mt-[3px] max-w-[70%]">
|
class="sticky-content no-content relative top-0 border-b px-[16px]"
|
||||||
<a-input
|
/>
|
||||||
v-model="scriptName"
|
<template v-if="activeTab === 'script'">
|
||||||
:placeholder="t('apiScenario.scriptOperationNamePlaceholder')"
|
<div class="ml-[16px] mt-[10px]">
|
||||||
:max-length="255"
|
<!-- <stepTypeVue v-if="props.step" :step="props.step" /> -->
|
||||||
:disabled="isReadonly"
|
{{ t('apiScenario.scriptOperationName') }}
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="mt-[10px] flex flex-1 gap-[8px]">
|
|
||||||
<conditionContent
|
|
||||||
v-if="visible"
|
|
||||||
v-model:data="activeItem"
|
|
||||||
condition-type="scenario"
|
|
||||||
:disabled="isReadonly"
|
|
||||||
:is-build-in="true"
|
|
||||||
script-code-editor-height="100%"
|
|
||||||
@change="unSaved = true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="currentResponse?.console" class="p-[8px]">
|
|
||||||
<div class="mb-[8px] font-medium text-[var(--color-text-1)]">{{ t('apiScenario.executionResult') }}</div>
|
|
||||||
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
|
||||||
<div class="h-[300px] bg-[var(--color-text-n9)] p-[12px]">
|
|
||||||
<pre class="response-header-pre">{{ currentResponse?.console }}</pre>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="ml-[16px] mt-[3px] max-w-[70%]">
|
||||||
|
<a-input
|
||||||
|
v-model="scriptName"
|
||||||
|
:placeholder="t('apiScenario.scriptOperationNamePlaceholder')"
|
||||||
|
:max-length="255"
|
||||||
|
:disabled="isReadonly"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mt-[10px] flex flex-1 gap-[8px]">
|
||||||
|
<conditionContent
|
||||||
|
v-if="visible"
|
||||||
|
v-model:data="scriptVModel"
|
||||||
|
condition-type="scenario"
|
||||||
|
:disabled="isReadonly"
|
||||||
|
:is-build-in="true"
|
||||||
|
script-code-editor-height="100%"
|
||||||
|
@change="unSaved = true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- <div v-if="currentResponse?.console" class="p-[8px]">
|
||||||
|
<div class="mb-[8px] font-medium text-[var(--color-text-1)]">{{ t('apiScenario.executionResult') }}</div>
|
||||||
|
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
||||||
|
<div class="h-[300px] bg-[var(--color-text-n9)] p-[12px]">
|
||||||
|
<pre class="response-header-pre">{{ currentResponse?.console }}</pre>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</template>
|
||||||
|
<div v-else-if="scriptVModel.children" class="p-[16px]">
|
||||||
|
<assertion
|
||||||
|
v-model:params="scriptVModel.children[0].assertionConfig.assertions"
|
||||||
|
is-definition
|
||||||
|
:disabled="isReadonly"
|
||||||
|
:assertion-config="scriptVModel.children[0].assertionConfig"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<response
|
||||||
|
v-if="visible && currentResponse && currentResponse.responseResult.responseCode"
|
||||||
|
ref="responseRef"
|
||||||
|
v-model:active-layout="activeLayout"
|
||||||
|
v-model:active-tab="responseActiveTab"
|
||||||
|
class="response"
|
||||||
|
:is-http-protocol="false"
|
||||||
|
:is-priority-local-exec="isPriorityLocalExec"
|
||||||
|
request-url=""
|
||||||
|
:is-expanded="isVerticalExpanded"
|
||||||
|
:request-result="currentResponse"
|
||||||
|
:console="currentResponse?.console"
|
||||||
|
:is-edit="false"
|
||||||
|
hide-layout-switch
|
||||||
|
>
|
||||||
|
<template #titleRight>
|
||||||
|
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
||||||
|
</template>
|
||||||
|
</response>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!props.detail" #footer>
|
<template v-if="!props.detail" #footer>
|
||||||
<a-button type="secondary" @click="handleDrawerCancel">
|
<a-button type="secondary" @click="handleDrawerCancel">
|
||||||
|
@ -60,6 +95,8 @@
|
||||||
|
|
||||||
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
|
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
import MsTab from '@/components/pure/ms-tab/index.vue';
|
||||||
|
import assertion from '@/components/business/ms-assertion/index.vue';
|
||||||
import loopPagination from './loopPagination.vue';
|
import loopPagination from './loopPagination.vue';
|
||||||
|
|
||||||
// import stepTypeVue from './stepType/stepType.vue';
|
// import stepTypeVue from './stepType/stepType.vue';
|
||||||
|
@ -67,9 +104,12 @@
|
||||||
|
|
||||||
import { ExecuteConditionProcessor, RequestResult } from '@/models/apiTest/common';
|
import { ExecuteConditionProcessor, RequestResult } from '@/models/apiTest/common';
|
||||||
import { ScenarioStepItem } from '@/models/apiTest/scenario';
|
import { ScenarioStepItem } from '@/models/apiTest/scenario';
|
||||||
import { RequestConditionProcessor } from '@/enums/apiEnum';
|
import { RequestConditionProcessor, ResponseComposition } from '@/enums/apiEnum';
|
||||||
|
|
||||||
const conditionContent = defineAsyncComponent(() => import('@/views/api-test/components/condition/content.vue'));
|
const conditionContent = defineAsyncComponent(() => import('@/views/api-test/components/condition/content.vue'));
|
||||||
|
const response = defineAsyncComponent(
|
||||||
|
() => import('@/views/api-test/components/requestComposition/response/index.vue')
|
||||||
|
);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
detail?: ExecuteConditionProcessor;
|
detail?: ExecuteConditionProcessor;
|
||||||
|
@ -89,9 +129,17 @@
|
||||||
scriptLanguage: LanguageEnum.BEANSHELL_JSR233,
|
scriptLanguage: LanguageEnum.BEANSHELL_JSR233,
|
||||||
commonScriptInfo: {},
|
commonScriptInfo: {},
|
||||||
polymorphicName: 'MsScriptElement',
|
polymorphicName: 'MsScriptElement',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
polymorphicName: 'MsCommonElement',
|
||||||
|
assertionConfig: {
|
||||||
|
assertions: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
} as unknown as ExecuteConditionProcessor;
|
} as unknown as ExecuteConditionProcessor;
|
||||||
const scriptName = ref('');
|
const scriptName = ref('');
|
||||||
const activeItem = ref<ExecuteConditionProcessor>(cloneDeep(defaultScript));
|
const scriptVModel = ref<ExecuteConditionProcessor>(cloneDeep(defaultScript));
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -105,13 +153,17 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const loopTotal = computed(() => (props.step?.uniqueId && props.stepResponses?.[props.step?.uniqueId]?.length) || 0);
|
const loopTotal = computed(() => (props.step?.uniqueId && props.stepResponses?.[props.step?.uniqueId]?.length) || 0);
|
||||||
|
const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
|
||||||
|
const responseActiveTab = ref<ResponseComposition>(ResponseComposition.BODY);
|
||||||
|
const isPriorityLocalExec = inject<Ref<boolean>>('isPriorityLocalExec');
|
||||||
|
const isVerticalExpanded = computed(() => activeLayout.value === 'vertical');
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => visible.value,
|
() => visible.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
scriptName.value = props.detail ? props.name || '' : '';
|
scriptName.value = props.detail ? props.name || '' : '';
|
||||||
activeItem.value = cloneDeep(
|
scriptVModel.value = cloneDeep(
|
||||||
props.detail
|
props.detail
|
||||||
? {
|
? {
|
||||||
...props.detail,
|
...props.detail,
|
||||||
|
@ -124,25 +176,38 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const activeTab = ref<'script' | 'assertion'>('script');
|
||||||
|
const contentTabList = [
|
||||||
|
{
|
||||||
|
value: 'script',
|
||||||
|
label: t('apiTestManagement.script'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'assertion',
|
||||||
|
label: t('apiTestDebug.assertion'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
function handleDrawerCancel() {
|
function handleDrawerCancel() {
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAndContinue() {
|
function saveAndContinue() {
|
||||||
emit('add', scriptName.value, activeItem.value);
|
emit('add', scriptName.value, scriptVModel.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
emit('add', scriptName.value, activeItem.value);
|
emit('add', scriptName.value, scriptVModel.value);
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
if (props.detail) {
|
if (props.detail) {
|
||||||
emit('save', scriptName.value, activeItem.value, unSaved.value);
|
emit('save', scriptName.value, scriptVModel.value, unSaved.value);
|
||||||
}
|
}
|
||||||
scriptName.value = '';
|
scriptName.value = '';
|
||||||
activeItem.value = defaultScript as unknown as ExecuteConditionProcessor;
|
scriptVModel.value = defaultScript as unknown as ExecuteConditionProcessor;
|
||||||
|
activeTab.value = 'script';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -156,6 +221,9 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
:deep(.arco-tabs-tab:first-child) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
.response-header-pre {
|
.response-header-pre {
|
||||||
@apply h-full overflow-auto bg-white;
|
@apply h-full overflow-auto bg-white;
|
||||||
.ms-scroll-bar();
|
.ms-scroll-bar();
|
||||||
|
@ -163,4 +231,9 @@
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-radius: var(--border-radius-small);
|
border-radius: var(--border-radius-small);
|
||||||
}
|
}
|
||||||
|
.sticky-content {
|
||||||
|
@apply sticky overflow-visible bg-white;
|
||||||
|
|
||||||
|
z-index: 101;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -48,8 +48,9 @@
|
||||||
<template v-if="scenario.executeTime">
|
<template v-if="scenario.executeTime">
|
||||||
<div class="action-group">
|
<div class="action-group">
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('apiScenario.executeTime') }}</div>
|
<div class="text-[var(--color-text-4)]">{{ t('apiScenario.executeTime') }}</div>
|
||||||
<div class="text-[var(--color-text-4)]">{{ scenario.executeTime }}</div>
|
<div class="text-[var(--color-text-1)]">{{ scenario.executeTime }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a-divider direction="vertical" :margin="8"></a-divider>
|
||||||
<div class="action-group">
|
<div class="action-group">
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('apiScenario.executeResult') }}</div>
|
<div class="text-[var(--color-text-4)]">{{ t('apiScenario.executeResult') }}</div>
|
||||||
<div class="flex items-center gap-[4px]">
|
<div class="flex items-center gap-[4px]">
|
||||||
|
@ -67,8 +68,10 @@
|
||||||
<MsButton
|
<MsButton
|
||||||
v-if="scenario.isDebug === false && !scenario.executeLoading && !scenario.isNew"
|
v-if="scenario.isDebug === false && !scenario.executeLoading && !scenario.isNew"
|
||||||
type="text"
|
type="text"
|
||||||
|
class="ml-[8px]"
|
||||||
@click="checkReport"
|
@click="checkReport"
|
||||||
>
|
>
|
||||||
|
<icon-eye class="mr-[4px] text-[rgb(var(--primary-5))]" />
|
||||||
{{ t('apiScenario.checkReport') }}
|
{{ t('apiScenario.checkReport') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
<div class="h-full w-full overflow-hidden">
|
<div class="h-full w-full overflow-hidden">
|
||||||
<div class="px-[24px] pt-[16px]">
|
<div class="px-[24px] pt-[16px]">
|
||||||
<MsDetailCard :title="`【${scenario.num}】${scenario.name}`" :description="description" class="!py-[8px]">
|
<MsDetailCard :title="`【${scenario.num}】${scenario.name}`" :description="description" class="!py-[8px]">
|
||||||
|
<template #titlePrefix>
|
||||||
|
<apiStatus :status="scenario.status" size="small" />
|
||||||
|
<caseLevel :case-level="scenario.priority as CaseLevel" />
|
||||||
|
</template>
|
||||||
<template #titleAppend>
|
<template #titleAppend>
|
||||||
<a-tooltip :content="t(scenario.follow ? 'common.forked' : 'common.notForked')">
|
<a-tooltip :content="t(scenario.follow ? 'common.forked' : 'common.notForked')">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
|
@ -21,10 +25,6 @@
|
||||||
@click="share"
|
@click="share"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<apiStatus :status="scenario.status" size="small" />
|
|
||||||
</template>
|
|
||||||
<template #priority="{ value }">
|
|
||||||
<caseLevel :case-level="value as CaseLevel" />
|
|
||||||
</template>
|
</template>
|
||||||
</MsDetailCard>
|
</MsDetailCard>
|
||||||
</div>
|
</div>
|
||||||
|
@ -190,11 +190,6 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const description = computed(() => [
|
const description = computed(() => [
|
||||||
{
|
|
||||||
key: 'priority',
|
|
||||||
locale: 'apiScenario.scenarioLevel',
|
|
||||||
value: scenario.value.priority,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'tag',
|
key: 'tag',
|
||||||
locale: 'common.tag',
|
locale: 'common.tag',
|
||||||
|
|
Loading…
Reference in New Issue