fix(all): 修复部分 bug

This commit is contained in:
baiqi 2024-04-03 18:54:04 +08:00 committed by Craftsman
parent cd57414bd2
commit 8438be13ee
14 changed files with 118 additions and 28 deletions

View File

@ -95,7 +95,7 @@ export const pathMap: PathMapItem[] = [
}, },
{ {
key: 'API_TEST_MANAGEMENT_RECYCLE', // 接口测试-回收站 key: 'API_TEST_MANAGEMENT_RECYCLE', // 接口测试-回收站
locale: 'menu.bugManagement.bugRecycle', locale: 'menu.apiTest.scenario.recycle',
route: RouteEnum.API_TEST_MANAGEMENT_RECYCLE, route: RouteEnum.API_TEST_MANAGEMENT_RECYCLE,
permission: [], permission: [],
level: MENU_LEVEL[2], level: MENU_LEVEL[2],
@ -103,15 +103,29 @@ export const pathMap: PathMapItem[] = [
], ],
}, },
{ {
key: 'API_SCENARIO_MANAGEMENT_SCENARIO', // 接口测试-场景 key: 'API_TEST_SCENARIO_MANAGEMENT', // 接口测试-场景
locale: 'menu.apiTest.scenario', locale: 'menu.apiTest.scenario',
route: RouteEnum.API_TEST_SCENARIO, route: RouteEnum.API_TEST_SCENARIO,
permission: [], permission: [],
level: MENU_LEVEL[2], level: MENU_LEVEL[2],
children: [ children: [
{ {
key: 'API_TEST_SCENARIO_RECYCLE', // 接口测试-回收站 key: 'API_TEST_SCENARIO_MANAGEMENT_SCENARIO', // 接口测试-场景
locale: 'menu.bugManagement.bugRecycle', locale: 'menu.apiTest.scenario',
route: RouteEnum.API_TEST_SCENARIO,
permission: [],
level: MENU_LEVEL[2],
},
{
key: 'API_TEST_SCENARIO_MANAGEMENT_MODULE', // 接口测试-场景-模块
locale: 'common.module',
route: RouteEnum.API_TEST_SCENARIO,
permission: [],
level: MENU_LEVEL[2],
},
{
key: 'API_TEST_SCENARIO_RECYCLE', // 接口测试-场景-回收站
locale: 'menu.apiTest.scenario.recycle',
route: RouteEnum.API_TEST_SCENARIO_RECYCLE, route: RouteEnum.API_TEST_SCENARIO_RECYCLE,
permission: [], permission: [],
level: MENU_LEVEL[2], level: MENU_LEVEL[2],

View File

@ -31,6 +31,7 @@ export default {
'menu.apiTest.management': 'API', 'menu.apiTest.management': 'API',
'menu.apiTest.management.definition': 'API', 'menu.apiTest.management.definition': 'API',
'menu.apiTest.scenario': 'Scenario', 'menu.apiTest.scenario': 'Scenario',
'menu.apiTest.scenario.recycle': 'Recycle',
'menu.apiTest.report': 'Report', 'menu.apiTest.report': 'Report',
'menu.uiTest': 'UI Test', 'menu.uiTest': 'UI Test',
'menu.performanceTest': 'Performance Test', 'menu.performanceTest': 'Performance Test',

View File

@ -32,6 +32,7 @@ export default {
'menu.apiTest.api': 'API列表', 'menu.apiTest.api': 'API列表',
'menu.apiTest.apiScenario': '场景', 'menu.apiTest.apiScenario': '场景',
'menu.apiTest.scenario': '场景', 'menu.apiTest.scenario': '场景',
'menu.apiTest.scenario.recycle': '回收站',
'menu.apiTest.report': '报告', 'menu.apiTest.report': '报告',
'menu.uiTest': 'UI测试', 'menu.uiTest': 'UI测试',
'menu.workstation': '工作台', 'menu.workstation': '工作台',

View File

@ -99,6 +99,7 @@ export default {
'apiTestDebug.storageByResult': 'Store by result', 'apiTestDebug.storageByResult': 'Store by result',
'apiTestDebug.storageByResultPlaceholder': 'E.g. {a}; Subsequent use such as {b}', 'apiTestDebug.storageByResultPlaceholder': 'E.g. {a}; Subsequent use such as {b}',
'apiTestDebug.extractParameter': 'Extract', 'apiTestDebug.extractParameter': 'Extract',
'apiTestDebug.sqlExtractParameter': 'Extract values by column',
'apiTestDebug.searchTip': 'Please enter a group name', 'apiTestDebug.searchTip': 'Please enter a group name',
'apiTestDebug.allRequest': 'All requests', 'apiTestDebug.allRequest': 'All requests',
'apiTestDebug.deleteFolderTipTitle': 'Remove the `{name}` module?', 'apiTestDebug.deleteFolderTipTitle': 'Remove the `{name}` module?',

View File

@ -93,6 +93,7 @@ export default {
'apiTestDebug.storageByResult': '按结果存储', 'apiTestDebug.storageByResult': '按结果存储',
'apiTestDebug.storageByResultPlaceholder': '如 {a}; 后续使用如{b}', 'apiTestDebug.storageByResultPlaceholder': '如 {a}; 后续使用如{b}',
'apiTestDebug.extractParameter': '提取参数', 'apiTestDebug.extractParameter': '提取参数',
'apiTestDebug.sqlExtractParameter': '按列提取值',
'apiTestDebug.searchTip': '请输入模块/请求名称', 'apiTestDebug.searchTip': '请输入模块/请求名称',
'apiTestDebug.allRequest': '全部请求', 'apiTestDebug.allRequest': '全部请求',
'apiTestDebug.deleteFolderTipTitle': '是否删除 {name} 模块?', 'apiTestDebug.deleteFolderTipTitle': '是否删除 {name} 模块?',

View File

@ -184,9 +184,9 @@
:max-length="255" :max-length="255"
class="flex-1" class="flex-1"
></a-input> ></a-input>
<MsButton type="text" @click="taskDrawerVisible = true">{{ <MsButton type="text" @click="taskDrawerVisible = true">
t('apiTestManagement.timeTaskList') {{ t('apiTestManagement.timeTaskList') }}
}}</MsButton> </MsButton>
</div> </div>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
@ -501,6 +501,11 @@
name: importForm.value.name, name: importForm.value.name,
}); });
Message.success(t('apiTestManagement.createTaskSuccess')); Message.success(t('apiTestManagement.createTaskSuccess'));
importForm.value = { ...defaultForm };
importFormRef.value?.resetFields();
importType.value = 'time';
fileList.value = [];
moreSettingActive.value = [];
taskDrawerVisible.value = true; taskDrawerVisible.value = true;
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console

View File

@ -14,6 +14,7 @@ export default {
'apiTestManagement.disableTaskSuccess': 'Closing the scheduled import task successfully', 'apiTestManagement.disableTaskSuccess': 'Closing the scheduled import task successfully',
'apiTestManagement.addSubModule': 'Add submodule', 'apiTestManagement.addSubModule': 'Add submodule',
'apiTestManagement.allApi': 'All api', 'apiTestManagement.allApi': 'All api',
'apiTestManagement.allCase': 'All case',
'apiTestManagement.searchTip': 'Please enter module/api name', 'apiTestManagement.searchTip': 'Please enter module/api name',
'apiTestManagement.moveSearchTip': 'Please enter the module name to search', 'apiTestManagement.moveSearchTip': 'Please enter the module name to search',
'apiTestManagement.noMatchModule': 'No matching module/api yet', 'apiTestManagement.noMatchModule': 'No matching module/api yet',

View File

@ -14,6 +14,7 @@ export default {
'apiTestManagement.disableTaskSuccess': '关闭定时导入任务成功', 'apiTestManagement.disableTaskSuccess': '关闭定时导入任务成功',
'apiTestManagement.addSubModule': '添加子模块', 'apiTestManagement.addSubModule': '添加子模块',
'apiTestManagement.allApi': '全部接口', 'apiTestManagement.allApi': '全部接口',
'apiTestManagement.allCase': '全部用例',
'apiTestManagement.searchTip': '请输入模块/接口名称', 'apiTestManagement.searchTip': '请输入模块/接口名称',
'apiTestManagement.moveSearchTip': '请输入模块名称搜索', 'apiTestManagement.moveSearchTip': '请输入模块名称搜索',
'apiTestManagement.noMatchModule': '暂无匹配的模块/接口', 'apiTestManagement.noMatchModule': '暂无匹配的模块/接口',

View File

@ -178,7 +178,6 @@
import { ref } from 'vue'; import { ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { cloneDeep } from 'lodash-es';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<div class="mb-[12px] flex items-center gap-[8px]"> <div class="mb-[8px] flex items-center gap-[8px]">
<a-input v-model:model-value="moduleKeyword" :placeholder="t('apiScenario.quoteTreeSearchTip')" allow-clear /> <a-input v-model:model-value="moduleKeyword" :placeholder="t('apiScenario.quoteTreeSearchTip')" allow-clear />
<a-tooltip :content="isExpandAll ? t('apiScenario.collapseAll') : t('apiScenario.expandAllStep')"> <a-tooltip :content="isExpandAll ? t('apiScenario.collapseAll') : t('apiScenario.expandAllStep')">
<a-button <a-button
@ -13,6 +13,14 @@
</a-button> </a-button>
</a-tooltip> </a-tooltip>
</div> </div>
<div class="folder" @click="setActiveFolder('all')">
<div :class="allFolderClass">
<MsIcon type="icon-icon_folder_filled1" class="folder-icon" />
<div class="folder-name">{{ folderText }}</div>
<div class="folder-count">({{ allScenarioCount }})</div>
</div>
</div>
<a-divider class="my-[8px]" />
<a-spin class="w-full" :loading="loading"> <a-spin class="w-full" :loading="loading">
<MsTree <MsTree
v-model:selected-keys="selectedKeys" v-model:selected-keys="selectedKeys"
@ -85,6 +93,26 @@
const isExpandAll = ref(false); const isExpandAll = ref(false);
const moduleCountMap = ref<Record<string, number>>({}); const moduleCountMap = ref<Record<string, number>>({});
const selectedKeys = ref<string[]>([]); const selectedKeys = ref<string[]>([]);
const folderText = computed(() => {
if (props.type === 'api') {
return t('apiTestManagement.allApi');
}
if (props.type === 'case') {
return t('apiTestManagement.allCase');
}
if (props.type === 'scenario') {
return t('apiScenario.tree.folder.allScenario');
}
});
const allScenarioCount = computed(() => moduleCountMap.value.all || 0);
const allFolderClass = computed(() =>
selectedKeys.value[0] === 'all' ? 'folder-text folder-text--active' : 'folder-text'
);
function setActiveFolder(id: string) {
selectedKeys.value = [id];
emit('select', [], { id, name: folderText.value });
}
/** /**
* 初始化模块树 * 初始化模块树
@ -104,8 +132,7 @@
} else if (type === 'scenario') { } else if (type === 'scenario') {
folderTree.value = await getScenarioModuleTree(params); folderTree.value = await getScenarioModuleTree(params);
} }
selectedKeys.value = [folderTree.value[0]?.id]; setActiveFolder('all');
emit('select', [folderTree.value[0]?.id], folderTree.value[0]);
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(error); console.log(error);
@ -154,6 +181,36 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.folder {
@apply flex cursor-pointer items-center justify-between;
padding: 8px 4px;
border-radius: var(--border-radius-small);
&:hover {
background-color: rgb(var(--primary-1));
}
.folder-text {
@apply flex flex-1 cursor-pointer items-center;
.folder-icon {
margin-right: 4px;
color: var(--color-text-4);
}
.folder-name {
color: var(--color-text-1);
}
.folder-count {
margin-left: 4px;
color: var(--color-text-4);
}
}
.folder-text--active {
.folder-icon,
.folder-name,
.folder-count {
color: rgb(var(--primary-5));
}
}
}
.expand-btn { .expand-btn {
padding: 8px; padding: 8px;
.arco-icon { .arco-icon {

View File

@ -5,6 +5,7 @@
:page-size="1" :page-size="1"
:total="props.loopTotal" :total="props.loopTotal"
:show-jumper="props.loopTotal > 5" :show-jumper="props.loopTotal > 5"
:base-size="Infinity"
show-total show-total
size="mini" size="mini"
class="loop-pagination" class="loop-pagination"

View File

@ -60,7 +60,11 @@
<div class="text-[var(--color-text-1)]">{{ t('common.fail') }}</div> <div class="text-[var(--color-text-1)]">{{ t('common.fail') }}</div>
<div class="text-[rgb(var(--success-6))]">{{ scenario.executeFailCount }}</div> <div class="text-[rgb(var(--success-6))]">{{ scenario.executeFailCount }}</div>
</div> </div>
<MsButton v-if="scenario.isDebug === false && !scenario.executeLoading" type="text" @click="checkReport"> <MsButton
v-if="scenario.isDebug === false && !scenario.executeLoading && !scenario.isNew"
type="text"
@click="checkReport"
>
{{ t('apiScenario.checkReport') }} {{ t('apiScenario.checkReport') }}
</MsButton> </MsButton>
</div> </div>
@ -267,6 +271,7 @@
function checkReport() { function checkReport() {
openNewPage(ApiTestRouteEnum.API_TEST_REPORT, { openNewPage(ApiTestRouteEnum.API_TEST_REPORT, {
type: 'API_SCENARIO',
reportId: scenario.value.reportId, reportId: scenario.value.reportId,
}); });
} }

View File

@ -1203,9 +1203,12 @@
function handleStopExecute(step?: ScenarioStepItem) { function handleStopExecute(step?: ScenarioStepItem) {
if (step?.reportId) { if (step?.reportId) {
const realStep = findNodeByKey<ScenarioStepItem>(steps.value, step.uniqueId, 'uniqueId');
websocketMap[step.reportId].close(); websocketMap[step.reportId].close();
step.isExecuting = false; if (realStep) {
step.executeStatus = undefined; realStep.isExecuting = false;
updateStepStatus([realStep as ScenarioStepItem], scenario.value.stepResponses);
}
} }
} }

View File

@ -311,6 +311,19 @@
setStepExecuteStatus(activeScenarioTab.value); setStepExecuteStatus(activeScenarioTab.value);
} }
const folderTree = ref<ModuleTreeNode[]>([]);
const folderTreePathMap = ref<Record<string, any>>({});
const activeModule = ref<string>('all');
const activeFolder = ref<string>('all');
const offspringIds = ref<string[]>([]);
const isShowScenario = ref(false);
//
const getActiveClass = (type: string) => {
return activeFolder.value === type ? 'folder-text case-active' : 'folder-text';
};
const recycleModulesCount = ref(0);
function newTab(defaultScenarioInfo?: Scenario, action?: 'copy' | 'execute') { function newTab(defaultScenarioInfo?: Scenario, action?: 'copy' | 'execute') {
if (defaultScenarioInfo) { if (defaultScenarioInfo) {
const isCopy = action === 'copy'; const isCopy = action === 'copy';
@ -382,7 +395,7 @@
...cloneDeep(defaultScenario), ...cloneDeep(defaultScenario),
id: getGenerateId(), id: getGenerateId(),
label: `${t('apiScenario.createScenario')}${scenarioTabs.value.length}`, label: `${t('apiScenario.createScenario')}${scenarioTabs.value.length}`,
moduleId: 'root', moduleId: activeModule.value === 'all' ? 'root' : activeModule.value,
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
priority: 'P0', priority: 'P0',
}); });
@ -390,19 +403,6 @@
activeScenarioTab.value = scenarioTabs.value[scenarioTabs.value.length - 1] as ScenarioParams; activeScenarioTab.value = scenarioTabs.value[scenarioTabs.value.length - 1] as ScenarioParams;
} }
const folderTree = ref<ModuleTreeNode[]>([]);
const folderTreePathMap = ref<Record<string, any>>({});
const activeModule = ref<string>('all');
const activeFolder = ref<string>('all');
const offspringIds = ref<string[]>([]);
const isShowScenario = ref(false);
//
const getActiveClass = (type: string) => {
return activeFolder.value === type ? 'folder-text case-active' : 'folder-text';
};
const recycleModulesCount = ref(0);
const scenarioModuleTreeRef = ref<InstanceType<typeof scenarioModuleTree>>(); const scenarioModuleTreeRef = ref<InstanceType<typeof scenarioModuleTree>>();
function handleModuleInit(tree: any, _protocol: string, pathMap: Record<string, any>) { function handleModuleInit(tree: any, _protocol: string, pathMap: Record<string, any>) {