This commit is contained in:
wenyann 2020-08-04 16:10:43 +08:00
commit fdfee3a6b8
24 changed files with 183 additions and 53 deletions

View File

@ -47,10 +47,6 @@ public class APITestController {
return apiTestService.getApiTestByProjectId(projectId);
}
@GetMapping("/state/get/{testId}")
public ApiTest apiState(@PathVariable String testId) {
return apiTestService.getApiTestByTestId(testId);
}
@PostMapping(value = "/schedule/update")
public void updateSchedule(@RequestBody Schedule request) {

View File

@ -126,9 +126,6 @@ public class APITestService {
return null;
}
public ApiTest getApiTestByTestId(String testId) {
return apiTestMapper.selectByPrimaryKey(testId);
}
public List<ApiTest> getApiTestByProjectId(String projectId) {
return extApiTestMapper.getApiTestByProjectId(projectId);

View File

@ -225,7 +225,12 @@
</foreach>
</if>
</where>
order by update_time desc
<if test="request.orders != null and request.orders.size() > 0">
order by
<foreach collection="request.orders" separator="," item="order">
${order.name} ${order.type}
</foreach>
</if>
</select>
<select id="getMaxNumByProjectId" resultType="io.metersphere.base.domain.TestCase">

View File

@ -128,7 +128,6 @@ public class UserController {
}
@GetMapping("/list")
@RequiresRoles(value = {RoleConstants.ADMIN, RoleConstants.ORG_ADMIN, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public List<User> getUserList() {
return userService.getUserList();
}

View File

@ -1,6 +1,7 @@
package io.metersphere.track.request.testcase;
import io.metersphere.base.domain.TestCaseWithBLOBs;
import io.metersphere.controller.request.OrderRequest;
import lombok.Getter;
import lombok.Setter;
@ -10,4 +11,5 @@ import java.util.List;
@Setter
public class TestCaseBatchRequest extends TestCaseWithBLOBs {
private List<String> ids;
private List<OrderRequest> orders;
}

View File

@ -356,6 +356,12 @@ public class TestCaseService {
}
private List<TestCaseExcelData> generateTestCaseExcel(TestCaseBatchRequest request) {
List<OrderRequest> orderList = ServiceUtils.getDefaultOrder(request.getOrders());
OrderRequest order = new OrderRequest();
order.setName("sort");
order.setType("desc");
orderList.add(order);
request.setOrders(orderList);
List<TestCaseDTO> TestCaseList = extTestCaseMapper.listByTestCaseIds(request);
List<TestCaseExcelData> list = new ArrayList<>();
StringBuilder step = new StringBuilder("");
@ -466,6 +472,7 @@ public class TestCaseService {
/**
* 导入用例前检查数据库是否存在此用例
*
* @param testCaseWithBLOBs
* @return
*/

View File

@ -0,0 +1,2 @@
ALTER TABLE load_test_report_result
MODIFY report_value LONGTEXT NULL;

View File

@ -62,17 +62,22 @@ export default {
let url = "/api/report/get/" + this.reportId;
this.$get(url, response => {
this.report = response.data || {};
if (this.isNotRunning) {
try {
this.content = JSON.parse(this.report.content);
} catch (e) {
console.log(this.report.content)
throw e;
if (response.data) {
if (this.isNotRunning) {
try {
this.content = JSON.parse(this.report.content);
} catch (e) {
console.log(this.report.content)
throw e;
}
this.getFails();
this.loading = false;
} else {
setTimeout(this.getReport, 2000)
}
this.getFails();
this.loading = false;
} else {
setTimeout(this.getReport, 2000)
this.loading = false;
this.$error(this.$t('api_report.not_exist'));
}
});
}

View File

@ -52,7 +52,7 @@
<ms-api-report-dialog :test-id="id" ref="reportDialog"/>
<ms-schedule-config :schedule="test.schedule" :save="saveCronExpression" @scheduleChange="saveSchedule" :check-open="checkScheduleEdit"/>
<ms-schedule-config :schedule="test.schedule" :is-read-only="isReadOnly" :save="saveCronExpression" @scheduleChange="saveSchedule" :check-open="checkScheduleEdit"/>
</el-row>
</el-header>
<ms-api-scenario-config :is-read-only="isReadOnly" :scenarios="test.scenarioDefinition" :project-id="test.projectId" ref="config"/>

View File

@ -9,13 +9,13 @@
<el-input v-if="!suggestions" :disabled="isReadOnly" v-model="item.name" size="small" maxlength="200"
@change="change"
:placeholder="keyText" show-word-limit/>
<el-autocomplete :maxlength="200" v-if="suggestions" v-model="item.name" size="small"
<el-autocomplete :disabled="isReadOnly" :maxlength="200" v-if="suggestions" v-model="item.name" size="small"
:fetch-suggestions="querySearch" @change="change" :placeholder="keyText"
show-word-limit/>
</el-col>
<el-col>
<el-input :disabled="isReadOnly" v-model="item.value" size="small" maxlength="2000" @change="change"
<el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change"
:placeholder="valueText" show-word-limit/>
</el-col>
<el-col class="kv-delete">

View File

@ -6,7 +6,7 @@
:placeholder="$t('api_test.request.extract.json_path_expression')"/>
</el-col>
<el-col>
<el-input :disabled="isReadOnly" v-model="jsonPath.expect" maxlength="2000" size="small" show-word-limit
<el-input :disabled="isReadOnly" v-model="jsonPath.expect" size="small" show-word-limit
:placeholder="$t('api_test.request.assertions.expect')"/>
</el-col>
<el-col class="assertion-btn">

View File

@ -10,7 +10,7 @@
</el-select>
</el-col>
<el-col>
<el-input :disabled="isReadOnly" v-model="regex.expression" maxlength="2000" size="small" show-word-limit
<el-input :disabled="isReadOnly" v-model="regex.expression" size="small" show-word-limit
:placeholder="$t('api_test.request.assertions.expression')"/>
</el-col>
<el-col class="assertion-btn">

View File

@ -11,7 +11,7 @@
@change="change" show-word-limit :placeholder="$t('api_test.variable_name')"/>
</el-col>
<el-col>
<el-input :disabled="isReadOnly" v-model="common.expression" maxlength="2000" size="small" show-word-limit
<el-input :disabled="isReadOnly" v-model="common.expression" size="small" show-word-limit
:placeholder="expression"/>
</el-col>
<el-col class="extract-btn">

View File

@ -5,8 +5,8 @@
<i class="el-icon-date" size="small"></i>
<span class="character" @click="scheduleEdit">SCHEDULER</span>
</span>
<el-switch :disabled="!schedule.value" v-model="schedule.enable" @change="scheduleChange"/>
<ms-schedule-edit :schedule="schedule" :save="save" :custom-validate="customValidate" ref="scheduleEdit"/>
<el-switch :disabled="!schedule.value && isReadOnly" v-model="schedule.enable" @change="scheduleChange"/>
<ms-schedule-edit :is-read-only="isReadOnly" :schedule="schedule" :save="save" :custom-validate="customValidate" ref="scheduleEdit"/>
<crontab-result v-show="false" :ex="schedule.value" ref="crontabResult" @resultListChange="resultListChange"/>
</div>
<div>
@ -44,6 +44,10 @@
type: Function,
default: defaultCustomValidate
},
isReadOnly: {
type: Boolean,
default: false
}
},
methods: {
scheduleEdit() {

View File

@ -4,12 +4,12 @@
<el-form :model="form" :rules="rules" ref="from">
<el-form-item
prop="cronValue">
<el-input v-model="form.cronValue" class="inp" :placeholder="$t('schedule.please_input_cron_expression')"/>
<el-input :disabled="isReadOnly" v-model="form.cronValue" class="inp" :placeholder="$t('schedule.please_input_cron_expression')"/>
<!-- <el-button type="primary" @click="showCronDialog">{{$t('schedule.generate_expression')}}</el-button>-->
<el-button type="primary" @click="saveCron">{{$t('commons.save')}}</el-button>
<el-button :disabled="isReadOnly" type="primary" @click="saveCron">{{$t('commons.save')}}</el-button>
</el-form-item>
<el-form-item>
<el-link type="primary" @click="showCronDialog">{{$t('schedule.generate_expression')}}</el-link>
<el-link :disabled="isReadOnly" type="primary" @click="showCronDialog">{{$t('schedule.generate_expression')}}</el-link>
</el-form-item>
<crontab-result :ex="form.cronValue" ref="crontabResult" />
</el-form>
@ -38,6 +38,10 @@
type: Function,
default: defaultCustomValidate
},
isReadOnly: {
type: Boolean,
default: false
}
},
watch: {
'schedule.value'() {

View File

@ -43,12 +43,12 @@
</el-col>
</el-row>
<el-divider></el-divider>
<el-divider/>
<el-tabs v-model="active" type="border-card" :stretch="true">
<el-tab-pane :label="$t('report.test_overview')">
<!-- <ms-report-test-overview :id="reportId" :status="status"/>-->
<ms-report-test-overview :report="report"/>
<ms-report-test-overview :report="report" ref="testOverview"/>
</el-tab-pane>
<el-tab-pane :label="$t('report.test_request_statistics')">
<ms-report-request-statistics :report="report"/>
@ -63,8 +63,8 @@
</el-card>
<el-dialog :title="$t('report.test_stop_now_confirm')" :visible.sync="dialogFormVisible" width="30%">
<p v-html="$t('report.force_stop_tips')"></p>
<p v-html="$t('report.stop_tips')"></p>
<p v-html="$t('report.force_stop_tips')"/>
<p v-html="$t('report.stop_tips')"/>
<div slot="footer" class="dialog-footer">
<el-button type="danger" size="small" @click="stopTest(true)">{{$t('report.force_stop_btn')}}
</el-button>
@ -190,7 +190,7 @@
} else {
this.report.status = 'Completed';
}
})
});
this.dialogFormVisible = false;
},
rerun(testId) {
@ -201,7 +201,7 @@
}).then(() => {
this.result = this.$post('/performance/run', {id: testId, triggerMode: 'MANUAL'}, (response) => {
this.reportId = response.data;
this.$router.push({path: '/performance/report/view/' + this.reportId})
this.$router.push({path: '/performance/report/view/' + this.reportId});
// socket
this.initWebSocket();
})
@ -235,16 +235,21 @@
this.reportId = this.$route.path.split('/')[4];
this.result = this.$get("/performance/report/" + this.reportId, res => {
let data = res.data;
this.status = data.status;
this.$set(this.report, "id", this.reportId);
this.$set(this.report, "status", data.status);
this.checkReportStatus(data.status);
if (this.status === "Completed" || this.status === "Running") {
this.initReportTimeInfo();
if (data) {
this.status = data.status;
this.$set(this.report, "id", this.reportId);
this.$set(this.report, "status", data.status);
this.checkReportStatus(data.status);
if (this.status === "Completed" || this.status === "Running") {
this.initReportTimeInfo();
}
this.initBreadcrumb();
this.initWebSocket();
} else {
this.$error(this.$t('report.not_exist'))
}
})
this.initBreadcrumb();
this.initWebSocket();
});
},
beforeDestroy() {
this.websocket.close() //websocket
@ -288,6 +293,8 @@
} else {
this.clearData();
}
} else {
this.$error(this.$t('report.not_exist'));
}
});

