feat(测试计划): 创建测试计划抽屉
This commit is contained in:
parent
9b0f27215a
commit
1fba073345
|
@ -1,6 +1,7 @@
|
||||||
import MSR from '@/api/http/index';
|
import MSR from '@/api/http/index';
|
||||||
import {
|
import {
|
||||||
addTestPlanModuleUrl,
|
addTestPlanModuleUrl,
|
||||||
|
AddTestPlanUrl,
|
||||||
DeleteTestPlanModuleUrl,
|
DeleteTestPlanModuleUrl,
|
||||||
GetTestPlanListUrl,
|
GetTestPlanListUrl,
|
||||||
GetTestPlanModuleCountUrl,
|
GetTestPlanModuleCountUrl,
|
||||||
|
@ -12,7 +13,7 @@ import {
|
||||||
import type { CreateOrUpdateModule, UpdateModule } from '@/models/caseManagement/featureCase';
|
import type { CreateOrUpdateModule, UpdateModule } from '@/models/caseManagement/featureCase';
|
||||||
import type { CommonList, MoveModules, TableQueryParams } from '@/models/common';
|
import type { CommonList, MoveModules, TableQueryParams } from '@/models/common';
|
||||||
import { ModuleTreeNode } from '@/models/common';
|
import { ModuleTreeNode } from '@/models/common';
|
||||||
import type { TestPlanItem } from '@/models/testPlan/testPlan';
|
import type { AddTestPlanParams, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||||
|
|
||||||
// 获取模块树
|
// 获取模块树
|
||||||
export function getTestPlanModule(params: TableQueryParams) {
|
export function getTestPlanModule(params: TableQueryParams) {
|
||||||
|
@ -48,3 +49,8 @@ export function getPlanModulesCounts(data: TableQueryParams) {
|
||||||
export function getTestPlanList(data: TableQueryParams) {
|
export function getTestPlanList(data: TableQueryParams) {
|
||||||
return MSR.post<CommonList<TestPlanItem>>({ url: GetTestPlanListUrl, data });
|
return MSR.post<CommonList<TestPlanItem>>({ url: GetTestPlanListUrl, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建测试计划
|
||||||
|
export function addTestPlan(data: AddTestPlanParams) {
|
||||||
|
return MSR.post({ url: AddTestPlanUrl, data });
|
||||||
|
}
|
||||||
|
|
|
@ -12,3 +12,5 @@ export const DeleteTestPlanModuleUrl = '/test-plan/module/delete';
|
||||||
export const GetTestPlanModuleCountUrl = '/test-plan/module/count';
|
export const GetTestPlanModuleCountUrl = '/test-plan/module/count';
|
||||||
// 测试计划列表
|
// 测试计划列表
|
||||||
export const GetTestPlanListUrl = '/test-plan/page';
|
export const GetTestPlanListUrl = '/test-plan/page';
|
||||||
|
// 创建测试计划
|
||||||
|
export const AddTestPlanUrl = '/test-plan/add';
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<a-collapse v-model:active-key="moreSettingActive" :bordered="false" :show-expand-icon="false">
|
||||||
|
<a-collapse-item :key="1">
|
||||||
|
<template #header>
|
||||||
|
<MsButton
|
||||||
|
type="text"
|
||||||
|
@click="() => (moreSettingActive.length > 0 ? (moreSettingActive = []) : (moreSettingActive = [1]))"
|
||||||
|
>
|
||||||
|
{{ t('common.moreSetting') }}
|
||||||
|
<icon-down v-if="moreSettingActive.length > 0" class="text-rgb(var(--primary-5))" />
|
||||||
|
<icon-right v-else class="text-rgb(var(--primary-5))" />
|
||||||
|
</MsButton>
|
||||||
|
</template>
|
||||||
|
<div class="mt-[24px]">
|
||||||
|
<slot name="content"></slot>
|
||||||
|
</div>
|
||||||
|
</a-collapse-item>
|
||||||
|
</a-collapse>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const moreSettingActive = ref<number[]>([]);
|
||||||
|
function clearMoreSettingActive() {
|
||||||
|
moreSettingActive.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
clearMoreSettingActive,
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -164,4 +164,6 @@ export default {
|
||||||
'common.unExecute': 'Not executed',
|
'common.unExecute': 'Not executed',
|
||||||
'common.pass': 'Pass',
|
'common.pass': 'Pass',
|
||||||
'common.unPass': 'Fail pass',
|
'common.unPass': 'Fail pass',
|
||||||
|
'common.belongModule': 'Belong module',
|
||||||
|
'common.moreSetting': 'More settings',
|
||||||
};
|
};
|
||||||
|
|
|
@ -164,4 +164,6 @@ export default {
|
||||||
'common.unExecute': '未执行',
|
'common.unExecute': '未执行',
|
||||||
'common.pass': '通过',
|
'common.pass': '通过',
|
||||||
'common.unPass': '不通过',
|
'common.unPass': '不通过',
|
||||||
|
'common.belongModule': '所属模块',
|
||||||
|
'common.moreSetting': '更多设置',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { BatchApiParams } from '../common';
|
||||||
|
|
||||||
// 计划分页
|
// 计划分页
|
||||||
export interface TestPlanItem {
|
export interface TestPlanItem {
|
||||||
id?: string;
|
id?: string;
|
||||||
|
@ -24,4 +26,31 @@ export interface ResourcesItem {
|
||||||
status: boolean;
|
status: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AssociateCaseRequest extends BatchApiParams {
|
||||||
|
functionalSelectIds?: string[];
|
||||||
|
apiSelectIds?: string[];
|
||||||
|
apiCaseSelectIds?: string[];
|
||||||
|
apiScenarioSelectIds?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddTestPlanParams {
|
||||||
|
id?: string;
|
||||||
|
name: string;
|
||||||
|
projectId: string;
|
||||||
|
groupId?: string;
|
||||||
|
moduleId: string;
|
||||||
|
cycle?: number[];
|
||||||
|
plannedStartTime?: number;
|
||||||
|
plannedEndTime?: number;
|
||||||
|
tags: string[];
|
||||||
|
description?: string;
|
||||||
|
testPlanning: boolean; // 是否开启测试规划
|
||||||
|
automaticStatusUpdate: boolean; // 是否自定更新功能用例状态
|
||||||
|
repeatCase: boolean; // 是否允许重复添加用例
|
||||||
|
passThreshold: number;
|
||||||
|
type: string;
|
||||||
|
baseAssociateCaseRequest: AssociateCaseRequest;
|
||||||
|
groupOption?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -164,10 +164,7 @@
|
||||||
if (isSetDefaultKey) {
|
if (isSetDefaultKey) {
|
||||||
selectedNodeKeys.value = [caseTree.value[0].id];
|
selectedNodeKeys.value = [caseTree.value[0].id];
|
||||||
}
|
}
|
||||||
emits(
|
emits('init', caseTree.value);
|
||||||
'init',
|
|
||||||
caseTree.value.map((e) => e.name)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
<template>
|
||||||
|
<MsDrawer
|
||||||
|
v-model:visible="innerVisible"
|
||||||
|
:title="form.id ? t('case.updateCase') : t('testPlan.testPlanIndex.createTestPlan')"
|
||||||
|
:width="800"
|
||||||
|
unmount-on-close
|
||||||
|
:ok-text="form.id ? 'common.update' : 'common.create'"
|
||||||
|
:save-continue-text="t('case.saveContinueText')"
|
||||||
|
:show-continue="!form.id"
|
||||||
|
:ok-loading="drawerLoading"
|
||||||
|
@confirm="handleDrawerConfirm(false)"
|
||||||
|
@continue="handleDrawerConfirm(true)"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<a-form ref="formRef" :model="form" layout="vertical">
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
:label="t('caseManagement.featureCase.planName')"
|
||||||
|
:rules="[{ required: true, message: t('testPlan.planForm.nameRequired') }]"
|
||||||
|
class="w-[732px]"
|
||||||
|
>
|
||||||
|
<a-input v-model="form.name" :max-length="255" :placeholder="t('testPlan.planForm.namePlaceholder')" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="description" :label="t('common.desc')" class="w-[732px]">
|
||||||
|
<a-textarea v-model:model-value="form.description" :placeholder="t('common.pleaseInput')" :max-length="1000" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="t('common.belongModule')" class="w-[436px]">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:modelValue="form.moduleId"
|
||||||
|
:data="props.moduleTree"
|
||||||
|
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
||||||
|
:tree-props="{
|
||||||
|
virtualListProps: {
|
||||||
|
height: 200,
|
||||||
|
threshold: 200,
|
||||||
|
},
|
||||||
|
}"
|
||||||
|
allow-search
|
||||||
|
:filter-tree-node="filterTreeNode"
|
||||||
|
>
|
||||||
|
<template #tree-slot-title="node">
|
||||||
|
<a-tooltip :content="`${node.name}`" position="tl">
|
||||||
|
<div class="inline-flex w-full">
|
||||||
|
<div class="one-line-text w-[240px] text-[var(--color-text-1)]">
|
||||||
|
{{ node.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="cycle"
|
||||||
|
:label="t('testPlan.planForm.planStartAndEndTime')"
|
||||||
|
asterisk-position="end"
|
||||||
|
class="w-[436px]"
|
||||||
|
>
|
||||||
|
<a-range-picker
|
||||||
|
v-model:model-value="form.cycle"
|
||||||
|
show-time
|
||||||
|
value-format="timestamp"
|
||||||
|
:separator="t('common.to')"
|
||||||
|
:time-picker-props="{
|
||||||
|
defaultValue: ['00:00:00', '00:00:00'],
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="tags" :label="t('common.tag')" class="w-[436px]">
|
||||||
|
<MsTagsInput v-model:model-value="form.tags" :max-tag-count="10" :max-length="50" />
|
||||||
|
</a-form-item>
|
||||||
|
<MsMoreSettingCollapse>
|
||||||
|
<template #content>
|
||||||
|
<div v-for="item in switchList" :key="item.key" class="mb-[24px] flex items-center gap-[8px]">
|
||||||
|
<a-switch v-model="form[item.key as keyof AddTestPlanParams] as boolean" size="small" />
|
||||||
|
{{ t(item.label) }}
|
||||||
|
<a-tooltip :position="item.tooltipPosition">
|
||||||
|
<template #content>
|
||||||
|
<div v-for="descItem in item.desc" :key="descItem">{{ t(descItem) }}</div>
|
||||||
|
</template>
|
||||||
|
<IconQuestionCircle class="h-[16px] w-[16px] text-[--color-text-4] hover:text-[rgb(var(--primary-5))]" />
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
<a-form-item field="passThreshold" :label="t('testPlan.planForm.passThreshold')">
|
||||||
|
<a-input-number
|
||||||
|
v-model:model-value="form.passThreshold"
|
||||||
|
size="small"
|
||||||
|
mode="button"
|
||||||
|
class="w-[120px]"
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
:default-value="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
</MsMoreSettingCollapse>
|
||||||
|
</a-form>
|
||||||
|
</MsDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { FormInstance, Message, TreeNodeData } from '@arco-design/web-vue';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
import MsMoreSettingCollapse from '@/components/pure/ms-more-setting-collapse/index.vue';
|
||||||
|
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||||
|
|
||||||
|
import { addTestPlan } from '@/api/modules/test-plan/testPlan';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
import { ModuleTreeNode } from '@/models/common';
|
||||||
|
import type { AddTestPlanParams } from '@/models/testPlan/testPlan';
|
||||||
|
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
|
||||||
|
|
||||||
|
interface SwitchListModel {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
desc: string[];
|
||||||
|
tooltipPosition: 'top' | 'tl' | 'tr' | 'bottom' | 'bl' | 'br' | 'left' | 'lt' | 'lb' | 'right' | 'rt' | 'rb';
|
||||||
|
}
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
moduleTree?: ModuleTreeNode[];
|
||||||
|
}>();
|
||||||
|
const innerVisible = defineModel<boolean>('visible', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const drawerLoading = ref(false);
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const initForm: AddTestPlanParams = {
|
||||||
|
name: '',
|
||||||
|
projectId: '',
|
||||||
|
moduleId: 'root',
|
||||||
|
cycle: [],
|
||||||
|
tags: [],
|
||||||
|
description: '',
|
||||||
|
testPlanning: false,
|
||||||
|
automaticStatusUpdate: true,
|
||||||
|
repeatCase: false,
|
||||||
|
passThreshold: 100,
|
||||||
|
type: testPlanTypeEnum.TEST_PLAN,
|
||||||
|
baseAssociateCaseRequest: { selectIds: [], selectAll: false, condition: {} },
|
||||||
|
};
|
||||||
|
const form = ref<AddTestPlanParams>(cloneDeep(initForm));
|
||||||
|
|
||||||
|
function filterTreeNode(searchValue: string, nodeData: TreeNodeData) {
|
||||||
|
return (nodeData as ModuleTreeNode).name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchList: SwitchListModel[] = [
|
||||||
|
{
|
||||||
|
key: 'repeatCase',
|
||||||
|
label: 'testPlan.planForm.associateRepeatCase',
|
||||||
|
tooltipPosition: 'bl',
|
||||||
|
desc: ['testPlan.planForm.repeatCaseTip1', 'testPlan.planForm.repeatCaseTip2'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function handleCancel() {
|
||||||
|
innerVisible.value = false;
|
||||||
|
formRef.value?.resetFields();
|
||||||
|
form.value = cloneDeep(initForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDrawerConfirm(isContinue: boolean) {
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
drawerLoading.value = true;
|
||||||
|
try {
|
||||||
|
// TODO 更新
|
||||||
|
const params: AddTestPlanParams = {
|
||||||
|
...cloneDeep(form.value),
|
||||||
|
plannedStartTime: form.value.cycle ? form.value.cycle[0] : undefined,
|
||||||
|
plannedEndTime: form.value.cycle ? form.value.cycle[1] : undefined,
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
};
|
||||||
|
if (!form.value?.id) {
|
||||||
|
await addTestPlan(params);
|
||||||
|
Message.success(t('common.createSuccess'));
|
||||||
|
}
|
||||||
|
// TODO 刷新外层数据
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
drawerLoading.value = false;
|
||||||
|
}
|
||||||
|
if (!isContinue) {
|
||||||
|
handleCancel();
|
||||||
|
}
|
||||||
|
form.value.name = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -9,7 +9,7 @@
|
||||||
:placeholder="t('caseManagement.featureCase.searchTip')"
|
:placeholder="t('caseManagement.featureCase.searchTip')"
|
||||||
allow-clear
|
allow-clear
|
||||||
/>
|
/>
|
||||||
<a-dropdown-button class="ml-2" type="primary" @click="handleSelect">
|
<a-dropdown-button class="ml-2" type="primary" @click="handleSelect('createPlan')">
|
||||||
{{ t('common.newCreate') }}
|
{{ t('common.newCreate') }}
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-down />
|
<icon-down />
|
||||||
|
@ -87,6 +87,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MsSplitBox>
|
</MsSplitBox>
|
||||||
|
<CreateAndEditPlanDrawer v-model:visible="showPlanDrawer" :module-tree="folderTree" />
|
||||||
</MsCard>
|
</MsCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -101,12 +102,14 @@
|
||||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||||
import PlanTable from './components/planTable.vue';
|
import PlanTable from './components/planTable.vue';
|
||||||
import TestPlanTree from './components/testPlanTree.vue';
|
import TestPlanTree from './components/testPlanTree.vue';
|
||||||
|
import CreateAndEditPlanDrawer from './createAndEditPlanDrawer.vue';
|
||||||
|
|
||||||
import { createPlanModuleTree } from '@/api/modules/test-plan/testPlan';
|
import { createPlanModuleTree } from '@/api/modules/test-plan/testPlan';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import type { CaseModuleQueryParams, CreateOrUpdateModule, ValidateInfo } from '@/models/caseManagement/featureCase';
|
import type { CaseModuleQueryParams, CreateOrUpdateModule, ValidateInfo } from '@/models/caseManagement/featureCase';
|
||||||
|
import type { ModuleTreeNode } from '@/models/common';
|
||||||
|
|
||||||
import Message from '@arco-design/web-vue/es/message';
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
|
@ -141,7 +144,6 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const addSubVisible = ref(false);
|
const addSubVisible = ref(false);
|
||||||
const rootModulesName = ref<string[]>([]);
|
|
||||||
const planTreeRef = ref();
|
const planTreeRef = ref();
|
||||||
const confirmLoading = ref(false);
|
const confirmLoading = ref(false);
|
||||||
const confirmRef = ref();
|
const confirmRef = ref();
|
||||||
|
@ -186,8 +188,11 @@
|
||||||
* 设置根模块名称列表
|
* 设置根模块名称列表
|
||||||
* @param names 根模块名称列表
|
* @param names 根模块名称列表
|
||||||
*/
|
*/
|
||||||
function setRootModules(names: string[]) {
|
const rootModulesName = ref<string[]>([]);
|
||||||
rootModulesName.value = names;
|
const folderTree = ref<ModuleTreeNode[]>([]);
|
||||||
|
function setRootModules(treeNode: ModuleTreeNode[]) {
|
||||||
|
folderTree.value = treeNode;
|
||||||
|
rootModulesName.value = treeNode.map((e) => e.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,7 +200,16 @@
|
||||||
*/
|
*/
|
||||||
function initModulesCount(params: any) {}
|
function initModulesCount(params: any) {}
|
||||||
|
|
||||||
function handleSelect() {}
|
const showPlanDrawer = ref(false);
|
||||||
|
function handleSelect(value: string | number | Record<string, any> | undefined) {
|
||||||
|
switch (value) {
|
||||||
|
case 'createPlan':
|
||||||
|
showPlanDrawer.value = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -60,4 +60,11 @@ export default {
|
||||||
'project.testPlanIndex.functionalUseCase': 'case',
|
'project.testPlanIndex.functionalUseCase': 'case',
|
||||||
'project.testPlanIndex.apiCase': 'Api use case',
|
'project.testPlanIndex.apiCase': 'Api use case',
|
||||||
'project.testPlanIndex.apiScenarioCase': 'Api scenario use cases',
|
'project.testPlanIndex.apiScenarioCase': 'Api scenario use cases',
|
||||||
|
'testPlan.planForm.namePlaceholder': 'Please enter the name of the test plan',
|
||||||
|
'testPlan.planForm.nameRequired': 'Test plan name cannot be empty',
|
||||||
|
'testPlan.planForm.planStartAndEndTime': 'Planned start and end time',
|
||||||
|
'testPlan.planForm.associateRepeatCase': 'Allow associated duplicate cases',
|
||||||
|
'testPlan.planForm.passThreshold': 'Pass threshold',
|
||||||
|
'testPlan.planForm.repeatCaseTip1': 'Enable: Repeatedly associate the same case',
|
||||||
|
'testPlan.planForm.repeatCaseTip2': 'Close: Cannot be associated with the same case repeatedly',
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,4 +60,11 @@ export default {
|
||||||
'project.testPlanIndex.functionalUseCase': '功能用例',
|
'project.testPlanIndex.functionalUseCase': '功能用例',
|
||||||
'project.testPlanIndex.apiCase': '接口用例',
|
'project.testPlanIndex.apiCase': '接口用例',
|
||||||
'project.testPlanIndex.apiScenarioCase': '接口场景用例',
|
'project.testPlanIndex.apiScenarioCase': '接口场景用例',
|
||||||
|
'testPlan.planForm.namePlaceholder': '请输入测试计划名称',
|
||||||
|
'testPlan.planForm.nameRequired': '测试计划名称不能为空',
|
||||||
|
'testPlan.planForm.planStartAndEndTime': '计划起止时间',
|
||||||
|
'testPlan.planForm.associateRepeatCase': '允许关联重复用例',
|
||||||
|
'testPlan.planForm.passThreshold': '通过阀值',
|
||||||
|
'testPlan.planForm.repeatCaseTip1': '开启:可重复关联同一个用例',
|
||||||
|
'testPlan.planForm.repeatCaseTip2': '关闭:不可重复关联同一用例',
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue