Merge remote-tracking branch 'origin/master'

This commit is contained in:
song.tianyang 2021-03-04 19:21:32 +08:00
commit 0c6704b742
16 changed files with 145 additions and 72 deletions

View File

@ -84,8 +84,7 @@ public class MsAuthManager extends MsTestElement {
authManager.setProperty(TestElement.TEST_CLASS, AuthManager.class.getName());
authManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AuthPanel"));
Authorization auth = new Authorization();
auth.setURL(samplerProxy.getUrl().toString());
auth.setDomain(samplerProxy.getDomain());
auth.setURL(samplerProxy.getProtocol() + "://" + samplerProxy.getDomain());
auth.setUser(msAuthManager.getUsername());
auth.setPass(msAuthManager.getPassword());
auth.setMechanism(AuthManager.Mechanism.DIGEST);

View File

@ -45,6 +45,10 @@ public class DateUtils {
SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_PATTERN);
return dateFormat.format(timeStamp);
}
public static String getDataStr(long timeStamp) {
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_PATTERM);
return dateFormat.format(timeStamp);
}
public static Date dateSum (Date date,int countDays){

View File

@ -50,4 +50,10 @@ public class TestPlanApiCaseController {
testPlanApiCaseService.deleteApiCaseBath(request);
}
@PostMapping("/batch/update/env")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void batchUpdateEnv(@RequestBody TestPlanApiCaseBatchRequest request) {
testPlanApiCaseService.batchUpdateEnv(request);
}
}

View File

@ -5,9 +5,20 @@ import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
@Getter
@Setter
public class TestPlanApiCaseBatchRequest extends TestPlanTestCase {
private List<String> ids;
/**
* 批量修改选中的数据
*/
private Map<String, String> selectRows;
/**
* 项目ID环境ID对应关系
*/
private Map<String, String> projectEnvMap;
}

View File

@ -12,6 +12,7 @@ import io.metersphere.api.dto.definition.request.MsThreadGroup;
import io.metersphere.api.service.ApiDefinitionExecResultService;
import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.base.domain.ApiTestCaseExample;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.TestPlanApiCase;
import io.metersphere.base.domain.TestPlanApiCaseExample;
@ -27,9 +28,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
@Service
@Transactional(rollbackFor = Exception.class)
@ -129,4 +128,19 @@ public class TestPlanApiCaseService {
request.setIds(extTestPlanApiCaseMapper.getNotRelevanceCaseIds(planId, relevanceProjectIds));
deleteApiCaseBath(request);
}
public void batchUpdateEnv(TestPlanApiCaseBatchRequest request) {
// 批量修改用例环境
Map<String, String> rows = request.getSelectRows();
Set<String> ids = rows.keySet();
Map<String, String> env = request.getProjectEnvMap();
if (env != null && !env.isEmpty()) {
ids.forEach(id -> {
TestPlanApiCase apiCase = new TestPlanApiCase();
apiCase.setId(id);
apiCase.setEnvironmentId(env.get(rows.get(id)));
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
});
}
}
}

View File

@ -48,7 +48,8 @@
"vuedraggable": "^2.24.3",
"vuex": "^3.1.2",
"xml-js": "^1.6.11",
"yan-progress": "^1.0.3"
"yan-progress": "^1.0.3",
"jsonpath": "^1.1.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.1.0",

View File

@ -133,7 +133,7 @@
<!-- 步骤组件-->
<ms-component-config :type="data.type" :scenario="data" :response="response" :currentScenario="currentScenario"
:currentEnvironmentId="currentEnvironmentId" :node="node" :project-list="projectList" :env-map="projectEnvMap"
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick" @refReload="reload"/>
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick" @refReload="refReload"/>
</span>
</el-tree>
</div>
@ -215,8 +215,8 @@
import ScenarioRelevance from "./api/ScenarioRelevance";
import MsComponentConfig from "./component/ComponentConfig";
import {handleCtrlSEvent} from "../../../../../common/js/utils";
import {getProject} from "@/business/components/api/automation/scenario/event";
import EnvPopover from "@/business/components/api/automation/scenario/EnvPopover";
let jsonPath = require('jsonpath');
export default {
name: "EditApiScenario",
props: {
@ -295,12 +295,6 @@
this.getApiScenario();
this.addListener(); // ctrl s
},
mounted() {
getProject.$on('addProjectEnv', (projectId, projectEnv) => {
this.projectIds.add(projectId);
// this.projectEnvMap.set(projectId, projectEnv);
})
},
directives: {OutsideClick},
computed: {
buttons() {
@ -397,7 +391,7 @@
},
{
title: this.$t('api_test.automation.scenario_import'),
show: this.operatingElements && this.operatingElements.indexOf('scenario') === 0,
show:this.showButton("scenario"),
titleColor: "#606266",
titleBgColor: "#F4F4F5",
icon: "movie",
@ -583,6 +577,7 @@
}
this.sort();
this.reload();
this.initProjectIds();
this.scenarioVisible = false;
},
setApiParameter(item, refType, referenced) {
@ -624,6 +619,7 @@
});
this.sort();
this.reload();
this.initProjectIds();
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
@ -647,15 +643,10 @@
const parent = node.parent
const hashTree = parent.data.hashTree || parent.data;
const index = hashTree.findIndex(d => d.resourceId != undefined && row.resourceId != undefined && d.resourceId === row.resourceId)
if (hashTree[index] && hashTree[index].projectId) {
this.projectIds.delete(hashTree[index].projectId);
if (this.projectEnvMap.has(hashTree[index].projectId)) {
this.projectEnvMap.delete(hashTree[index].projectId);
}
}
hashTree.splice(index, 1);
this.sort();
this.reload();
this.initProjectIds();
}
}
});
@ -928,6 +919,7 @@
}
this.enableCookieShare = obj.enableCookieShare;
this.scenarioDefinition = obj.hashTree;
this.initProjectIds();
}
}
if (this.currentScenario.copy) {
@ -992,9 +984,6 @@
}
return size;
},
beforeDestroy() {
getProject.$off('addProjectEnv');
},
handleEnv() {
this.$refs.apiScenarioEnv.open();
},
@ -1006,6 +995,18 @@
this.projectList = res.data;
})
},
refReload() {
this.initProjectIds();
this.reload();
},
initProjectIds() {
//
this.projectIds.clear();
this.scenarioDefinition.forEach(data=>{
let arr = jsonPath.query(data, "$..projectId");
arr.forEach(a => this.projectIds.add(a));
})
}
}
}
</script>

View File

@ -62,7 +62,9 @@ export default {
//
let temp = this.data.find(dt => dt.id === id);
temp.envs = envs;
temp.selectEnv = this.envMap.get(id);
let envId = this.envMap.get(id);
//
temp.selectEnv = envs.filter(e =>e.id === envId).length === 0 ? null : envId;
})
})
},

View File