View File

@ -66,8 +66,8 @@
<el-table-column label="Throughput">
<el-table-column
prop="transactions"
label="Transactions"
width="100"
label="Transactions/s"
width="150"
/>
</el-table-column>
@ -76,13 +76,13 @@
prop="received"
label="Received"
align="center"
width="200"
width="150"
/>
<el-table-column
prop="sent"
label="Sent"
align="center"
width="200"
width="150"
/>
</el-table-column>

View File

@ -8,7 +8,11 @@
</template>
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip/>
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
<template v-slot:default="scope">
<pre>{{scope.row.description}}</pre>
</template>
</el-table-column>
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
<el-table-column
sortable

View File

@ -0,0 +1,78 @@
<template>
<div>
<el-dialog
title="批量编辑用例"
:visible.sync="dialogVisible"
width="25%"
class="batch-edit-dialog"
:destroy-on-close="true"
@close="handleClose"
>
<el-form :model="form" label-position="right" label-width="150px" size="medium" ref="form" :rules="rules">
<el-form-item :label="$t('test_track.case.batch_update', [size])" prop="type">
<el-select v-model="form.type" style="width: 80%">
<el-option label="用例等级" value="priority"/>
<el-option label="类型" value="type"/>
<el-option label="测试方式" value="method"/>
<el-option label="维护人" value="maintainer"/>
</el-select>
</el-form-item>
<el-form-item label="更新后属性值为" prop="value">
<el-select v-model="form.value" style="width: 80%">
<el-option label="值1" value="value1"/>
<el-option label="值2" value="value2"/>
</el-select>
</el-form-item>
</el-form>
<template v-slot:footer>
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="submit('form')"/>
</template>
</el-dialog>
</div>
</template>
<script>
import MsDialogFooter from "../../../common/components/MsDialogFooter";
export default {
name: "BatchEdit",
components: {
MsDialogFooter
},
data() {
return {
dialogVisible: false,
form: {},
size: 0,
rules: {
type: {required: true, message: "请选择属性", trigger: ['blur','change']},
value: {required: true, message: "请选择属性对应的值", trigger: ['blur','change']}
},
}
},
methods: {
submit(form) {
this.$refs[form].validate((valid) => {
if (valid) {
this.$emit("submit", this.form);
} else {
return false;
}
});
},
open() {
this.dialogVisible = true;
this.size = this.$parent.selectRows.size;
},
handleClose() {
this.form = {};
}
}
}
</script>
<style scoped>
</style>

