Merge remote-tracking branch 'origin/master'

This commit is contained in:
wenyann 2020-11-26 12:12:17 +08:00
commit 51682762e1
24 changed files with 119 additions and 59 deletions

View File

@ -156,7 +156,7 @@
<dependency> <dependency>
<groupId>org.python</groupId> <groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId> <artifactId>jython-standalone</artifactId>
<version>2.7.2</version> <version>2.7.0</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -161,7 +161,9 @@ public class JmeterDocumentParser {
break; break;
case "Argument.value": case "Argument.value":
String textContent = ele.getTextContent(); String textContent = ele.getTextContent();
ele.setTextContent(ScriptEngineUtils.calculate(textContent)); if (StringUtils.startsWith(textContent, "@")) {
ele.setTextContent(ScriptEngineUtils.calculate(textContent));
}
break; break;
default: default:
break; break;

View File

@ -133,6 +133,7 @@
LEFT JOIN user ON user.id = r.user_id LEFT JOIN user ON user.id = r.user_id
<where> <where>
r.test_id = #{testId} r.test_id = #{testId}
and r.status != 'Debug'
</where> </where>
ORDER BY r.update_time DESC ORDER BY r.update_time DESC
</select> </select>

View File

@ -44,7 +44,7 @@ public class ShiroConfig implements EnvironmentAware {
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap(); Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap); ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
filterChainDefinitionMap.put("/display/info", "anon"); filterChainDefinitionMap.put("/display/info", "anon");
filterChainDefinitionMap.put("/display/file/*", "anon"); filterChainDefinitionMap.put("/display/file/**", "anon");
filterChainDefinitionMap.put("/**", "apikey, authc"); filterChainDefinitionMap.put("/**", "apikey, authc");
return shiroFilterFactoryBean; return shiroFilterFactoryBean;
} }

View File

@ -72,13 +72,15 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
*/ */
private void loadJars() { private void loadJars() {
List<JarConfig> jars = jarConfigService.list(); List<JarConfig> jars = jarConfigService.list();
try {
jars.forEach(jarConfig -> { jars.forEach(jarConfig -> {
try {
NewDriverManager.loadJar(jarConfig.getPath()); NewDriverManager.loadJar(jarConfig.getPath());
}); } catch (Exception e) {
} catch (Exception e) { e.printStackTrace();
e.printStackTrace(); LogUtil.error(e.getMessage(), e);
LogUtil.error(e.getMessage(), e); }
} });
} }
} }

View File

