fix(测试跟踪): 功能用例公共用例库bug修改 (#8684)

--bug=1009040 --user=王孝刚 公共用例库bug https://www.tapd.cn/55049933/s/1084396

Co-authored-by: wxg0103 <727495428@qq.com>
This commit is contained in:
metersphere-bot 2021-12-21 20:35:16 +08:00 committed by GitHub
parent 894460a590
commit dccb66f289
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1047 additions and 19 deletions

View File

@ -1818,12 +1818,12 @@ public class ApiAutomationService {
List<String> scenarioNames = extApiScenarioMapper.selectNameByIdIn(scenarioIdList);
if (StringUtils.isNotEmpty(deleteScenarioName) && CollectionUtils.isNotEmpty(scenarioNames)) {
String nameListStr = "";
String nameListStr = "[";
for (String name : scenarioNames) {
nameListStr += name + ",";
}
if (nameListStr.length() > 1) {
nameListStr = nameListStr.substring(0, nameListStr.length() - 1) + "";
nameListStr = nameListStr.substring(0, nameListStr.length() - 1) + "]";
}
String msg = deleteScenarioName + " " + Translator.get("delete_check_reference_by") + ": " + nameListStr + " ";
checkMsgList.add(msg);

View File

@ -962,12 +962,12 @@ public class ApiTestCaseService {
String deleteCaseName = extApiTestCaseMapper.selectNameById(refreceId);
if (StringUtils.isNotEmpty(deleteCaseName) && CollectionUtils.isNotEmpty(scenarioNameList)) {
String nameListStr = "";
String nameListStr = "[";
for (String name : scenarioNameList) {
nameListStr += name + ",";
}
if (nameListStr.length() > 1) {
nameListStr = nameListStr.substring(0, nameListStr.length() - 1) + "";
nameListStr = nameListStr.substring(0, nameListStr.length() - 1) + "]";
}
String msg = deleteCaseName + " " + Translator.get("delete_check_reference_by") + ": " + nameListStr + " ";
checkMsgList.add(msg);

View File

@ -484,7 +484,7 @@ export default {
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: "生成依赖关系",
name: this.$t('test_track.case.generate_dependencies'),
handleClick: this.generateGraph,
isXPack: true,
permissions: ['PROJECT_API_SCENARIO:READ+EDIT']
@ -1057,7 +1057,7 @@ export default {
if (!checkResult.deleteFlag) {
alertMsg = "";
checkResult.checkMsg.forEach(item => {
alertMsg += item + ";";
alertMsg += item;
});
if (alertMsg === "") {
alertMsg = this.$t('load_test.delete_threadgroup_confirm') + " ";

View File

@ -467,6 +467,7 @@ export default {
if (this.validate(row)) {
return;
}
this.compare = [];
if (this.compare.indexOf(row.id) === -1) {
this.compare.push(row.id);
if (this.api.saved) {

View File

@ -6,7 +6,7 @@
<el-col :span="8" v-if="item.type !== 'richText'">
<el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name" :prop="item.name"
:label-width="formLabelWidth">
<custom-filed-component :data="item" :form="form" prop="defaultValue"/>
<custom-filed-component :data="item" :form="form" prop="defaultValue" :disabled="isPublic"/>
</el-form-item>
</el-col>
<div v-else>
@ -38,7 +38,13 @@ export default {
}
},
formLabelWidth: String,
form: Object
form: Object,
isPublic: {
type: Boolean,
default() {
return false;
}
}
},
computed: {
customFieldRowNums() {

View File

@ -49,6 +49,7 @@
:public-enable="true"
@refreshTable="refresh"
@testCaseEdit="editTestCase"
@testCaseEditShow="editTestCaseShow"
@testCaseCopy="copyTestCase"
@testCaseDetail="showTestCaseDetail"
@getTrashList="getTrashList"
@ -101,7 +102,7 @@
:label="item.label"
:name="item.name"
closable>
<div class="ms-api-scenario-div">
<div class="ms-api-scenario-div" v-if="!showPublic">
<test-case-edit
:currentTestCaseInfo="item.testCaseInfo"
@refresh="refreshTable"
@ -116,6 +117,22 @@
ref="testCaseEdit">
</test-case-edit>
</div>
<div class="ms-api-scenario-div" v-if="showPublic">
<test-case-edit-show
:currentTestCaseInfo="item.testCaseInfo"
@refresh="refreshTable"
@caseEdit="handleCaseCreateOrEdit($event,'edit')"
@caseCreate="handleCaseCreateOrEdit($event,'add')"
:read-only="testCaseReadOnly"
:tree-nodes="treeNodes"
:select-node="selectNode"
:select-condition="condition"
:type="type"
:is-public="publicEnable"
@addTab="addTabShow"
ref="testCaseEditShow">
</test-case-edit-show>
</div>
</el-tab-pane>
<el-tab-pane name="add" v-if="hasPermission('PROJECT_TRACK_CASE:READ+CREATE')">
<template v-slot:label>
@ -162,7 +179,7 @@ import MsTabButton from "@/business/components/common/components/MsTabButton";
import TestCaseMinder from "@/business/components/track/common/minder/TestCaseMinder";
import IsChangeConfirm from "@/business/components/common/components/IsChangeConfirm";
import {openMinderConfirm, saveMinderConfirm} from "@/business/components/track/common/minder/minderUtils";
import TestCaseEditShow from "@/business/components/track/case/components/TestCaseEditShow";
export default {
name: "TestCase",
components: {
@ -171,7 +188,7 @@ export default {
MsTabButton,
TestCaseNodeTree,
MsMainContainer,
MsAsideContainer, MsContainer, TestCaseList, NodeTree, TestCaseEdit, SelectMenu
MsAsideContainer, MsContainer, TestCaseList, NodeTree, TestCaseEdit, SelectMenu, TestCaseEditShow
},
comments: {},
data() {
@ -182,6 +199,7 @@ export default {
testCaseReadOnly: true,
trashEnable: false,
publicEnable: false,
showPublic: false,
condition: {},
activeName: 'default',
tabs: [],
@ -321,6 +339,7 @@ export default {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
this.showPublic = true
if (tab.name === 'add') {
let label = this.$t('test_track.case.create');
let name = getUUID().substring(0, 8);
@ -338,6 +357,21 @@ export default {
setCurTabId(this, tab, 'testCaseEdit');
},
addTabShow(tab) {
if (!this.projectId) {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
if (tab.name === 'show') {
this.showPublic = true
let label = this.$t('test_track.case.create');
let name = getUUID().substring(0, 8);
this.activeName = name;
label = tab.testCaseInfo.name;
this.tabs.push({label: label, name: name, testCaseInfo: tab.testCaseInfo});
}
setCurTabId(this, tab, 'testCaseEditShow');
},
handleTabClose() {
let message = "";
this.tabs.forEach(t => {
@ -458,6 +492,25 @@ export default {
this.activeName = index.name;
}
},
editTestCaseShow(testCase) {
const index = this.tabs.find(p => p.testCaseInfo && p.testCaseInfo.id === testCase.id);
if (!index) {
this.type = "edit";
this.testCaseReadOnly = false;
if (testCase.label !== "redirect") {
if (this.treeNodes.length < 1) {
this.$warning(this.$t('test_track.case.create_module_first'));
return;
}
}
let hasEditPermission = hasPermission('PROJECT_TRACK_CASE:READ+EDIT');
this.$set(testCase, 'rowClickHasPermission', hasEditPermission);
this.addTabShow({name: 'show', testCaseInfo: testCase});
} else {
this.activeName = index.name;
}
},
handleCaseCreateOrEdit(data, type) {
if (this.$refs.minder) {
this.$refs.minder.addCase(data, type);

View File

@ -0,0 +1,949 @@
<template>
<el-card>
<div class="card-content">
<div class="ms-main-div" @click="showAll">
<!--操作按钮-->
<div class="ms-opt-btn">
<el-tooltip :content="$t('commons.follow')" placement="bottom" effect="dark" v-if="!showFollow">
<i class="el-icon-star-off"
style="color: #783987; font-size: 25px; margin-right: 15px;cursor: pointer;position: relative;top: 5px "
@click="saveFollow"/>
</el-tooltip>
<el-tooltip :content="$t('commons.cancel')" placement="bottom" effect="dark" v-if="showFollow">
<i class="el-icon-star-on"
style="color: #783987; font-size: 28px; margin-right: 15px;cursor: pointer;position: relative;top: 5px "
@click="saveFollow"/>
</el-tooltip>
<el-link type="primary" style="margin-right: 20px" @click="openHis" v-if="form.id">
{{ $t('operating_log.change_history') }}
</el-link>
<ms-table-button v-if="this.path!=='/test/case/add'"
id="inputDelay"
type="primary"
:content="$t('commons.copy')"
size="small" @click="handleCopyPublic"
icon=""
:disabled="readOnly"/>
</div>
<el-form :model="form" :rules="rules" ref="caseFrom" v-loading="result.loading" class="case-form">
<ms-form-divider :title="$t('test_track.plan_view.base_info')"/>
<el-row>
<el-col :span="8">
<el-form-item
:placeholder="$t('test_track.case.input_name')"
:label="$t('test_track.case.name')"
:label-width="formLabelWidth"
prop="name">
<el-input :disabled="true" v-model="form.name" size="small" class="ms-case-input"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="$t('test_track.case.project')" :label-width="formLabelWidth" prop="projectId">
<el-select v-model="form.projectId" filterable clearable :disabled="true">
<el-option v-for="item in projectList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="$t('commons.tag')" :label-width="formLabelWidth" prop="tag">
<ms-input-tag :read-only="true" :currentScenario="form" v-if="showInputTag" ref="tag" :disabled="true"
class="ms-case-input"/>
</el-form-item>
</el-col>
</el-row>
<!-- 自定义字段 -->
<el-form v-if="isFormAlive" :model="customFieldForm" :rules="customFieldRules" ref="customFieldForm"
class="case-form">
<custom-filed-form-item :form="customFieldForm" :form-label-width="formLabelWidth"
:issue-template="testCaseTemplate" :is-public="isPublic"/>
</el-form>
<el-row v-if="isCustomNum">
<el-col :span="7">
<el-form-item label="ID" :label-width="formLabelWidth" prop="customNum">
<el-input :disabled="true" v-model.trim="form.customNum" size="small"
class="ms-case-input"></el-input>
</el-form-item>
</el-col>
</el-row>
<ms-form-divider :title="$t('test_track.case.step_info')"/>
<form-rich-text-item :disabled="true" :label-width="formLabelWidth"
:title="$t('test_track.case.prerequisite')" :data="form" prop="prerequisite"/>
<step-change-item :label-width="formLabelWidth" :form="form"/>
<form-rich-text-item :disabled="true" :label-width="formLabelWidth" v-if="form.stepModel === 'TEXT'"
:title="$t('test_track.case.step_desc')" :data="form" prop="stepDescription"/>
<form-rich-text-item :disabled="true" :label-width="formLabelWidth" v-if="form.stepModel === 'TEXT'"
:title="$t('test_track.case.expected_results')" :data="form" prop="expectedResult"/>
<test-case-step-item :label-width="formLabelWidth" v-if="form.stepModel === 'STEP' || !form.stepModel"
:form="form" :read-only="true"/>
<ms-form-divider :title="$t('test_track.case.other_info')"/>
<test-case-edit-other-info :read-only="true" :project-id="projectIds" :form="form"
:label-width="formLabelWidth" :case-id="form.id" ref="otherInfo"/>
<el-row style="margin-top: 10px" v-if="type!=='add'">
<el-col :span="20" :offset="1">{{ $t('test_track.review.comment') }}:
<el-button icon="el-icon-plus" type="mini" @click="openComment" :disabled="true"></el-button>
</el-col>
</el-row>
<el-row v-if="type!=='add'">
<el-col :span="20" :offset="1">
<review-comment-item v-for="(comment,index) in comments"
:key="index"
:comment="comment"
@refresh="getComments" :disabled="true"/>
<div v-if="comments.length === 0" style="text-align: center">
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
<span style="font-size: 15px; color: #8a8b8d;">
{{ $t('test_track.comment.no_comment') }}
</span>
</i>
</div>
</el-col>
</el-row>
<test-case-comment :case-id="form.id"
@getComments="getComments" ref="testCaseComment"/>
</el-form>
</div>
<ms-change-history ref="changeHistory"/>
</div>
<batch-move ref="testBatchMove" :public-enable="isPublic"
@copyPublic="copyPublic"/>
</el-card>
</template>
<script>
import {TokenKey} from '@/common/js/constants';
import MsDialogFooter from '../../../common/components/MsDialogFooter'
import {
getCurrentProjectID,
getCurrentUser,
getNodePath, getUUID,
handleCtrlSEvent, hasLicense, hasPermission,
listenGoBack,
removeGoBackListener
} from "@/common/js/utils";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import CaseComment from "@/business/components/track/case/components/CaseComment";
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
import MsPreviousNextButton from "../../../common/components/MsPreviousNextButton";
import {STEP} from "@/business/components/api/automation/scenario/Setting";
import TestCaseComment from "@/business/components/track/case/components/TestCaseComment";
import ReviewCommentItem from "@/business/components/track/review/commom/ReviewCommentItem";
import {API_STATUS, REVIEW_STATUS} from "@/business/components/api/definition/model/JsonData";
import MsTableButton from "@/business/components/common/components/MsTableButton";
import MsSelectTree from "../../../common/select-tree/SelectTree";
import MsTestCaseStepRichText from "./MsRichText";
import CustomFiledComponent from "@/business/components/settings/workspace/template/CustomFiledComponent";
import {
buildCustomFields,
buildTestCaseOldFields,
getTemplate,
parseCustomField
} from "@/common/js/custom_field";
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
import TestCaseEditOtherInfo from "@/business/components/track/case/components/TestCaseEditOtherInfo";
import FormRichTextItem from "@/business/components/track/case/components/FormRichTextItem";
import TestCaseStepItem from "@/business/components/track/case/components/TestCaseStepItem";
import StepChangeItem from "@/business/components/track/case/components/StepChangeItem";
import MsChangeHistory from "../../../history/ChangeHistory";
import {getTestTemplate} from "@/network/custom-field-template";
import CustomFiledFormItem from "@/business/components/common/components/form/CustomFiledFormItem";
import BatchMove from "@/business/components/track/case/components/BatchMove";
export default {
name: "TestCaseEditShow",
components: {
CustomFiledFormItem,
StepChangeItem,
TestCaseStepItem,
FormRichTextItem,
TestCaseEditOtherInfo,
MsFormDivider,
CustomFiledComponent,
MsTableButton,
MsSelectTree,
ReviewCommentItem,
TestCaseComment, MsPreviousNextButton, MsInputTag, CaseComment, MsDialogFooter, TestCaseAttachment,
MsTestCaseStepRichText,
MsChangeHistory,
BatchMove
},
data() {
return {
// sysList: [],//
path: "/test/case/add",
selectIds: [],
projectList: [],
publicEnable: false,
isXpack: false,
testCaseTemplate: {},
options: REVIEW_STATUS,
statuOptions: API_STATUS,
comments: [],
result: {},
dialogFormVisible: false,
showFollow: false,
form: {
name: '',
module: 'default-module',
nodePath: '/未规划用例',
maintainer: getCurrentUser().id,
priority: 'P0',
type: '',
method: '',
prerequisite: '',
testId: '',
otherTestName: '',
steps: [{
num: 1,
desc: '',
result: ''
}],
stepDesc: '',
stepResult: '',
selected: [],
remark: '',
tags: [],
demandId: '',
demandName: '',
status: 'Prepare',
reviewStatus: 'Prepare',
stepDescription: '',
expectedResult: '',
stepModel: 'STEP',
customNum: '',
followPeople: '',
},
maintainerOptions: [],
// testOptions: [],
workspaceId: '',
rules: {
name: [
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
{max: 255, message: this.$t('test_track.length_less_than') + '255', trigger: 'blur'}
],
module: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
customNum: [
{required: true, message: "ID必填", trigger: 'blur'},
{max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
],
demandName: [{required: true, message: this.$t('test_track.case.input_demand_name'), trigger: 'change'}],
maintainer: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
priority: [{required: true, message: this.$t('test_track.case.input_priority'), trigger: 'change'}],
method: [{required: true, message: this.$t('test_track.case.input_method'), trigger: 'change'}],
// prerequisite: [{max: 500, message: this.$t('test_track.length_less_than') + '500', trigger: 'blur'}],
// remark: [{max: 1000, message: this.$t('test_track.length_less_than') + '1000', trigger: 'blur'}]
},
customFieldRules: {},
customFieldForm: null,
formLabelWidth: "100px",
operationType: '',
isCreateContinue: false,
isStepTableAlive: true,
isFormAlive: true,
methodOptions: [
{value: 'auto', label: this.$t('test_track.case.auto')},
{value: 'manual', label: this.$t('test_track.case.manual')}
],
testCase: {},
testCases: [],
index: 0,
showInputTag: true,
tableType: "",
stepFilter: new STEP,
moduleObj: {
id: 'id',
label: 'name',
},
tabId: getUUID()
};
},
props: {
treeNodes: {
type: Array
},
currentTestCaseInfo: {},
selectNode: {
type: Object
},
selectCondition: {
type: Object
},
type: String,
isPublic: {
type: Boolean
}
},
computed: {
projectIds() {
return getCurrentProjectID();
},
moduleOptions() {
return this.$store.state.testCaseModuleOptions;
},
isCustomNum() {
return this.$store.state.currentProjectIsCustomNum;
},
readOnly() {
const {rowClickHasPermission} = this.currentTestCaseInfo;
if (rowClickHasPermission !== undefined) {
return !rowClickHasPermission;
}
return !hasPermission('PROJECT_TRACK_CASE:READ+CREATE') &&
!hasPermission('PROJECT_TRACK_CASE:READ+EDIT');
}
},
beforeDestroy() {
this.removeListener();
},
mounted() {
this.getSelectOptions();
if (this.type === 'edit' || this.type === 'copy') {
this.open(this.currentTestCaseInfo)
this.getComments(this.currentTestCaseInfo)
}
// Cascader : input
setInterval(function () {
document.querySelectorAll('.el-cascader-node__label').forEach(el => {
el.onclick = function () {
if (this.previousElementSibling) this.previousElementSibling.click();
};
});
}, 1000);
if (this.selectNode && this.selectNode.data && !this.form.id) {
this.form.module = this.selectNode.data.id;
this.form.nodePath = this.selectNode.data.path;
}
if ((!this.form.module || this.form.module === "default-module" || this.form.module === "root") && this.treeNodes.length > 0) {
this.form.module = this.treeNodes[0].id;
this.form.nodePath = this.treeNodes[0].path;
}
if (!(this.$store.state.testCaseMap instanceof Map)) {
this.$store.state.testCaseMap = new Map();
}
this.$store.state.testCaseMap.set(this.form.id, 0);
},
created() {
if (!this.projectList || this.projectList.length === 0) { //
this.$get("/project/listAll", (response) => {
this.projectList = response.data; //,
})
}
this.projectId = this.projectIds;
let initAddFuc = this.initAddFuc;
getTestTemplate()
.then((template) => {
this.testCaseTemplate = template;
this.$store.commit('setTestCaseTemplate', this.testCaseTemplate);
initAddFuc();
});
if (this.selectNode && this.selectNode.data && !this.form.id) {
this.form.module = this.selectNode.data.id;
this.form.nodePath = this.selectNode.data.path;
} else {
this.form.module = this.treeNodes && this.length > 0 ? this.treeNodes[0].id : "";
}
if (this.type === 'edit' || this.type === 'copy') {
this.form.module = this.currentTestCaseInfo.nodeId;
this.form.nodePath = this.currentTestCaseInfo.nodePath;
}
if ((!this.form.module || this.form.module === "default-module" || this.form.module === "root") && this.treeNodes.length > 0) {
this.form.module = this.treeNodes[0].id;
this.form.nodePath = this.treeNodes[0].path;
}
this.$get('/test/case/follow/' + this.currentTestCaseInfo.id, response => {
this.form.follows = response.data;
for (let i = 0; i < response.data.length; i++) {
if (response.data[i] === this.currentUser().id) {
this.showFollow = true;
break;
}
}
}),
this.result = this.$get('/project/get/' + this.projectId, res => {
let data = res.data;
if (data.casePublic) {
this.publicEnable = true;
}
})
if (hasLicense()) {
this.isXpack = true;
} else {
this.isXpack = false;
}
},
methods: {
currentUser: () => {
return getCurrentUser();
},
openHis() {
this.$refs.changeHistory.open(this.form.id, ["测试用例", "測試用例", "Test case"]);
},
setModule(id, data) {
this.form.module = id;
this.form.nodePath = data.path;
},
initAddFuc() {
// this.loadOptions();
this.addListener(); // ctrl s
if (this.selectNode && this.selectNode.data && !this.form.id) {
this.form.module = this.selectNode.data.id;
this.form.nodePath = this.selectNode.data.path;
} else {
this.form.module = this.treeNodes && this.length > 0 ? this.treeNodes[0].id : "";
}
if (this.type === 'edit' || this.type === 'copy') {
this.form.module = this.currentTestCaseInfo.nodeId;
this.form.nodePath = this.currentTestCaseInfo.nodePath;
}
if ((!this.form.module || this.form.module === "default-module" || this.form.module === "root") && this.treeNodes.length > 0) {
this.form.module = this.treeNodes[0].id;
this.form.nodePath = this.treeNodes[0].path;
}
if (this.type === 'add') {
//
this.customFieldForm = parseCustomField(this.form, this.testCaseTemplate, this.customFieldRules);
this.form.name = this.testCaseTemplate.caseName;
this.form.stepDescription = this.testCaseTemplate.stepDescription;
this.form.expectedResult = this.testCaseTemplate.expectedResult;
this.form.prerequisite = this.testCaseTemplate.prerequisite;
this.form.stepModel = this.testCaseTemplate.stepModel;
if (this.testCaseTemplate.steps) {
this.form.steps = JSON.parse(this.testCaseTemplate.steps);
}
}
},
setDefaultValue() {
if (!this.form.prerequisite) {
this.form.prerequisite = "";
}
if (!this.form.stepDescription) {
this.form.stepDescription = "";
}
if (!this.form.expectedResult) {
this.form.expectedResult = "";
}
if (!this.form.remark) {
this.form.remark = "";
}
this.$store.state.testCaseMap.set(this.form.id, 0);
},
handleCommand(e) {
if (e === "ADD_AND_CREATE") {
this.$refs['caseFrom'].validate((valid) => {
if (!valid) {
this.saveCase();
} else {
this.saveCase(function (t) {
let tab = {};
tab.name = 'add';
t.$emit('addTab', tab);
});
}
})
} else if (e === 'ADD_AND_PUBLIC') {
this.form.casePublic = true;
this.saveCase();
} else {
this.saveCase();
}
},
openComment() {
this.$refs.testCaseComment.open()
},
getComments(testCase) {
let id = '';
if (testCase) {
id = testCase.id;
} else {
id = this.form.id;
}
this.result = this.$get('/test/case/comment/list/' + id, res => {
this.comments = res.data;
})
},
showAll() {
if (!this.customizeVisible) {
this.operatingElements = this.stepFilter.get("ALL");
this.selectedTreeNode = undefined;
}
//this.reload();
},
reload() {
this.isStepTableAlive = false;
this.$nextTick(() => {
this.isStepTableAlive = true;
this.$store.state.testCaseMap.set(this.form.id, 0);
});
},
reloadForm() {
this.isFormAlive = false;
this.$nextTick(() => (this.isFormAlive = true));
},
open(testCase) {
/*
this.form.selected=[["automation", "3edaaf31-3fa4-4a53-9654-320205c2953a"],["automation", "3aa58bd1-c986-448c-8060-d32713dbd4eb"]]
*/
this.projectId = this.projectIds;
let initFuc = this.initEdit;
getTemplate('field/template/case/get/relate/', this)
.then((template) => {
this.testCaseTemplate = template;
this.$store.commit('setTestCaseTemplate', this.testCaseTemplate);
initFuc(testCase);
});
},
initEdit(testCase) {
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
window.addEventListener('popstate', this.close);
}
this.resetForm();
listenGoBack(this.close);
this.operationType = 'add';
if (testCase) {
//
this.operationType = 'edit';
//
if (this.type === 'copy') {
this.operationType = 'add';
this.setFormData(testCase);
this.setTestCaseExtInfo(testCase);
this.getSelectOptions();
//
this.customFieldForm = parseCustomField(this.form, this.testCaseTemplate, this.customFieldRules, buildTestCaseOldFields(this.form));
this.reload();
} else {
this.initTestCases(testCase);
}
} else {
if (this.selectNode.data) {
this.form.module = this.selectNode.data.id;
} else {
if (this.moduleOptions.length > 0) {
this.form.module = this.moduleOptions[0].id;
}
}
let user = JSON.parse(localStorage.getItem(TokenKey));
this.form.priority = 'P3';
this.form.type = 'functional';
this.form.method = 'manual';
this.form.maintainer = user.id;
this.form.tags = [];
this.getSelectOptions();
this.customFieldForm = parseCustomField(this.form, this.testCaseTemplate, this.customFieldRules);
this.reload();
}
},
handlePre() {
this.index--;
this.getTestCase(this.index)
},
handleNext() {
this.index++;
this.getTestCase(this.index);
},
initTestCases(testCase) {
this.selectCondition.workspaceId = null;
this.result = this.$post('/test/case/list/ids', this.selectCondition, response => {
this.testCases = response.data;
for (let i = 0; i < this.testCases.length; i++) {
if (this.testCases[i].id === testCase.id) {
this.index = i;
this.getTestCase(i);
}
}
});
},
getTestCase(index) {
let id = "";
this.showInputTag = false;
let testCase = this.testCases[index];
if (typeof (index) == "undefined") {
id = this.currentTestCaseInfo.id;
} else {
id = testCase.id;
}
this.result = this.$get('/test/case/get/' + id, response => {
if (response.data) {
this.path = "/test/case/edit";
if (this.currentTestCaseInfo.isCopy) {
this.path = "/test/case/add";
}
} else {
this.path = "/test/case/add";
}
let testCase = response.data;
this.setFormData(testCase);
this.setTestCaseExtInfo(testCase);
this.getSelectOptions();
this.reload();
this.$nextTick(() => {
this.showInputTag = true;
});
});
},
async setFormData(testCase) {
try {
testCase.selected = JSON.parse(testCase.testId);
} catch (error) {
testCase.selected = testCase.testId
}
let tmp = {};
Object.assign(tmp, testCase);
tmp.steps = JSON.parse(testCase.steps);
if (!tmp.steps || tmp.steps.length < 1) {
tmp.steps = [{
num: 1,
desc: '',
result: ''
}];
}
tmp.tags = JSON.parse(tmp.tags);
Object.assign(this.form, tmp);
if (!this.form.stepModel) {
this.form.stepModel = "STEP";
}
this.form.module = testCase.nodeId;
//
this.customFieldForm = parseCustomField(this.form, this.testCaseTemplate, this.customFieldRules, testCase ? buildTestCaseOldFields(this.form) : null);
this.setDefaultValue();
//
this.reloadForm();
},
setTestCaseExtInfo(testCase) {
this.testCase = {};
if (testCase) {
//
this.testCase = testCase.isCopy ? {} : testCase;
}
},
close() {
//
removeGoBackListener(this.close);
this.dialogFormVisible = false;
},
handleCopyPublic(testCase) {
this.selectIds.push(this.form.id);
this.$refs.testBatchMove.open(this.treeNodes, this.selectIds, this.moduleOptions);
},
copyPublic(param) {
param.condition = this.condition;
this.result = this.$post('/test/case/batch/copy/public', param, () => {
this.$success(this.$t('commons.save_success'));
this.$refs.testBatchMove.close();
this.$emit("refresh", this.form);
});
},
saveCase(callback) {
let isValidate = true;
this.$refs['caseFrom'].validate((valid) => {
if (!valid) {
isValidate = false;
return false;
}
});
this.$refs['customFieldForm'].validate((valid) => {
if (!valid) {
isValidate = false;
return false;
}
});
if (isValidate) {
this._saveCase(callback);
}
},
_saveCase(callback) {
let param = this.buildParam();
if (this.validate(param)) {
let option = this.getOption(param);
this.result = this.$request(option, (response) => {
this.$success(this.$t('commons.save_success'));
this.path = "/test/case/edit";
// this.operationType = "edit"
this.$emit("refreshTestCase",);
this.$store.state.testCaseMap.delete(this.form.id);
//this.tableType = 'edit';
this.$emit("refresh", this.form);
if (this.form.id) {
this.$emit("caseEdit", param);
} else {
param.id = response.data.id;
this.$emit("caseCreate", param);
this.close();
}
this.form.id = response.data.id;
if (callback) {
callback(this);
}
//
});
}
},
buildParam() {
let param = {};
Object.assign(param, this.form);
param.steps = JSON.stringify(this.form.steps);
param.nodeId = this.form.module;
param.nodePath = getNodePath(this.form.module, this.moduleOptions);
if (this.projectId) {
param.projectId = this.projectId;
}
param.name = param.name.trim();
if (this.form.tags instanceof Array) {
this.form.tags = JSON.stringify(this.form.tags);
}
param.testId = JSON.stringify(this.form.selected);
param.tags = this.form.tags;
param.type = 'functional';
buildCustomFields(this.form, param, this.testCaseTemplate);
this.parseOldFields(param);
return param;
},
parseOldFields(param) {
let customFieldsStr = param.customFields;
if (customFieldsStr) {
let customFields = JSON.parse(customFieldsStr);
customFields.forEach(item => {
if (item.name === '用例等级') {
param.priority = item.value;
}
if (item.name === '责任人') {
param.maintainer = item.value;
}
if (item.name === '用例状态') {
param.status = item.value;
}
});
}
},
getOption(param) {
let formData = new FormData();
if (this.$refs.otherInfo && this.$refs.otherInfo.uploadList) {
this.$refs.otherInfo.uploadList.forEach(f => {
formData.append("file", f);
});
}
if (this.$refs.otherInfo && this.$refs.otherInfo.fileList) {
if (param.isCopy) {
// copyID
param.fileIds = this.$refs.otherInfo.fileList.map(f => f.id);
}
param.updatedFileList = this.$refs.otherInfo.fileList;
} else {
param.fileIds = [];
param.updatedFileList = [];
}
let requestJson = JSON.stringify(param, function (key, value) {
return key === "file" ? undefined : value
});
formData.append('request', new Blob([requestJson], {
type: "application/json"
}));
return {
method: 'POST',
url: this.path,
data: formData,
headers: {
'Content-Type': undefined
}
};
},
validate(param) {
for (let i = 0; i < param.steps.length; i++) {
if ((param.steps[i].desc && param.steps[i].desc.length > 300) ||
(param.steps[i].result && param.steps[i].result.length > 300)) {
this.$warning(this.$t('test_track.case.step_desc') + ","
+ this.$t('test_track.case.expected_results') + this.$t('test_track.length_less_than') + '300');
return false;
}
}
if (param.name === '') {
this.$warning(this.$t('test_track.case.input_name'));
return false;
}
return true;
},
typeChange() {
this.form.testId = '';
},
getMaintainerOptions() {
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
this.maintainerOptions = response.data;
});
},
getSelectOptions() {
this.getMaintainerOptions();
},
resetForm() {
//
if (this.$refs['caseFrom']) {
this.$refs['caseFrom'].validate((valid) => {
this.$refs['caseFrom'].resetFields();
this._resetForm();
return true;
});
} else {
this._resetForm();
}
},
_resetForm() {
this.form.name = '';
this.form.module = '';
this.form.type = '';
this.form.method = '';
this.form.maintainer = '';
this.form.priority = '';
this.form.prerequisite = '';
this.form.remark = '';
this.form.testId = '';
this.form.testName = '';
this.form.steps = [{
num: 1,
desc: '',
result: ''
}];
this.form.customNum = '';
},
addListener() {
document.addEventListener("keydown", this.createCtrlSHandle);
},
removeListener() {
document.removeEventListener("keydown", this.createCtrlSHandle);
},
createCtrlSHandle(event) {
let curTabId = this.$store.state.curTabId;
if (curTabId === this.tabId)
handleCtrlSEvent(event, this.saveCase);
},
saveFollow() {
if (this.showFollow) {
this.showFollow = false;
for (let i = 0; i < this.form.follows.length; i++) {
if (this.form.follows[i] === this.currentUser().id) {
this.form.follows.splice(i, 1)
break;
}
}
if (this.path === "/test/case/edit") {
this.result.loading = true
this.$post('/test/case/edit/follows/' + this.form.id, this.form.follows, () => {
this.result.loading = false
this.$success(this.$t('commons.cancel_follow_success'));
});
}
} else {
this.showFollow = true;
if (!this.form.follows) {
this.form.follows = [];
}
this.form.follows.push(this.currentUser().id)
if (this.path === "/test/case/edit") {
this.result.loading = true
this.$post('/test/case/edit/follows/' + this.form.id, this.form.follows, () => {
this.result.loading = false
this.$success(this.$t('commons.follow_success'));
});
}
}
}
}
}
</script>
<style scoped>
.el-switch {
margin-bottom: 10px;
}
.case-name {
width: 194px;
}
.container {
height: 100vh;
}
.case-form {
height: 95%;
overflow: auto;
}
.case-dialog >>> .el-dialog__body {
padding: 0 20px 10px 20px;
}
.container >>> .el-card__body {
height: calc(100vh - 120px);
}
.comment-card >>> .el-card__header {
padding: 27px 20px;
}
.comment-card >>> .el-card__body {
height: calc(100vh - 120px);
}
.head-right {
text-align: right;
}
.ms-main-div {
background-color: white;
}
.ms-opt-btn {
position: fixed;
right: 50px;
z-index: 1;
}
.ms-case-input {
width: 100%;
}
.ms-case {
width: 100%;
}
/deep/ .el-button-group > .el-button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
height: 32px;
width: 56px;
}
.other-info-tabs {
padding-left: 60px;
margin-left: 40px;
}
</style>

View File

@ -12,6 +12,7 @@
:total="page.total"
:page-size.sync="page.pageSize"
:operators="operators"
operator-width="170px"
:screen-height="screenHeight"
:batch-operators="batchButtons"
:remember-order="true"
@ -406,6 +407,11 @@ export default {
}
],
publicOperators: [
{
tip: this.$t('commons.view'), icon: "el-icon-view",
exec: this.handleEditShow,
permissions: ['PROJECT_TRACK_CASE:READ'],
},
{
tip: this.$t('commons.edit'), icon: "el-icon-edit",
exec: this.handleEdit,
@ -757,6 +763,15 @@ export default {
});
}
},
handleEditShow(testCase, column) {
if (column.label !== this.$t('test_track.case.case_desc')) {
this.$get('test/case/get/' + testCase.id, response => {
let testCase = response.data;
this.$emit('testCaseEditShow', testCase);
});
}
},
isPublic(testCase) {
if (testCase.maintainer && testCase.maintainer !== getCurrentUserId()) {

View File

@ -75,7 +75,8 @@ export default {
treeNodes: [],
condition: {
filterText: "",
trashEnable: false
trashEnable: false,
publicEnable: false
},
operators: [
{

View File

@ -103,6 +103,7 @@ export default {
system_setting: 'Settings',
api: 'API',
encode: 'Encode',
view: 'view',
follow_api: 'Follow API definition',
response_time_delay: 'Response delay time',
my_workstation: 'MyWorkstation',
@ -219,7 +220,7 @@ export default {
run_completed: "Run Completed",
run_fail: "Run Fail",
run_warning: "Is running, please check later",
run_stop: "當前任務已停止,無法查看報告",
run_stop: "The current task has been stopped and the report cannot be viewed",
follow_success: "Follow Success",
cancel_follow_success: "Cancel Follow Success",
generate_test_data: "Generate test data",
@ -696,7 +697,7 @@ export default {
repeatable_info: 'After enabling, the interface definition repeatability check will not check the URL',
case_public: 'Public Library',
public: 'Start Public Library',
public_info: 'You can use public test case library data, or you can add test cases to the public test case library by yourself',
public_info: 'You can add test cases to the public test case library by yourself',
upload_file_again: 'Upload again',
code_segment: {
code_segment: "Custom Code",
@ -981,7 +982,7 @@ export default {
custom_ratio: 'Custom',
specify_resource: 'Specify node',
schedule_tip: 'The interval must not be less than the pressure measuring time',
delete_threadgroup_confirm: 'Confirm delete scenario: ',
delete_threadgroup_confirm: 'Confirm delete scenario',
scenario_list: 'Scenario List',
scenario_name: 'Scenario Name',
upload_jmx: 'Upload JMX',
@ -1091,7 +1092,7 @@ export default {
api_all: 'All interfaces',
unplanned_api: 'Unplanned interface',
id: 'Api Definition ID',
api_title: "Api test",
api_title: "Api Test",
case_title: "Test Case",
doc_title: "DOC",
api_name: "Api name",
@ -2314,7 +2315,7 @@ export default {
home: 'Home',
definition: 'Api Definition',
automation: 'Api Automation',
report: 'Test report',
report: 'Test Report',
},
ldap: {
url: 'LDAP URL',

View File

@ -105,6 +105,7 @@ export default {
api: '接口测试',
follow_api: '跟随API定义',
encode: '编码',
view: '查看',
response_time_delay: '响应延迟时间',
performance: '性能测试',
enable_settings: '启用设置',
@ -700,7 +701,7 @@ export default {
repeatable_info: '启用后接口定义重复性校验将不校验URL',
case_public: '公共用例库',
public: '启动公共用例库',
public_info: '可以使用公共用例库数据,也可以自行添加用例至公共用例库',
public_info: '可以自行添加用例至公共用例库',
upload_file_again: '重新上传',
code_segment: {
code_segment: "自定义代码片段",

View File

@ -105,6 +105,7 @@ export default {
api: '接口測試',
follow_api: '跟隨API定義',
encode: '編碼',
view: '查看',
response_time_delay: '響應延遲時間',
performance: '性能測試',
enable_settings: '啟用設置',
@ -700,7 +701,7 @@ export default {
repeatable_info: '啟用後接口定義重復性校驗將不校驗URL',
case_public: '公共用例庫',
public: '啟動公共用例庫',
public_info: '可以使用公共用例庫數據,也可以自行添加用例至公共用例庫',
public_info: '可以自行添加用例至公共用例庫',
upload_file_again: '重新上傳',
code_segment: {
code_segment: "自定義代碼片段",