View File

@ -49,8 +49,8 @@
.show-more-btn {
width: 20px;
height: 30px;
line-height: 30px;
height: 25px;
line-height: 25px;
background-color: #FFF;
}

View File

@ -119,6 +119,8 @@
:total="total"/>
</el-card>
<batch-edit ref="batchEdit"/>
</div>
</template>
@ -139,6 +141,7 @@
import {_filter, _sort} from "../../../../../common/js/utils";
import {TEST_CASE_CONFIGS} from "../../../common/components/search/search-components";
import ShowMoreBtn from "./ShowMoreBtn";
import BatchEdit from "./BatchEdit";
export default {
name: "TestCaseList",
@ -149,7 +152,14 @@
MethodTableItem,
TypeTableItem,
PriorityTableItem,
MsCreateBox, TestCaseImport, TestCaseExport, MsTablePagination, NodeBreadcrumb, MsTableHeader, ShowMoreBtn
MsCreateBox,
TestCaseImport,
TestCaseExport,
MsTablePagination,
NodeBreadcrumb,
MsTableHeader,
ShowMoreBtn,
BatchEdit
},
data() {
return {
@ -326,6 +336,7 @@
this.selectRows.add(row);
}
// todo
if (this.selectRows.size > 1) {
Array.from(this.selectRows).forEach(row => {
this.$set(row, "showMore", true);
@ -393,7 +404,7 @@
this.initTableData();
},
handleClickStop() {
console.log("click stop");
this.$refs.batchEdit.open();
}
}
}

View File

@ -266,6 +266,7 @@ export default {
stop_tips: 'A <strong>Graceful shutdown</strong> will archive the JTL files and then stop the servers.',
force_stop_btn: 'Terminating',
stop_btn: 'Graceful shutdown',
not_exist: "Test report does not exist",
},
load_test: {
operating: 'Operating',
@ -476,6 +477,7 @@ export default {
detail: "Report detail",
delete: "Delete report",
running: "The test is running",
not_exist: "Test report does not exist",
},
test_track: {
test_track: "Track",
@ -531,6 +533,7 @@ export default {
relate_test: "Relate test",
relate_test_not_find: 'The associated test does not exist, please check the test case',
batch_handle: 'Batch processing (select {0} item)',
batch_update: 'Update the attributes of {0} cases',
import: {
import: "Import test case",
case_import: "Import test case",

View File

@ -264,6 +264,7 @@ export default {
stop_tips: '<strong>停止</strong>测试会结束当前测试并保留报告数据',
force_stop_btn: '强制停止',
stop_btn: '停止',
not_exist: "测试报告不存在",
},
load_test: {
operating: '操作',
@ -475,6 +476,7 @@ export default {
detail: "报告详情",
delete: "删除报告",
running: "测试执行中",
not_exist: "测试报告不存在",
},
test_track: {
test_track: "测试跟踪",
@ -531,6 +533,7 @@ export default {
relate_test: "关联测试",
relate_test_not_find: '关联的测试不存在,请检查用例',
batch_handle: '批量处理 (选中{0}项)',
batch_update: '更新{0}个用例的属性',
import: {
import: "导入用例",
case_import: "导入测试用例",

View File

@ -264,6 +264,7 @@ export default {
stop_tips: '<strong>停止</strong>測試會結束當前測試並保留報告數據',
force_stop_btn: '強制停止',
stop_btn: '停止',
not_exist: "測試報告不存在",
},
load_test: {
operating: '操作',
@ -475,6 +476,7 @@ export default {
detail: "報告詳情",
delete: "刪除報告",
running: "測試執行中",
not_exist: "測試報告不存在",
},
test_track: {
test_track: "測試跟踪",
@ -530,6 +532,7 @@ export default {
relate_test: "關聯測試",
relate_test_not_find: '關聯的測試不存在,請檢查用例',
batch_handle: '批量處理 (選中{0}項)',
batch_update: '更新{0}個用例的屬性',
import: {
import: "導入用例",
case_import: "導入測試用例",