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', // 接口测试-回收站
locale: 'menu.bugManagement.bugRecycle',
locale: 'menu.apiTest.scenario.recycle',
route: RouteEnum.API_TEST_MANAGEMENT_RECYCLE,
permission: [],
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',
route: RouteEnum.API_TEST_SCENARIO,
permission: [],
level: MENU_LEVEL[2],
children: [
{
key: 'API_TEST_SCENARIO_RECYCLE', // 接口测试-回收站
locale: 'menu.bugManagement.bugRecycle',
key: 'API_TEST_SCENARIO_MANAGEMENT_SCENARIO', // 接口测试-场景
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,
permission: [],
level: MENU_LEVEL[2],

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
<template>
<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-tooltip :content="isExpandAll ? t('apiScenario.collapseAll') : t('apiScenario.expandAllStep')">
<a-button
@ -13,6 +13,14 @@
</a-button>
</a-tooltip>
</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">
<MsTree
v-model:selected-keys="selectedKeys"
@ -85,6 +93,26 @@
const isExpandAll = ref(false);
const moduleCountMap = ref<Record<string, number>>({});
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') {
folderTree.value = await getScenarioModuleTree(params);
}
selectedKeys.value = [folderTree.value[0]?.id];
emit('select', [folderTree.value[0]?.id], folderTree.value[0]);
setActiveFolder('all');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
@ -154,6 +181,36 @@
</script>
<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 {
padding: 8px;
.arco-icon {

View File

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

View File

@ -60,7 +60,11 @@
<div class="text-[var(--color-text-1)]">{{ t('common.fail') }}</div>
<div class="text-[rgb(var(--success-6))]">{{ scenario.executeFailCount }}</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') }}
</MsButton>
</div>
@ -267,6 +271,7 @@
function checkReport() {
openNewPage(ApiTestRouteEnum.API_TEST_REPORT, {
type: 'API_SCENARIO',
reportId: scenario.value.reportId,
});
}

View File

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

View File

@ -311,6 +311,19 @@
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') {
if (defaultScenarioInfo) {
const isCopy = action === 'copy';
@ -382,7 +395,7 @@
...cloneDeep(defaultScenario),
id: getGenerateId(),
label: `${t('apiScenario.createScenario')}${scenarioTabs.value.length}`,
moduleId: 'root',
moduleId: activeModule.value === 'all' ? 'root' : activeModule.value,
projectId: appStore.currentProjectId,
priority: 'P0',
});
@ -390,19 +403,6 @@
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>>();
function handleModuleInit(tree: any, _protocol: string, pathMap: Record<string, any>) {