@ -231,7 +231,7 @@ public class XmindCaseParser {
JSONObject step = new JSONObject(true); JSONObject step = new JSONObject(true);
step.put("num", i + 1); step.put("num", i + 1);
step.put("desc", attacheds.get(i).getTitle()); step.put("desc", attacheds.get(i).getTitle());
if (attacheds.get(i) != null && attacheds.get(i).getChildren() != null && attacheds.get(i).getChildren().getAttached()!=null) { if (attacheds.get(i) != null && attacheds.get(i).getChildren() != null && attacheds.get(i).getChildren().getAttached() != null) {
step.put("result", attacheds.get(i).getChildren().getAttached().get(0).getTitle()); step.put("result", attacheds.get(i).getChildren().getAttached().get(0).getTitle());
} }
jsonArray.add(step); jsonArray.add(step);
@ -283,17 +283,20 @@ public class XmindCaseParser {
// 测试步骤处理 // 测试步骤处理
List<Attached> steps = new LinkedList<>(); List<Attached> steps = new LinkedList<>();
StringBuilder rc = new StringBuilder();
if (attacheds != null && !attacheds.isEmpty()) { if (attacheds != null && !attacheds.isEmpty()) {
attacheds.forEach(item -> { attacheds.forEach(item -> {
if (isAvailable(item.getTitle(), PC_REGEX)) { if (isAvailable(item.getTitle(), PC_REGEX)) {
testCase.setPrerequisite(replace(item.getTitle(), PC_REGEX)); testCase.setPrerequisite(replace(item.getTitle(), PC_REGEX));
} else if (isAvailable(item.getTitle(), RC_REGEX)) { } else if (isAvailable(item.getTitle(), RC_REGEX)) {
testCase.setRemark(replace(item.getTitle(), RC_REGEX)); rc.append(replace(item.getTitle(), RC_REGEX));
rc.append("\n");
} else { } else {
steps.add(item); steps.add(item);
} }
}); });
} }
testCase.setRemark(rc.toString());
testCase.setSteps(this.getSteps(steps)); testCase.setSteps(this.getSteps(steps));
testCases.add(testCase); testCases.add(testCase);
// 校验合规性 // 校验合规性

@ -1 +1 @@
Subproject commit 57d6f78efa4b0300be188e8b024511ceef0873ed Subproject commit bb494fc68a2367359c9048fa7250c7618de4afb6

View File

@ -7,8 +7,7 @@
</el-row> </el-row>
<el-row id="header-top" type="flex" justify="space-between" align="middle"> <el-row id="header-top" type="flex" justify="space-between" align="middle">
<el-col :span="12"> <el-col :span="12">
<img v-if="logoId" :src="'/display/file/' + logoId" style="width: 156px;height: 37px;" alt=""> <img :src="'/display/file/logo'" style="width: 156px;height: 37px;" alt="">
<a v-else class="logo"/>
<ms-top-menus/> <ms-top-menus/>
</el-col> </el-col>

View File

@ -46,10 +46,9 @@ import MsScenarioResults from "./components/ScenarioResults";
import MsContainer from "@/business/components/common/components/MsContainer"; import MsContainer from "@/business/components/common/components/MsContainer";
import MsMainContainer from "@/business/components/common/components/MsMainContainer"; import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import MsApiReportExport from "./ApiReportExport"; import MsApiReportExport from "./ApiReportExport";
import {exportPdf} from "@/common/js/utils";
import html2canvas from "html2canvas";
import MsApiReportViewHeader from "./ApiReportViewHeader"; import MsApiReportViewHeader from "./ApiReportViewHeader";
import {RequestFactory} from "../test/model/ScenarioModel"; import {RequestFactory} from "../test/model/ScenarioModel";
import {windowPrint} from "../../../../common/js/utils";
export default { export default {
name: "MsApiReportViewDetail", name: "MsApiReportViewDetail",
@ -154,23 +153,16 @@ export default {
this.scenarioName = requestResult.scenarioName; this.scenarioName = requestResult.scenarioName;
}); });
}, },
handleExport(name) { handleExport() {
this.loading = true;
this.reportExportVisible = true; this.reportExportVisible = true;
let reset = this.exportReportReset; let reset = this.exportReportReset;
this.$nextTick(() => {
this.$nextTick(function () { windowPrint('apiTestReport', 0.57);
html2canvas(document.getElementById('apiTestReport'), { reset();
// scale: 2,
}).then(function (canvas) {
exportPdf(name, [canvas]);
reset();
});
}); });
}, },
exportReportReset() { exportReportReset() {
this.reportExportVisible = false; this.$router.go(0);
this.loading = false;
} }
}, },

View File

@ -17,7 +17,6 @@
:scenario="scenario" :scenario="scenario"
:extract="extract" :extract="extract"
type="body" type="body"
:description="$t('api_test.request.parameters_desc')"
v-if="body.isKV()"/> v-if="body.isKV()"/>
<div class="body-raw" v-if="body.type == 'Raw'"> <div class="body-raw" v-if="body.type == 'Raw'">
<ms-code-edit :mode="body.format" :enable-format="false" :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" ref="codeEdit"/> <ms-code-edit :mode="body.format" :enable-format="false" :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" ref="codeEdit"/>

View File

