Merge remote-tracking branch 'origin/master'

This commit is contained in:
song.tianyang 2021-01-20 15:26:22 +08:00
commit 4ae7a4753d
9 changed files with 163 additions and 90 deletions

View File

@ -8,7 +8,7 @@ import org.apache.commons.lang3.StringUtils;
@Data
public class MsExtractCommon extends MsExtractType{
private String variable;
private String value; // value: ${variable}
private String value;
private String expression;
private String description;
private boolean multipleMatching;

View File

@ -83,7 +83,7 @@ public class ApiTestCaseService {
}
public List<ApiTestCaseDTO> listSimple(ApiTestCaseRequest request) {
request = this.initRequest(request,true,true);
request = this.initRequest(request, true, true);
List<ApiTestCaseDTO> apiTestCases = extApiTestCaseMapper.listSimple(request);
if (CollectionUtils.isEmpty(apiTestCases)) {
@ -95,16 +95,17 @@ public class ApiTestCaseService {
/**
* 初始化部分参数
*
* @param request
* @param setDefultOrders
* @param checkThisWeekData
* @return
*/
private ApiTestCaseRequest initRequest(ApiTestCaseRequest request, boolean setDefultOrders, boolean checkThisWeekData) {
if(setDefultOrders){
if (setDefultOrders) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
}
if(checkThisWeekData){
if (checkThisWeekData) {
if (request.isSelectThisWeedData()) {
Map<String, Date> weekFirstTimeAndLastTime = DateUtils.getWeedFirstTimeAndLastTime(new Date());
Date weekFirstTime = weekFirstTimeAndLastTime.get("firstTime");
@ -412,23 +413,38 @@ public class ApiTestCaseService {
apiDefinitionWithBLOBs.setUpdateTime(System.currentTimeMillis());
apiTestCaseMapper.updateByExampleSelective(apiDefinitionWithBLOBs, apiDefinitionExample);
}
if ((StringUtils.isNotEmpty(request.getMethod()) || StringUtils.isNotEmpty(request.getPath())) && request.getProtocol().equals(RequestType.HTTP)) {
if ((StringUtils.isNotEmpty(request.getMethod()) || StringUtils.isNotEmpty(request.getPath())) && RequestType.HTTP.equals(request.getProtocol())) {
List<ApiTestCaseWithBLOBs> bloBs = apiTestCaseMapper.selectByExampleWithBLOBs(apiDefinitionExample);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiTestCaseMapper batchMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
bloBs.forEach(apiTestCase -> {
MsHTTPSamplerProxy req = JSON.parseObject(apiTestCase.getRequest(), MsHTTPSamplerProxy.class);
if (StringUtils.isNotEmpty(request.getMethod())) {
req.setMethod(request.getMethod());
}
if (StringUtils.isNotEmpty(request.getPath())) {
req.setPath(request.getPath());
try {
JSONObject element = JSON.parseObject(apiTestCase.getRequest());
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
});
req.setHashTree(elements);
}
if (StringUtils.isNotEmpty(request.getMethod())) {
req.setMethod(request.getMethod());
}
if (StringUtils.isNotEmpty(request.getPath())) {
req.setPath(request.getPath());
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.error(e.getMessage());
}
String requestStr = JSON.toJSONString(req);
apiTestCase.setRequest(requestStr);
batchMapper.updateByPrimaryKeySelective(apiTestCase);
});
sqlSession.flushStatements();
}
}

View File

@ -16,43 +16,43 @@
</template>
<script>
import ApiBaseComponent from "../common/ApiBaseComponent";
import MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
import ElCollapseTransition from "element-ui/src/transitions/collapse-transition";
import MsRequestMetric from "../../../definition/components/response/RequestMetric";
import ApiBaseComponent from "../common/ApiBaseComponent";
import MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
import ElCollapseTransition from "element-ui/src/transitions/collapse-transition";
import MsRequestMetric from "../../../definition/components/response/RequestMetric";
export default {
name: "ApiResponseComponent",
components: {ElCollapseTransition, MsRequestResultTail, ApiBaseComponent, MsRequestMetric},
props: ['apiItem'],
data() {
return {
isActive: false,
response: {responseResult: {}}
export default {
name: "ApiResponseComponent",
components: {ElCollapseTransition, MsRequestResultTail, ApiBaseComponent, MsRequestMetric},
props: ['apiItem'],
data() {
return {
isActive: false,
response: {responseResult: {}}
}
},
created() {
this.getExecResult();
},
methods: {
getExecResult() {
//
if (this.apiItem) {
let url = "/api/definition/report/getReport/" + this.apiItem.id;
this.$get(url, response => {
if (response.data) {
let data = JSON.parse(response.data.content);
this.response = data;
this.$set(this.apiItem, 'responseData', data);
}
});
}
},
methods: {
getExecResult() {
//
if (this.apiItem) {
let url = "/api/definition/report/getReport/" + this.apiItem.id;
this.$get(url, response => {
if (response.data) {
let data = JSON.parse(response.data.content);
this.response = data;
this.$set(this.apiItem, 'responseData', data);
}
});
}
},
active() {
this.isActive = !this.isActive;
if (this.isActive) {
this.getExecResult();
}
}
active() {
this.isActive = !this.isActive;
}
}
}
</script>
<style scoped>

View File

@ -1,7 +1,7 @@
<template>
<div class="request-form">
<component :is="component" :scenario="scenario" :controller="scenario" :timer="scenario" :assertions="scenario" :extract="scenario" :jsr223-processor="scenario" :request="scenario" :currentScenario="currentScenario" :currentEnvironmentId="currentEnvironmentId" :node="node"
:draggable="true" :title="title" @suggestClick="suggestClick(node)" :response="response"
:draggable="true" :title="title" :color="titleColor" :background-color="backgroundColor" @suggestClick="suggestClick(node)" :response="response"
@remove="remove" @copyRow="copyRow"/>
</div>
</template>
@ -32,6 +32,8 @@
data() {
return {
title: this.$t('api_test.automation.customize_script'),
titleColor: "",
backgroundColor: "",
}
},
computed: {
@ -79,25 +81,31 @@
getComponent(type) {
if (type === ELEMENT_TYPE.JSR223PreProcessor) {
this.title = this.$t('api_test.definition.request.pre_script');
this.titleColor = "#B8741A";
this.backgroundColor = "#F9F1EA";
return "MsJsr233Processor";
} else if (type === ELEMENT_TYPE.JSR223PostProcessor) {
this.title = this.$t('api_test.definition.request.post_script');
this.titleColor = "#783887";
this.backgroundColor = "#F2ECF3";
return "MsJsr233Processor";
} else {
this.title = this.$t('api_test.automation.customize_script');
this.titleColor = "#7B4D12";
this.backgroundColor = "#F1EEE9";
return "MsJsr233Processor";
}
},
remove(row, node) {
this.$emit('remove',row,node);
this.$emit('remove', row, node);
},
copyRow(row, node) {
this.$emit('copyRow',row,node);
this.$emit('copyRow', row, node);
},
suggestClick(node) {
this.$emit('suggestClick',node);
this.$emit('suggestClick', node);
},
}
}

View File

@ -4,8 +4,8 @@
@remove="remove"
:data="jsr223ProcessorData"
:draggable="draggable"
color="#B8741A"
background-color="#F9F1EA"
:color="color"
:background-color="backgroundColor"
:title="title">
<el-row style="margin:0px 10px 10px">
<el-col>
@ -18,9 +18,9 @@
</el-row>
<el-row>
<el-col :span="20" class="script-content">
<ms-code-edit v-if="isCodeEditAlive" :mode="jsr223ProcessorData.scriptLanguage"
<ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223ProcessorData.scriptLanguage]"
:read-only="isReadOnly"
:data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="[]"
:data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="['java','python']"
ref="codeEdit"/>
</el-col>
<el-col :span="4" class="script-index">
@ -81,11 +81,12 @@
],
isCodeEditAlive: true,
languages: [
'beanshell', "python"
'beanshell', "python", "groovy"
],
codeEditModeMap: {
beanshell: 'beanshell',
python: 'python'
beanshell: 'java',
python: 'python',
groovy: 'java'
}
}
},
@ -111,7 +112,8 @@
false
},
title: String,
styleType: String,
color: String,
backgroundColor: String,
node: {},
},
watch: {

View File

@ -56,7 +56,8 @@
@command="handleCommand" v-tester>
+{{$t('api_test.definition.request.case')}}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="run">{{$t('commons.test')}}</el-dropdown-item>
<el-dropdown-item command="run">{{$t('api_test.automation.batch_execute')}}</el-dropdown-item>
<el-dropdown-item command="batch_edit_case">{{$t('test_track.case.batch_edit_case')}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-col>
@ -169,6 +170,9 @@
if (e === "run") {
this.$emit('batchRun');
}
if (e === 'batch_edit_case') {
this.$emit('batchEditCase');
}
},
getColor(enable, method) {
if (enable) {

View File

@ -9,6 +9,7 @@
@addCase="addCase"
@batchRun="batchRun"
@selectAll="selectAll"
@batchEditCase="batchEditCase"
:condition="condition"
:priorities="priorities"
:apiCaseList="apiCaseList"
@ -39,9 +40,9 @@
<!-- 执行组件 -->
<ms-run :debug="false" :environment="environment" :reportId="reportId" :run-data="runData"
@runRefresh="runRefresh" ref="runTest"/>
<!--批量编辑-->
<ms-batch-edit ref="batchEdit" @batchEdit="batchEdit" :typeArr="typeArr" :value-arr="valueArr"/>
</div>
</template>
<script>
@ -52,6 +53,8 @@
import MsDrawer from "../../../../common/components/MsDrawer";
import {CASE_ORDER} from "../../model/JsonData";
import {API_CASE_CONFIGS} from "@/business/components/common/components/search/search-components";
import MsBatchEdit from "../basis/BatchEdit";
import {CASE_PRIORITY, REQ_METHOD} from "../../model/JsonData";
export default {
name: 'ApiCaseList',
@ -60,6 +63,7 @@
MsRun,
ApiCaseHeader,
ApiCaseItem,
MsBatchEdit
},
props: {
createCase: String,
@ -82,6 +86,7 @@
singleLoading: false,
singleRunId: "",
runData: [],
selectdCases: [],
reportId: "",
projectId: "",
testCaseId: "",
@ -90,7 +95,22 @@
condition: {
components: API_CASE_CONFIGS
},
api: {}
api: {},
typeArr: [
{id: 'priority', name: this.$t('test_track.case.priority')},
{id: 'method', name: this.$t('api_test.definition.api_type')},
{id: 'path', name: this.$t('api_test.request.path')},
],
priorityFilters: [
{text: 'P0', value: 'P0'},
{text: 'P1', value: 'P1'},
{text: 'P2', value: 'P2'},
{text: 'P3', value: 'P3'}
],
valueArr: {
priority: CASE_PRIORITY,
method: REQ_METHOD,
},
}
},
watch: {
@ -108,8 +128,6 @@
this.projectId = getCurrentProjectID();
if (this.createCase) {
this.sysAddition();
} else {
this.getApiTest();
}
},
computed: {
@ -133,11 +151,19 @@
this.condition.projectId = this.projectId;
this.condition.apiDefinitionId = this.api.id;
this.$post("/api/testcase/list", this.condition, response => {
for (let index in response.data) {
let test = response.data[index];
test.request = JSON.parse(test.request);
}
this.apiCaseList = response.data;
this.apiCaseList.forEach(apiCase => {
if (apiCase.tags && apiCase.tags.length > 0) {
apiCase.tags = JSON.parse(apiCase.tags);
this.$set(apiCase, 'selected', false);
}
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() != 'object') {
apiCase.request = JSON.parse(apiCase.request);
}
if (!apiCase.request.hashTree) {
apiCase.request.hashTree = [];
}
})
this.addCase();
});
},
@ -180,24 +206,22 @@
this.condition.apiDefinitionId = this.api.id;
}
this.result = this.$post("/api/testcase/list", this.condition, response => {
for (let index in response.data) {
let test = response.data[index];
test.request = JSON.parse(test.request);
if (!test.request.hashTree) {
test.request.hashTree = [];
}
}
this.apiCaseList = response.data;
if (addCase && this.apiCaseList.length == 0 && !this.loaded) {
this.addCase();
}
this.apiCaseList.forEach(apiCase => {
if (apiCase.tags && apiCase.tags.length > 0) {
apiCase.tags = JSON.parse(apiCase.tags);
this.$set(apiCase, 'selected', false);
}
if (Object.prototype.toString.call(apiCase.request).match(/\[object (\w+)\]/)[1].toLowerCase() != 'object') {
apiCase.request = JSON.parse(apiCase.request);
}
if (!apiCase.request.hashTree) {
apiCase.request.hashTree = [];
}
})
if (addCase && this.apiCaseList.length == 0 && !this.loaded) {
this.addCase();
}
});
}
},
@ -249,6 +273,7 @@
return;
}
this.runData = [];
this.batchLoadingIds = [];
if (this.apiCaseList.length > 0) {
this.apiCaseList.forEach(item => {
if (item.selected && item.id) {
@ -268,6 +293,37 @@
this.$warning("没有可执行的用例!");
}
},
batchEditCase() {
if (this.apiCaseList.length > 0) {
this.apiCaseList.forEach(item => {
if (item.selected && item.id) {
this.selectdCases.push(item.id);
}
})
}
if (this.selectdCases.length == 0) {
this.$warning("请选择用例!");
return;
}
this.$refs.batchEdit.open();
},
batchEdit(form) {
let param = {};
param[form.type] = form.value;
param.ids = this.selectdCases;
param.projectId = getCurrentProjectID();
if (this.api) {
param.protocol = this.api.protocol;
}
param.selectAllDate = this.isSelectAllDate;
param.unSelectIds = this.unSelection;
param = Object.assign(param, this.condition);
this.$post('/api/testcase/batch/editByParam', param, () => {
this.$success(this.$t('commons.save_success'));
this.selectdCases = [];
this.getApiTest();
});
},
}
}
</script>

View File

@ -413,19 +413,6 @@
this.initTable();
});
return;
// }
// this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + apiCase.name + " ", '', {
// confirmButtonText: this.$t('commons.confirm'),
// callback: (action) => {
// if (action === 'confirm') {
// let ids = [apiCase.id];
// this.$post('/api/testcase/removeToGc/', ids, () => {
// this.$success(this.$t('commons.delete_success'));
// this.initTable();
// });
// }
// }
// });
},
setEnvironment(data) {
this.environmentId = data.id;

View File

@ -9,10 +9,10 @@
<div v-for="row in request.hashTree" :key="row.id">
<!--前置脚本-->
<ms-jsr233-processor v-if="row.type==='JSR223PreProcessor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.definition.request.pre_script')"
:jsr223-processor="row"/>
:jsr223-processor="row" color="#B8741A" background-color="#F9F1EA"/>
<!--后置脚本-->
<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.post_script')"
:jsr223-processor="row"/>
:jsr223-processor="row" color="#783887" background-color="#F2ECF3"/>
<!--断言规则-->
<div style="margin-top: 10px">
<ms-api-assertions :response="response" v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>