refactor(接口测试): 响应内容增加断言和提取
This commit is contained in:
parent
0c49a5d4c1
commit
8464a2e39d
|
@ -14,15 +14,7 @@
|
|||
|
||||
<select id="list" resultType="io.metersphere.api.domain.ApiReport">
|
||||
select
|
||||
api_report.id,
|
||||
api_report.name,
|
||||
api_report.integrated,
|
||||
api_report.status,
|
||||
api_report.start_time,
|
||||
api_report.update_time,
|
||||
api_report.create_user,
|
||||
api_report.update_user,
|
||||
api_report.trigger_mode
|
||||
api_report.*
|
||||
from api_report where api_report.deleted = false
|
||||
and api_report.test_plan_id = 'NONE'
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
|
|
|
@ -14,15 +14,7 @@
|
|||
|
||||
<select id="list" resultType="io.metersphere.api.domain.ApiScenarioReport">
|
||||
select
|
||||
api_scenario_report.id,
|
||||
api_scenario_report.name,
|
||||
api_scenario_report.integrated,
|
||||
api_scenario_report.status,
|
||||
api_scenario_report.start_time,
|
||||
api_scenario_report.update_time,
|
||||
api_scenario_report.create_user,
|
||||
api_scenario_report.update_user,
|
||||
api_scenario_report.trigger_mode
|
||||
api_scenario_report.*
|
||||
from api_scenario_report where api_scenario_report.deleted = false
|
||||
and api_scenario_report.test_plan_id = 'NONE'
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
|
|
|
@ -757,15 +757,15 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
private ScenarioVariable getScenarioVariable() {
|
||||
ScenarioVariable scenarioVariable = new ScenarioVariable();
|
||||
CommonVariables commonVariables1 = new CommonVariables();
|
||||
commonVariables1.setType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables1.setParamType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables1.setKey("a");
|
||||
commonVariables1.setValue("b");
|
||||
CommonVariables commonVariables2 = new CommonVariables();
|
||||
commonVariables2.setType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables2.setParamType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables2.setKey("b");
|
||||
commonVariables2.setValue("c");
|
||||
CommonVariables commonVariables3 = new CommonVariables();
|
||||
commonVariables3.setType(VariableTypeConstants.LIST.name());
|
||||
commonVariables3.setParamType(VariableTypeConstants.LIST.name());
|
||||
commonVariables3.setKey("list1");
|
||||
commonVariables3.setValue("1,2,3");
|
||||
scenarioVariable.setCommonVariables(List.of(commonVariables1, commonVariables2, commonVariables3));
|
||||
|
|
|
@ -66,15 +66,15 @@ public class BaseEnvTestService {
|
|||
environmentConfig.setDataSources(List.of(dataSource));
|
||||
|
||||
CommonVariables commonVariables1 = new CommonVariables();
|
||||
commonVariables1.setType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables1.setParamType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables1.setKey("a");
|
||||
commonVariables1.setValue("c");
|
||||
CommonVariables commonVariables2 = new CommonVariables();
|
||||
commonVariables2.setType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables2.setParamType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables2.setKey("q");
|
||||
commonVariables2.setValue("qq");
|
||||
CommonVariables commonVariables3 = new CommonVariables();
|
||||
commonVariables3.setType(VariableTypeConstants.LIST.name());
|
||||
commonVariables3.setParamType(VariableTypeConstants.LIST.name());
|
||||
commonVariables3.setKey("list1");
|
||||
commonVariables3.setValue("1,2,3,5");
|
||||
environmentConfig.setCommonVariables(List.of(commonVariables1, commonVariables2, commonVariables3));
|
||||
|
|
|
@ -19,7 +19,7 @@ public class CommonVariables implements Serializable {
|
|||
@Schema(description = "变量名")
|
||||
private String key;
|
||||
@Schema(description = "变量类型 CONSTANT LIST JSON")
|
||||
private String type = VariableTypeConstants.CONSTANT.name();
|
||||
private String paramType = VariableTypeConstants.CONSTANT.name();
|
||||
@Schema(description = "变量值")
|
||||
private String value;
|
||||
@Schema(description = "状态")
|
||||
|
@ -32,17 +32,17 @@ public class CommonVariables implements Serializable {
|
|||
|
||||
@JsonIgnore
|
||||
public boolean isConstantValid() {
|
||||
return StringUtils.equals(this.type, VariableTypeConstants.CONSTANT.name()) && StringUtils.isNotEmpty(key);
|
||||
return StringUtils.equals(this.paramType, VariableTypeConstants.CONSTANT.name()) && StringUtils.isNotEmpty(key);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isListValid() {
|
||||
return StringUtils.equals(this.type, VariableTypeConstants.LIST.name()) && StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value) && value.indexOf(",") != -1;
|
||||
return StringUtils.equals(this.paramType, VariableTypeConstants.LIST.name()) && StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value) && value.indexOf(",") != -1;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isJsonValid() {
|
||||
return StringUtils.equals(this.type, VariableTypeConstants.JSON.name()) && StringUtils.isNotEmpty(key);
|
||||
return StringUtils.equals(this.paramType, VariableTypeConstants.JSON.name()) && StringUtils.isNotEmpty(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ public class GlobalParamsControllerTests extends BaseTest {
|
|||
envVariable.setValue("value" + i);
|
||||
envVariable.setDescription("desc" + i);
|
||||
envVariable.setTags(List.of("tag" + i));
|
||||
envVariable.setType(VariableTypeConstants.CONSTANT.name());
|
||||
envVariable.setParamType(VariableTypeConstants.CONSTANT.name());
|
||||
commonVariables.add(envVariable);
|
||||
}
|
||||
return commonVariables;
|
||||
|
|
|
@ -396,6 +396,8 @@ export interface ResponseResult {
|
|||
sslHandshakeTime: number;
|
||||
tcpHandshakeTime: number;
|
||||
transferStartTime: number;
|
||||
vars: string;
|
||||
assertions: any;
|
||||
}
|
||||
export interface RequestResult {
|
||||
body: string;
|
||||
|
|
|
@ -126,6 +126,8 @@ export const defaultResponse: RequestTaskResult = {
|
|||
tcpHandshakeTime: 0,
|
||||
transferStartTime: 0,
|
||||
sslHandshakeTime: 0,
|
||||
vars: '',
|
||||
assertions: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
</div>
|
||||
<MsBaseTable v-else-if="activeTab === 'ASSERTION'" v-bind="propsRes" v-on="propsEvent">
|
||||
<template #status="{ record }">
|
||||
<MsTag :type="record.status === 1 ? 'success' : 'danger'" theme="light">
|
||||
{{ record.status === 1 ? t('common.success') : t('common.fail') }}
|
||||
<MsTag :type="record.pass === true ? 'success' : 'danger'" theme="light">
|
||||
{{ record.pass === true ? t('common.success') : t('common.fail') }}
|
||||
</MsTag>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
|
@ -127,14 +127,14 @@
|
|||
label: t('apiTestDebug.console'),
|
||||
value: ResponseComposition.CONSOLE,
|
||||
},
|
||||
// {
|
||||
// label: t('apiTestDebug.extract'),
|
||||
// value: ResponseComposition.EXTRACT,
|
||||
// },
|
||||
// {
|
||||
// label: t('apiTestDebug.assertion'),
|
||||
// value: ResponseComposition.ASSERTION,
|
||||
// }, // TODO:断言暂时没加
|
||||
{
|
||||
label: t('apiTestDebug.extract'),
|
||||
value: ResponseComposition.EXTRACT,
|
||||
},
|
||||
{
|
||||
label: t('apiTestDebug.assertion'),
|
||||
value: ResponseComposition.ASSERTION,
|
||||
},
|
||||
];
|
||||
const activeTab = defineModel<ResponseComposition>('activeTab', {
|
||||
required: true,
|
||||
|
@ -179,10 +179,8 @@
|
|||
props.requestResult.headers
|
||||
}\nBody:\n${props.requestResult.body.trim()}`
|
||||
: '';
|
||||
// case ResponseComposition.EXTRACT:
|
||||
// return Object.keys(props.request.response.extract)
|
||||
// .map((e) => `${e}: ${props.request.response.extract[e]}`)
|
||||
// .join('\n'); // TODO:断言暂时没加
|
||||
case ResponseComposition.EXTRACT:
|
||||
return props.requestResult?.responseResult?.vars?.trim();
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
@ -196,34 +194,32 @@
|
|||
},
|
||||
{
|
||||
title: 'apiTestDebug.status',
|
||||
dataIndex: 'status',
|
||||
dataIndex: 'pass',
|
||||
slotName: 'status',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'desc',
|
||||
title: 'apiTestDebug.reason',
|
||||
dataIndex: 'message',
|
||||
showTooltip: true,
|
||||
},
|
||||
];
|
||||
const { propsRes, propsEvent } = useTable(() => Promise.resolve([]), {
|
||||
const { propsRes, propsEvent } = useTable(undefined, {
|
||||
scroll: { x: '100%' },
|
||||
columns,
|
||||
});
|
||||
propsRes.value.data = [
|
||||
{
|
||||
id: new Date().getTime(),
|
||||
content: 'Response Code equals: 200',
|
||||
status: 1,
|
||||
desc: '',
|
||||
|
||||
watch(
|
||||
() => props.requestResult?.responseResult.assertions,
|
||||
(val) => {
|
||||
if (val) {
|
||||
propsRes.value.data = props.requestResult?.responseResult.assertions || [];
|
||||
}
|
||||
},
|
||||
{
|
||||
id: new Date().getTime(),
|
||||
content: '$.users[1].age REGEX: 31',
|
||||
status: 0,
|
||||
desc: `Value expected to match regexp '31', but it did not match: '30' match: '30'`,
|
||||
},
|
||||
] as any;
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
@ -231,7 +227,7 @@
|
|||
margin-top: 8px;
|
||||
height: calc(100% - 48px);
|
||||
.response-header-pre {
|
||||
@apply h-full overflow-auto bg-white;
|
||||
@apply h-full overflow-auto bg-white;
|
||||
.ms-scroll-bar();
|
||||
|
||||
padding: 8px 12px;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
:all-names="rootModulesName"
|
||||
parent-id="NONE"
|
||||
:add-module-api="addDebugModule"
|
||||
@add-finish="initModules"
|
||||
@add-finish="handleAddFinish"
|
||||
>
|
||||
<MsButton type="icon" class="!mr-0 p-[2px]">
|
||||
<MsIcon
|
||||
|
@ -119,7 +119,7 @@
|
|||
:parent-id="nodeData.id"
|
||||
:add-module-api="addDebugModule"
|
||||
@close="resetFocusNodeKey"
|
||||
@add-finish="() => initModules()"
|
||||
@add-finish="handleAddFinish"
|
||||
>
|
||||
<MsButton type="icon" size="mini" class="ms-tree-node-extra__btn !mr-0" @click="setFocusNodeKey(nodeData)">
|
||||
<MsIcon type="icon-icon_add_outlined" size="14" class="text-[var(--color-text-4)]" />
|
||||
|
@ -167,7 +167,15 @@
|
|||
isExpandAll?: boolean; // 是否展开所有节点
|
||||
activeNodeId?: string | number; // 当前选中节点 id
|
||||
}>();
|
||||
const emit = defineEmits(['init', 'clickApiNode', 'newApi', 'import', 'renameFinish', 'deleteFinish']);
|
||||
const emit = defineEmits([
|
||||
'init',
|
||||
'clickApiNode',
|
||||
'newApi',
|
||||
'import',
|
||||
'renameFinish',
|
||||
'deleteFinish',
|
||||
'updateApiNode',
|
||||
]);
|
||||
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
|
@ -422,6 +430,7 @@
|
|||
targetId: dropNode.type === 'MODULE' ? dragNode.id : dropNode.id,
|
||||
moduleId: dropNode.type === 'API' ? dropNode.parentId : dropNode.id, // 释放节点是 API,则传入它所属模块id;模块的话直接是模块id
|
||||
});
|
||||
emit('updateApiNode', { ...dragNode, moduleId: dropNode.type === 'API' ? dropNode.parentId : dropNode.id });
|
||||
}
|
||||
Message.success(t('apiTestDebug.moduleMoveSuccess'));
|
||||
} catch (error) {
|
||||
|
@ -434,6 +443,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function handleAddFinish() {
|
||||
await initModules();
|
||||
initModuleCount();
|
||||
}
|
||||
|
||||
function moreActionsClose() {
|
||||
if (!renamePopVisible.value) {
|
||||
// 当下拉菜单关闭时,若不是触发重命名气泡显示,则清空聚焦节点 key
|
||||
|
|
|
@ -180,6 +180,7 @@ export default {
|
|||
'apiTestDebug.resourcePool': 'Resource pool',
|
||||
'apiTestDebug.content': 'Content',
|
||||
'apiTestDebug.status': 'Status',
|
||||
'apiTestDebug.reason': 'Reason',
|
||||
'apiTestDebug.requestName': 'Request name',
|
||||
'apiTestDebug.requestNameRequired': 'Request name cannot be empty',
|
||||
'apiTestDebug.requestNamePlaceholder': 'Please enter a request name',
|
||||
|
|
|
@ -169,6 +169,7 @@ export default {
|
|||
'apiTestDebug.resourcePool': '资源池',
|
||||
'apiTestDebug.content': '内容',
|
||||
'apiTestDebug.status': '状态',
|
||||
'apiTestDebug.reason': '原因',
|
||||
'apiTestDebug.requestName': '请求名称',
|
||||
'apiTestDebug.requestNameRequired': '请求名称不能为空',
|
||||
'apiTestDebug.requestNamePlaceholder': '请输入请求名称',
|
||||
|
|
Loading…
Reference in New Issue