This commit is contained in:
chenjianxing 2020-09-18 11:50:16 +08:00
commit 5badcc3a21
14 changed files with 154 additions and 48 deletions

View File

@ -3,6 +3,7 @@ package io.metersphere.api.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.request.RequestType;
@ -23,7 +24,7 @@ public class MsParser extends ApiImportAbstractParser {
}
private String parsePluginFormat(String testStr) {
JSONObject testObject = JSONObject.parseObject(testStr);
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
if (testObject.get("scenarios") != null) {
return testStr;
} else {

View File

@ -10,7 +10,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
public class KafkaProperties {
public static final String KAFKA_PREFIX = "kafka";
private String acks;
private String acks = "all";
private String topic;
private String fields;
private String timestamp;

View File

@ -81,8 +81,8 @@ public class TestPlanController {
@PostMapping("/edit")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void editTestPlan(@RequestBody TestPlan testPlan) {
testPlanService.editTestPlan(testPlan);
public void editTestPlan(@RequestBody TestPlanDTO testPlanDTO) {
testPlanService.editTestPlan(testPlanDTO);
}
@PostMapping("/edit/status/{planId}")

View File

@ -4,8 +4,11 @@ import io.metersphere.base.domain.TestPlan;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class TestPlanDTO extends TestPlan {
private String projectName;
private List<String> projectIds;
}

View File

@ -34,6 +34,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
@ -110,12 +111,51 @@ public class TestPlanService {
return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlan());
}
public int editTestPlan(TestPlan testPlan) {
public int editTestPlan(TestPlanDTO testPlan) {
editTestPlanProject(testPlan);
testPlan.setUpdateTime(System.currentTimeMillis());
checkTestPlanExist(testPlan);
return testPlanMapper.updateByPrimaryKeySelective(testPlan);
}
private void editTestPlanProject(TestPlanDTO testPlan) {
List<String> projectIds = testPlan.getProjectIds();
if (!CollectionUtils.isEmpty(projectIds)) {
TestPlanProjectExample testPlanProjectExample1 = new TestPlanProjectExample();
testPlanProjectExample1.createCriteria().andTestPlanIdEqualTo(testPlan.getId());
List<TestPlanProject> testPlanProjects = testPlanProjectMapper.selectByExample(testPlanProjectExample1);
// 已经关联的项目idList
List<String> dbProjectIds = testPlanProjects.stream().map(TestPlanProject::getProjectId).collect(Collectors.toList());
// 修改后传过来的项目idList如果还未关联进行关联
projectIds.forEach(projectId -> {
if (!dbProjectIds.contains(projectId)) {
TestPlanProject testPlanProject = new TestPlanProject();
testPlanProject.setTestPlanId(testPlan.getId());
testPlanProject.setProjectId(projectId);
testPlanProjectMapper.insert(testPlanProject);
}
});
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
testPlanProjectExample.createCriteria().andTestPlanIdEqualTo(testPlan.getId()).andProjectIdNotIn(projectIds);
testPlanProjectMapper.deleteByExample(testPlanProjectExample);
// 关联的项目下的用例idList
TestCaseExample example = new TestCaseExample();
example.createCriteria().andProjectIdIn(projectIds);
List<TestCase> caseList = testCaseMapper.selectByExample(example);
List<String> caseIds = caseList.stream().map(TestCase::getId).collect(Collectors.toList());
// 取消关联所属项目下的用例和计划的关系
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
TestPlanTestCaseExample.Criteria criteria = testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(testPlan.getId());
if (!CollectionUtils.isEmpty(caseIds)) {
criteria.andCaseIdNotIn(caseIds);
}
testPlanTestCaseMapper.deleteByExample(testPlanTestCaseExample);
}
}
private void checkTestPlanExist(TestPlan testPlan) {
if (testPlan.getName() != null) {
TestPlanExample example = new TestPlanExample();

View File

@ -55,7 +55,7 @@ public class XmindToTestCaseParser {
// 递归处理案例数据
private void makeXmind(StringBuffer processBuffer, Attached parent, int level, String nodePath, List<Attached> attacheds) {
for (Attached item : attacheds) {
if (isBlack(item.getTitle(), "(?:tc|tc)")) { // 用例
if (isBlack(item.getTitle(), "(?:tc|tc:|tc)")) { // 用例
item.setParent(parent);
this.newTestCase(item.getTitle(), parent.getPath(), item.getChildren() != null ? item.getChildren().getAttached() : null);
} else {

View File

@ -40,7 +40,6 @@ spring.flyway.validate-on-migrate=false
spring.messages.basename=i18n/messages
# kafka
kafka.acks=1
kafka.fields=
kafka.timestamp=yyyy-MM-dd'T'HH:mm:ss.SSSZZ
kafka.sample-filter=

View File

@ -1,5 +1,13 @@
<template>
<el-col v-if="auth">
<el-row id="header-top1" type="flex" justify="space-between" align="middle">
<el-col>
<div class="license-head" v-if="valid === true && validData.status == 'expired'">License has expired since
{{(validData!= undefined && validData.license!= undefined) ? validData.license.expired:''}},please
update license.
</div>
</el-col>
</el-row>
<el-row id="header-top" type="flex" justify="space-between" align="middle">
<el-col :span="12">
@ -26,11 +34,22 @@
import MsHeaderOrgWs from "./components/common/head/HeaderOrgWs";
import MsLanguageSwitch from "./components/common/head/LanguageSwitch";
import {saveLocalStorage} from "../common/js/utils";
import {saveLicense} from "../common/js/utils";
import Setting from "@/business/components/settings/router";
export default {
name: 'app',
data() {
let xpack = false;
Setting.children.forEach(child => {
if (child.path === "license") {
xpack = true;
return;
}
})
return {
valid: xpack,
validData: {},
auth: false
}
},
@ -47,6 +66,15 @@
window.location.href = "/login"
});
},
beforeMount() {
if (this.valid === true) {
// license
this.result = this.$get("/license/valid", response => {
this.validData = response.data;
saveLicense(response.data);
});
}
},
components: {MsLanguageSwitch, MsUser, MsView, MsTopMenus, MsHeaderOrgWs},
methods: {}
}
@ -98,5 +126,13 @@
.align-right {
float: right;
}
.license-head {
height: 30px;
background: #BA331B;
text-align: center;
line-height: 30px;
color: white;
}
</style>

View File

@ -47,6 +47,7 @@
<script>
import {checkoutCurrentOrganization, checkoutCurrentWorkspace} from "@/common/js/utils";
import Setting from "@/business/components/settings/router";
import {LicenseKey} from '@/common/js/constants';
export default {
name: "MsSettingMenu",
@ -87,35 +88,35 @@
},
methods: {
valid() {
let _this = this;
this.result = this.$get("/license/valid", response => {
let data = response.data;
if (data === undefined || data === null || data.status != "valid") {
this.systems.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.systems.splice(this.systems.indexOf(item), 1);
}
})
let data = localStorage.getItem(LicenseKey);
if (data != undefined && data != null) {
data = JSON.parse(data);
}
if (data === undefined || data === null || data.status != "valid") {
this.systems.forEach(item => {
if (item.valid != undefined && item.valid === true) {
this.systems.splice(this.systems.indexOf(item), 1);
}
})
this.organizations.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.organizations.splice(this.organizations.indexOf(item), 1);
}
})
this.organizations.forEach(item => {
if (item.valid != undefined && item.valid === true) {
this.organizations.splice(this.organizations.indexOf(item), 1);
}
})
this.workspaces.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.workspaces.splice(this.workspaces.indexOf(item), 1);
}
})
this.workspaces.forEach(item => {
if (item.valid != undefined && item.valid === true) {
this.workspaces.splice(this.workspaces.indexOf(item), 1);
}
})
this.persons.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.persons.splice(this.persons.indexOf(item), 1);
}
})
}
})
this.persons.forEach(item => {
if (item.valid != undefined && item.valid === true) {
this.persons.splice(this.persons.indexOf(item), 1);
}
})
}
}
}
}

View File

@ -4,7 +4,7 @@
:close-on-click-modal="false"
class="ms-switch-project"
>
<ms-table-header :condition.sync="condition" @search="initData" title="" :show-create="false"/>
<ms-table-header :condition.sync="condition" @search="initData" title="切换项目" :show-create="false"/>
<el-table
:data="tableData"
highlight-current-row

View File

@ -24,7 +24,6 @@
<el-col :span="11" :offset="2">
<el-form-item :label="$t('test_track.plan.plan_project')" :label-width="formLabelWidth" prop="projectIds">
<el-select
:disabled="(form.status == null) ? false : true"
v-model="form.projectIds"
:placeholder="$t('test_track.plan.input_plan_project')"
multiple
@ -175,18 +174,34 @@ export default {
return;
}
param.workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/test/plan/' + this.operationType, param, () => {
this.$success(this.$t('commons.save_success'));
this.dialogFormVisible = false;
this.$emit("refresh");
// 广 head
TrackEvent.$emit(LIST_CHANGE);
});
if (this.operationType === 'edit') {
this.$confirm('取消项目关联会同时取消该项目下已关联的测试用例', '提示', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
this.editTestPlan(param);
}).catch(() => {
this.$info(this.$t('commons.cancel'))
});
} else {
this.editTestPlan(param);
}
} else {
return false;
}
});
},
editTestPlan(param) {
this.$post('/test/plan/' + this.operationType, param, () => {
this.$success(this.$t('commons.save_success'));
this.dialogFormVisible = false;
this.$emit("refresh");
// 广 head
TrackEvent.$emit(LIST_CHANGE);
});
},
getProjects() {
this.$get("/project/listAll", (response) => {
if (response.success) {

View File

@ -6,6 +6,7 @@
:title="operationType === 'edit' ? '编辑用例评审' : '创建用例评审'"
:visible.sync="dialogFormVisible"
@close="close"
v-loading="result.loading"
width="65%">
<el-form :model="form" :rules="rules" ref="reviewForm">
@ -122,6 +123,7 @@ export default {
data() {
return {
dialogFormVisible: false,
result: {},
form: {
name: '',
projectIds: [],
@ -187,7 +189,7 @@ export default {
});
},
getProjects() {
this.$get("/project/listAll", (response) => {
this.result = this.$get("/project/listAll", (response) => {
if (response.success) {
this.projects = response.data;
} else {
@ -197,7 +199,7 @@ export default {
},
setReviewerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.result = this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.reviewerOptions = response.data;
});
},

View File

@ -1,4 +1,5 @@
export const TokenKey = 'Admin-Token';
export const LicenseKey = 'License';
export const DEFAULT_LANGUAGE = 'default_language';
export const ROLE_ADMIN = 'admin';

View File

@ -5,7 +5,8 @@ import {
ROLE_TEST_MANAGER,
ROLE_TEST_USER,
ROLE_TEST_VIEWER,
TokenKey
TokenKey,
LicenseKey
} from "./constants";
import axios from "axios";
@ -90,6 +91,12 @@ export function saveLocalStorage(response) {
localStorage.setItem("roles", roles);
}
export function saveLicense(data) {
// 保存License
localStorage.setItem(LicenseKey, JSON.stringify(data));
}
export function refreshSessionAndCookies(sign, sourceId) {
axios.post(REFRESH_SESSION_USER_URL + "/" + sign + "/" + sourceId).then(r => {
saveLocalStorage(r.data);
@ -175,7 +182,7 @@ export function downloadFile(name, content) {
}
}
export function listenGoBack( callback) {
export function listenGoBack(callback) {
//监听浏览器返回操作,关闭该对话框
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
@ -189,9 +196,10 @@ export function removeGoBackListener(callback) {
export function getUUID() {
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}