@ -31,7 +31,7 @@
</el-dialog> </el-dialog>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('schedule.task_notification')" name="second"> <el-tab-pane :label="$t('schedule.task_notification')" name="second">
<schedule-task-notification :test-id="testId" :schedule-receiver-options="scheduleReceiverOptions"></schedule-task-notification> <schedule-task-notification :is-tester-permission="isTesterPermission" :test-id="testId" :schedule-receiver-options="scheduleReceiverOptions"></schedule-task-notification>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@ -46,6 +46,7 @@ import CrontabResult from "../cron/CrontabResult";
import {cronValidate} from "@/common/js/cron"; import {cronValidate} from "@/common/js/cron";
import {listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
import ScheduleTaskNotification from "../../settings/organization/components/ScheduleTaskNotification"; import ScheduleTaskNotification from "../../settings/organization/components/ScheduleTaskNotification";
import {checkoutTestManagerOrTestUser} from "../../../../common/js/utils";
function defaultCustomValidate() { function defaultCustomValidate() {
return {pass: true}; return {pass: true};
} }
@ -113,10 +114,13 @@ export default {
name: '', name: '',
organizationId: this.currentUser().lastOrganizationId organizationId: this.currentUser().lastOrganizationId
}; };
this.result = this.$post('user/org/member/list/all', param, response => {
this.scheduleReceiverOptions = response.data
}); if (this.isTesterPermission) {
this.result = this.$post('user/org/member/list/all', param, response => {
this.scheduleReceiverOptions = response.data
});
}
}, },
/* handleClick() { /* handleClick() {
if (this.activeName === "second") { if (this.activeName === "second") {
@ -188,6 +192,11 @@ export default {
let time1 = new Date(resultList[0]); let time1 = new Date(resultList[0]);
let time2 = new Date(resultList[1]); let time2 = new Date(resultList[1]);
return time2 - time1; return time2 - time1;
},
},
computed: {
isTesterPermission() {
return checkoutTestManagerOrTestUser();
} }
} }
} }

View File

@ -9,9 +9,7 @@
</div> </div>
</div> </div>
<div class="report-right"> <div class="report-right">
<div class="test"> <img class="logo" src="@/assets/logo-MeterSphere.png">
<img class="logo" src="@/assets/logo-MeterSphere.png">
</div>
</div> </div>
</div> </div>

View File

@ -272,7 +272,7 @@ export default {
this.$nextTick(function () { this.$nextTick(function () {
html2canvas(document.getElementById('performanceReportExport'), { html2canvas(document.getElementById('performanceReportExport'), {
// scale: 2 scale: 2
}).then(function (canvas) { }).then(function (canvas) {
exportPdf(name, [canvas]); exportPdf(name, [canvas]);
reset(); reset();

View File

@ -2,7 +2,7 @@
<div> <div>
<el-row> <el-row>
<el-col :span="10"> <el-col :span="10">
<el-button icon="el-icon-circle-plus-outline" plain size="mini" @click="handleAddTaskModel('scheduleTask')"> <el-button :disabled="!isTesterPermission" icon="el-icon-circle-plus-outline" plain size="mini" @click="handleAddTaskModel('scheduleTask')">
{{ $t('organization.message.create_new_notification') }} {{ $t('organization.message.create_new_notification') }}
</el-button> </el-button>
</el-col> </el-col>
@ -69,12 +69,14 @@
type="primary" type="primary"
size="mini" size="mini"
v-show="scope.row.isSet" v-show="scope.row.isSet"
:disabled="!isTesterPermission"
@click="handleAddTask(scope.$index,scope.row)" @click="handleAddTask(scope.$index,scope.row)"
>{{ $t('commons.add') }} >{{ $t('commons.add') }}
</el-button> </el-button>
<el-button <el-button
size="mini" size="mini"
v-show="scope.row.isSet" v-show="scope.row.isSet"
:disabled="!isTesterPermission"
@click.native.prevent="removeRowTask(scope.$index,form.scheduleTask)" @click.native.prevent="removeRowTask(scope.$index,form.scheduleTask)"
>{{ $t('commons.cancel') }} >{{ $t('commons.cancel') }}
</el-button> </el-button>
@ -82,6 +84,7 @@
type="primary" type="primary"
size="mini" size="mini"
v-show="!scope.row.isSet" v-show="!scope.row.isSet"
:disabled="!isTesterPermission"
@click="handleEditTask(scope.$index,scope.row)" @click="handleEditTask(scope.$index,scope.row)"
>{{ $t('commons.edit') }}</el-button> >{{ $t('commons.edit') }}</el-button>
<el-button <el-button
@ -89,6 +92,7 @@
icon="el-icon-delete" icon="el-icon-delete"
size="mini" size="mini"
v-show="!scope.row.isSet" v-show="!scope.row.isSet"
:disabled="!isTesterPermission"
@click.native.prevent="deleteRowTask(scope.$index,scope.row)" @click.native.prevent="deleteRowTask(scope.$index,scope.row)"
></el-button> ></el-button>
</template> </template>
@ -106,6 +110,10 @@ export default {
props: { props: {
testId:String, testId:String,
scheduleReceiverOptions:Array, scheduleReceiverOptions:Array,
isTesterPermission: {
type: Boolean,
default: true
}
}, },
data() { data() {
return { return {
@ -120,7 +128,6 @@ export default {
identification: "", identification: "",
isReadOnly: false, isReadOnly: false,
testId:this.testId, testId:this.testId,
}], }],
}, },
scheduleEventOptions: [ scheduleEventOptions: [

View File

@ -8,7 +8,7 @@
:tip="$t('commons.search_by_name_or_id')" :tip="$t('commons.search_by_name_or_id')"
:create-tip="$t('test_track.case.create')" @create="testCaseCreate"> :create-tip="$t('test_track.case.create')" @create="testCaseCreate">
<template v-slot:title> <template v-slot:title>
<node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="showAll"/> <node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="refresh"/>
</template> </template>
<template v-slot:button> <template v-slot:button>
<ms-table-button :is-tester-permission="true" icon="el-icon-download" <ms-table-button :is-tester-permission="true" icon="el-icon-download"
@ -292,6 +292,8 @@ export default {
}, },
methods: { methods: {
initTableData() { initTableData() {
this.condition.planId = "";
this.condition.nodeIds = [];
if (this.planId) { if (this.planId) {
// param.planId = this.planId; // param.planId = this.planId;
this.condition.planId = this.planId; this.condition.planId = this.planId;
@ -377,10 +379,6 @@ export default {
this.selectRows.clear(); this.selectRows.clear();
this.$emit('refresh'); this.$emit('refresh');
}, },
showAll() {
this.condition = {components: TEST_CASE_CONFIGS};
this.getData();
},
showDetail(row, event, column) { showDetail(row, event, column) {
this.$emit('testCaseDetail', row); this.$emit('testCaseDetail', row);
}, },
@ -499,7 +497,6 @@ export default {
}, },
showPopover(row, column, cell) { showPopover(row, column, cell) {
if (column.property === 'name') { if (column.property === 'name') {
console.log(row, column);
this.currentCaseId = row.id; this.currentCaseId = row.id;
} }
} }

View File

@ -193,8 +193,7 @@ export default {
let param = {}; let param = {};
Object.assign(param, this.form); Object.assign(param, this.form);
param.name = param.name.trim(); param.name = param.name.trim();
if (param.name === '') { if (!this.validate(param)) {
this.$warning(this.$t('test_track.plan.input_plan_name'));
return; return;
} }
param.workspaceId = localStorage.getItem(WORKSPACE_ID); param.workspaceId = localStorage.getItem(WORKSPACE_ID);
@ -227,6 +226,17 @@ export default {
} }
}); });
}, },
validate(param) {
if (param.name === '') {
this.$warning(this.$t('test_track.plan.input_plan_name'));
return false;
}
if (param.plannedStartTime > param.plannedEndTime) {
this.$warning(this.$t('commons.date.data_time_error'));
return false;
}
return true;
},
editTestPlan(param) { editTestPlan(param) {
this.$post('/test/plan/' + this.operationType, param, () => { this.$post('/test/plan/' + this.operationType, param, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));

View File

@ -215,6 +215,16 @@
item.checked = false; item.checked = false;
}); });
flag ? this.testCases = tableData : this.testCases = this.testCases.concat(tableData); flag ? this.testCases = tableData : this.testCases = this.testCases.concat(tableData);
//
let hash = {}
this.testCases = this.testCases.reduce((item, next) => {
if (!hash[next.id]) {
hash[next.id] = true
item.push(next)
}
return item
}, [])
this.lineStatus = tableData.length === 50 && this.testCases.length < this.total; this.lineStatus = tableData.length === 50 && this.testCases.length < this.total;
}); });
} }

View File

@ -211,7 +211,7 @@
this.$nextTick(function () { this.$nextTick(function () {
html2canvas(document.getElementById('testCaseReportExport'), { html2canvas(document.getElementById('testCaseReportExport'), {
// scale: 2 scale: 2
}).then(function(canvas) { }).then(function(canvas) {
exportPdf(name, [canvas]); exportPdf(name, [canvas]);
reset(); reset();
@ -225,7 +225,7 @@
}, },
} }
} }
</script> </script>cd
<style scoped> <style scoped>

View File

@ -23,9 +23,10 @@
resize="none" resize="none"
:autosize="{ minRows: 4, maxRows: 4}" :autosize="{ minRows: 4, maxRows: 4}"
@keyup.ctrl.enter.native="sendComment" @keyup.ctrl.enter.native="sendComment"
:disabled="isReadOnly"
> >
</el-input> </el-input>
<el-button type="primary" size="mini" class="send-btn" @click="sendComment"> <el-button type="primary" size="mini" class="send-btn" @click="sendComment" :disabled="isReadOnly">
{{ $t('test_track.comment.send') }} {{ $t('test_track.comment.send') }}
</el-button> </el-button>
</div> </div>
@ -34,6 +35,7 @@
<script> <script>
import ReviewCommentItem from "./ReviewCommentItem"; import ReviewCommentItem from "./ReviewCommentItem";
import {checkoutTestManagerOrTestUser} from "@/common/js/utils";
export default { export default {
name: "ReviewComment", name: "ReviewComment",
@ -47,8 +49,12 @@ export default {
return { return {
result: {}, result: {},
textarea: '', textarea: '',
isReadOnly: false
} }
}, },
created() {
this.isReadOnly = !checkoutTestManagerOrTestUser();
},
methods: { methods: {
sendComment() { sendComment() {
let comment = {}; let comment = {};

View File

@ -219,6 +219,15 @@
item.checked = false; item.checked = false;
}); });
flag ? this.testReviews = tableData : this.testReviews = this.testReviews.concat(tableData); flag ? this.testReviews = tableData : this.testReviews = this.testReviews.concat(tableData);
//
let hash = {}
this.testReviews = this.testReviews.reduce((item, next) => {
if (!hash[next.id]) {
hash[next.id] = true
item.push(next)
}
return item
}, [])
this.lineStatus = tableData.length === 50 && this.testReviews.length < this.total; this.lineStatus = tableData.length === 50 && this.testReviews.length < this.total;
}); });

@ -1 +1 @@
Subproject commit 71d57ae5d7f8bb5c93a29504ac6f2300dc189ce9 Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8

View File

@ -43,7 +43,9 @@ export default {
success(response.data); success(response.data);
} else { } else {
window.console.warn(response.data); window.console.warn(response.data);
Message.warning(response.data.message || response.data); if (response.data.message) {
Message.warning(response.data.message);
}
} }
result.loading = false; result.loading = false;
} }

View File

@ -259,3 +259,17 @@ export function exportPdf(name, canvasList) {
} }
export function windowPrint(id, zoom) {
//根据div标签ID拿到div中的局部内容
let bdhtml=window.document.body.innerHTML;
let el = document.getElementById(id);
var jubuData = el.innerHTML;
document.getElementsByTagName('body')[0].style.zoom=zoom;
//把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容
window.document.body.innerHTML= jubuData;
//调用打印功能
window.print();
window.document.body.innerHTML=bdhtml;//重新给页面内容赋值;
return false;
}

View File

@ -4,8 +4,7 @@
<el-col :span="12"> <el-col :span="12">
<el-form :model="form" :rules="rules" ref="form"> <el-form :model="form" :rules="rules" ref="form">
<div class="logo"> <div class="logo">
<img v-if="loginLogoId" :src="'/display/file/' + loginLogoId" style="width: 224px;height: 45px;" alt=""> <img :src="'/display/file/loginLogo'" style="width: 224px;height: 45px;" alt="">
<img v-else src="../assets/logo-dark-MeterSphere.svg" style="width: 224px; " alt="">
</div> </div>
<div class="title"> <div class="title">
<span id="s1">{{ loginTitle }}</span> <span id="s1">{{ loginTitle }}</span>
@ -41,8 +40,7 @@
</el-form> </el-form>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<img v-if="loginImageId" :src="'/display/file/' + loginImageId" style="height: 560px; width: 100%"> <img :src="'/display/file/loginImage'" style="height: 560px; width: 100%">
<img v-else src="../assets/info.png" style="height: 560px; width: 100%">
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -86,8 +84,6 @@ export default {
msg: '', msg: '',
ready: false, ready: false,
openLdap: false, openLdap: false,
loginLogoId: '_blank',
loginImageId: '_blank',
loginTitle: this.$t("commons.login") + " MeterSphere" loginTitle: this.$t("commons.login") + " MeterSphere"
} }
}, },
@ -264,6 +260,10 @@ export default {
background: url(../assets/info.png); background: url(../assets/info.png);
height: 560px; height: 560px;
} }
.login-logo {
background: url(../assets/logo-dark-MeterSphere.svg);
}
</style> </style>
<style> <style>