Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9d134f85a4
|
@ -6,11 +6,11 @@ ARG MS_VERSION=dev
|
||||||
|
|
||||||
RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter/lib/junit
|
RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter/lib/junit
|
||||||
|
|
||||||
COPY backend/target/backend-1.7.jar /opt/apps
|
COPY backend/target/backend-1.8.jar /opt/apps
|
||||||
|
|
||||||
COPY backend/target/classes/jmeter/ /opt/jmeter/
|
COPY backend/target/classes/jmeter/ /opt/jmeter/
|
||||||
|
|
||||||
ENV JAVA_APP_JAR=/opt/apps/backend-1.7.jar
|
ENV JAVA_APP_JAR=/opt/apps/backend-1.8.jar
|
||||||
|
|
||||||
ENV AB_OFF=true
|
ENV AB_OFF=true
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>metersphere-server</artifactId>
|
<artifactId>metersphere-server</artifactId>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<version>1.7</version>
|
<version>1.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -201,7 +201,7 @@ public class MsLoopController extends MsTestElement {
|
||||||
jsr223PreProcessor.setName("循环超时处理");
|
jsr223PreProcessor.setName("循环超时处理");
|
||||||
jsr223PreProcessor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
jsr223PreProcessor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
||||||
jsr223PreProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
jsr223PreProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||||
jsr223PreProcessor.setProperty("cacheKey", "true");
|
/*jsr223PreProcessor.setProperty("cacheKey", "true");*/
|
||||||
jsr223PreProcessor.setProperty("scriptLanguage", "beanshell");
|
jsr223PreProcessor.setProperty("scriptLanguage", "beanshell");
|
||||||
jsr223PreProcessor.setProperty("script", script());
|
jsr223PreProcessor.setProperty("script", script());
|
||||||
hashTree.add(jsr223PreProcessor);
|
hashTree.add(jsr223PreProcessor);
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class MsJSR223Processor extends MsTestElement {
|
||||||
|
|
||||||
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
||||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||||
processor.setProperty("cacheKey", "true");
|
/*processor.setProperty("cacheKey", "true");*/
|
||||||
processor.setProperty("scriptLanguage", this.getScriptLanguage());
|
processor.setProperty("scriptLanguage", this.getScriptLanguage());
|
||||||
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
|
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
|
||||||
processor.setProperty("scriptLanguage", "nashorn");
|
processor.setProperty("scriptLanguage", "nashorn");
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class MsJSR223PostProcessor extends MsTestElement {
|
||||||
}
|
}
|
||||||
processor.setProperty(TestElement.TEST_CLASS, JSR223PostProcessor.class.getName());
|
processor.setProperty(TestElement.TEST_CLASS, JSR223PostProcessor.class.getName());
|
||||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||||
processor.setProperty("cacheKey", "true");
|
/*processor.setProperty("cacheKey", "true");*/
|
||||||
processor.setProperty("scriptLanguage", this.getScriptLanguage());
|
processor.setProperty("scriptLanguage", this.getScriptLanguage());
|
||||||
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
|
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
|
||||||
processor.setProperty("scriptLanguage", "nashorn");
|
processor.setProperty("scriptLanguage", "nashorn");
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class MsJSR223PreProcessor extends MsTestElement {
|
||||||
}
|
}
|
||||||
processor.setProperty(TestElement.TEST_CLASS, JSR223PreProcessor.class.getName());
|
processor.setProperty(TestElement.TEST_CLASS, JSR223PreProcessor.class.getName());
|
||||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||||
processor.setProperty("cacheKey", "true");
|
/*processor.setProperty("cacheKey", "true");*/
|
||||||
processor.setProperty("scriptLanguage", this.getScriptLanguage());
|
processor.setProperty("scriptLanguage", this.getScriptLanguage());
|
||||||
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
|
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
|
||||||
processor.setProperty("scriptLanguage", "nashorn");
|
processor.setProperty("scriptLanguage", "nashorn");
|
||||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.api.service.*;
|
||||||
import io.metersphere.base.domain.ApiDefinitionExecResult;
|
import io.metersphere.base.domain.ApiDefinitionExecResult;
|
||||||
import io.metersphere.base.domain.ApiScenarioReport;
|
import io.metersphere.base.domain.ApiScenarioReport;
|
||||||
import io.metersphere.base.domain.ApiTestReport;
|
import io.metersphere.base.domain.ApiTestReport;
|
||||||
|
import io.metersphere.base.domain.TestPlanReport;
|
||||||
import io.metersphere.commons.constants.*;
|
import io.metersphere.commons.constants.*;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
@ -14,6 +15,7 @@ import io.metersphere.notice.sender.NoticeModel;
|
||||||
import io.metersphere.notice.service.NoticeSendService;
|
import io.metersphere.notice.service.NoticeSendService;
|
||||||
import io.metersphere.service.SystemParameterService;
|
import io.metersphere.service.SystemParameterService;
|
||||||
import io.metersphere.track.service.TestPlanReportService;
|
import io.metersphere.track.service.TestPlanReportService;
|
||||||
|
import io.metersphere.track.service.TestPlanService;
|
||||||
import io.metersphere.track.service.TestPlanTestCaseService;
|
import io.metersphere.track.service.TestPlanTestCaseService;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
|
@ -403,17 +403,24 @@ public class ApiDefinitionService {
|
||||||
|
|
||||||
private void importMsCase(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestCaseMapper apiTestCaseMapper) {
|
private void importMsCase(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestCaseMapper apiTestCaseMapper) {
|
||||||
List<ApiTestCaseWithBLOBs> cases = apiImport.getCases();
|
List<ApiTestCaseWithBLOBs> cases = apiImport.getCases();
|
||||||
|
List<String> caseNames = apiTestCaseService.listPorjectAllCaseName(SessionUtils.getCurrentProjectId());
|
||||||
|
Set<String> existCaseName = new HashSet<>();
|
||||||
|
caseNames.forEach(item -> {
|
||||||
|
existCaseName.add(item);
|
||||||
|
});
|
||||||
if (CollectionUtils.isNotEmpty(cases)) {
|
if (CollectionUtils.isNotEmpty(cases)) {
|
||||||
int batchCount = 0;
|
int batchCount = 0;
|
||||||
cases.forEach(item -> {
|
cases.forEach(item -> {
|
||||||
item.setId(UUID.randomUUID().toString());
|
if(!existCaseName.contains(item.getName())) {
|
||||||
item.setCreateTime(System.currentTimeMillis());
|
item.setId(UUID.randomUUID().toString());
|
||||||
item.setUpdateTime(System.currentTimeMillis());
|
item.setCreateTime(System.currentTimeMillis());
|
||||||
item.setCreateUserId(SessionUtils.getUserId());
|
item.setUpdateTime(System.currentTimeMillis());
|
||||||
item.setUpdateUserId(SessionUtils.getUserId());
|
item.setCreateUserId(SessionUtils.getUserId());
|
||||||
item.setProjectId(SessionUtils.getCurrentProjectId());
|
item.setUpdateUserId(SessionUtils.getUserId());
|
||||||
item.setNum(getNextNum(item.getApiDefinitionId()));
|
item.setProjectId(SessionUtils.getCurrentProjectId());
|
||||||
apiTestCaseMapper.insert(item);
|
item.setNum(getNextNum(item.getApiDefinitionId()));
|
||||||
|
apiTestCaseMapper.insert(item);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (batchCount % 300 == 0) {
|
if (batchCount % 300 == 0) {
|
||||||
sqlSession.flushStatements();
|
sqlSession.flushStatements();
|
||||||
|
@ -628,12 +635,7 @@ public class ApiDefinitionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(apiImport.getCases())) {
|
if (!CollectionUtils.isEmpty(apiImport.getCases())) {
|
||||||
for (int i = 0; i < apiImport.getCases().size(); i++) {
|
importMsCase(apiImport, sqlSession, apiTestCaseMapper);
|
||||||
importMsCase(apiImport, sqlSession, apiTestCaseMapper);
|
|
||||||
if (i % 300 == 0) {
|
|
||||||
sqlSession.flushStatements();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sqlSession.flushStatements();
|
sqlSession.flushStatements();
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,10 @@ public class ApiTestCaseService {
|
||||||
|
|
||||||
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
|
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
|
||||||
|
|
||||||
|
public List<String> listPorjectAllCaseName(String projectId) {
|
||||||
|
return extApiTestCaseMapper.listPorjectAllCaseName(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
public List<ApiTestCaseResult> list(ApiTestCaseRequest request) {
|
public List<ApiTestCaseResult> list(ApiTestCaseRequest request) {
|
||||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||||
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);
|
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);
|
||||||
|
|
|
@ -12,6 +12,8 @@ import java.util.List;
|
||||||
|
|
||||||
public interface ExtApiTestCaseMapper {
|
public interface ExtApiTestCaseMapper {
|
||||||
|
|
||||||
|
List<String> listPorjectAllCaseName(@Param("projectId") String projectId);
|
||||||
|
|
||||||
List<ApiTestCaseResult> list(@Param("request") ApiTestCaseRequest request);
|
List<ApiTestCaseResult> list(@Param("request") ApiTestCaseRequest request);
|
||||||
|
|
||||||
List<ApiTestCaseDTO> listSimple(@Param("request") ApiTestCaseRequest request);
|
List<ApiTestCaseDTO> listSimple(@Param("request") ApiTestCaseRequest request);
|
||||||
|
|
|
@ -391,6 +391,8 @@
|
||||||
<select id="getNextNum" resultType="io.metersphere.base.domain.ApiTestCase">
|
<select id="getNextNum" resultType="io.metersphere.base.domain.ApiTestCase">
|
||||||
SELECT * FROM api_test_case WHERE api_test_case.api_definition_id = #{definitionId} ORDER BY num DESC LIMIT 1;
|
SELECT * FROM api_test_case WHERE api_test_case.api_definition_id = #{definitionId} ORDER BY num DESC LIMIT 1;
|
||||||
</select>
|
</select>
|
||||||
|
<select id="listPorjectAllCaseName" resultType="java.lang.String">
|
||||||
|
select name from api_test_case where project_id = #{projectId}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -120,8 +120,8 @@ public class TestCaseController {
|
||||||
|
|
||||||
@PostMapping(value = "/add", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/add", consumes = {"multipart/form-data"})
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public void addTestCase(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file") List<MultipartFile> files) {
|
public String addTestCase(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file") List<MultipartFile> files) {
|
||||||
testCaseService.save(request, files);
|
return testCaseService.save(request, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/edit", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/edit", consumes = {"multipart/form-data"})
|
||||||
|
|
|
@ -192,3 +192,6 @@ CREATE TABLE IF NOT EXISTS test_case_test
|
||||||
|
|
||||||
alter table test_case
|
alter table test_case
|
||||||
modify test_id varchar(2000) null;
|
modify test_id varchar(2000) null;
|
||||||
|
|
||||||
|
-- update history data
|
||||||
|
update test_case set review_status = 'Prepare' where review_status is null;
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>metersphere-server</artifactId>
|
<artifactId>metersphere-server</artifactId>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<version>1.7</version>
|
<version>1.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -37,14 +37,19 @@
|
||||||
</div>
|
</div>
|
||||||
<!--最大化不显示具体内容-->
|
<!--最大化不显示具体内容-->
|
||||||
<div class="header" v-if="!isMax">
|
<div class="header" v-if="!isMax">
|
||||||
<fieldset :disabled="data.disabled" class="ms-fieldset">
|
<el-collapse-transition>
|
||||||
<el-collapse-transition>
|
<div v-if="data.active && showCollapse" :draggable="draggable">
|
||||||
<div v-if="data.active && showCollapse" :draggable="draggable">
|
<el-divider></el-divider>
|
||||||
<el-divider></el-divider>
|
<fieldset :disabled="data.disabled" class="ms-fieldset">
|
||||||
|
<!--四种协议请求内容-->
|
||||||
|
<slot name="request"></slot>
|
||||||
|
<!--其他模版内容,比如断言,提取等-->
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</fieldset>
|
||||||
</el-collapse-transition>
|
<!--四种协议执行结果内容-->
|
||||||
</fieldset>
|
<slot name="result"></slot>
|
||||||
|
</div>
|
||||||
|
</el-collapse-transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
|
@ -27,48 +27,58 @@
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<customize-req-info :is-customize-req="isCustomizeReq" :request="request"/>
|
<!--请求内容-->
|
||||||
|
<template v-slot:request>
|
||||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
<customize-req-info :is-customize-req="isCustomizeReq" :request="request"/>
|
||||||
<ms-api-request-form :isShowEnable="true" :referenced="true" :headers="request.headers " :request="request"
|
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||||
v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"/>
|
<ms-api-request-form v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
|
||||||
<esb-definition v-xpack :request="request" :showScript="false" v-if="this.showXpackCompnent&&request.esbDataStruct!=null" ref="esbDefinition"/>
|
:isShowEnable="true"
|
||||||
<ms-tcp-basis-parameters :request="request" v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&&request.esbDataStruct==null " :showScript="false"/>
|
:referenced="true"
|
||||||
|
:headers="request.headers "
|
||||||
<ms-sql-basis-parameters :request="request" v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
|
:request="request"/>
|
||||||
:showScript="false"/>
|
<esb-definition v-if="showXpackCompnent&&request.esbDataStruct!=null"
|
||||||
<ms-dubbo-basis-parameters :request="request"
|
v-xpack
|
||||||
v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
|
:request="request"
|
||||||
|
:showScript="false"
|
||||||
|
ref="esbDefinition"/>
|
||||||
|
<ms-tcp-basis-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&&request.esbDataStruct==null "
|
||||||
|
:request="request"
|
||||||
:showScript="false"/>
|
:showScript="false"/>
|
||||||
|
<ms-sql-basis-parameters v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
|
||||||
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
|
:request="request"
|
||||||
<div v-if="request.result">
|
:showScript="false"/>
|
||||||
<el-tabs v-model="request.activeName" closable class="ms-tabs">
|
<ms-dubbo-basis-parameters v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
|
||||||
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in request.result.scenarios" :key="index">
|
:request="request"
|
||||||
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
:showScript="false"/>
|
||||||
<api-response-component v-if="result.name===request.name" :result="result"/>
|
</template>
|
||||||
</div>
|
<!-- 执行结果内容 -->
|
||||||
</el-tab-pane>
|
<template v-slot:result>
|
||||||
</el-tabs>
|
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
|
||||||
</div>
|
<div v-if="request.result">
|
||||||
<div v-else-if="showXpackCompnent&&request.backEsbDataStruct != null">
|
<el-tabs v-model="request.activeName" closable class="ms-tabs">
|
||||||
<esb-definition-response :currentProtocol="request.protocol" :request="request" :is-api-component="false"
|
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in request.result.scenarios" :key="index">
|
||||||
:show-options-button="false" :show-header="true" :result="request.requestResult"/>
|
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
||||||
</div>
|
<api-response-component v-if="result.name===request.name" :result="result"/>
|
||||||
<div v-else>
|
</div>
|
||||||
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult"/>
|
</el-tab-pane>
|
||||||
</div>
|
</el-tabs>
|
||||||
|
</div>
|
||||||
<!-- 保存操作 -->
|
<div v-else-if="showXpackCompnent&&request.backEsbDataStruct != null">
|
||||||
<el-button type="primary" size="small" class="ms-btn-flot" @click="saveTestCase(item)"
|
<esb-definition-response :currentProtocol="request.protocol" :request="request" :is-api-component="false"
|
||||||
v-if="!request.referenced">
|
:show-options-button="false" :show-header="true" :result="request.requestResult"/>
|
||||||
{{ $t('commons.save') }}
|
</div>
|
||||||
</el-button>
|
<div v-else>
|
||||||
|
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult"/>
|
||||||
|
</div>
|
||||||
|
<!-- 保存操作 -->
|
||||||
|
<el-button type="primary" size="small" class="ms-btn-flot" @click="saveTestCase(item)" v-if="!request.referenced">
|
||||||
|
{{ $t('commons.save') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
</api-base-component>
|
</api-base-component>
|
||||||
<ms-run :debug="true" :reportId="reportId" :run-data="runData" :env-map="envMap"
|
<ms-run :debug="true" :reportId="reportId" :run-data="runData" :env-map="envMap"
|
||||||
@runRefresh="runRefresh" ref="runTest"/>
|
@runRefresh="runRefresh" ref="runTest"/>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,9 @@ export default {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.isActive = true;
|
this.isActive = true;
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
setJsonImport(data) {
|
||||||
|
this.importJson = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
@setTreeNodes="setTreeNodes"
|
@setTreeNodes="setTreeNodes"
|
||||||
@exportTestCase="exportTestCase"
|
@exportTestCase="exportTestCase"
|
||||||
@saveAsEdit="editTestCase"
|
@saveAsEdit="editTestCase"
|
||||||
|
@createCase="handleCaseSimpleCreate($event, 'add')"
|
||||||
@refreshAll="refreshAll"
|
@refreshAll="refreshAll"
|
||||||
:type="'edit'"
|
:type="'edit'"
|
||||||
ref="nodeTree"
|
ref="nodeTree"
|
||||||
|
@ -44,7 +45,7 @@
|
||||||
:tree-nodes="treeNodes"
|
:tree-nodes="treeNodes"
|
||||||
:project-id="projectId"
|
:project-id="projectId"
|
||||||
v-if="activeDom === 'right'"
|
v-if="activeDom === 'right'"
|
||||||
ref="testCaseList"/>
|
ref="minder"/>
|
||||||
</ms-tab-button>
|
</ms-tab-button>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
|
@ -58,6 +59,8 @@
|
||||||
:currentTestCaseInfo="item.testCaseInfo"
|
:currentTestCaseInfo="item.testCaseInfo"
|
||||||
@refresh="refreshTable"
|
@refresh="refreshTable"
|
||||||
@setModuleOptions="setModuleOptions"
|
@setModuleOptions="setModuleOptions"
|
||||||
|
@caseEdit="handleCaseCreateOrEdit($event,'edit')"
|
||||||
|
@caseCreate="handleCaseCreateOrEdit($event,'add')"
|
||||||
:read-only="testCaseReadOnly"
|
:read-only="testCaseReadOnly"
|
||||||
:tree-nodes="treeNodes"
|
:tree-nodes="treeNodes"
|
||||||
:select-node="selectNode"
|
:select-node="selectNode"
|
||||||
|
@ -155,6 +158,11 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
activeName(newVal, oldVal) {
|
||||||
|
if (oldVal !== 'default' && newVal === 'default' && this.$refs.minder) {
|
||||||
|
this.$refs.minder.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
checkRedirectID: function () {
|
checkRedirectID: function () {
|
||||||
|
@ -282,7 +290,9 @@ export default {
|
||||||
this.selectParentNodes = pNodes;
|
this.selectParentNodes = pNodes;
|
||||||
},
|
},
|
||||||
refreshTable() {
|
refreshTable() {
|
||||||
this.$refs.testCaseList.initTableData();
|
if ( this.$refs.testCaseList) {
|
||||||
|
this.$refs.testCaseList.initTableData();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
editTestCase(testCase) {
|
editTestCase(testCase) {
|
||||||
this.type="edit"
|
this.type="edit"
|
||||||
|
@ -293,11 +303,20 @@ export default {
|
||||||
}
|
}
|
||||||
this.addTab({name: 'edit', testCaseInfo: testCase});
|
this.addTab({name: 'edit', testCaseInfo: testCase});
|
||||||
},
|
},
|
||||||
|
handleCaseCreateOrEdit(data, type) {
|
||||||
|
if (this.$refs.minder) {
|
||||||
|
this.$refs.minder.addCase(data, type);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCaseSimpleCreate(data, type) {
|
||||||
|
this.handleCaseCreateOrEdit(data, type);
|
||||||
|
if (this.$refs.minder) {
|
||||||
|
this.$refs.minder.refresh();
|
||||||
|
}
|
||||||
|
},
|
||||||
copyTestCase(testCase) {
|
copyTestCase(testCase) {
|
||||||
this.type="copy"
|
this.type="copy"
|
||||||
this.testCaseReadOnly = false;
|
this.testCaseReadOnly = false;
|
||||||
let item = {};
|
|
||||||
testCase.isCopy = true;
|
testCase.isCopy = true;
|
||||||
this.addTab({name: 'edit', testCaseInfo: testCase});
|
this.addTab({name: 'edit', testCaseInfo: testCase});
|
||||||
},
|
},
|
||||||
|
|
|
@ -125,6 +125,7 @@ export default {
|
||||||
this.$emit('saveAsEdit', this.testCaseForm);
|
this.$emit('saveAsEdit', this.testCaseForm);
|
||||||
} else {
|
} else {
|
||||||
this.$emit('refresh');
|
this.$emit('refresh');
|
||||||
|
this.$emit('createCase', this.testCaseForm);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -109,7 +109,6 @@
|
||||||
class="ms-case" @change="clearInput" ref="cascade"></el-cascader>
|
class="ms-case" @change="clearInput" ref="cascade"></el-cascader>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item label="关联需求" :label-width="formLabelWidth" prop="demandId">
|
<el-form-item label="关联需求" :label-width="formLabelWidth" prop="demandId">
|
||||||
<el-select filterable :disabled="readOnly" v-model="form.demandId" @visible-change="visibleChange"
|
<el-select filterable :disabled="readOnly" v-model="form.demandId" @visible-change="visibleChange"
|
||||||
|
@ -404,7 +403,7 @@ export default {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
projectId() {
|
projectIds() {
|
||||||
return this.$store.state.projectId
|
return this.$store.state.projectId
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -456,6 +455,7 @@ export default {
|
||||||
},
|
},
|
||||||
getTestOptions(val) {
|
getTestOptions(val) {
|
||||||
this.form.type = val
|
this.form.type = val
|
||||||
|
this.projectId = this.projectIds
|
||||||
this.testOptions = [];
|
this.testOptions = [];
|
||||||
let url = '';
|
let url = '';
|
||||||
if (this.form.type === 'testcase' || this.form.type === 'automation') {
|
if (this.form.type === 'testcase' || this.form.type === 'automation') {
|
||||||
|
@ -556,6 +556,7 @@ export default {
|
||||||
/*
|
/*
|
||||||
this.form.selected=[["automation", "3edaaf31-3fa4-4a53-9654-320205c2953a"],["automation", "3aa58bd1-c986-448c-8060-d32713dbd4eb"]]
|
this.form.selected=[["automation", "3edaaf31-3fa4-4a53-9654-320205c2953a"],["automation", "3aa58bd1-c986-448c-8060-d32713dbd4eb"]]
|
||||||
*/
|
*/
|
||||||
|
this.projectId = this.projectIds;
|
||||||
if (window.history && window.history.pushState) {
|
if (window.history && window.history.pushState) {
|
||||||
history.pushState(null, null, document.URL);
|
history.pushState(null, null, document.URL);
|
||||||
window.addEventListener('popstate', this.close);
|
window.addEventListener('popstate', this.close);
|
||||||
|
@ -717,7 +718,7 @@ export default {
|
||||||
let param = this.buildParam();
|
let param = this.buildParam();
|
||||||
if (this.validate(param)) {
|
if (this.validate(param)) {
|
||||||
let option = this.getOption(param);
|
let option = this.getOption(param);
|
||||||
this.result = this.$request(option, () => {
|
this.result = this.$request(option, (response) => {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
if (this.operationType == 'add' && this.isCreateContinue) {
|
if (this.operationType == 'add' && this.isCreateContinue) {
|
||||||
this.form.name = '';
|
this.form.name = '';
|
||||||
|
@ -736,6 +737,13 @@ export default {
|
||||||
}
|
}
|
||||||
this.dialogFormVisible = false;
|
this.dialogFormVisible = false;
|
||||||
this.$emit("refresh");
|
this.$emit("refresh");
|
||||||
|
if (this.type === 'add' || this.type === 'copy') {
|
||||||
|
param.id = response.data;
|
||||||
|
this.$emit("caseCreate", param);
|
||||||
|
this.close();
|
||||||
|
} else {
|
||||||
|
this.$emit("caseEdit", param);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<test-case-create
|
<test-case-create
|
||||||
:tree-nodes="treeNodes"
|
:tree-nodes="treeNodes"
|
||||||
@saveAsEdit="saveAsEdit"
|
@saveAsEdit="saveAsEdit"
|
||||||
|
@createCase="createCase"
|
||||||
@refresh="refresh"
|
@refresh="refresh"
|
||||||
ref="testCaseCreate"
|
ref="testCaseCreate"
|
||||||
></test-case-create>
|
></test-case-create>
|
||||||
|
@ -98,6 +99,9 @@ export default {
|
||||||
saveAsEdit(data) {
|
saveAsEdit(data) {
|
||||||
this.$emit('saveAsEdit', data);
|
this.$emit('saveAsEdit', data);
|
||||||
},
|
},
|
||||||
|
createCase(data) {
|
||||||
|
this.$emit('createCase', data);
|
||||||
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.$emit("refreshTable");
|
this.$emit("refreshTable");
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,12 +6,17 @@
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
:distinct-tags="tags"
|
:distinct-tags="tags"
|
||||||
@save="save"
|
@save="save"
|
||||||
|
ref="minder"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsModuleMinder from "@/business/components/common/components/MsModuleMinder";
|
import MsModuleMinder from "@/business/components/common/components/MsModuleMinder";
|
||||||
import {getTestCaseDataMap} from "@/business/components/track/common/minder/minderUtils";
|
import {
|
||||||
|
appendChild,
|
||||||
|
getTestCaseDataMap,
|
||||||
|
parseCase, updateNode
|
||||||
|
} from "@/business/components/track/common/minder/minderUtils";
|
||||||
export default {
|
export default {
|
||||||
name: "TestCaseMinder",
|
name: "TestCaseMinder",
|
||||||
components: {MsModuleMinder},
|
components: {MsModuleMinder},
|
||||||
|
@ -48,6 +53,7 @@ name: "TestCaseMinder",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
save(data) {
|
save(data) {
|
||||||
|
console.log(data);
|
||||||
let saveCases = [];
|
let saveCases = [];
|
||||||
let deleteCases = [];
|
let deleteCases = [];
|
||||||
this.buildSaveCase(data.root, saveCases, deleteCases, undefined);
|
this.buildSaveCase(data.root, saveCases, deleteCases, undefined);
|
||||||
|
@ -130,7 +136,22 @@ name: "TestCaseMinder",
|
||||||
throw new Error(tip);
|
throw new Error(tip);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addCase(data, type) {
|
||||||
|
let nodeData = parseCase(data, new Map());
|
||||||
|
let minder = window.minder;
|
||||||
|
let jsonImport = minder.exportJson();
|
||||||
|
if (type === 'edit') {
|
||||||
|
updateNode(jsonImport.root, nodeData);
|
||||||
|
} else {
|
||||||
|
appendChild(data.nodeId, jsonImport.root, nodeData);
|
||||||
|
}
|
||||||
|
this.$refs.minder.setJsonImport(jsonImport);
|
||||||
|
},
|
||||||
|
refresh() {
|
||||||
|
if (this.$refs.minder) {
|
||||||
|
this.$refs.minder.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -47,13 +47,13 @@ name: "TestPlanMinder",
|
||||||
if (this.projectId) {
|
if (this.projectId) {
|
||||||
this.result = this.$get('/test/plan/case/list/minder/' + this.planId, response => {
|
this.result = this.$get('/test/plan/case/list/minder/' + this.planId, response => {
|
||||||
this.dataMap = getTestCaseDataMap(response.data, true, (data, item) => {
|
this.dataMap = getTestCaseDataMap(response.data, true, (data, item) => {
|
||||||
if (item.stats === 'Pass') {
|
if (item.status === 'Pass') {
|
||||||
data.resource.push(this.$t('test_track.plan_view.pass'));
|
data.resource.push(this.$t('test_track.plan_view.pass'));
|
||||||
} else if (item.reviewStatus === 'Failure') {
|
} else if (item.status === 'Failure') {
|
||||||
data.resource.push(this.$t('test_track.plan_view.failure'));
|
data.resource.push(this.$t('test_track.plan_view.failure'));
|
||||||
} else if (item.reviewStatus === 'Blocking') {
|
} else if (item.status === 'Blocking') {
|
||||||
data.resource.push(this.$t('test_track.plan_view.blocking'));
|
data.resource.push(this.$t('test_track.plan_view.blocking'));
|
||||||
} else if (item.reviewStatus === 'Skip') {
|
} else if (item.status === 'Skip') {
|
||||||
data.resource.push(this.$t('test_track.plan_view.skip'));
|
data.resource.push(this.$t('test_track.plan_view.skip'));
|
||||||
} else {
|
} else {
|
||||||
data.resource.push(this.$t('test_track.plan.plan_status_prepare'));
|
data.resource.push(this.$t('test_track.plan.plan_status_prepare'));
|
||||||
|
|
|
@ -1,44 +1,55 @@
|
||||||
|
import {getUUID} from "@/common/js/utils";
|
||||||
|
|
||||||
export function getTestCaseDataMap(testCase, isDisable, setParamCallback) {
|
export function getTestCaseDataMap(testCase, isDisable, setParamCallback) {
|
||||||
let dataMap = new Map();
|
let dataMap = new Map();
|
||||||
if (testCase) {
|
if (testCase) {
|
||||||
testCase.forEach(item => {
|
testCase.forEach(item => {
|
||||||
item.steps = JSON.parse(item.steps);
|
parseCase(item, dataMap, isDisable, setParamCallback);
|
||||||
// if (item.tags && item.tags.length > 0) {
|
|
||||||
// item.tags = JSON.parse(item.tags);
|
|
||||||
// }
|
|
||||||
let mapItem = dataMap.get(item.nodeId);
|
|
||||||
let nodeItem = {
|
|
||||||
data: {
|
|
||||||
id: item.id,
|
|
||||||
text: item.name,
|
|
||||||
priority: Number.parseInt(item.priority.substring(item.priority.length - 1 )) + 1,
|
|
||||||
resource: ["用例"],
|
|
||||||
type: item.type,
|
|
||||||
method: item.method,
|
|
||||||
maintainer: item.maintainer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (setParamCallback) {
|
|
||||||
setParamCallback(nodeItem.data, item);
|
|
||||||
}
|
|
||||||
if (isDisable) {
|
|
||||||
nodeItem.data.disable = true;
|
|
||||||
// 用例节点可以打标签
|
|
||||||
nodeItem.data.allowDisabledTag = true;
|
|
||||||
}
|
|
||||||
parseChildren(nodeItem, item, isDisable);
|
|
||||||
if (mapItem) {
|
|
||||||
mapItem.push(nodeItem);
|
|
||||||
} else {
|
|
||||||
mapItem = [];
|
|
||||||
mapItem.push(nodeItem);
|
|
||||||
dataMap.set(item.nodeId, mapItem);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return dataMap;
|
return dataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function parseCase(item, dataMap, isDisable, setParamCallback) {
|
||||||
|
if (item.steps) {
|
||||||
|
item.steps = JSON.parse(item.steps);
|
||||||
|
} else {
|
||||||
|
item.steps = [];
|
||||||
|
}
|
||||||
|
// if (item.tags && item.tags.length > 0) {
|
||||||
|
// item.tags = JSON.parse(item.tags);
|
||||||
|
// }
|
||||||
|
let mapItem = dataMap.get(item.nodeId);
|
||||||
|
let nodeItem = {
|
||||||
|
data: {
|
||||||
|
id: item.id,
|
||||||
|
text: item.name,
|
||||||
|
priority: Number.parseInt(item.priority.substring(item.priority.length - 1 )) + 1,
|
||||||
|
resource: ["用例"],
|
||||||
|
type: item.type,
|
||||||
|
method: item.method,
|
||||||
|
maintainer: item.maintainer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (setParamCallback) {
|
||||||
|
setParamCallback(nodeItem.data, item);
|
||||||
|
}
|
||||||
|
if (isDisable) {
|
||||||
|
nodeItem.data.disable = true;
|
||||||
|
// 用例节点可以打标签
|
||||||
|
nodeItem.data.allowDisabledTag = true;
|
||||||
|
}
|
||||||
|
parseChildren(nodeItem, item, isDisable);
|
||||||
|
if (mapItem) {
|
||||||
|
mapItem.push(nodeItem);
|
||||||
|
} else {
|
||||||
|
mapItem = [];
|
||||||
|
mapItem.push(nodeItem);
|
||||||
|
dataMap.set(item.nodeId, mapItem);
|
||||||
|
}
|
||||||
|
return nodeItem;
|
||||||
|
}
|
||||||
|
|
||||||
function parseChildren(nodeItem, item, isDisable) {
|
function parseChildren(nodeItem, item, isDisable) {
|
||||||
nodeItem.children = [];
|
nodeItem.children = [];
|
||||||
let children = [];
|
let children = [];
|
||||||
|
@ -63,7 +74,8 @@ function _parseChildren(children, k, v, isDisable) {
|
||||||
data: {
|
data: {
|
||||||
text: k,
|
text: k,
|
||||||
resource: v ? [v] : []
|
resource: v ? [v] : []
|
||||||
}
|
},
|
||||||
|
children: []
|
||||||
}
|
}
|
||||||
if (isDisable) {
|
if (isDisable) {
|
||||||
node.data.disable = true;
|
node.data.disable = true;
|
||||||
|
@ -72,3 +84,40 @@ function _parseChildren(children, k, v, isDisable) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function appendChild(appendPid, root, node) {
|
||||||
|
if (root.data.id === appendPid) {
|
||||||
|
root.children.push(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!root.children) {
|
||||||
|
root.children = [];
|
||||||
|
}
|
||||||
|
let children = root.children;
|
||||||
|
for (const index in children) {
|
||||||
|
let item = children[index];
|
||||||
|
if (item.data.id === appendPid) {
|
||||||
|
item.data.expandState = "expand";
|
||||||
|
item.children.push(node);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
appendChild(appendPid, item, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateNode(root, node) {
|
||||||
|
if (!root.children) {
|
||||||
|
root.children = [];
|
||||||
|
}
|
||||||
|
let children = root.children;
|
||||||
|
for (const index in children) {
|
||||||
|
let item = children[index];
|
||||||
|
if (item.data.id === node.data.id) {
|
||||||
|
children[index] = node;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
updateNode(item, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
:key="index">
|
:key="index">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-progress :percentage="scope.row.passRate.substring(0, scope.row.passRate.length-1)"></el-progress>
|
<el-progress :percentage="calPassRate(scope)"></el-progress>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
@ -293,6 +293,10 @@ export default {
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
calPassRate(scope) {
|
||||||
|
let passRate = scope.row.passRate.substring(0, scope.row.passRate.length-1);
|
||||||
|
return Number.parseInt(passRate, 10);
|
||||||
|
},
|
||||||
customHeader() {
|
customHeader() {
|
||||||
this.$refs.headerCustom.open(this.tableLabel)
|
this.$refs.headerCustom.open(this.tableLabel)
|
||||||
},
|
},
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -4,7 +4,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<artifactId>metersphere-server</artifactId>
|
<artifactId>metersphere-server</artifactId>
|
||||||
<version>1.7</version>
|
<version>1.8</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
|
|
Loading…
Reference in New Issue