fix(项目管理): 环境管理断言参数调整&部项目管理bug修复
This commit is contained in:
parent
de60f207be
commit
ad7bcaa7cf
|
@ -7,14 +7,16 @@
|
|||
</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
<div v-if="activeTab === 'jsonPath'" class="mt-[16px]">
|
||||
<!-- jsonPath开始 -->
|
||||
<div v-if="activeTab === ResponseBodyAssertionType.JSON_PATH" class="mt-[16px]">
|
||||
<paramsTable
|
||||
v-model:params="innerParams.jsonPath"
|
||||
ref="extractParamsTableRef"
|
||||
v-model:params="condition.jsonPathAssertion.assertions"
|
||||
:selectable="false"
|
||||
:columns="jsonPathColumns"
|
||||
:scroll="{ minWidth: '700px' }"
|
||||
:default-param-item="jsonPathDefaultParamItem"
|
||||
@change="(data) => handleChange(data, 'jsonPath')"
|
||||
@change="(data) => handleChange(data, ResponseBodyAssertionType.JSON_PATH)"
|
||||
@more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)"
|
||||
>
|
||||
<template #expression="{ record, rowIndex }">
|
||||
|
@ -82,24 +84,22 @@
|
|||
</template>
|
||||
</paramsTable>
|
||||
</div>
|
||||
<div v-if="activeTab === 'xPath'" class="mt-[16px]">
|
||||
<!-- jsonPath结束 -->
|
||||
<!-- xPath开始 -->
|
||||
<div v-if="activeTab === ResponseBodyAssertionType.XPATH" class="mt-[16px]">
|
||||
<div class="text-[var(--color-text-1)]">{{ t('ms.assertion.responseContentType') }}</div>
|
||||
<a-radio-group
|
||||
v-model:model-value="innerParams.xPath.responseFormat"
|
||||
class="mb-[16px] mt-[16px]"
|
||||
type="button"
|
||||
size="small"
|
||||
>
|
||||
<a-radio value="XML">XML</a-radio>
|
||||
<a-radio value="HTML">HTML</a-radio>
|
||||
<a-radio-group v-model="activeResponseFormat" class="mb-[16px] mt-[16px]" type="button" size="small">
|
||||
<a-radio key="XML" value="XML">XML</a-radio>
|
||||
<a-radio key="HTML" value="HTML">HTML</a-radio>
|
||||
</a-radio-group>
|
||||
<paramsTable
|
||||
v-model:params="innerParams.xPath.data"
|
||||
ref="extractParamsTableRef"
|
||||
v-model:params="condition.xpathAssertion.assertions"
|
||||
:selectable="false"
|
||||
:columns="xPathColumns"
|
||||
:scroll="{ minWidth: '700px' }"
|
||||
:default-param-item="xPathDefaultParamItem"
|
||||
@change="(data) => handleChange(data, 'xPath')"
|
||||
@change="(data) => handleChange(data, ResponseBodyAssertionType.XPATH)"
|
||||
@more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)"
|
||||
>
|
||||
<template #expression="{ record, rowIndex }">
|
||||
|
@ -167,22 +167,24 @@
|
|||
</template>
|
||||
</paramsTable>
|
||||
</div>
|
||||
<div v-if="activeTab === 'document'" class="relative mt-[16px]">
|
||||
<!-- xPath结束 -->
|
||||
<!-- document开始 -->
|
||||
<div v-if="activeTab === ResponseBodyAssertionType.DOCUMENT" class="relative mt-[16px]">
|
||||
<div class="text-[var(--color-text-1)]">
|
||||
{{ t('ms.assertion.responseContentType') }}
|
||||
</div>
|
||||
<a-radio-group v-model:model-value="innerParams.document.responseFormat" class="mt-[16px]" size="small">
|
||||
<a-radio-group v-model:model-value="condition.document.responseFormat" class="mt-[16px]" size="small">
|
||||
<a-radio value="JSON">JSON</a-radio>
|
||||
<a-radio value="XML">XML</a-radio>
|
||||
</a-radio-group>
|
||||
<div class="mt-[16px]">
|
||||
<a-checkbox v-model:model-value="innerParams.document.followApi">
|
||||
<a-checkbox v-model:model-value="condition.document.followApi">
|
||||
<span class="text-[var(--color-text-1)]">{{ t('ms.assertion.followApi') }}</span>
|
||||
</a-checkbox>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<paramsTable
|
||||
v-model:params="innerParams.document.data"
|
||||
v-model:params="condition.document.jsonAssertion"
|
||||
:selectable="false"
|
||||
:columns="documentColumns"
|
||||
:scroll="{
|
||||
|
@ -193,7 +195,7 @@
|
|||
:span-method="documentSpanMethod"
|
||||
is-tree-table
|
||||
@tree-delete="deleteAllParam"
|
||||
@change="(data) => handleChange(data, 'document')"
|
||||
@change="(data) => handleChange(data, ResponseBodyAssertionType.DOCUMENT)"
|
||||
>
|
||||
<template #matchValueDelete="{ record }">
|
||||
<icon-minus-circle
|
||||
|
@ -227,14 +229,17 @@
|
|||
</paramsTable>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="activeTab === 'regular'" class="mt-[16px]">
|
||||
<!-- document结束 -->
|
||||
<!-- 正则开始 -->
|
||||
<div v-if="activeTab === ResponseBodyAssertionType.REGEX" class="mt-[16px]">
|
||||
<paramsTable
|
||||
v-model:params="innerParams.regular"
|
||||
ref="extractParamsTableRef"
|
||||
v-model:params="condition.regexAssertion.assertions"
|
||||
:selectable="false"
|
||||
:columns="xPathColumns"
|
||||
:scroll="{ minWidth: '700px' }"
|
||||
:default-param-item="xPathDefaultParamItem"
|
||||
@change="(data) => handleChange(data, 'regular')"
|
||||
@change="(data) => handleChange(data, ResponseBodyAssertionType.REGEX)"
|
||||
@more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)"
|
||||
>
|
||||
<template #expression="{ record, rowIndex }">
|
||||
|
@ -302,14 +307,17 @@
|
|||
</template>
|
||||
</paramsTable>
|
||||
</div>
|
||||
<div v-if="activeTab === 'script'" class="mt-[16px]">
|
||||
<conditionContent v-model:data="innerParams.script" :height-used="600" is-build-in class="mt-[16px]" />
|
||||
</div>
|
||||
<!-- 正则结束 -->
|
||||
<!-- 这一版断言里边的脚本不需要 -->
|
||||
<!-- <div v-if="activeTab === ResponseBodyAssertionType.SCRIPT" class="mt-[16px]">
|
||||
<conditionContent v-model:data="condition.script" :height-used="600" is-build-in class="mt-[16px]" />
|
||||
</div> -->
|
||||
</div>
|
||||
<fastExtraction v-model:visible="fastExtractionVisible" :config="activeRecord" @apply="handleFastExtractionApply" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { TableColumnData, TableData } from '@arco-design/web-vue';
|
||||
|
||||
import { statusCodeOptions } from '@/components/pure/ms-advance-filter';
|
||||
|
@ -345,6 +353,7 @@
|
|||
RequestExtractExpressionRuleType,
|
||||
RequestExtractResultMatchingRule,
|
||||
RequestExtractScope,
|
||||
ResponseBodyAssertionType,
|
||||
ResponseBodyXPathAssertionFormat,
|
||||
} from '@/enums/apiEnum';
|
||||
|
||||
|
@ -353,7 +362,7 @@
|
|||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:data', data: ExecuteConditionProcessor): void;
|
||||
// (e: 'update:data', data: ExecuteConditionProcessor): void;
|
||||
(e: 'copy'): void;
|
||||
(e: 'delete', id: number): void;
|
||||
(e: 'change', param: Param): void;
|
||||
|
@ -362,44 +371,43 @@
|
|||
const rootId = 0; // 1970-01-01 00:00:00 UTC
|
||||
|
||||
const props = defineProps<{
|
||||
value: Param;
|
||||
data: Param;
|
||||
}>();
|
||||
|
||||
const activeTab = ref(ResponseBodyAssertionType.JSON_PATH);
|
||||
const activeResponseFormat = ref('XML');
|
||||
const defaultParamItem = {
|
||||
jsonPath: [],
|
||||
xPath: { responseFormat: 'XML', data: [] },
|
||||
document: {
|
||||
data: [
|
||||
{
|
||||
id: rootId,
|
||||
paramsName: 'root',
|
||||
mustInclude: false,
|
||||
typeChecking: false,
|
||||
paramType: 'object',
|
||||
matchCondition: '',
|
||||
matchValue: '',
|
||||
},
|
||||
],
|
||||
responseFormat: 'JSON',
|
||||
followApi: false,
|
||||
jsonPathAssertion: {
|
||||
assertions: [],
|
||||
},
|
||||
script: {
|
||||
id: new Date().getTime(),
|
||||
processorType: RequestConditionProcessor.SCRIPT,
|
||||
scriptName: '断言脚本名称',
|
||||
enableCommonScript: false,
|
||||
params: [],
|
||||
scriptId: '',
|
||||
scriptLanguage: RequestConditionScriptLanguage.JAVASCRIPT,
|
||||
script: new Date().getTime().toString(),
|
||||
xpathAssertion: { responseFormat: 'XML', assertions: [] },
|
||||
assertionBodyType: activeTab.value,
|
||||
regexAssertion: {
|
||||
assertions: [],
|
||||
},
|
||||
// TODO文档暂时不做
|
||||
// documentAssertion: {
|
||||
// jsonAssertion: [
|
||||
// {
|
||||
// id: rootId,
|
||||
// paramsName: 'root',
|
||||
// mustInclude: false,
|
||||
// typeChecking: false,
|
||||
// paramType: 'object',
|
||||
// matchCondition: '',
|
||||
// matchValue: '',
|
||||
// },
|
||||
// ],
|
||||
// responseFormat: 'JSON',
|
||||
// followApi: false,
|
||||
// },
|
||||
};
|
||||
|
||||
const innerParams = ref<Param>(props.value || defaultParamItem);
|
||||
watchEffect(() => {
|
||||
emit('change', innerParams.value);
|
||||
});
|
||||
const activeTab = ref('jsonPath');
|
||||
const condition = useVModel(props, 'data', emit);
|
||||
// const condition = ref<Param>(props.data || defaultParamItem);
|
||||
// watchEffect(() => {
|
||||
// emit('change', { ...condition.value });
|
||||
// });
|
||||
|
||||
const extractParamsTableRef = ref<InstanceType<typeof paramsTable>>();
|
||||
const fastExtractionVisible = ref(false);
|
||||
const disabledExpressionSuffix = ref(false);
|
||||
|
@ -422,11 +430,10 @@
|
|||
const activeRecord = ref({ ...defaultExtractParamItem }); // 用于暂存当前操作的提取参数表格项
|
||||
|
||||
const responseRadios = [
|
||||
{ label: 'ms.assertion.jsonPath', value: 'jsonPath' },
|
||||
{ label: 'ms.assertion.xpath', value: 'xPath' },
|
||||
{ label: 'ms.assertion.jsonPath', value: ResponseBodyAssertionType.JSON_PATH },
|
||||
{ label: 'ms.assertion.xpath', value: ResponseBodyAssertionType.XPATH },
|
||||
// { label: 'ms.assertion.document', value: 'document' },
|
||||
{ label: 'ms.assertion.regular', value: 'regular' },
|
||||
{ label: 'ms.assertion.script', value: 'script' },
|
||||
{ label: 'ms.assertion.regular', value: ResponseBodyAssertionType.REGEX },
|
||||
];
|
||||
|
||||
const jsonPathColumns: ParamTableColumn[] = [
|
||||
|
@ -438,15 +445,15 @@
|
|||
},
|
||||
{
|
||||
title: 'ms.assertion.matchCondition',
|
||||
dataIndex: 'matchCondition',
|
||||
slotName: 'matchCondition',
|
||||
dataIndex: 'condition',
|
||||
slotName: 'condition',
|
||||
options: statusCodeOptions,
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: 'ms.assertion.matchValue',
|
||||
dataIndex: 'matchValue',
|
||||
slotName: 'matchValue',
|
||||
dataIndex: 'expectedValue',
|
||||
slotName: 'expectedValue',
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
|
@ -469,19 +476,38 @@
|
|||
|
||||
const jsonPathDefaultParamItem = {
|
||||
expression: '',
|
||||
matchCondition: '',
|
||||
matchValue: '',
|
||||
enable: true,
|
||||
condition: '',
|
||||
expectedValue: '',
|
||||
valid: true,
|
||||
};
|
||||
|
||||
const handleChange = (data: any[], type: string) => {
|
||||
if (type === 'jsonPath') {
|
||||
innerParams.value.jsonPath = data;
|
||||
} else if (type === 'xPath') {
|
||||
innerParams.value.xPath.data = data;
|
||||
} else if (type === 'document') {
|
||||
innerParams.value.document.data = data;
|
||||
} else if (type === 'regular') {
|
||||
innerParams.value.regular = data;
|
||||
switch (type) {
|
||||
case ResponseBodyAssertionType.JSON_PATH:
|
||||
if (data.length > 1) {
|
||||
data.splice(data.length - 1, 1);
|
||||
}
|
||||
condition.value.jsonPathAssertion.assertions = data;
|
||||
emit('change', { ...defaultParamItem, ...condition.value, assertionBodyType: activeTab.value });
|
||||
break;
|
||||
case ResponseBodyAssertionType.XPATH:
|
||||
condition.value.xpathAssertion.assertions = data;
|
||||
emit('change', {
|
||||
...defaultParamItem,
|
||||
...condition.value,
|
||||
assertionBodyType: activeTab.value,
|
||||
responseFormat: activeResponseFormat.value,
|
||||
});
|
||||
break;
|
||||
case ResponseBodyAssertionType.DOCUMENT:
|
||||
condition.value.documentAssertion.jsonAssertion = data;
|
||||
break;
|
||||
case ResponseBodyAssertionType.REGEX:
|
||||
condition.value.regexAssertion.assertions = data;
|
||||
emit('change', { ...defaultParamItem, ...condition.value, assertionBodyType: activeTab.value });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
function handleExpressionChange(rowIndex: number) {
|
||||
|
@ -615,20 +641,22 @@
|
|||
* 提取参数表格-保存快速提取的配置
|
||||
*/
|
||||
function handleFastExtractionApply(config: RegexExtract | JSONPathExtract | XPathExtract) {
|
||||
// condition.value.extractParams = condition.value.extractParams?.map((e) => {
|
||||
// if (e.id === activeRecord.value.id) {
|
||||
// return {
|
||||
// ...e,
|
||||
// ...config,
|
||||
// };
|
||||
// }
|
||||
// return e;
|
||||
// });
|
||||
// fastExtractionVisible.value = false;
|
||||
// nextTick(() => {
|
||||
// extractParamsTableRef.value?.addTableLine();
|
||||
// });
|
||||
// emit('change');
|
||||
condition.value.jsonPathAssertion.assertions = condition.value.jsonPathAssertion.assertions?.map((e) => {
|
||||
if (e.id === activeRecord.value.id) {
|
||||
return {
|
||||
...e,
|
||||
...config,
|
||||
};
|
||||
}
|
||||
return e;
|
||||
});
|
||||
fastExtractionVisible.value = false;
|
||||
nextTick(() => {
|
||||
extractParamsTableRef.value?.addTableLine(
|
||||
condition.value.jsonPathAssertion.assertions?.findIndex((e) => e.id === activeRecord.value.id) || 0
|
||||
);
|
||||
});
|
||||
emit('change', { ...condition.value });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -672,9 +700,9 @@
|
|||
const addValidateChild = (record: Record<string, any>) => {
|
||||
if (record.groupId) {
|
||||
// 子项点击,找到父级
|
||||
const parent = innerParams.value.document.data.find((item: any) => item.id === record.groupId);
|
||||
const parent = condition.value.documentAssertion.jsonAssertion.find((item: any) => item.id === record.groupId);
|
||||
insertNode(
|
||||
innerParams.value.document.data,
|
||||
condition.value.documentAssertion.jsonAssertion,
|
||||
{ id: record.id, groupId: record.groupId },
|
||||
{
|
||||
...record,
|
||||
|
@ -688,18 +716,18 @@
|
|||
parent.rowSpan = parent.rowSpan ? parent.rowSpan + 1 : 2;
|
||||
} else {
|
||||
// 找到第一个子节点
|
||||
const fisrtChildNode = findFirstByGroupId(innerParams.value.document.data, record.groupId);
|
||||
const fisrtChildNode = findFirstByGroupId(condition.value.documentAssertion.jsonAssertion, record.groupId);
|
||||
if (fisrtChildNode) {
|
||||
fisrtChildNode.rowSpan = fisrtChildNode.rowSpan
|
||||
? fisrtChildNode.rowSpan + 1
|
||||
: countNodesByGroupId(innerParams.value.document.data, record.groupId) + 1;
|
||||
: countNodesByGroupId(condition.value.documentAssertion.jsonAssertion, record.groupId) + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
record.rowSpan = record.rowSpan ? record.rowSpan + 1 : 2;
|
||||
// 父级点击
|
||||
insertNode(
|
||||
innerParams.value.document.data,
|
||||
condition.value.documentAssertion.jsonAssertion,
|
||||
{ id: record.id, groupId: record.groupId },
|
||||
{
|
||||
...record,
|
||||
|
@ -712,23 +740,23 @@
|
|||
}
|
||||
};
|
||||
const showDeleteSingle = computed(() => {
|
||||
return countNodes(innerParams.value.document.data) > 1;
|
||||
return countNodes(condition.value.documentAssertion.jsonAssertion) > 1;
|
||||
});
|
||||
const deleteSingleParam = (record: Record<string, any>) => {
|
||||
deleteNodeById(innerParams.value.document.data, record.id);
|
||||
deleteNodeById(condition.value.documentAssertion.jsonAssertion, record.id);
|
||||
};
|
||||
const deleteAllParam = (record: Record<string, any>) => {
|
||||
if (record.groupId) {
|
||||
// 验证子项,根据groupId删除
|
||||
deleteNodesByGroupId(innerParams.value.document.data, record.groupId);
|
||||
deleteNodesByGroupId(condition.value.documentAssertion.jsonAssertion, record.groupId);
|
||||
} else if (record.rowspan > 2) {
|
||||
// 验证主体, 根据主体的id 作为groupId删除
|
||||
deleteNodesByGroupId(innerParams.value.document.data, record.id);
|
||||
deleteNodesByGroupId(condition.value.documentAssertion.jsonAssertion, record.id);
|
||||
// 删除本体
|
||||
deleteNodeById(innerParams.value.document.data, record.id);
|
||||
deleteNodeById(condition.value.documentAssertion.jsonAssertion, record.id);
|
||||
} else {
|
||||
// 删除本体
|
||||
deleteNodeById(innerParams.value.document.data, record.id);
|
||||
deleteNodeById(condition.value.documentAssertion.jsonAssertion, record.id);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -752,6 +780,6 @@
|
|||
}
|
||||
};
|
||||
const handleScriptChange = (data: ExecuteConditionProcessor) => {
|
||||
innerParams.value.script = data;
|
||||
condition.value.script = data;
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -11,86 +11,101 @@
|
|||
<a-doption v-for="item in assertOptionSource" :key="item.value" :value="item.value">{{ item.label }}</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<div v-if="showBody" class="ms-assertion-body">
|
||||
<VueDraggable v-model="assertions" class="ms-assertion-body-left" ghost-class="ghost" handle=".sort-handle">
|
||||
<div
|
||||
v-for="(item, index) in assertions"
|
||||
:key="item.id"
|
||||
class="ms-assertion-body-left-item"
|
||||
:class="{
|
||||
'ms-assertion-body-left-item-active': activeKey === item.id,
|
||||
'ms-assertion-body-left-item-active-focus': focusKey === item.id,
|
||||
}"
|
||||
@click="handleItemClick(item)"
|
||||
>
|
||||
<div class="ms-assertion-body-left-item-row">
|
||||
<span class="ms-assertion-body-left-item-row-num">{{ index + 1 }}</span>
|
||||
<span class="ms-assertion-body-left-item-row-title">{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="ms-assertion-body-left-item-switch">
|
||||
<div class="ms-assertion-body-left-item-switch-action">
|
||||
<MsIcon
|
||||
type="icon-icon_drag"
|
||||
class="action-btn-move sort-handle cursor-move text-[12px] text-[var(--color-text-4)]"
|
||||
/>
|
||||
<MsTableMoreAction
|
||||
:list="itemMoreActions"
|
||||
trigger="click"
|
||||
@select="handleMoreActionSelect($event, item)"
|
||||
@close="focusKey = ''"
|
||||
>
|
||||
<MsButton type="icon" size="mini" class="action-btn-more">
|
||||
<MsIcon
|
||||
type="icon-icon_more_outlined"
|
||||
size="14"
|
||||
class="text-[var(--color-text-4)]"
|
||||
@click="focusKey = item.id"
|
||||
/>
|
||||
</MsButton>
|
||||
</MsTableMoreAction>
|
||||
</div>
|
||||
|
||||
<a-switch v-model:model-value="item.enable" type="line" size="small" />
|
||||
<div v-if="showBody" class="ms-assertion-body">
|
||||
<a-scrollbar
|
||||
:style="{
|
||||
overflow: 'auto',
|
||||
height: 'calc(100vh - 458px)',
|
||||
}"
|
||||
>
|
||||
<VueDraggable v-model="assertions" class="ms-assertion-body-left" ghost-class="ghost" handle=".sort-handle">
|
||||
<div
|
||||
v-for="(item, index) in assertions"
|
||||
:key="item.id"
|
||||
class="ms-assertion-body-left-item"
|
||||
:class="{
|
||||
'ms-assertion-body-left-item-active': activeKey === item.id,
|
||||
'ms-assertion-body-left-item-active-focus': focusKey === item.id,
|
||||
}"
|
||||
@click="handleItemClick(item)"
|
||||
>
|
||||
<div class="ms-assertion-body-left-item-row">
|
||||
<span class="ms-assertion-body-left-item-row-num">{{ index + 1 }}</span>
|
||||
<span class="ms-assertion-body-left-item-row-title">{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="ms-assertion-body-left-item-switch">
|
||||
<div class="ms-assertion-body-left-item-switch-action">
|
||||
<MsIcon
|
||||
type="icon-icon_drag"
|
||||
class="action-btn-move sort-handle cursor-move text-[12px] text-[var(--color-text-4)]"
|
||||
/>
|
||||
<MsTableMoreAction
|
||||
:list="itemMoreActions"
|
||||
trigger="click"
|
||||
@select="handleMoreActionSelect($event, item)"
|
||||
@close="focusKey = ''"
|
||||
>
|
||||
<MsButton type="icon" size="mini" class="action-btn-more">
|
||||
<MsIcon
|
||||
type="icon-icon_more_outlined"
|
||||
size="14"
|
||||
class="text-[var(--color-text-4)]"
|
||||
@click="focusKey = item.id"
|
||||
/>
|
||||
</MsButton>
|
||||
</MsTableMoreAction>
|
||||
</div>
|
||||
|
||||
<a-switch v-model:model-value="item.enable" type="line" size="small" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VueDraggable>
|
||||
</VueDraggable>
|
||||
</a-scrollbar>
|
||||
<section class="ms-assertion-body-right">
|
||||
<!-- 响应头 -->
|
||||
<ResponseHeaderTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_HEADER"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 状态码 -->
|
||||
<StatusCodeTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_CODE"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 响应体 -->
|
||||
<ResponseBodyTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_BODY"
|
||||
:value="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 响应时间 -->
|
||||
<ResponseTimeTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_TIME"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 变量 -->
|
||||
<VariableTab
|
||||
v-if="valueKey === ResponseAssertionType.VARIABLE"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 脚本 -->
|
||||
<ScriptTab
|
||||
v-if="valueKey === ResponseAssertionType.SCRIPT"
|
||||
:value="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<a-scrollbar
|
||||
:style="{
|
||||
overflow: 'auto',
|
||||
height: '200px',
|
||||
}"
|
||||
>
|
||||
<!-- 响应头 -->
|
||||
<ResponseHeaderTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_HEADER"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 状态码 -->
|
||||
<StatusCodeTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_CODE"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 响应体 -->
|
||||
<ResponseBodyTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_BODY"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 响应时间 -->
|
||||
<ResponseTimeTab
|
||||
v-if="valueKey === ResponseAssertionType.RESPONSE_TIME"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 变量 -->
|
||||
<VariableTab
|
||||
v-if="valueKey === ResponseAssertionType.VARIABLE"
|
||||
v-model:data="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<!-- 脚本 -->
|
||||
<ScriptTab
|
||||
v-if="valueKey === ResponseAssertionType.SCRIPT"
|
||||
:value="getCurrentItemState"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</a-scrollbar>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -133,11 +148,50 @@
|
|||
const valueKey = computed(() => {
|
||||
return activeKey.value && assertions.value.find((item) => item.id === activeKey.value)?.assertionType;
|
||||
});
|
||||
const defaultResBodyItem = {
|
||||
jsonPathAssertion: {
|
||||
assertions: [],
|
||||
},
|
||||
xpathAssertion: { responseFormat: 'XML', assertions: [] },
|
||||
assertionBodyType: '',
|
||||
regexAssertion: {
|
||||
assertions: [],
|
||||
},
|
||||
// TODO文档暂时不做
|
||||
// documentAssertion: {
|
||||
// jsonAssertion: [
|
||||
// {
|
||||
// id: rootId,
|
||||
// paramsName: 'root',
|
||||
// mustInclude: false,
|
||||
// typeChecking: false,
|
||||
// paramType: 'object',
|
||||
// matchCondition: '',
|
||||
// matchValue: '',
|
||||
// },
|
||||
// ],
|
||||
// responseFormat: 'JSON',
|
||||
// followApi: false,
|
||||
// },
|
||||
};
|
||||
|
||||
// 计算当前页面的存储的状态
|
||||
const getCurrentItemState = computed({
|
||||
get: () => {
|
||||
return assertions.value.find((item) => item.id === activeKey.value);
|
||||
const currentResItem =
|
||||
assertions.value.find((item: any) => item.id === activeKey.value) || assertions.value[0] || {};
|
||||
if (currentResItem && currentResItem?.assertionType === ResponseAssertionType.RESPONSE_BODY) {
|
||||
const { jsonPathAssertion, xpathAssertion, regexAssertion } = currentResItem;
|
||||
return {
|
||||
...currentResItem,
|
||||
jsonPathAssertion: jsonPathAssertion || defaultResBodyItem.jsonPathAssertion,
|
||||
xpathAssertion: xpathAssertion || defaultResBodyItem.xpathAssertion,
|
||||
assertionBodyType: '',
|
||||
regexAssertion: regexAssertion || defaultResBodyItem.regexAssertion,
|
||||
bodyAssertionDataByType: {},
|
||||
};
|
||||
}
|
||||
return currentResItem;
|
||||
},
|
||||
set: (val: ExecuteAssertion) => {
|
||||
const currentIndex = assertions.value.findIndex((item) => item.id === activeKey.value);
|
||||
|
@ -223,11 +277,12 @@
|
|||
assertions: [],
|
||||
},
|
||||
xpathAssertion: {
|
||||
responseFormat: 'XML',
|
||||
assertions: [],
|
||||
},
|
||||
regexAssertion: {
|
||||
assertions: [],
|
||||
},
|
||||
// regexAssertion: {
|
||||
// assertions: [],
|
||||
// },
|
||||
bodyAssertionDataByType: {},
|
||||
});
|
||||
break;
|
||||
|
@ -284,6 +339,7 @@
|
|||
getCurrentItemState.value = { ...val };
|
||||
break;
|
||||
case ResponseAssertionType.RESPONSE_BODY:
|
||||
getCurrentItemState.value = { ...val };
|
||||
break;
|
||||
case ResponseAssertionType.RESPONSE_TIME:
|
||||
getCurrentItemState.value = { ...val };
|
||||
|
@ -300,7 +356,9 @@
|
|||
};
|
||||
|
||||
watchEffect(() => {
|
||||
console.log(getCurrentItemState.value);
|
||||
getCurrentItemState.value =
|
||||
assertions.value.find((item: any) => item.id === activeKey.value) || assertions.value[0] || {};
|
||||
activeKey.value = getCurrentItemState.value.id;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -317,7 +375,6 @@
|
|||
padding: 12px;
|
||||
width: 216px;
|
||||
min-width: 216px;
|
||||
height: calc(100vh - 394px);
|
||||
background-color: var(--color-text-n9);
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
|
|
@ -119,4 +119,8 @@ export const editorProps = {
|
|||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
widthClass: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -68,10 +68,9 @@ export const MEMBER = {
|
|||
value: '',
|
||||
options: [],
|
||||
props: {
|
||||
'multiple': false,
|
||||
multiple: false,
|
||||
// 'placeholder': t('formCreate.PleaseSelect'),
|
||||
'modelValue': '',
|
||||
'allow-clear': true,
|
||||
modelValue: '',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -82,11 +81,10 @@ export const MULTIPLE_MEMBER = {
|
|||
value: [],
|
||||
options: [],
|
||||
props: {
|
||||
'multiple': true,
|
||||
multiple: true,
|
||||
// 'placeholder': t('formCreate.PleaseSelect'),
|
||||
'options': [],
|
||||
'modelValue': [],
|
||||
'allow-clear': true,
|
||||
options: [],
|
||||
modelValue: [],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -657,7 +657,7 @@ export const pathMap: PathMapItem[] = [
|
|||
level: MENU_LEVEL[2],
|
||||
},
|
||||
{
|
||||
key: 'PROJECT_MANAGEMENT_COMMON_SCRIPT', // 项目管理-公共脚本
|
||||
key: ' PROJECT_CUSTOM_FUNCTION', // 项目管理-公共脚本
|
||||
locale: 'menu.projectManagement.commonScript',
|
||||
route: RouteEnum.PROJECT_MANAGEMENT_COMMON_SCRIPT,
|
||||
permission: [],
|
||||
|
|
|
@ -113,6 +113,7 @@ export enum ResponseBodyAssertionType {
|
|||
JSON_PATH = 'JSON_PATH',
|
||||
REGEX = 'REGEX', // 正则表达式
|
||||
XPATH = 'XPATH',
|
||||
SCRIPT = 'SCRIPT',
|
||||
}
|
||||
// 接口断言-响应体断言-文档类型
|
||||
export enum ResponseBodyAssertionDocumentType {
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { downloadByteFile, getGenerateId } from '@/utils';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
|
@ -279,12 +280,15 @@
|
|||
CreateOrUpdateCase,
|
||||
CustomAttributes,
|
||||
DetailCase,
|
||||
OptionsFieldId,
|
||||
StepList,
|
||||
} from '@/models/caseManagement/featureCase';
|
||||
import type { ModuleTreeNode, TableQueryParams } from '@/models/common';
|
||||
|
||||
import { convertToFile, initFormCreate } from './utils';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const appStore = useAppStore();
|
||||
|
@ -382,16 +386,33 @@
|
|||
const { customFields, id } = res;
|
||||
form.value.templateId = id;
|
||||
const result = customFields.map((item: any) => {
|
||||
const memberType = ['MEMBER', 'MULTIPLE_MEMBER'];
|
||||
let initValue = item.defaultValue;
|
||||
let optionsValue: OptionsFieldId[] = item.options;
|
||||
if (memberType.includes(item.type)) {
|
||||
optionsValue = [
|
||||
{
|
||||
fieldId: item.fieldId,
|
||||
internal: item.internal,
|
||||
text: userStore.name || '',
|
||||
value: userStore.id || '',
|
||||
},
|
||||
];
|
||||
if (item.defaultValue === 'CREATE_USER') {
|
||||
initValue = item.type === 'MEMBER' ? userStore.id : [userStore.id];
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: item.type,
|
||||
name: item.fieldId,
|
||||
label: item.fieldName,
|
||||
value: item.defaultValue,
|
||||
value: initValue,
|
||||
required: item.required,
|
||||
options: item.options || [],
|
||||
props: {
|
||||
modelValue: item.defaultValue,
|
||||
options: item.options || [],
|
||||
modelValue: initValue,
|
||||
options: optionsValue || [],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
tableSelectData: DefinedFieldItem[]; // 表格选择字段
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['confirm', 'update:visible', 'update-data']);
|
||||
const emit = defineEmits(['confirm', 'update:visible', 'update-data', 'brash']);
|
||||
|
||||
const totalList = ref<DefinedFieldItem[]>([]);
|
||||
|
||||
|
@ -229,9 +229,9 @@
|
|||
showAddDrawer.value = false;
|
||||
};
|
||||
|
||||
const okHandler = () => {
|
||||
const okHandler = (editFlag: boolean, fieldId: string) => {
|
||||
// eslint-disable-next-line vue/custom-event-name-casing
|
||||
emit('update-data');
|
||||
emit('update-data', editFlag, fieldId);
|
||||
};
|
||||
|
||||
watch(
|
||||
|
|
|
@ -182,6 +182,7 @@
|
|||
:table-select-data="(selectData as DefinedFieldItem[])"
|
||||
:mode="props.mode"
|
||||
@confirm="confirmHandler"
|
||||
@update-data="updateFieldHandler"
|
||||
/>
|
||||
<EditFieldDrawer
|
||||
ref="fieldDrawerRef"
|
||||
|
|
Loading…
Reference in New Issue