This commit is contained in:
shiziyuan9527 2021-03-09 18:09:58 +08:00
commit abe640cba5
14 changed files with 326 additions and 173 deletions

View File

@ -96,7 +96,7 @@ public class MsAssertions extends MsTestElement {
assertion.setJsonValidationBool(true); assertion.setJsonValidationBool(true);
assertion.setExpectNull(false); assertion.setExpectNull(false);
assertion.setInvert(false); assertion.setInvert(false);
assertion.setIsRegex(false); assertion.setIsRegex(true);
return assertion; return assertion;
} }

View File

@ -157,17 +157,6 @@ public class ApiAutomationService {
return request; return request;
} }
public List<String> selectIdsNotExistsInPlan(String projectId, String planId) {
return extApiScenarioMapper.selectIdsNotExistsInPlan(projectId, planId);
}
public void deleteByIds(List<String> nodeIds) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andApiScenarioModuleIdIn(nodeIds);
apiScenarioMapper.deleteByExample(example);
}
public void removeToGcByIds(List<String> nodeIds) { public void removeToGcByIds(List<String> nodeIds) {
ApiScenarioExample example = new ApiScenarioExample(); ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andApiScenarioModuleIdIn(nodeIds); example.createCriteria().andApiScenarioModuleIdIn(nodeIds);
@ -387,7 +376,7 @@ public class ApiAutomationService {
return report; return report;
} }
private void pase(String scenarioDefinition, MsScenario scenario) { private void parse(String scenarioDefinition, MsScenario scenario) {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try { try {
@ -424,7 +413,7 @@ public class ApiAutomationService {
if (planEnvMap.size() > 0) { if (planEnvMap.size() > 0) {
scenario.setEnvironmentMap(planEnvMap); scenario.setEnvironmentMap(planEnvMap);
} }
pase(item.getScenarioDefinition(), scenario); parse(item.getScenarioDefinition(), scenario);
group.setEnableCookieShare(scenario.isEnableCookieShare()); group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>(); LinkedList<MsTestElement> scenarios = new LinkedList<>();
@ -453,7 +442,7 @@ public class ApiAutomationService {
if (scenario == null) { if (scenario == null) {
return null; return null;
} }
pase(apiScenario.getScenarioDefinition(), scenario); parse(apiScenario.getScenarioDefinition(), scenario);
// 针对导入的jmx 处理 // 针对导入的jmx 处理
if (CollectionUtils.isNotEmpty(scenario.getHashTree()) && (scenario.getHashTree().get(0) instanceof MsJmeterElement)) { if (CollectionUtils.isNotEmpty(scenario.getHashTree()) && (scenario.getHashTree().get(0) instanceof MsJmeterElement)) {
scenario.toHashTree(jmeterHashTree, scenario.getHashTree(), config); scenario.toHashTree(jmeterHashTree, scenario.getHashTree(), config);
@ -527,12 +516,13 @@ public class ApiAutomationService {
report = createScenarioReport(reportId, item.getId(), item.getName(), request.getTriggerMode(), report = createScenarioReport(reportId, item.getId(), item.getName(), request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID()); request.getExecuteType(), item.getProjectId(), request.getReportUserID());
} }
//存储报告
batchMapper.insert(report);
// 生成报告和HashTree // 生成报告和HashTree
HashTree hashTree = generateHashTree(item, reportId, planEnvMap); HashTree hashTree = generateHashTree(item, reportId, planEnvMap);
//存储报告
batchMapper.insert(report);
// 调用执行方法 // 调用执行方法
jMeterService.runDefinition(report.getId(), hashTree, request.getReportId(), request.getRunMode()); jMeterService.runDefinition(report.getId(), hashTree, request.getReportId(), request.getRunMode());
// 重置报告ID // 重置报告ID

View File

@ -100,7 +100,7 @@
select test_case_review_test_case.id as id, test_case.id as caseId, test_case.name, test_case.priority, select test_case_review_test_case.id as id, test_case.id as caseId, test_case.name, test_case.priority,
test_case.type, test_case.node_path, test_case.method, test_case.num, test_case_review_test_case.reviewer, test_case.type, test_case.node_path, test_case.method, test_case.num, test_case_review_test_case.reviewer,
test_case.review_status, test_case_review_test_case.update_time, test_case_node.name as model, test_case.review_status, test_case_review_test_case.update_time, test_case_node.name as model,
project.name as projectName, test_case_review_test_case.review_id as reviewId project.name as projectName, test_case_review_test_case.review_id as reviewId,test_case.test_id as testId
from test_case_review_test_case from test_case_review_test_case
inner join test_case on test_case_review_test_case.case_id = test_case.id inner join test_case on test_case_review_test_case.case_id = test_case.id
left join test_case_node on test_case_node.id=test_case.node_id left join test_case_node on test_case_node.id=test_case.node_id

View File

@ -68,8 +68,8 @@ public class TestCaseReviewController {
@PostMapping("/edit") @PostMapping("/edit")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void editCaseReview(@RequestBody SaveTestCaseReviewRequest testCaseReview) { public String editCaseReview(@RequestBody SaveTestCaseReviewRequest testCaseReview) {
testCaseReviewService.editCaseReview(testCaseReview); return testCaseReviewService.editCaseReview(testCaseReview);
} }
@GetMapping("/delete/{reviewId}") @GetMapping("/delete/{reviewId}")

View File

@ -203,7 +203,7 @@ public class TestCaseReviewService {
return extTestCaseReviewMapper.listByWorkspaceId(currentWorkspaceId, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId()); return extTestCaseReviewMapper.listByWorkspaceId(currentWorkspaceId, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId());
} }
public void editCaseReview(SaveTestCaseReviewRequest testCaseReview) { public String editCaseReview(SaveTestCaseReviewRequest testCaseReview) {
editCaseReviewer(testCaseReview); editCaseReviewer(testCaseReview);
testCaseReview.setUpdateTime(System.currentTimeMillis()); testCaseReview.setUpdateTime(System.currentTimeMillis());
checkCaseReviewExist(testCaseReview); checkCaseReviewExist(testCaseReview);
@ -221,6 +221,7 @@ public class TestCaseReviewService {
.event(NoticeConstants.Event.UPDATE) .event(NoticeConstants.Event.UPDATE)
.build(); .build();
noticeSendService.send(NoticeConstants.TaskType.REVIEW_TASK, noticeModel); noticeSendService.send(NoticeConstants.TaskType.REVIEW_TASK, noticeModel);
return testCaseReview.getId();
} }
private void editCaseReviewer(SaveTestCaseReviewRequest testCaseReview) { private void editCaseReviewer(SaveTestCaseReviewRequest testCaseReview) {

View File

@ -1,15 +1,18 @@
<template> <template>
<el-card> <el-card>
<div class="card-content"> <div class="card-content">
<div class="ms-main-div" @click="showAll"> <div class="ms-main-div" @click="showAll" v-if="type!=='detail'">
<!--操作按钮--> <!--操作按钮-->
<div class="ms-opt-btn"> <div class="ms-opt-btn">
<el-button id="inputDelay" type="primary" size="small" @click="editScenario" title="ctrl + s">{{$t('commons.save')}}</el-button> <el-button id="inputDelay" type="primary" size="small" @click="editScenario" title="ctrl + s">
{{ $t('commons.save') }}
</el-button>
</div> </div>
<div class="tip">{{$t('test_track.plan_view.base_info')}}</div> <div class="tip">{{ $t('test_track.plan_view.base_info') }}</div>
<el-form :model="currentScenario" label-position="right" label-width="80px" size="small" :rules="rules" ref="currentScenario" style="margin-right: 20px"> <el-form :model="currentScenario" label-position="right" label-width="80px" size="small" :rules="rules"
ref="currentScenario" style="margin-right: 20px">
<!-- 基础信息 --> <!-- 基础信息 -->
<el-row> <el-row>
<el-col :span="7"> <el-col :span="7">
@ -99,7 +102,7 @@
<div class="ms-debug-div" @click="showAll"> <div class="ms-debug-div" @click="showAll">
<el-row style="margin: 5px"> <el-row style="margin: 5px">
<el-col :span="6" class="ms-col-one ms-font"> <el-col :span="6" class="ms-col-one ms-font">
{{currentScenario.name ===undefined || ''? $t('api_test.scenario.name') : currentScenario.name}} {{ currentScenario.name === undefined || '' ? $t('api_test.scenario.name') : currentScenario.name }}
</el-col> </el-col>
<el-col :span="3" class="ms-col-one ms-font"> <el-col :span="3" class="ms-col-one ms-font">
{{$t('api_test.automation.step_total')}}{{scenarioDefinition.length}} {{$t('api_test.automation.step_total')}}{{scenarioDefinition.length}}
@ -160,30 +163,35 @@
</div> </div>
<!--接口列表--> <!--接口列表-->
<scenario-api-relevance @save="pushApiOrCase" ref="scenarioApiRelevance"/> <scenario-api-relevance @save="pushApiOrCase" ref="scenarioApiRelevance" v-if="type!=='detail'"/>
<!--自定义接口--> <!--自定义接口-->
<el-drawer :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('api_test.automation.customize_req')" style="overflow: auto" :modal="false" size="90%"> <el-drawer v-if="type!=='detail'" :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr"
:withHeader="false" :title="$t('api_test.automation.customize_req')" style="overflow: auto"
:modal="false" size="90%">
<ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/> <ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/>
</el-drawer> </el-drawer>
<!--场景导入 --> <!--场景导入 -->
<scenario-relevance @save="addScenario" ref="scenarioRelevance"/> <scenario-relevance v-if="type!=='detail'" @save="addScenario" ref="scenarioRelevance"/>
<!-- 环境 --> <!-- 环境 -->
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/> <api-environment-config v-if="type!=='detail'" ref="environmentConfig" @close="environmentConfigClose"/>
<!--执行组件--> <!--执行组件-->
<ms-run :debug="true" :environment="projectEnvMap" :reportId="reportId" :run-data="debugData" <ms-run :debug="true" v-if="type!=='detail'" :environment="projectEnvMap" :reportId="reportId"
:run-data="debugData"
@runRefresh="runRefresh" ref="runTest"/> @runRefresh="runRefresh" ref="runTest"/>
<!-- 调试结果 --> <!-- 调试结果 -->
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="true" :modal="false" size="90%"> <el-drawer v-if="type!=='detail'" :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr"
:withHeader="true" :modal="false" size="90%">
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId"/> <ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId"/>
</el-drawer> </el-drawer>
<!--场景公共参数--> <!--场景公共参数-->
<ms-variable-list @setVariables="setVariables" ref="scenarioParameters" class="ms-sc-variable-header"/> <ms-variable-list v-if="type!=='detail'" @setVariables="setVariables" ref="scenarioParameters"
class="ms-sc-variable-header"/>
<!--外部导入--> <!--外部导入-->
<api-import ref="apiImport" :saved="false" @refresh="apiImport"/> <api-import v-if="type!=='detail'" ref="apiImport" :saved="false" @refresh="apiImport"/>
</div> </div>
</el-card> </el-card>
</template> </template>
@ -222,6 +230,7 @@
props: { props: {
moduleOptions: Array, moduleOptions: Array,
currentScenario: {}, currentScenario: {},
type: String
}, },
components: { components: {
MsVariableList, MsVariableList,

View File

@ -1,6 +1,6 @@
<template> <template>
<el-card style="margin-top: 5px" @click.native="selectTestCase(apiCase,$event)"> <el-card style="margin-top: 5px" @click.native="selectTestCase(apiCase,$event)">
<div @click="active(apiCase)"> <div @click="active(apiCase)" v-if="type!=='detail'">
<el-row> <el-row>
<el-col :span="5"> <el-col :span="5">
<el-row> <el-row>
@ -79,16 +79,14 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<el-divider ></el-divider>
</div> </div>
<!-- 请求参数--> <!-- 请求参数-->
<el-collapse-transition> <el-collapse-transition>
<div v-if="apiCase.active"> <div v-if="apiCase.active||type==='detail'">
<el-divider></el-divider>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form :isShowEnable="true" :showScript="true" :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
<ms-api-request-form :isShowEnable="true" :showScript="true" :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='TCP'"/> <ms-tcp-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='SQL'"/> <ms-sql-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='DUBBO'"/> <ms-dubbo-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='DUBBO'"/>
@ -99,12 +97,13 @@
<ms-jmx-step :request="apiCase.request" :response="apiCase.responseData"/> <ms-jmx-step :request="apiCase.request" :response="apiCase.responseData"/>
<!-- 保存操作 --> <!-- 保存操作 -->
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(apiCase)" v-tester> <el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(apiCase)" v-tester v-if="type!=='detail'">
{{ $t('commons.save') }} {{ $t('commons.save') }}
</el-button> </el-button>
</div> </div>
</el-collapse-transition> </el-collapse-transition>
</el-card> </el-card>
</template> </template>
<script> <script>
@ -183,6 +182,7 @@
return {} return {}
} }
}, },
type:String,
isCaseEdit: Boolean, isCaseEdit: Boolean,
}, },
watch: {}, watch: {},

View File

@ -132,7 +132,8 @@
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
} },
type: String,
}, },
data() { data() {

View File

@ -85,7 +85,7 @@
<el-button type="primary" @click="saveReview"> <el-button type="primary" @click="saveReview">
{{ $t('test_track.confirm') }} {{ $t('test_track.confirm') }}
</el-button> </el-button>
<el-button type="primary" @click="reviewInfo('form')"> <el-button type="primary" @click="reviewInfo">
{{ $t('test_track.planning_execution') }} {{ $t('test_track.planning_execution') }}
</el-button> </el-button>
</div> </div>
@ -137,7 +137,23 @@ export default {
}; };
}, },
methods: { methods: {
reviewInfo(form) { openCaseReviewEditDialog(caseReview) {
this.resetForm();
this.setReviewerOptions();
this.operationType = 'save';
if (caseReview) {
//
this.operationType = 'edit';
let tmp = {};
Object.assign(tmp, caseReview);
Object.assign(this.form, tmp);
this.dbProjectIds = JSON.parse(JSON.stringify(this.form.projectIds));
}
listenGoBack(this.close);
this.dialogFormVisible = true;
},
reviewInfo() {
this.$refs['reviewForm'].validate((valid) => { this.$refs['reviewForm'].validate((valid) => {
if (valid) { if (valid) {
let param = {}; let param = {};
@ -155,7 +171,6 @@ export default {
if (!this.compareTime(new Date().getTime(), this.form.endTime)) { if (!this.compareTime(new Date().getTime(), this.form.endTime)) {
return false; return false;
} }
this.result = this.$post('/test/case/review/' + this.operationType, param, response => { this.result = this.$post('/test/case/review/' + this.operationType, param, response => {
this.dialogFormVisible = false; this.dialogFormVisible = false;
this.$router.push('/track/review/view/' + response.data); this.$router.push('/track/review/view/' + response.data);
@ -165,21 +180,7 @@ export default {
} }
}); });
}, },
openCaseReviewEditDialog(caseReview) {
this.resetForm();
this.setReviewerOptions();
this.operationType = 'save';
if (caseReview) {
//
this.operationType = 'edit';
let tmp = {};
Object.assign(tmp, caseReview);
Object.assign(this.form, tmp);
this.dbProjectIds = JSON.parse(JSON.stringify(this.form.projectIds));
}
listenGoBack(this.close);
this.dialogFormVisible = true;
},
saveReview() { saveReview() {
this.$refs['reviewForm'].validate((valid) => { this.$refs['reviewForm'].validate((valid) => {
if (valid) { if (valid) {

View File

@ -14,7 +14,7 @@
<el-menu-item index="functional">功能测试用例</el-menu-item> <el-menu-item index="functional">功能测试用例</el-menu-item>
<el-menu-item index="api">接口测试用例</el-menu-item> <el-menu-item index="api">接口测试用例</el-menu-item>
<el-menu-item index="load">性能测试用例</el-menu-item> <el-menu-item index="load">性能测试用例</el-menu-item>
<el-menu-item index="report">报告统计</el-menu-item> <!-- <el-menu-item index="report">报告统计</el-menu-item>-->
</el-menu> </el-menu>
</template> </template>
</ms-test-plan-header-bar> </ms-test-plan-header-bar>
@ -24,6 +24,7 @@
:review-id="reviewId"></test-review-api> :review-id="reviewId"></test-review-api>
<test-review-load v-if="activeIndex === 'load'" :redirectCharType="redirectCharType" :clickType="clickType" <test-review-load v-if="activeIndex === 'load'" :redirectCharType="redirectCharType" :clickType="clickType"
:review-id="reviewId"></test-review-load> :review-id="reviewId"></test-review-load>
</div> </div>
</template> </template>

View File

@ -1,55 +1,116 @@
<template> <template>
<ms-test-plan-common-component> <ms-test-plan-common-component>
<template v-slot:aside> <template v-slot:aside>
<ms-node-tree <ms-api-module
class="node-tree" v-if="model === 'api'"
:all-label="$t('commons.all_label.review')"
v-loading="result.loading"
@nodeSelectEvent="nodeChange" @nodeSelectEvent="nodeChange"
:tree-nodes="treeNodes" @protocolChange="handleProtocolChange"
ref="nodeTree"/> @refreshTable="refreshTable"
@setModuleOptions="setModuleOptions"
:review-id="reviewId"
:is-read-only="true"
:redirectCharType="redirectCharType"
ref="apiNodeTree"
>
<template v-slot:header>
<div class="model-change-radio">
<el-radio v-model="model" label="api">接口用例</el-radio>
<el-radio v-model="model" label="scenario">场景用例</el-radio>
</div>
</template>
</ms-api-module>
<ms-api-scenario-module
v-if="model === 'scenario'"
@nodeSelectEvent="nodeChange"
@refreshTable="refreshTable"
@setModuleOptions="setModuleOptions"
:is-read-only="true"
:review-id="reviewId"
ref="scenarioNodeTree">
<template v-slot:header>
<div class="model-change-radio">
<el-radio v-model="model" label="api">接口用例</el-radio>
<el-radio v-model="model" label="scenario">场景用例</el-radio>
</div>
</template>
</ms-api-scenario-module>
</template> </template>
<template v-slot:main> <template v-slot:main>
<test-review-test-case-list <test-plan-api-case-list
class="table-list" v-if="model === 'api'"
@openTestReviewRelevanceDialog="openTestReviewRelevanceDialog" :current-protocol="currentProtocol"
@refresh="refresh" :currentRow="currentRow"
:review-id="reviewId" :select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
:is-case-relevance="true"
:model="'plan'"
:review-id="reviewId"
:clickType="clickType"
@refresh="refreshTree"
@relevanceCase="openTestCaseRelevanceDialog"
ref="apiCaseList"/>
<ms-test-plan-api-scenario-list
v-if="model === 'scenario'"
:select-node-ids="selectNodeIds" :select-node-ids="selectNodeIds"
:select-parent-nodes="selectParentNodes" :trash-enable="trashEnable"
:review-id="reviewId"
:clickType="clickType" :clickType="clickType"
ref="testPlanTestCaseList"/> @refresh="refreshTree"
@relevanceCase="openTestCaseRelevanceDialog"
ref="apiScenarioList"/>
</template> </template>
<test-review-relevance <test-case-api-relevance
@refresh="refresh" @refresh="refresh"
:review-id="reviewId" :review-id="reviewId"
ref="testReviewRelevance"/> :model="model"
ref="apiCaseRelevance"/>
<test-case-scenario-relevance
@refresh="refresh"
:review-id="reviewId"
:model="model"
ref="scenarioCaseRelevance"/>
</ms-test-plan-common-component> </ms-test-plan-common-component>
</template> </template>
<script> <script>
import MsTestPlanCommonComponent from "@/business/components/track/plan/view/comonents/base/TestPlanCommonComponent"; import MsTestPlanCommonComponent from "@/business/components/track/plan/view/comonents/base/TestPlanCommonComponent";
import FunctionalTestCaseList from "@/business/components/track/plan/view/comonents/functional/FunctionalTestCaseList"; import TestCaseScenarioRelevance from "@/business/components/track/plan/view/comonents/api/TestCaseScenarioRelevance";
import MsNodeTree from "@/business/components/track/common/NodeTree"; import MsTestPlanApiScenarioList from "@/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList";
import TestReviewRelevance from "@/business/components/track/review/view/components/TestReviewRelevance"; import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule";
import TestReviewTestCaseList from "@/business/components/track/review/view/components/TestReviewTestCaseList"; import ApiCaseSimpleList from "@/business/components/api/definition/components/list/ApiCaseSimpleList";
import TestCaseApiRelevance from "@/business/components/track/plan/view/comonents/api/TestCaseApiRelevance";
import TestPlanApiCaseList from "@/business/components/track/plan/view/comonents/api/TestPlanApiCaseList";
import TestCaseRelevance from "@/business/components/track/plan/view/comonents/functional/TestCaseFunctionalRelevance";
import NodeTree from "@/business/components/track/common/NodeTree";
import MsApiModule from "../../../../api/definition/components/module/ApiModule"
export default { export default {
name: "TestReviewApi", name: "TestReviewApi",
components: { components: {
TestReviewTestCaseList, TestCaseScenarioRelevance,
TestReviewRelevance, MsNodeTree, FunctionalTestCaseList, MsTestPlanCommonComponent MsTestPlanApiScenarioList,
MsApiScenarioModule,
ApiCaseSimpleList,
TestCaseApiRelevance,
TestPlanApiCaseList,
MsTestPlanCommonComponent,
TestCaseRelevance,
NodeTree,
MsApiModule,
}, },
data() { data() {
return { return {
result: {}, result: {},
testReviews: [],
currentReview: {},
selectNodeIds: [],
selectParentNodes: [],
treeNodes: [], treeNodes: [],
isMenuShow: true, currentRow: "",
trashEnable: false,
currentProtocol: null,
currentModule: null,
selectNodeIds: [],
moduleOptions: {},
model: 'api'
} }
}, },
props: [ props: [
@ -58,32 +119,66 @@ export default {
'clickType' 'clickType'
], ],
mounted() { mounted() {
this.getNodeTreeByReviewId() this.checkRedirectCharType();
}, },
activated() { watch: {
this.getNodeTreeByReviewId() model() {
this.selectNodeIds = [];
this.moduleOptions = {};
},
redirectCharType(){
if(this.redirectCharType=='scenario'){
this.model = 'scenario';
}else{
this.model = 'api';
}
}
}, },
methods: { methods: {
refresh() { checkRedirectCharType(){
this.selectNodeIds = []; if(this.redirectCharType=='scenario'){
this.selectParentNodes = []; this.model = 'scenario';
this.$refs.testReviewRelevance.search(); }else{
this.getNodeTreeByReviewId(); this.model = 'api';
},
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
this.selectParentNodes = pNodes;
},
getNodeTreeByReviewId() {
if (this.reviewId) {
this.result = this.$get("/case/node/list/review/" + this.reviewId, response => {
this.treeNodes = response.data;
});
} }
}, },
openTestReviewRelevanceDialog() { refresh() {
this.$refs.testReviewRelevance.openTestReviewRelevanceDialog(); this.refreshTree();
this.refreshTable();
},
refreshTable() {
if (this.$refs.apiCaseList) {
this.$refs.apiCaseList.initTable();
}
if (this.$refs.apiScenarioList) {
this.$refs.apiScenarioList.search();
}
},
refreshTree() {
if (this.$refs.apiNodeTree) {
this.$refs.apiNodeTree.list();
}
if (this.$refs.scenarioNodeTree) {
this.$refs.scenarioNodeTree.list();
}
},
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
},
handleProtocolChange(protocol) {
this.currentProtocol = protocol;
},
setModuleOptions(data) {
this.moduleOptions = data;
},
openTestCaseRelevanceDialog(model) {
if (model === 'scenario') {
this.$refs.scenarioCaseRelevance.open();
} else {
this.$refs.apiCaseRelevance.open();
}
}, },
} }
} }

View File

@ -1,55 +1,52 @@
<template> <template>
<ms-test-plan-common-component> <ms-test-plan-common-component>
<template v-slot:aside> <template v-slot:aside>
<ms-node-tree <node-tree
class="node-tree" class="node-tree"
:all-label="$t('commons.all_label.review')"
v-loading="result.loading" v-loading="result.loading"
@nodeSelectEvent="nodeChange" @nodeSelectEvent="nodeChange"
:tree-nodes="treeNodes" :tree-nodes="treeNodes"
ref="nodeTree"/> ref="nodeTree"/>
</template> </template>
<template v-slot:main> <template v-slot:main>
<test-review-test-case-list <test-plan-load-case-list
class="table-list" class="table-list"
@openTestReviewRelevanceDialog="openTestReviewRelevanceDialog"
@refresh="refresh" @refresh="refresh"
:review-id="reviewId" :review-id="reviewId"
:select-node-ids="selectNodeIds"
:select-parent-nodes="selectParentNodes"
:clickType="clickType" :clickType="clickType"
ref="testPlanTestCaseList"/> :select-project-id="selectProjectId"
:select-parent-nodes="selectParentNodes"
@relevanceCase="openTestCaseRelevanceDialog"
ref="testPlanLoadCaseList"/>
</template> </template>
<test-review-relevance <test-case-load-relevance
@refresh="refresh" @refresh="refresh"
:review-id="reviewId" :review-id="reviewId"
ref="testReviewRelevance"/> ref="testCaseLoadRelevance"/>
</ms-test-plan-common-component> </ms-test-plan-common-component>
</template> </template>
<script> <script>
import MsTestPlanCommonComponent from "@/business/components/track/plan/view/comonents/base/TestPlanCommonComponent"; import MsTestPlanCommonComponent from "@/business/components/track/plan/view/comonents/base/TestPlanCommonComponent";
import FunctionalTestCaseList from "@/business/components/track/plan/view/comonents/functional/FunctionalTestCaseList"; import NodeTree from "@/business/components/track/common/NodeTree";
import MsNodeTree from "@/business/components/track/common/NodeTree"; import TestPlanLoadCaseList from "@/business/components/track/plan/view/comonents/load/TestPlanLoadCaseList";
import TestReviewRelevance from "@/business/components/track/review/view/components/TestReviewRelevance"; import TestCaseLoadRelevance from "@/business/components/track/plan/view/comonents/load/TestCaseLoadRelevance";
import TestReviewTestCaseList from "@/business/components/track/review/view/components/TestReviewTestCaseList";
export default { export default {
name: "TestReviewLoad", name: "TestReviewLoad",
components: { components: {
TestReviewTestCaseList, MsTestPlanCommonComponent,
TestReviewRelevance, MsNodeTree, FunctionalTestCaseList, MsTestPlanCommonComponent NodeTree,
TestPlanLoadCaseList,
TestCaseLoadRelevance,
}, },
data() { data() {
return { return {
result: {}, result: {},
testReviews: [],
currentReview: {},
selectNodeIds: [], selectNodeIds: [],
selectParentNodes: [], selectParentNodes: [],
selectProjectId: "",
treeNodes: [], treeNodes: [],
isMenuShow: true,
} }
}, },
props: [ props: [
@ -57,34 +54,42 @@ export default {
'redirectCharType', 'redirectCharType',
'clickType' 'clickType'
], ],
mounted() { watch: {
this.getNodeTreeByReviewId() planId() {
this.initData();
}
}, },
activated() { mounted() {
this.getNodeTreeByReviewId() this.initData();
}, },
methods: { methods: {
refresh() { refresh() {
this.selectNodeIds = []; this.selectProjectId = '';
this.selectParentNodes = []; this.selectParentNodes = [];
this.$refs.testReviewRelevance.search(); this.$refs.testPlanLoadCaseList.initTable();
this.getNodeTreeByReviewId(); this.getNodeTreeByPlanId();
},
initData() {
this.getNodeTreeByPlanId();
},
openTestCaseRelevanceDialog() {
this.$refs.testCaseLoadRelevance.open();
}, },
nodeChange(node, nodeIds, pNodes) { nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds; this.selectProjectId = node.key;
this.selectParentNodes = pNodes; // node
this.$refs.testPlanLoadCaseList.currentPage = 1;
this.$refs.testPlanLoadCaseList.pageSize = 10;
}, },
getNodeTreeByReviewId() { getNodeTreeByPlanId() {
if (this.reviewId) { if (this.planId) {
this.result = this.$get("/case/node/list/review/" + this.reviewId, response => { this.result = this.$get("/case/node/list/plan/" + this.planId, response => {
this.treeNodes = response.data; this.treeNodes = response.data;
//
this.treeNodes.map(node => node.children = null);
}); });
} }
}, },
openTestReviewRelevanceDialog() {
this.$refs.testReviewRelevance.openTestReviewRelevanceDialog();
},
} }
} }
</script> </script>

View File

@ -39,11 +39,14 @@
<el-divider direction="vertical"></el-divider> <el-divider direction="vertical"></el-divider>
<el-button type="success" size="mini" <el-button type="success" size="mini"
:disabled="isReadOnly" :icon="testCase.reviewStatus === 'Pass' ? 'el-icon-check' : ''" @click="saveCase('Pass')"> :disabled="isReadOnly" :icon="testCase.reviewStatus === 'Pass' ? 'el-icon-check' : ''"
@click="saveCase('Pass')">
{{ $t('test_track.review.pass') }} {{ $t('test_track.review.pass') }}
</el-button> </el-button>
<el-button type="danger" size="mini" <el-button type="danger" size="mini"
:disabled="isReadOnly" :icon="testCase.reviewStatus === 'UnPass' ? 'el-icon-check' : ''" @click="saveCase('UnPass')"> :disabled="isReadOnly"
:icon="testCase.reviewStatus === 'UnPass' ? 'el-icon-check' : ''"
@click="saveCase('UnPass')">
{{ $t('test_track.review.un_pass') }} {{ $t('test_track.review.un_pass') }}
</el-button> </el-button>
</el-col> </el-col>
@ -66,29 +69,22 @@
</el-col> </el-col>
<el-col :span="5"> <el-col :span="5">
<span class="cast_label">{{ $t('test_track.case.case_type') }}</span> <span class="cast_label">{{ $t('test_track.case.case_type') }}</span>
<span class="cast_item" v-if="testCase.type === 'functional'">{{ <span class="cast_item" v-if="testCase.type === 'automation'">
$t('commons.functional') 场景用例
}}</span> </span>
<span class="cast_item" <span class="cast_item"
v-if="testCase.type === 'performance'">{{ $t('commons.performance') }}</span> v-if="testCase.type === 'performance'">{{ $t('commons.performance') }}</span>
<span class="cast_item" v-if="testCase.type === 'api'">{{ $t('commons.api') }}</span> <span class="cast_item" v-if="testCase.type === 'api'">{{ $t('commons.api') }}</span>
<span class="cast_item" v-if="testCase.type === 'testcase'">接口用例</span>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="4" :offset="1"> <el-col :offset="1">
<span class="cast_label">{{ $t('test_track.case.method') }}</span>
<span v-if="testCase.method === 'manual'">{{ $t('test_track.case.manual') }}</span>
<span v-if="testCase.method === 'auto'">{{ $t('test_track.case.auto') }}</span>
</el-col>
<el-col :span="5">
<span class="cast_label">{{ $t('test_track.case.module') }}</span> <span class="cast_label">{{ $t('test_track.case.module') }}</span>
<span class="cast_item">{{ testCase.nodePath }}</span> <span class="cast_item">{{ testCase.nodePath }}</span>
</el-col> </el-col>
<el-col :span="4" :offset="1">
<span class="cast_label">{{ $t('test_track.plan.plan_project') }}</span>
<span class="cast_item">{{ testCase.projectName }}</span>
</el-col>
</el-row> </el-row>
<el-row> <el-row>
@ -98,7 +94,7 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row v-if="testCase.method === 'auto' && testCase.testId"> <el-row>
<el-col class="test-detail" :span="20" :offset="1"> <el-col class="test-detail" :span="20" :offset="1">
<el-tabs v-model="activeTab" type="border-card"> <el-tabs v-model="activeTab" type="border-card">
<el-tab-pane name="detail" :label="$t('test_track.plan_view.test_detail')"> <el-tab-pane name="detail" :label="$t('test_track.plan_view.test_detail')">
@ -108,12 +104,17 @@
:is-read-only="true" :is-read-only="true"
:id="testCase.testId" :id="testCase.testId"
ref="performanceTestDetail"/> ref="performanceTestDetail"/>
<api-case-item :type="mark" :api="api" :api-case="apiCase" v-if="testCase.type==='testcase'"
ref="apiCaseConfig"/>
<ms-edit-api-scenario :type="mark" v-if="testCase.type==='automation'" :currentScenario="currentScenario"
ref="autoScenarioConfig"></ms-edit-api-scenario>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-col> </el-col>
</el-row> </el-row>
<el-row v-if="testCase.method && testCase.method !== 'auto'"> <el-row v-if="testCase.type === 'function'">
<el-col :span="20" :offset="1"> <el-col :span="20" :offset="1">
<div> <div>
<span class="cast_label">{{ $t('test_track.case.steps') }}</span> <span class="cast_label">{{ $t('test_track.case.steps') }}</span>
@ -229,7 +230,8 @@
<i class="el-icon-refresh" @click="getComments(testCase)" <i class="el-icon-refresh" @click="getComments(testCase)"
style="margin-left:10px;font-size: 14px; cursor: pointer"/> style="margin-left:10px;font-size: 14px; cursor: pointer"/>
</template> </template>
<review-comment :comments="comments" :case-id="testCase.caseId" :review-id="testCase.reviewId" @getComments="getComments"/> <review-comment :comments="comments" :case-id="testCase.caseId" :review-id="testCase.reviewId"
@getComments="getComments"/>
</el-card> </el-card>
</el-col> </el-col>
</div> </div>
@ -248,9 +250,11 @@ import PerformanceTestDetail from "../../../plan/view/comonents/test/Performance
import ApiTestResult from "../../../plan/view/comonents/test/ApiTestResult"; import ApiTestResult from "../../../plan/view/comonents/test/ApiTestResult";
import ApiTestDetail from "../../../plan/view/comonents/test/ApiTestDetail"; import ApiTestDetail from "../../../plan/view/comonents/test/ApiTestDetail";
import TestPlanTestCaseStatusButton from "../../../plan/common/TestPlanTestCaseStatusButton"; import TestPlanTestCaseStatusButton from "../../../plan/common/TestPlanTestCaseStatusButton";
import {listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {getCurrentProjectID, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import ReviewComment from "../../commom/ReviewComment"; import ReviewComment from "../../commom/ReviewComment";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment"; import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import ApiCaseItem from "@/business/components/api/definition/components/case/ApiCaseItem";
import MsEditApiScenario from "@/business/components/api/automation/scenario/EditApiScenario"
export default { export default {
name: "TestReviewTestCaseEdit", name: "TestReviewTestCaseEdit",
@ -261,7 +265,10 @@ export default {
ApiTestDetail, ApiTestDetail,
TestPlanTestCaseStatusButton, TestPlanTestCaseStatusButton,
ReviewComment, ReviewComment,
TestCaseAttachment TestCaseAttachment,
ApiCaseItem,
MsEditApiScenario
}, },
data() { data() {
return { return {
@ -277,7 +284,11 @@ export default {
users: [], users: [],
activeName: 'comment', activeName: 'comment',
comments: [], comments: [],
tableData: [] tableData: [],
currentScenario: {},
mark: 'detail',
api: {},
apiCase: {},
}; };
}, },
props: { props: {
@ -378,16 +389,55 @@ export default {
listenGoBack(this.handleClose); listenGoBack(this.handleClose);
this.initData(testCase); this.initData(testCase);
this.getComments(testCase); this.getComments(testCase);
this.getApiTestCase(testCase);
this.getCurrentScenario(testCase)
},
getApiTestCase(testCase) {
let param = {}
param.projectId = getCurrentProjectID();
param.id = testCase.testId;
this.result = this.$post("/api/testcase/list", param, response => {
let apiCaseList = []
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.apiCase = apiCase
this.handleTestCase(apiCase)
})
});
},
getCurrentScenario(testCase) {
this.result = this.$get("/api/automation/getApiScenario/" + testCase.testId, response => {
this.currentScenario=response.data
});
},
handleTestCase(testCase) {
this.$get('/api/definition/get/' + testCase.apiDefinitionId, (response) => {
this.api = response.data;
});
}, },
initTest() { initTest() {
this.$nextTick(() => { this.$nextTick(() => {
if (this.testCase.testId && this.testCase.testId !== 'other') { if (this.testCase.testId && this.testCase.testId !== 'other') {
if (this.testCase.method === 'auto') { if (this.$refs.apiTestDetail && this.testCase.type === 'api') {
if (this.$refs.apiTestDetail && this.testCase.type === 'api') { this.$refs.apiTestDetail.init();
this.$refs.apiTestDetail.init(); } else if (this.testCase.type === 'performance') {
} else if (this.testCase.type === 'performance') { this.$refs.performanceTestDetail.init();
this.$refs.performanceTestDetail.init(); } else if (this.testCase.type === 'testcase') {
} this.$refs.apiCaseConfig.active(this.api);
} else if (this.testCase.type === 'automation') {
this.$refs.autoScenarioConfig.showAll();
} }
} }
}); });

View File

@ -84,7 +84,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <!-- <el-table-column
v-if="item.id=='method'" v-if="item.id=='method'"
prop="method" prop="method"
:filters="methodFilters" :filters="methodFilters"
@ -95,7 +95,7 @@
<template v-slot:default="scope"> <template v-slot:default="scope">
<method-table-item :value="scope.row.method"/> <method-table-item :value="scope.row.method"/>
</template> </template>
</el-table-column> </el-table-column>-->
<el-table-column <el-table-column
v-if="item.id=='nodePath'" v-if="item.id=='nodePath'"