feat(接口测试): curl导入解析
This commit is contained in:
parent
6020b0781c
commit
2ad6cc78d0
|
@ -5,12 +5,14 @@ import {
|
|||
GetPluginOptionsUrl,
|
||||
GetPluginScriptUrl,
|
||||
GetProtocolListUrl,
|
||||
ImportCurlUrl,
|
||||
LocalExecuteApiDebugUrl,
|
||||
StopExecuteUrl,
|
||||
StopLocalExecuteUrl,
|
||||
} from '@/api/requrls/api-test/common';
|
||||
|
||||
import {
|
||||
type CurlParseResult,
|
||||
ExecuteRequestParams,
|
||||
GetPluginOptionsParams,
|
||||
PluginConfig,
|
||||
|
@ -61,3 +63,8 @@ export function stopLocalExecute(host: string, id: string | number, type?: Scena
|
|||
export function stopExecute(id: string | number, type?: ScenarioStepType) {
|
||||
return MSR.get({ url: type ? `${StopExecuteUrl}/${type}/${id}` : `${StopExecuteUrl}/${id}` });
|
||||
}
|
||||
|
||||
// 导入curl
|
||||
export function importByCurl(curl: string) {
|
||||
return MSR.post<CurlParseResult>({ url: ImportCurlUrl, data: { curl } });
|
||||
}
|
||||
|
|
|
@ -6,3 +6,4 @@ export const GetEnvListUrl = '/api/test/env-list'; // 获取接口测试环境
|
|||
export const GetEnvironmentUrl = '/api/test/environment'; // 获取接口测试环境详情
|
||||
export const StopExecuteUrl = '/task/center/api/project/stop'; // 停止执行
|
||||
export const StopLocalExecuteUrl = '/api/stop'; // 停止本地执行
|
||||
export const ImportCurlUrl = '/api/debug/import-curl'; // 导入curl
|
||||
|
|
|
@ -463,3 +463,11 @@ export type ApiCaseReportDetail = {
|
|||
scriptIdentifier: string;
|
||||
content: RequestResult;
|
||||
};
|
||||
// curl解析结果
|
||||
export interface CurlParseResult {
|
||||
method: RequestMethods | string;
|
||||
url: string;
|
||||
headers: Record<string, any>;
|
||||
body: string;
|
||||
queryParams: Record<string, any>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
title-align="start"
|
||||
:width="680"
|
||||
:ok-disabled="curlCode.trim() === ''"
|
||||
:ok-text="t('common.import')"
|
||||
:ok-button-props="{
|
||||
disabled: curlCode.trim() === '',
|
||||
}"
|
||||
class="ms-modal-form"
|
||||
@cancel="curlCode = ''"
|
||||
@before-ok="handleCurlImportConfirm"
|
||||
>
|
||||
<template #title>
|
||||
<a-tooltip position="right" :content="t('apiTestDebug.importByCURLTip')">
|
||||
<span
|
||||
>{{ t('apiTestDebug.importByCURL') }}
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<div class="h-full">
|
||||
<MsCodeEditor
|
||||
v-if="visible"
|
||||
v-model:model-value="curlCode"
|
||||
theme="MS-text"
|
||||
height="500px"
|
||||
:language="LanguageEnum.PLAINTEXT"
|
||||
:show-theme-change="false"
|
||||
:show-full-screen="false"
|
||||
>
|
||||
</MsCodeEditor>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
|
||||
|
||||
import { importByCurl } from '@/api/modules/api-test/common';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
import type { CurlParseResult } from '@/models/apiTest/common';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done', res: CurlParseResult): void;
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const visible = defineModel('visible', {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
});
|
||||
|
||||
const importLoading = ref(false);
|
||||
const curlCode = ref('');
|
||||
|
||||
async function handleCurlImportConfirm(done: (closed: boolean) => void) {
|
||||
try {
|
||||
importLoading.value = true;
|
||||
const res = await importByCurl(curlCode.value);
|
||||
emit('done', res);
|
||||
done(true);
|
||||
Message.success(t('common.importSuccess'));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
importLoading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
|
@ -9,7 +9,7 @@
|
|||
@init="(val) => (folderTree = val)"
|
||||
@new-api="addDebugTab"
|
||||
@click-api-node="openApiTab"
|
||||
@import="importDrawerVisible = true"
|
||||
@import="importDialogVisible = true"
|
||||
@update-api-node="handleApiUpdateFromModuleTree"
|
||||
@delete-finish="handleDeleteFinish"
|
||||
/>
|
||||
|
@ -63,38 +63,7 @@
|
|||
</template>
|
||||
</MsSplitBox>
|
||||
</MsCard>
|
||||
<MsDrawer
|
||||
v-model:visible="importDrawerVisible"
|
||||
:width="680"
|
||||
:ok-disabled="curlCode.trim() === ''"
|
||||
disabled-width-drag
|
||||
@cancel="curlCode = ''"
|
||||
@confirm="handleCurlImportConfirm"
|
||||
>
|
||||
<template #title>
|
||||
<a-tooltip position="right" :content="t('apiTestDebug.importByCURLTip')">
|
||||
<span
|
||||
>{{ t('apiTestDebug.importByCURL') }}
|
||||
<icon-exclamation-circle
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<div class="h-full">
|
||||
<MsCodeEditor
|
||||
v-if="importDrawerVisible"
|
||||
v-model:model-value="curlCode"
|
||||
theme="MS-text"
|
||||
height="100%"
|
||||
:language="LanguageEnum.PLAINTEXT"
|
||||
:show-theme-change="false"
|
||||
:show-full-screen="false"
|
||||
>
|
||||
</MsCodeEditor>
|
||||
</div>
|
||||
</MsDrawer>
|
||||
<importCurlDialog v-model:visible="importDialogVisible" @done="handleImportCurlDone" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -105,14 +74,12 @@
|
|||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import MsEditableTab from '@/components/pure/ms-editable-tab/index.vue';
|
||||
import { TabItem } from '@/components/pure/ms-editable-tab/types';
|
||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||
import moduleTree from './components/moduleTree.vue';
|
||||
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
|
||||
import importCurlDialog from '@/views/api-test/components/importCurlDialog.vue';
|
||||
import requestComposition, { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
||||
|
||||
import { localExecuteApiDebug } from '@/api/modules/api-test/common';
|
||||
|
@ -128,9 +95,9 @@
|
|||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useLeaveTabUnSaveCheck from '@/hooks/useLeaveTabUnSaveCheck';
|
||||
import useRequestCompositionStore from '@/store/modules/api/requestComposition';
|
||||
import { parseCurlScript } from '@/utils';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
import { CurlParseResult } from '@/models/apiTest/common';
|
||||
import { ModuleTreeNode } from '@/models/common';
|
||||
import {
|
||||
ProtocolKeyEnum,
|
||||
|
@ -151,8 +118,7 @@
|
|||
|
||||
const moduleTreeRef = ref<InstanceType<typeof moduleTree>>();
|
||||
const folderTree = ref<ModuleTreeNode[]>([]);
|
||||
const importDrawerVisible = ref(false);
|
||||
const curlCode = ref('');
|
||||
const importDialogVisible = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
async function handleDebugAddDone() {
|
||||
|
@ -283,20 +249,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
function handleCurlImportConfirm() {
|
||||
const { url, headers, queryParameters, method } = parseCurlScript(curlCode.value);
|
||||
function handleImportCurlDone(res: CurlParseResult) {
|
||||
const { url, method, headers, queryParams } = res;
|
||||
addDebugTab({
|
||||
url,
|
||||
method: method?.toUpperCase() || RequestMethods.GET,
|
||||
headers:
|
||||
headers?.map((e) => ({
|
||||
Object.keys(headers)?.map((e) => ({
|
||||
contentType: RequestContentTypeEnum.TEXT,
|
||||
description: '',
|
||||
enable: true,
|
||||
...e,
|
||||
key: e,
|
||||
value: headers[e],
|
||||
})) || [],
|
||||
query:
|
||||
queryParameters?.map((e) => ({
|
||||
Object.keys(queryParams)?.map((e) => ({
|
||||
paramType: RequestParamsType.STRING,
|
||||
description: '',
|
||||
required: false,
|
||||
|
@ -304,11 +271,11 @@
|
|||
minLength: undefined,
|
||||
encode: false,
|
||||
enable: true,
|
||||
...e,
|
||||
key: e,
|
||||
value: queryParams[e],
|
||||
})) || [],
|
||||
});
|
||||
curlCode.value = '';
|
||||
importDrawerVisible.value = false;
|
||||
importDialogVisible.value = false;
|
||||
nextTick(() => {
|
||||
handleActiveDebugChange();
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<MsDrawer
|
||||
v-model:visible="visible"
|
||||
:width="960"
|
||||
|
@ -41,7 +42,6 @@
|
|||
</a-tooltip>
|
||||
<a-input
|
||||
v-if="isShowEditStepNameInput"
|
||||
ref="stepNameInputRef"
|
||||
v-model:model-value="requestVModel.stepName"
|
||||
class="flex-1"
|
||||
:placeholder="t('apiScenario.pleaseInputStepName')"
|
||||
|
@ -156,6 +156,14 @@
|
|||
<template v-if="showEnvPrefix" #prefix>
|
||||
{{ (appStore.currentEnvConfig as EnvConfig)?.httpConfig.find((e) => e.type === 'NONE')?.url }}
|
||||
</template>
|
||||
<template #suffix>
|
||||
<MsIcon
|
||||
type="icon-icon_curl"
|
||||
:size="18"
|
||||
class="cursor-pointer hover:text-[rgb(var(--primary-5))]"
|
||||
@click="importDialogVisible = true"
|
||||
/>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-input-group>
|
||||
</div>
|
||||
|
@ -339,6 +347,8 @@
|
|||
</div>
|
||||
<!-- <addDependencyDrawer v-model:visible="showAddDependencyDrawer" :mode="addDependencyMode" /> -->
|
||||
</MsDrawer>
|
||||
<importCurlDialog v-model:visible="importDialogVisible" @done="handleImportCurlDone" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -356,6 +366,7 @@
|
|||
import stepTypeVue from './stepType/stepType.vue';
|
||||
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
|
||||
import apiMethodSelect from '@/views/api-test/components/apiMethodSelect.vue';
|
||||
import importCurlDialog from '@/views/api-test/components/importCurlDialog.vue';
|
||||
import auth from '@/views/api-test/components/requestComposition/auth.vue';
|
||||
import { TabErrorMessage } from '@/views/api-test/components/requestComposition/index.vue';
|
||||
import postcondition from '@/views/api-test/components/requestComposition/postcondition.vue';
|
||||
|
@ -372,6 +383,7 @@
|
|||
import { getLocalStorage, setLocalStorage } from '@/utils/local-storage';
|
||||
|
||||
import {
|
||||
CurlParseResult,
|
||||
EnableKeyValueParam,
|
||||
ExecuteApiRequestFullParams,
|
||||
ExecuteBody,
|
||||
|
@ -1268,6 +1280,27 @@
|
|||
});
|
||||
}
|
||||
|
||||
const importDialogVisible = ref(false);
|
||||
function handleImportCurlDone(res: CurlParseResult) {
|
||||
const { url, method, headers, queryParams } = res;
|
||||
requestVModel.value.url = url;
|
||||
requestVModel.value.method = method;
|
||||
requestVModel.value.headers = Object.keys(headers).map((e) => ({
|
||||
...defaultHeaderParamsItem,
|
||||
key: e,
|
||||
value: headers[e],
|
||||
}));
|
||||
requestVModel.value.query = Object.keys(queryParams).map((e) => ({
|
||||
...defaultRequestParamsItem,
|
||||
key: e,
|
||||
value: queryParams[e],
|
||||
}));
|
||||
importDialogVisible.value = false;
|
||||
nextTick(() => {
|
||||
handleActiveDebugChange();
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.request?.uniqueId,
|
||||
() => {
|
||||
|
|
Loading…
Reference in New Issue