@ -6,7 +6,7 @@ export const ELEMENTS = new Map([
['JDBCSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
['TCPSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
['OT_IMPORT', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
['IfController', ["IfController", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['IfController', ["IfController","scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['LoopController', ["IfController", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
['ConstantTimer', []],
['JSR223Processor', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],

View File

@ -71,7 +71,6 @@
import ApiBaseComponent from "../common/ApiBaseComponent";
import ApiResponseComponent from "./ApiResponseComponent";
import CustomizeReqInfo from "@/business/components/api/automation/scenario/common/CustomizeReqInfo";
import {getProject} from "@/business/components/api/automation/scenario/event";
export default {
name: "MsApiComponent",
@ -123,7 +122,6 @@
}
}
}
getProject.$emit('addProjectEnv', this.request.projectId, this.currentEnvironmentId);
},
computed: {
displayColor() {

View File

@ -29,7 +29,6 @@
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
import ApiBaseComponent from "../common/ApiBaseComponent";
import {getProject} from "@/business/components/api/automation/scenario/event";
import {getCurrentProjectID} from "@/common/js/utils";
export default {
@ -49,7 +48,6 @@
if (!this.scenario.projectId) {
this.scenario.projectId = getCurrentProjectID();
}
getProject.$emit('addProjectEnv', this.scenario.projectId, this.currentEnvironmentId);
if (this.scenario.id && this.scenario.referenced === 'REF' && !this.scenario.loaded) {
this.result = this.$get("/api/automation/getApiScenario/" + this.scenario.id, response => {
if (response.data) {

View File

@ -1,2 +0,0 @@
import Vue from 'vue';
export const getProject = new Vue();

View File

@ -14,7 +14,11 @@
<el-option v-for="(type, index) in typeArr" :key="index" :value="type.id" :label="type.name"/>
</el-select>
</el-form-item>
<el-form-item :label="$t('test_track.case.updated_attr_value')" prop="value">
<el-form-item v-if="form.type === 'projectEnv'" :label="$t('test_track.case.updated_attr_value')">
<env-popover :env-map="projectEnvMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
:project-list="projectList" ref="envPopover"/>
</el-form-item>
<el-form-item v-else :label="$t('test_track.case.updated_attr_value')" prop="value">
<el-select v-model="form.value" style="width: 80%" :filterable="filterable">
<el-option v-for="(option, index) in options" :key="index" :value="option.id" :label="option.name">
<div v-if="option.email">
@ -35,11 +39,13 @@
<script>
import MsDialogFooter from "../../../common/components/MsDialogFooter";
import {listenGoBack, removeGoBackListener} from "../../../../../common/js/utils";
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
import EnvPopover from "@/business/components/api/automation/scenario/EnvPopover";
export default {
name: "BatchEdit",
components: {
EnvPopover,
MsDialogFooter
},
props: {
@ -50,7 +56,7 @@
default() {
return this.$t('test_track.case.batch_operate')
}
}
},
},
data() {
return {
@ -63,12 +69,22 @@
},
options: [],
filterable: false,
projectList: [],
projectIds: new Set(),
selectRows: new Set(),
projectEnvMap: new Map()
}
},
methods: {
submit(form) {
this.$refs[form].validate((valid) => {
if (valid) {
this.form.projectEnvMap = this.projectEnvMap;
if (this.form.type === 'projectEnv') {
if (!this.$refs.envPopover.checkEnv()) {
return false;
}
}
this.$emit("batchEdit", this.form);
this.dialogVisible = false;
} else {
@ -76,15 +92,25 @@
}
});
},
setProjectEnvMap(projectEnvMap) {
this.projectEnvMap = projectEnvMap;
},
open(size) {
this.dialogVisible = true;
if (size) {
this.size = size;
} else {
// this.size = this.$parent.selectRows.size;
this.size = this.$parent.selectDataCounts;
}
listenGoBack(this.handleClose);
this.getWsProjects();
},
setSelectRows(rows) {
this.selectRows = rows;
this.projectIds.clear();
this.selectRows.forEach(row => {
this.projectIds.add(row.projectId)
})
},
handleClose() {
this.form = {};
@ -104,7 +130,12 @@
return;
}
});
}
},
getWsProjects() {
this.$get("/project/listAll", res => {
this.projectList = res.data;
})
},
}
}
</script>

View File

@ -129,6 +129,10 @@
<ms-run :debug="false" :type="'API_PLAN'" :reportId="reportId" :run-data="runData"
@runRefresh="runRefresh" ref="runTest"/>
<!-- 批量编辑 -->
<batch-edit :dialog-title="$t('test_track.case.batch_edit_case')" :type-arr="typeArr" :value-arr="valueArr"
:select-row="selectRows" ref="batchEdit" @batchEdit="batchEdit"/>
</el-card>
</div>
@ -145,9 +149,9 @@ import ApiCaseList from "../../../../../api/definition/components/case/ApiCaseLi
import MsContainer from "../../../../../common/components/MsContainer";
import MsBottomContainer from "../../../../../api/definition/components/BottomContainer";
import ShowMoreBtn from "../../../../case/components/ShowMoreBtn";
import MsBatchEdit from "../../../../../api/definition/components/basis/BatchEdit";
import BatchEdit from "@/business/components/track/case/components/BatchEdit";
import {API_METHOD_COLOUR, CASE_PRIORITY, RESULT_MAP} from "../../../../../api/definition/model/JsonData";
import {getCurrentProjectID, getCurrentUser} from "@/common/js/utils";
import {getCurrentProjectID, strMapToObj} from "@/common/js/utils";
import ApiListContainer from "../../../../../api/definition/components/list/ApiListContainer";
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
import {getBodyUploadFiles, getUUID} from "../../../../../../../common/js/utils";
@ -156,16 +160,17 @@ import MsRun from "../../../../../api/definition/components/Run";
import TestPlanApiCaseResult from "./TestPlanApiCaseResult";
import TestPlan from "../../../../../api/definition/components/jmeter/components/test-plan";
import ThreadGroup from "../../../../../api/definition/components/jmeter/components/thread-group";
import {TEST_CASE_LIST, TEST_PLAN_API_CASE, WORKSPACE_ID} from "@/common/js/constants";
import {TEST_PLAN_API_CASE, WORKSPACE_ID} from "@/common/js/constants";
import {_filter, _sort, getLabel} from "@/common/js/tableUtils";
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
import {Test_Plan_Api_Case, Track_Test_Case} from "@/business/components/common/model/JsonData";
import {Test_Plan_Api_Case} from "@/business/components/common/model/JsonData";
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
export default {
name: "TestPlanApiCaseList",
components: {
BatchEdit,
HeaderLabelOperate,
HeaderCustom,
TestPlanApiCaseResult,
@ -182,7 +187,6 @@ export default {
MsContainer,
MsBottomContainer,
ShowMoreBtn,
MsBatchEdit
},
data() {
return {
@ -198,10 +202,11 @@ export default {
selectRows: new Set(),
buttons: [
{name: this.$t('test_track.case.batch_unlink'), handleClick: this.handleDeleteBatch},
{name: this.$t('api_test.automation.batch_execute'), handleClick: this.handleBatchExecute}
{name: this.$t('api_test.automation.batch_execute'), handleClick: this.handleBatchExecute},
{name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit}
],
typeArr: [
{id: 'priority', name: this.$t('test_track.case.priority')},
{id: 'projectEnv', name: this.$t('api_test.definition.request.run_env')},
],
priorityFilters: [
{text: 'P0', value: 'P0'},
@ -212,6 +217,7 @@ export default {
valueArr: {
priority: CASE_PRIORITY,
userId: [],
projectEnv: []
},
methodColorMap: new Map(API_METHOD_COLOUR),
tableData: [],
@ -225,7 +231,9 @@ export default {
reportId: "",
response: {},
rowLoading: "",
userFilters: []
userFilters: [],
projectIds: [],
projectList: []
}
},
props: {
@ -342,15 +350,6 @@ export default {
this.$set(row, "showMore", true);
this.selectRows.add(row);
}
let arr = Array.from(this.selectRows);
// 1
if (this.selectRows.size === 1) {
this.$set(arr[0], "showMore", false);
} else if (this.selectRows.size === 2) {
arr.forEach(row => {
this.$set(row, "showMore", true);
})
}
},
showExecResult(row) {
this.$emit('showExecResult', row);
@ -369,16 +368,10 @@ export default {
},
handleSelectAll(selection) {
if (selection.length > 0) {
if (selection.length === 1) {
selection.hashTree = [];
this.selectRows.add(selection[0]);
} else {
this.tableData.forEach(item => {
item.hashTree = [];
this.$set(item, "showMore", true);
this.selectRows.add(item);
});
}
this.tableData.forEach(item => {
this.$set(item, "showMore", true);
this.selectRows.add(item);
});
} else {
this.selectRows.clear();
this.tableData.forEach(row => {
@ -449,16 +442,27 @@ export default {
this.reportId = getUUID().substring(0, 8);
});
},
handleBatchEdit() {
this.$refs.batchEdit.open(this.selectRows.size);
this.$refs.batchEdit.setSelectRows(this.selectRows);
},
batchEdit(form) {
let arr = Array.from(this.selectRows);
let ids = arr.map(row => row.id);
let param = {};
param[form.type] = form.value;
param.ids = ids;
this.$post('/api/testcase/batch/edit', param, () => {
this.$success(this.$t('commons.save_success'));
this.initTable();
});
//
if (form.type === 'projectEnv') {
let map = new Map();
param.projectEnvMap = strMapToObj(form.projectEnvMap);
this.selectRows.forEach(row => {
map[row.id] = row.projectId;
})
param.selectRows = map;
this.$post('/test/plan/api/case/batch/update/env', param, () => {
this.$success(this.$t('commons.save_success'));
this.initTable();
});
} else {
//
}
},
handleBatchExecute() {
this.selectRows.forEach(row => {

View File

@ -194,6 +194,9 @@ export default {
module: {
select_module: "Select module",
default_module: "Default module",
},
report_statistics: {
title: "Report statistics"
}
},
license: {

View File

@ -195,6 +195,9 @@ export default {
module: {
select_module: "選擇模塊",
default_module: "默認模塊",
},
report_statistics: {
title: "報表統計"
}
},
license: {