fix(全局): bug修复
This commit is contained in:
parent
5b60c332db
commit
1a13f39a96
|
@ -124,7 +124,7 @@
|
|||
:selectable="true"
|
||||
:columns="xPathColumns"
|
||||
:scroll="{ minWidth: '700px' }"
|
||||
:default-param-item="xPathDefaultParamItem"
|
||||
:default-param-item="defaultAssertParamsItem"
|
||||
@change="(data:any[],isInit?: boolean) => handleChange(data, ResponseBodyAssertionType.XPATH,isInit)"
|
||||
@more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)"
|
||||
>
|
||||
|
@ -363,7 +363,7 @@
|
|||
import { TableColumnData, TableData } from '@arco-design/web-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
import { EQUAL, statusCodeOptions } from '@/components/pure/ms-advance-filter';
|
||||
import { statusCodeOptions } from '@/components/pure/ms-advance-filter';
|
||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||
import { TableOperationColumn } from '@/components/business/ms-user-group-comp/authTable.vue';
|
||||
import fastExtraction from '@/views/api-test/components/fastExtraction/index.vue';
|
||||
|
@ -387,15 +387,14 @@
|
|||
RegexExtract,
|
||||
XPathExtract,
|
||||
} from '@/models/apiTest/common';
|
||||
import { RequestExtractExpressionEnum, ResponseBodyAssertionType } from '@/enums/apiEnum';
|
||||
|
||||
import {
|
||||
RequestExtractEnvType,
|
||||
RequestExtractExpressionEnum,
|
||||
RequestExtractExpressionRuleType,
|
||||
RequestExtractResultMatchingRule,
|
||||
RequestExtractScope,
|
||||
ResponseBodyAssertionType,
|
||||
ResponseBodyXPathAssertionFormat,
|
||||
} from '@/enums/apiEnum';
|
||||
defaultAssertParamsItem,
|
||||
defaultExtractParamItem,
|
||||
jsonPathDefaultParamItem,
|
||||
regexDefaultParamItem,
|
||||
} from '@/views/api-test/components/config';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -445,20 +444,6 @@
|
|||
// const disabledExpressionSuffix = ref(false);
|
||||
export type ExpressionConfig = (RegexExtract | JSONPathExtract | XPathExtract) & Record<string, any>;
|
||||
|
||||
const defaultExtractParamItem: ExpressionConfig = {
|
||||
enable: true,
|
||||
variableName: '',
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
expression: '',
|
||||
extractType: RequestExtractExpressionEnum.JSON_PATH,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
|
||||
const activeRecord = ref({ ...defaultExtractParamItem }); // 用于暂存当前操作的提取参数表格项
|
||||
|
||||
const responseRadios = [
|
||||
|
@ -506,50 +491,6 @@
|
|||
},
|
||||
];
|
||||
|
||||
// json默认值
|
||||
const jsonPathDefaultParamItem = {
|
||||
enable: true,
|
||||
variableName: '',
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
expression: '',
|
||||
condition: EQUAL.value,
|
||||
extractType: RequestExtractExpressionEnum.JSON_PATH,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
// xpath默认值
|
||||
const xPathDefaultParamItem = {
|
||||
expression: '',
|
||||
enable: true,
|
||||
valid: true,
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
extractType: RequestExtractExpressionEnum.X_PATH,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
// xpath默认值
|
||||
const regexDefaultParamItem = {
|
||||
expression: '',
|
||||
enable: true,
|
||||
valid: true,
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
extractType: RequestExtractExpressionEnum.REGEX,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
|
||||
const handleChange = (data: any[], type: string, isInit?: boolean) => {
|
||||
switch (type) {
|
||||
case ResponseBodyAssertionType.JSON_PATH:
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
</div>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption v-for="item in assertOptionSource" :key="item.value" :value="item.value">{{
|
||||
item.label
|
||||
}}</a-doption>
|
||||
<a-doption v-for="item in assertOptionSource" :key="item.value" :value="item.value">
|
||||
{{ item.label }}
|
||||
</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<div v-if="props.isDefinition && innerConfig" class="flex items-center">
|
||||
|
|
|
@ -115,15 +115,26 @@
|
|||
/**
|
||||
* 替换文档
|
||||
* @param beautifyDoc 格式化后的文档
|
||||
* @param isHtml 是否是html
|
||||
*/
|
||||
function replaceDoc(beautifyDoc: string) {
|
||||
// 先将 HTML 字符串格式化,然后解析转换并给每个开始标签加上复制 icon
|
||||
flattenedXml.value = beautifyDoc
|
||||
function replaceDoc(beautifyDoc: string, isHtml = false) {
|
||||
// 先将 XML/HTML 字符串格式化,然后解析转换并给每个开始标签加上复制 icon
|
||||
let resultArr: XpathNode[] = [];
|
||||
const tempStr = beautifyDoc
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/(<([^/][^&]*?)>)/g, '<span style="color: rgb(var(--primary-5));cursor: pointer">$1📋</span>')
|
||||
.split(/\r?\n/)
|
||||
.map((e) => ({ content: e, xpath: '' }));
|
||||
.replace(/(<([^/][^&]*?)>)/g, '<span style="color: rgb(var(--primary-5));cursor: pointer">$1📋</span>');
|
||||
if (isHtml) {
|
||||
resultArr = HtmlBeautify(
|
||||
tempStr.replace(/(\S)(?=<)/gs, '$1\n'), // html 标签换行
|
||||
{ ocd: true }
|
||||
)
|
||||
.split(/\r?\n/)
|
||||
.map((e) => ({ content: e, xpath: '' }));
|
||||
} else {
|
||||
resultArr = tempStr.split(/\r?\n/).map((e) => ({ content: e, xpath: '' }));
|
||||
}
|
||||
flattenedXml.value = resultArr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -142,8 +153,9 @@
|
|||
isValidXml.value = true;
|
||||
parsedXml.value = xmlDoc;
|
||||
const beautifyDoc = HtmlBeautify(props.xmlString, { ocd: true });
|
||||
replaceDoc(beautifyDoc);
|
||||
replaceDoc(beautifyDoc, true);
|
||||
// 解析真实 HTML 并将其扁平化,得到每个节点的 xpath
|
||||
tempXmls.value = [];
|
||||
flattenHtml(xmlDoc.documentElement, '');
|
||||
// 将扁平化后的 XML/HTML 字符串中的每个节点的 xpath 替换为真实的 xpath
|
||||
flattenedXml.value = flattenedXml.value
|
||||
|
@ -157,7 +169,7 @@
|
|||
xpath,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
return e.content.includes('</') ? e : false;
|
||||
})
|
||||
.filter(Boolean) as any[];
|
||||
emit('init', 'html');
|
||||
|
@ -185,20 +197,23 @@
|
|||
const beautifyDoc = new XmlBeautify().beautify(props.xmlString);
|
||||
replaceDoc(beautifyDoc);
|
||||
// 解析真实 XML 并将其扁平化,得到每个节点的 xpath
|
||||
tempXmls.value = [];
|
||||
flattenXml(xmlDoc.documentElement, '');
|
||||
// 将扁平化后的 XML 字符串中的每个节点的 xpath 替换为真实的 xpath
|
||||
flattenedXml.value = flattenedXml.value.map((e) => {
|
||||
const targetNodeIndex = tempXmls.value.findIndex((txt) => e.content.includes(`<${txt.content}`));
|
||||
if (targetNodeIndex >= 0) {
|
||||
const { xpath } = tempXmls.value[targetNodeIndex];
|
||||
tempXmls.value.splice(targetNodeIndex, 1); // 匹配成功后,将匹配到的节点从 tempXmls 中删除,避免重复匹配
|
||||
return {
|
||||
...e,
|
||||
xpath,
|
||||
};
|
||||
}
|
||||
return e;
|
||||
});
|
||||
flattenedXml.value = flattenedXml.value
|
||||
.map((e) => {
|
||||
const targetNodeIndex = tempXmls.value.findIndex((txt) => e.content.includes(`<${txt.content}`));
|
||||
if (targetNodeIndex >= 0) {
|
||||
const { xpath } = tempXmls.value[targetNodeIndex];
|
||||
tempXmls.value.splice(targetNodeIndex, 1); // 匹配成功后,将匹配到的节点从 tempXmls 中删除,避免重复匹配
|
||||
return {
|
||||
...e,
|
||||
xpath,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.filter(Boolean) as any[];
|
||||
emit('init', 'xml');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -78,6 +78,8 @@ export interface ApiScenarioTableItem {
|
|||
deleteUser: string;
|
||||
deleteTime: number;
|
||||
deleted: boolean;
|
||||
environmentId: string;
|
||||
environmentName: string;
|
||||
createUserName: string;
|
||||
updateUserName: string;
|
||||
deleteUserName: string;
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
</div>
|
||||
<template v-if="condition.dataSourceId">
|
||||
<div class="mb-[8px] text-[var(--color-text-1)]">{{ t('apiTestDebug.sqlScript') }}</div>
|
||||
<div class="mb-[8px] h-[300px]">
|
||||
<div class="mb-[8px]">
|
||||
<MsCodeEditor
|
||||
v-model:model-value="condition.script"
|
||||
:read-only="props.disabled"
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
<template>
|
||||
<div class="mb-[8px] flex items-center justify-between">
|
||||
<a-dropdown @select="(val) => addCondition(val as ConditionType)">
|
||||
<a-button type="outline" :disabled="props.disabled">
|
||||
<template #icon>
|
||||
<icon-plus :size="14" />
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<a-dropdown @select="(val) => addCondition(val as ConditionType)">
|
||||
<a-button type="outline" :disabled="props.disabled">
|
||||
<template #icon>
|
||||
<icon-plus :size="14" />
|
||||
</template>
|
||||
{{ t(props.addText) }}
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption v-for="key of props.conditionTypes" :key="key" :value="key">
|
||||
{{ t(conditionTypeNameMap[key]) }}
|
||||
</a-doption>
|
||||
</template>
|
||||
{{ t(props.addText) }}
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption v-for="key of props.conditionTypes" :key="key" :value="key">
|
||||
{{ t(conditionTypeNameMap[key]) }}
|
||||
</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-dropdown>
|
||||
<div v-if="$slots.dropdownAppend" class="flex items-center">
|
||||
<slot name="dropdownAppend"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="$slots.titleRight" class="flex items-center">
|
||||
<slot name="titleRight"></slot>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { EQUAL } from '@/components/pure/ms-advance-filter';
|
||||
|
||||
import {
|
||||
EnableKeyValueParam,
|
||||
ExecuteBody,
|
||||
|
@ -13,11 +15,19 @@ import {
|
|||
RequestBodyFormat,
|
||||
RequestCaseStatus,
|
||||
RequestContentTypeEnum,
|
||||
RequestExtractEnvType,
|
||||
RequestExtractExpressionEnum,
|
||||
RequestExtractExpressionRuleType,
|
||||
RequestExtractResultMatchingRule,
|
||||
RequestExtractScope,
|
||||
RequestParamsType,
|
||||
ResponseBodyFormat,
|
||||
ResponseBodyXPathAssertionFormat,
|
||||
ResponseComposition,
|
||||
} from '@/enums/apiEnum';
|
||||
|
||||
import type { ExpressionConfig } from './fastExtraction/moreSetting.vue';
|
||||
|
||||
// 请求 body 参数表格默认行的值
|
||||
export const defaultBodyParamsItem: ExecuteRequestFormBodyFormValue = {
|
||||
key: '',
|
||||
|
@ -173,3 +183,47 @@ export const defaultAssertXpathParamsItem: ResponseAssertionItem = {
|
|||
expression: '',
|
||||
enable: true,
|
||||
};
|
||||
// 断言 xpath
|
||||
export const defaultExtractParamItem: ExpressionConfig = {
|
||||
enable: true,
|
||||
variableName: '',
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
expression: '',
|
||||
extractType: RequestExtractExpressionEnum.JSON_PATH,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
|
||||
// 断言 json默认值
|
||||
export const jsonPathDefaultParamItem = {
|
||||
enable: true,
|
||||
variableName: '',
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
expression: '',
|
||||
condition: EQUAL.value,
|
||||
extractType: RequestExtractExpressionEnum.JSON_PATH,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
// 断言 正则默认值
|
||||
export const regexDefaultParamItem = {
|
||||
expression: '',
|
||||
enable: true,
|
||||
valid: true,
|
||||
variableType: RequestExtractEnvType.TEMPORARY,
|
||||
extractScope: RequestExtractScope.BODY,
|
||||
extractType: RequestExtractExpressionEnum.REGEX,
|
||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||
resultMatchingRuleNum: 1,
|
||||
responseFormat: ResponseBodyXPathAssertionFormat.XML,
|
||||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
|
|
|
@ -237,10 +237,7 @@
|
|||
matchResult.value = [nodes];
|
||||
} else if (Array.isArray(nodes)) {
|
||||
// 匹配到多个节点信息
|
||||
matchResult.value = nodes
|
||||
.map((node) => node.textContent?.split('\n') || false)
|
||||
.flat(Infinity)
|
||||
.filter(Boolean);
|
||||
matchResult.value = nodes.map((node) => node.firstChild?.nodeValue || false).filter(Boolean);
|
||||
} else {
|
||||
// 匹配到单个节点信息
|
||||
matchResult.value = nodes.textContent ? [nodes.textContent] : [];
|
||||
|
|
|
@ -87,11 +87,12 @@
|
|||
v-if="columnConfig.inputType === 'autoComplete'"
|
||||
v-model:model-value="record[columnConfig.dataIndex as string]"
|
||||
:disabled="props.disabledExceptParam || columnConfig.disabledColumn"
|
||||
:data="record[columnConfig.dataIndex as string] !== '' ? columnConfig.autoCompleteParams?.filter((e) => e.isShow === true) : columnConfig.autoCompleteParams"
|
||||
:data="getAutoCompleteData(columnConfig, record)"
|
||||
class="ms-form-table-input"
|
||||
:trigger-props="{ contentClass: 'ms-form-table-input-trigger' }"
|
||||
:filter-option="false"
|
||||
size="mini"
|
||||
@focus="handleAutoCompleteFocus(record)"
|
||||
@search="(val) => handleSearchParams(val, columnConfig)"
|
||||
@change="() => addTableLine(rowIndex, columnConfig.addLineDisabled)"
|
||||
@select="(val) => selectAutoComplete(val, record, columnConfig)"
|
||||
|
@ -1041,6 +1042,21 @@
|
|||
});
|
||||
}
|
||||
|
||||
const activeRecord = ref<Record<string, any>>({});
|
||||
function getAutoCompleteData(columnConfig: ParamTableColumn, record: Record<string, any>) {
|
||||
if (activeRecord.value.id !== record.id) {
|
||||
// 非聚焦行,不显示联想输入
|
||||
return [];
|
||||
}
|
||||
return activeRecord.value[columnConfig.dataIndex as string] !== ''
|
||||
? columnConfig.autoCompleteParams?.filter((e) => e.isShow === true)
|
||||
: columnConfig.autoCompleteParams;
|
||||
}
|
||||
|
||||
function handleAutoCompleteFocus(record: Record<string, any>) {
|
||||
activeRecord.value = record;
|
||||
}
|
||||
|
||||
function selectAutoComplete(val: string, record: Record<string, any>, item: FormTableColumn) {
|
||||
record[item.dataIndex as string] = val;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { Message, SelectOptionData } from '@arco-design/web-vue';
|
||||
import { cloneDeep, debounce } from 'lodash-es';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
||||
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
||||
import MsTab from '@/components/pure/ms-tab/index.vue';
|
||||
|
@ -142,17 +142,21 @@
|
|||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
|
||||
import { ExecuteConditionConfig, PluginConfig } from '@/models/apiTest/common';
|
||||
import { PluginConfig } from '@/models/apiTest/common';
|
||||
import { ModuleTreeNode, TransferFileParams } from '@/models/common';
|
||||
import { RequestAuthType, RequestBodyFormat, RequestComposition, RequestConditionProcessor } from '@/enums/apiEnum';
|
||||
import { RequestAuthType, RequestBodyFormat, RequestComposition } from '@/enums/apiEnum';
|
||||
|
||||
import {
|
||||
defaultBodyParamsItem,
|
||||
defaultHeaderParamsItem,
|
||||
defaultKeyValueParamItem,
|
||||
defaultRequestParamsItem,
|
||||
} from '@/views/api-test/components/config';
|
||||
import { filterKeyValParams, parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||
import {
|
||||
filterAssertions,
|
||||
filterConditionsSqlValidParams,
|
||||
filterKeyValParams,
|
||||
parseRequestBodyFiles,
|
||||
} from '@/views/api-test/components/utils';
|
||||
import type { Api } from '@form-create/arco-design';
|
||||
|
||||
// 懒加载Http协议组件
|
||||
|
@ -430,20 +434,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
function filterConditionsSqlValidParams(condition: ExecuteConditionConfig) {
|
||||
const conditionCopy = cloneDeep(condition);
|
||||
conditionCopy.processors = conditionCopy.processors.map((processor) => {
|
||||
if (processor.processorType === RequestConditionProcessor.SQL) {
|
||||
processor.extractParams = filterKeyValParams(
|
||||
processor.extractParams || [],
|
||||
defaultKeyValueParamItem
|
||||
).validParams;
|
||||
}
|
||||
return processor;
|
||||
});
|
||||
return conditionCopy;
|
||||
}
|
||||
|
||||
// 生成请求参数
|
||||
function makeRequestParams(executeType?: 'localExec' | 'serverExec') {
|
||||
const isExecute = executeType === 'localExec' || executeType === 'serverExec';
|
||||
|
@ -498,6 +488,7 @@
|
|||
|
||||
const requestName = requestVModel.value.name ?? '';
|
||||
const requestModuleId = requestVModel.value.moduleId ?? '';
|
||||
const { assertionConfig } = requestVModel.value.children[0];
|
||||
return {
|
||||
id: requestVModel.value.id.toString(),
|
||||
name: requestName,
|
||||
|
@ -511,7 +502,10 @@
|
|||
children: [
|
||||
{
|
||||
polymorphicName: 'MsCommonElement', // 协议多态名称,写死MsCommonElement
|
||||
assertionConfig: requestVModel.value.children[0].assertionConfig,
|
||||
assertionConfig: {
|
||||
...requestVModel.value.children[0].assertionConfig,
|
||||
assertions: filterAssertions(assertionConfig, isExecute),
|
||||
},
|
||||
postProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].postProcessorConfig),
|
||||
preProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].preProcessorConfig),
|
||||
},
|
||||
|
|
|
@ -509,15 +509,13 @@
|
|||
import {
|
||||
casePriorityOptions,
|
||||
caseStatusOptions,
|
||||
defaultAssertParamsItem,
|
||||
defaultAssertXpathParamsItem,
|
||||
defaultBodyParamsItem,
|
||||
defaultHeaderParamsItem,
|
||||
defaultKeyValueParamItem,
|
||||
defaultRequestParamsItem,
|
||||
defaultResponse,
|
||||
} from '@/views/api-test/components/config';
|
||||
import { filterKeyValParams, parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||
import { filterAssertions, filterKeyValParams, parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||
import type { Api } from '@form-create/arco-design';
|
||||
|
||||
// 懒加载Http协议组件
|
||||
|
@ -1138,45 +1136,6 @@
|
|||
|
||||
// 处理断言参数
|
||||
const { assertionConfig } = requestVModel.value.children[0];
|
||||
const assertionList = assertionConfig.assertions.map((assertItem: any) => {
|
||||
const bodyAssertionDataByTypeList = filterKeyValParams(
|
||||
assertItem?.bodyAssertionDataByType?.assertions || [],
|
||||
defaultAssertParamsItem,
|
||||
isExecute
|
||||
).validParams;
|
||||
return {
|
||||
...assertItem,
|
||||
bodyAssertionDataByType: {
|
||||
...assertItem.bodyAssertionDataByType,
|
||||
assertions: bodyAssertionDataByTypeList,
|
||||
},
|
||||
regexAssertion: {
|
||||
...assertItem?.regexAssertion,
|
||||
assertions: filterKeyValParams(
|
||||
assertItem?.regexAssertion?.assertions || [],
|
||||
defaultAssertXpathParamsItem,
|
||||
isExecute
|
||||
).validParams,
|
||||
},
|
||||
xpathAssertion: {
|
||||
...assertItem.xpathAssertion,
|
||||
assertions: filterKeyValParams(
|
||||
assertItem?.xpathAssertion?.assertions || [],
|
||||
defaultAssertXpathParamsItem,
|
||||
isExecute
|
||||
).validParams,
|
||||
},
|
||||
jsonPathAssertion: {
|
||||
...assertItem.jsonPathAssertion,
|
||||
assertions: filterKeyValParams(
|
||||
assertItem?.jsonPathAssertion?.assertions || [],
|
||||
defaultAssertParamsItem,
|
||||
isExecute
|
||||
).validParams,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
id: requestVModel.value.id.toString(),
|
||||
reportId: reportId.value,
|
||||
|
@ -1195,7 +1154,7 @@
|
|||
polymorphicName: 'MsCommonElement', // 协议多态名称,写死MsCommonElement
|
||||
assertionConfig: {
|
||||
...assertionConfig,
|
||||
assertions: assertionList,
|
||||
assertions: filterAssertions(assertionConfig, isExecute),
|
||||
},
|
||||
postProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].postProcessorConfig),
|
||||
preProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].preProcessorConfig),
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
:sql-code-editor-height="props.sqlCodeEditorHeight"
|
||||
@change="emit('change')"
|
||||
>
|
||||
<template v-if="$slots.dropdownAppend" #dropdownAppend>
|
||||
<slot name="dropdownAppend" />
|
||||
</template>
|
||||
<template v-if="props.isDefinition" #titleRight>
|
||||
<a-switch
|
||||
v-model:model-value="innerConfig.enableGlobal"
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
add-text="apiTestDebug.precondition"
|
||||
@change="emit('change')"
|
||||
>
|
||||
<template v-if="$slots.dropdownAppend" #dropdownAppend>
|
||||
<slot name="dropdownAppend" />
|
||||
</template>
|
||||
<template v-if="props.isDefinition" #titleRight>
|
||||
<a-switch
|
||||
v-model:model-value="innerConfig.enableGlobal"
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import { cloneDeep, isEqual } from 'lodash-es';
|
||||
|
||||
import { ExecuteBody } from '@/models/apiTest/common';
|
||||
import { RequestParamsType } from '@/enums/apiEnum';
|
||||
import { type ExecuteAssertionConfig, ExecuteBody, type ExecuteConditionConfig } from '@/models/apiTest/common';
|
||||
import { RequestConditionProcessor, RequestParamsType, ResponseBodyAssertionType } from '@/enums/apiEnum';
|
||||
|
||||
import {
|
||||
defaultAssertParamsItem,
|
||||
defaultBodyParamsItem,
|
||||
defaultExtractParamItem,
|
||||
defaultHeaderParamsItem,
|
||||
defaultKeyValueParamItem,
|
||||
defaultRequestParamsItem,
|
||||
jsonPathDefaultParamItem,
|
||||
regexDefaultParamItem,
|
||||
} from './config';
|
||||
import type { RequestParam } from './requestComposition/index.vue';
|
||||
|
||||
|
@ -129,13 +133,18 @@ export function filterKeyValParams<T>(
|
|||
validParams: params,
|
||||
};
|
||||
}
|
||||
// id和enable属性不参与比较
|
||||
// id、enable、valid属性不参与比较
|
||||
delete lastData.id;
|
||||
delete lastData.enable;
|
||||
delete lastData.valid;
|
||||
delete defaultParam.valid;
|
||||
delete defaultParam.id;
|
||||
delete defaultParam.enable;
|
||||
const lastDataIsDefault = isEqual(lastData, defaultParam) || lastData.key === '';
|
||||
let validParams: (T & Record<string, any>)[];
|
||||
if (defaultParam.condition) {
|
||||
console.log(`assertionConfig`, lastDataIsDefault, lastData, defaultParam);
|
||||
}
|
||||
if (lastDataIsDefault) {
|
||||
// 如果最后一条数据是默认数据,非用户添加更改的,说明是无效参数,删除最后一个
|
||||
validParams = params.slice(0, params.length - 1);
|
||||
|
@ -170,3 +179,57 @@ export function getValidRequestTableParams(requestVModel: RequestParam) {
|
|||
})) || [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤无效的条件配置参数
|
||||
* @param condition 条件配置对象
|
||||
*/
|
||||
export function filterConditionsSqlValidParams(condition: ExecuteConditionConfig) {
|
||||
const conditionCopy = cloneDeep(condition);
|
||||
conditionCopy.processors = conditionCopy.processors.map((processor) => {
|
||||
if (processor.processorType === RequestConditionProcessor.SQL) {
|
||||
processor.extractParams = filterKeyValParams(processor.extractParams || [], defaultKeyValueParamItem).validParams;
|
||||
}
|
||||
return processor;
|
||||
});
|
||||
return conditionCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤无效的断言配置参数
|
||||
* @param assertionConfig 断言配置对象
|
||||
* @param isExecute 是否是执行时调用
|
||||
*/
|
||||
export function filterAssertions(assertionConfig: ExecuteAssertionConfig, isExecute = false) {
|
||||
return assertionConfig.assertions.map((assertItem: any) => {
|
||||
return {
|
||||
...assertItem,
|
||||
bodyAssertionDataByType: {
|
||||
...assertItem.bodyAssertionDataByType,
|
||||
assertions: filterKeyValParams(
|
||||
assertItem?.bodyAssertionDataByType?.assertions || [],
|
||||
defaultAssertParamsItem,
|
||||
isExecute
|
||||
).validParams,
|
||||
},
|
||||
regexAssertion: {
|
||||
...assertItem?.regexAssertion,
|
||||
assertions: filterKeyValParams(assertItem?.regexAssertion?.assertions || [], regexDefaultParamItem, isExecute)
|
||||
.validParams,
|
||||
},
|
||||
xpathAssertion: {
|
||||
...assertItem.xpathAssertion,
|
||||
assertions: filterKeyValParams(assertItem?.xpathAssertion?.assertions || [], defaultExtractParamItem, isExecute)
|
||||
.validParams,
|
||||
},
|
||||
jsonPathAssertion: {
|
||||
...assertItem.jsonPathAssertion,
|
||||
assertions: filterKeyValParams(
|
||||
assertItem?.jsonPathAssertion?.assertions || [],
|
||||
jsonPathDefaultParamItem,
|
||||
isExecute
|
||||
).validParams,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -395,7 +395,6 @@
|
|||
EnableKeyValueParam,
|
||||
ExecuteApiRequestFullParams,
|
||||
ExecuteBody,
|
||||
ExecuteConditionConfig,
|
||||
ExecutePluginRequestParams,
|
||||
ExecuteRequestCommonParam,
|
||||
ExecuteRequestFormBody,
|
||||
|
@ -409,7 +408,6 @@
|
|||
RequestAuthType,
|
||||
RequestBodyFormat,
|
||||
RequestComposition,
|
||||
RequestConditionProcessor,
|
||||
RequestMethods,
|
||||
ResponseComposition,
|
||||
ScenarioStepType,
|
||||
|
@ -420,11 +418,15 @@
|
|||
defaultBodyParams,
|
||||
defaultBodyParamsItem,
|
||||
defaultHeaderParamsItem,
|
||||
defaultKeyValueParamItem,
|
||||
defaultRequestParamsItem,
|
||||
defaultResponse,
|
||||
} from '@/views/api-test/components/config';
|
||||
import { filterKeyValParams, parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||
import {
|
||||
filterAssertions,
|
||||
filterConditionsSqlValidParams,
|
||||
filterKeyValParams,
|
||||
parseRequestBodyFiles,
|
||||
} from '@/views/api-test/components/utils';
|
||||
import type { Api } from '@form-create/arco-design';
|
||||
|
||||
// 懒加载Http协议组件
|
||||
|
@ -995,20 +997,6 @@
|
|||
verticalSplitBoxRef.value?.expand(0.6);
|
||||
}
|
||||
|
||||
function filterConditionsSqlValidParams(condition: ExecuteConditionConfig) {
|
||||
const conditionCopy = cloneDeep(condition);
|
||||
conditionCopy.processors = conditionCopy.processors.map((processor) => {
|
||||
if (processor.processorType === RequestConditionProcessor.SQL) {
|
||||
processor.extractParams = filterKeyValParams(
|
||||
processor.extractParams || [],
|
||||
defaultKeyValueParamItem
|
||||
).validParams;
|
||||
}
|
||||
return processor;
|
||||
});
|
||||
return conditionCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求参数
|
||||
* @param executeType 执行类型,执行时传入
|
||||
|
@ -1062,6 +1050,7 @@
|
|||
polymorphicName,
|
||||
};
|
||||
}
|
||||
const { assertionConfig } = requestVModel.value.children[0];
|
||||
return {
|
||||
...requestParams,
|
||||
resourceId: requestVModel.value.resourceId,
|
||||
|
@ -1077,7 +1066,10 @@
|
|||
children: [
|
||||
{
|
||||
polymorphicName: 'MsCommonElement', // 协议多态名称,写死MsCommonElement
|
||||
assertionConfig: requestVModel.value.children[0].assertionConfig,
|
||||
assertionConfig: {
|
||||
...requestVModel.value.children[0].assertionConfig,
|
||||
assertions: filterAssertions(assertionConfig, isExecute),
|
||||
},
|
||||
postProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].postProcessorConfig),
|
||||
preProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].preProcessorConfig),
|
||||
},
|
||||
|
|
|
@ -304,13 +304,12 @@
|
|||
import { characterLimit } from '@/utils';
|
||||
import { scrollIntoView } from '@/utils/dom';
|
||||
|
||||
import { ExecuteConditionConfig, PluginConfig, RequestResult } from '@/models/apiTest/common';
|
||||
import { PluginConfig, RequestResult } from '@/models/apiTest/common';
|
||||
import { ScenarioStepFileParams, ScenarioStepItem } from '@/models/apiTest/scenario';
|
||||
import {
|
||||
RequestAuthType,
|
||||
RequestBodyFormat,
|
||||
RequestComposition,
|
||||
RequestConditionProcessor,
|
||||
RequestMethods,
|
||||
ResponseComposition,
|
||||
ScenarioStepRefType,
|
||||
|
@ -322,11 +321,15 @@
|
|||
defaultBodyParams,
|
||||
defaultBodyParamsItem,
|
||||
defaultHeaderParamsItem,
|
||||
defaultKeyValueParamItem,
|
||||
defaultRequestParamsItem,
|
||||
defaultResponse,
|
||||
} from '@/views/api-test/components/config';
|
||||
import { filterKeyValParams, parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||
import {
|
||||
filterAssertions,
|
||||
filterConditionsSqlValidParams,
|
||||
filterKeyValParams,
|
||||
parseRequestBodyFiles,
|
||||
} from '@/views/api-test/components/utils';
|
||||
import { Api } from '@form-create/arco-design';
|
||||
// 懒加载Http协议组件
|
||||
const httpHeader = defineAsyncComponent(() => import('@/views/api-test/components/requestComposition/header.vue'));
|
||||
|
@ -824,20 +827,6 @@
|
|||
verticalSplitBoxRef.value?.expand(0.6);
|
||||
}
|
||||
|
||||
function filterConditionsSqlValidParams(condition: ExecuteConditionConfig) {
|
||||
const conditionCopy = cloneDeep(condition);
|
||||
conditionCopy.processors = conditionCopy.processors.map((processor) => {
|
||||
if (processor.processorType === RequestConditionProcessor.SQL) {
|
||||
processor.extractParams = filterKeyValParams(
|
||||
processor.extractParams || [],
|
||||
defaultKeyValueParamItem
|
||||
).validParams;
|
||||
}
|
||||
return processor;
|
||||
});
|
||||
return conditionCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求参数
|
||||
* @param executeType 执行类型,执行时传入
|
||||
|
@ -894,6 +883,7 @@
|
|||
polymorphicName,
|
||||
};
|
||||
}
|
||||
const { assertionConfig } = requestVModel.value.children[0];
|
||||
return {
|
||||
...requestParams,
|
||||
resourceId: requestVModel.value.resourceId,
|
||||
|
@ -908,7 +898,10 @@
|
|||
children: [
|
||||
{
|
||||
polymorphicName: 'MsCommonElement', // 协议多态名称,写死MsCommonElement
|
||||
assertionConfig: requestVModel.value.children[0].assertionConfig,
|
||||
assertionConfig: {
|
||||
...requestVModel.value.children[0].assertionConfig,
|
||||
assertions: filterAssertions(assertionConfig, isExecute),
|
||||
},
|
||||
postProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].postProcessorConfig),
|
||||
preProcessorConfig: filterConditionsSqlValidParams(requestVModel.value.children[0].preProcessorConfig),
|
||||
},
|
||||
|
|
|
@ -8,7 +8,16 @@
|
|||
:tip-content="t('apiScenario.openGlobalPreConditionTip')"
|
||||
is-scenario
|
||||
@change="emit('change', true)"
|
||||
/>
|
||||
>
|
||||
<template #dropdownAppend>
|
||||
<a-tooltip :content="t('apiScenario.preConditionTip')" position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</precondition>
|
||||
</div>
|
||||
<a-divider class="my-[8px]" type="dashed" />
|
||||
<div>
|
||||
|
@ -20,7 +29,16 @@
|
|||
:tip-content="t('apiScenario.openGlobalPostConditionTip')"
|
||||
is-scenario
|
||||
@change="emit('change', false)"
|
||||
/>
|
||||
>
|
||||
<template #dropdownAppend>
|
||||
<a-tooltip :content="t('apiScenario.postConditionTip')" position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</postcondition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -375,15 +375,15 @@
|
|||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center justify-end">
|
||||
<!-- <div class="flex items-center">
|
||||
<div class="text-[var(--color-text-4)]">
|
||||
{{ t('apiScenario.valuePriority') }}
|
||||
</div>
|
||||
<div v-if="scenarioConfigParamTip" class="text-[var(--color-text-1)]">
|
||||
{{ scenarioConfigParamTip }}
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="flex items-center gap-[12px]">
|
||||
<a-button type="secondary" @click="cancelScenarioConfig">{{ t('common.cancel') }}</a-button>
|
||||
<a-button type="primary" @click="saveScenarioConfig">{{ t('common.confirm') }}</a-button>
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
|
||||
import { defaultScenario } from './components/config';
|
||||
import updateStepStatus from './components/utils';
|
||||
import { filterAssertions, filterConditionsSqlValidParams } from '@/views/api-test/components/utils';
|
||||
|
||||
// 异步导入
|
||||
const detail = defineAsyncComponent(() => import('./detail/index.vue'));
|
||||
|
@ -169,6 +170,7 @@
|
|||
]);
|
||||
const activeScenarioTab = ref<ScenarioParams>(scenarioTabs.value[0] as ScenarioParams);
|
||||
const executeButtonRef = ref<InstanceType<typeof executeButton>>();
|
||||
const localExecuteUrl = computed(() => executeButtonRef.value?.localExecuteUrl);
|
||||
|
||||
const websocketMap: Record<string | number, WebSocket> = {};
|
||||
|
||||
|
@ -179,11 +181,11 @@
|
|||
/**
|
||||
* 开启websocket监听,接收执行结果
|
||||
*/
|
||||
function debugSocket(scenario: Scenario, executeType?: 'localExec' | 'serverExec', localExecuteUrl?: string) {
|
||||
function debugSocket(scenario: Scenario, executeType?: 'localExec' | 'serverExec') {
|
||||
websocketMap[scenario.reportId] = getSocket(
|
||||
scenario.reportId || '',
|
||||
executeType === 'localExec' ? '/ws/debug' : '',
|
||||
executeType === 'localExec' ? localExecuteUrl : ''
|
||||
executeType === 'localExec' ? localExecuteUrl.value : ''
|
||||
);
|
||||
websocketMap[scenario.reportId].addEventListener('message', (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
|
@ -227,13 +229,12 @@
|
|||
* @param executeParams 执行参数
|
||||
* @param isExecute 是否执行,否则是调试
|
||||
* @param executeType 执行类型
|
||||
* @param localExecuteUrl 本地执行地址
|
||||
*/
|
||||
async function realExecute(
|
||||
executeParams: Pick<ApiScenarioDebugRequest, 'steps' | 'stepDetails' | 'reportId'>,
|
||||
isExecute?: boolean,
|
||||
executeType?: 'localExec' | 'serverExec',
|
||||
localExecuteUrl?: string
|
||||
envId?: string
|
||||
) {
|
||||
try {
|
||||
activeScenarioTab.value.executeLoading = true;
|
||||
|
@ -244,7 +245,7 @@
|
|||
activeScenarioTab.value.executeFakeErrorCount = 0;
|
||||
activeScenarioTab.value.stepResponses = {};
|
||||
activeScenarioTab.value.reportId = executeParams.reportId; // 存储报告ID
|
||||
debugSocket(activeScenarioTab.value, executeType, localExecuteUrl); // 开启websocket
|
||||
debugSocket(activeScenarioTab.value, executeType); // 开启websocket
|
||||
activeScenarioTab.value.isDebug = !isExecute;
|
||||
let res;
|
||||
if (isExecute && executeType !== 'localExec' && !activeScenarioTab.value.isNew) {
|
||||
|
@ -252,7 +253,7 @@
|
|||
res = await executeScenario({
|
||||
id: activeScenarioTab.value.id,
|
||||
grouped: false,
|
||||
environmentId: appStore.getCurrentEnvId || '',
|
||||
environmentId: envId || appStore.getCurrentEnvId || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: activeScenarioTab.value.scenarioConfig,
|
||||
...executeParams,
|
||||
|
@ -268,7 +269,7 @@
|
|||
res = await debugScenario({
|
||||
id: activeScenarioTab.value.id,
|
||||
grouped: false,
|
||||
environmentId: appStore.getCurrentEnvId || '',
|
||||
environmentId: envId || appStore.getCurrentEnvId || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: activeScenarioTab.value.scenarioConfig,
|
||||
stepFileParam: activeScenarioTab.value.stepFileParam,
|
||||
|
@ -282,9 +283,9 @@
|
|||
}),
|
||||
});
|
||||
}
|
||||
if (executeType === 'localExec' && localExecuteUrl) {
|
||||
if (executeType === 'localExec' && localExecuteUrl.value) {
|
||||
// 本地执行需要调 debug 接口获取响应结果,然后再调本地执行接口
|
||||
await localExecuteApiDebug(localExecuteUrl, res);
|
||||
await localExecuteApiDebug(localExecuteUrl.value, res);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -298,9 +299,9 @@
|
|||
/**
|
||||
* 执行场景
|
||||
* @param executeType 执行类型
|
||||
* @param localExecuteUrl 本地执行地址
|
||||
* @param envId 环境ID
|
||||
*/
|
||||
function handleExecute(executeType?: 'localExec' | 'serverExec', localExecuteUrl?: string) {
|
||||
function handleExecute(executeType?: 'localExec' | 'serverExec', envId?: string) {
|
||||
const waitingDebugStepDetails: Record<string, ScenarioStepDetails> = {};
|
||||
const waitTingDebugSteps = filterTree(activeScenarioTab.value.steps, (node) => {
|
||||
if (node.enable) {
|
||||
|
@ -323,7 +324,7 @@
|
|||
},
|
||||
true,
|
||||
executeType,
|
||||
localExecuteUrl
|
||||
envId
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -431,7 +432,10 @@
|
|||
if (action === 'execute') {
|
||||
nextTick(() => {
|
||||
// 等待激活 tab 设置完毕后执行
|
||||
handleExecute(executeButtonRef.value?.isPriorityLocalExec ? 'localExec' : 'serverExec');
|
||||
handleExecute(
|
||||
executeButtonRef.value?.isPriorityLocalExec ? 'localExec' : 'serverExec',
|
||||
defaultScenarioInfo.environmentId
|
||||
);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
@ -485,6 +489,7 @@
|
|||
async function realSaveScenario() {
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
const { assertionConfig } = activeScenarioTab.value.scenarioConfig;
|
||||
if (activeScenarioTab.value.isNew) {
|
||||
const res = await addScenario({
|
||||
...activeScenarioTab.value,
|
||||
|
@ -494,6 +499,16 @@
|
|||
parent: null, // 原树形结构存在循环引用,这里要去掉以免 axios 序列化失败
|
||||
};
|
||||
}),
|
||||
scenarioConfig: {
|
||||
...activeScenarioTab.value.scenarioConfig,
|
||||
assertionConfig: { ...assertionConfig, assertions: filterAssertions(assertionConfig) },
|
||||
postProcessorConfig: filterConditionsSqlValidParams(
|
||||
activeScenarioTab.value.scenarioConfig.postProcessorConfig
|
||||
),
|
||||
preProcessorConfig: filterConditionsSqlValidParams(
|
||||
activeScenarioTab.value.scenarioConfig.preProcessorConfig
|
||||
),
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
environmentId: appStore.getCurrentEnvId || '',
|
||||
});
|
||||
|
@ -535,6 +550,16 @@
|
|||
} else {
|
||||
await updateScenario({
|
||||
...activeScenarioTab.value,
|
||||
scenarioConfig: {
|
||||
...activeScenarioTab.value.scenarioConfig,
|
||||
assertionConfig: { ...assertionConfig, assertions: filterAssertions(assertionConfig) },
|
||||
postProcessorConfig: filterConditionsSqlValidParams(
|
||||
activeScenarioTab.value.scenarioConfig.postProcessorConfig
|
||||
),
|
||||
preProcessorConfig: filterConditionsSqlValidParams(
|
||||
activeScenarioTab.value.scenarioConfig.preProcessorConfig
|
||||
),
|
||||
},
|
||||
environmentId: appStore.getCurrentEnvId || '',
|
||||
steps: mapTree(activeScenarioTab.value.steps, (node) => {
|
||||
return {
|
||||
|
@ -572,7 +597,10 @@
|
|||
activeScenarioTab.value = scenarioTabs.value[isLoadedTabIndex];
|
||||
// tab子组件里监听的是id变化,所以id相等的时候需要单独调执行
|
||||
if (action === 'execute') {
|
||||
handleExecute(executeButtonRef.value?.isPriorityLocalExec ? 'localExec' : 'serverExec');
|
||||
handleExecute(
|
||||
executeButtonRef.value?.isPriorityLocalExec ? 'localExec' : 'serverExec',
|
||||
typeof record === 'string' ? undefined : record.environmentId
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -605,7 +633,6 @@
|
|||
useLeaveTabUnSaveCheck(scenarioTabs.value, ['PROJECT_API_SCENARIO:READ+ADD', 'PROJECT_API_SCENARIO:READ+UPDATE']);
|
||||
|
||||
const hasLocalExec = computed(() => executeButtonRef.value?.hasLocalExec);
|
||||
const localExecuteUrl = computed(() => executeButtonRef.value?.localExecuteUrl);
|
||||
const isPriorityLocalExec = computed(() => executeButtonRef.value?.isPriorityLocalExec);
|
||||
const scenarioId = computed(() => activeScenarioTab.value.id);
|
||||
const scenarioExecuteLoading = computed(() => activeScenarioTab.value.executeLoading);
|
||||
|
|
|
@ -267,4 +267,6 @@ export default {
|
|||
'apiScenario.schedule.table.tooltip.disable': 'Scheduled task is disabled',
|
||||
'apiScenario.save.env': 'Scenario Environment',
|
||||
'apiScenario.execute.no.step.tips': 'No open step',
|
||||
'apiScenario.preConditionTip': 'Execute once before the scene step',
|
||||
'apiScenario.postConditionTip': 'Execute once after the scene step',
|
||||
};
|
||||
|
|
|
@ -254,4 +254,6 @@ export default {
|
|||
'apiScenario.schedule.table.tooltip.disable': '定时任务未开启',
|
||||
'apiScenario.save.env': '场景保存的环境',
|
||||
'apiScenario.execute.no.step.tips': '没有开启的步骤',
|
||||
'apiScenario.preConditionTip': '在场景步骤前分别执行一次',
|
||||
'apiScenario.postConditionTip': '在场景步骤后分别执行一次',
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue