Merge branch 'main' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
b55cdc4405
|
@ -428,9 +428,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String url = this.getUrl();
|
String url = this.getUrl();
|
||||||
if (StringUtils.isNotEmpty(this.getPort()) && this.getPort().startsWith("${")) {
|
|
||||||
url = url.replace(this.getPort(), "10990");
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(url)) {
|
if (StringUtils.isEmpty(url)) {
|
||||||
MSException.throwException("请重新选择环境");
|
MSException.throwException("请重新选择环境");
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
private String jsonDataStruct;
|
private String jsonDataStruct;
|
||||||
private String rawDataStruct;
|
private String rawDataStruct;
|
||||||
private boolean customizeReq;
|
private boolean customizeReq;
|
||||||
|
private Boolean isRefEnvironment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, MsParameter msParameter) {
|
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, MsParameter msParameter) {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import io.metersphere.api.dto.definition.request.ElementUtil;
|
||||||
import io.metersphere.api.dto.definition.request.MsScenario;
|
import io.metersphere.api.dto.definition.request.MsScenario;
|
||||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||||
|
import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler;
|
||||||
|
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
||||||
import io.metersphere.api.dto.plan.TestPlanApiScenarioInfoDTO;
|
import io.metersphere.api.dto.plan.TestPlanApiScenarioInfoDTO;
|
||||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.api.dto.scenario.environment.item.MsScenarioEnv;
|
import io.metersphere.api.dto.scenario.environment.item.MsScenarioEnv;
|
||||||
|
@ -69,24 +71,32 @@ public class ApiScenarioEnvService {
|
||||||
// 过滤掉禁用的步骤
|
// 过滤掉禁用的步骤
|
||||||
hashTree = hashTree.stream().filter(item -> item.isEnable()).collect(Collectors.toList());
|
hashTree = hashTree.stream().filter(item -> item.isEnable()).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
List<Boolean> hasFullUrlList = new ArrayList<>();
|
||||||
for (MsTestElement testElement : hashTree) {
|
for (MsTestElement testElement : hashTree) {
|
||||||
this.formatElement(testElement, env);
|
this.formatElement(testElement, env, hasFullUrlList);
|
||||||
if (CollectionUtils.isNotEmpty(testElement.getHashTree())) {
|
if (CollectionUtils.isNotEmpty(testElement.getHashTree()) && !hasFullUrlList.contains(false)) {
|
||||||
getHashTree(testElement.getHashTree(), env);
|
getHashTree(testElement.getHashTree(), env, hasFullUrlList);
|
||||||
|
}
|
||||||
|
if (hasFullUrlList.contains(false)) {
|
||||||
|
env.setFullUrl(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void getHashTree(List<MsTestElement> tree, ScenarioEnv env) {
|
private void getHashTree(List<MsTestElement> tree, ScenarioEnv env, List<Boolean> hasFullUrlList) {
|
||||||
try {
|
try {
|
||||||
// 过滤掉禁用的步骤
|
// 过滤掉禁用的步骤
|
||||||
tree = tree.stream().filter(item -> item.isEnable()).collect(Collectors.toList());
|
tree = tree.stream().filter(item -> item.isEnable()).collect(Collectors.toList());
|
||||||
for (MsTestElement element : tree) {
|
for (MsTestElement element : tree) {
|
||||||
this.formatElement(element, env);
|
this.formatElement(element, env, hasFullUrlList);
|
||||||
if (CollectionUtils.isNotEmpty(element.getHashTree())) {
|
if (CollectionUtils.isNotEmpty(element.getHashTree()) && !hasFullUrlList.contains(false)) {
|
||||||
getHashTree(element.getHashTree(), env);
|
getHashTree(element.getHashTree(), env, hasFullUrlList);
|
||||||
|
}
|
||||||
|
if (hasFullUrlList.contains(false)) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -94,7 +104,7 @@ public class ApiScenarioEnvService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void formatElement(MsTestElement testElement, ScenarioEnv env) {
|
private void formatElement(MsTestElement testElement, ScenarioEnv env, List<Boolean> hasFullUrlList) {
|
||||||
if (StringUtils.equals(MsTestElementConstants.REF.name(), testElement.getReferenced())) {
|
if (StringUtils.equals(MsTestElementConstants.REF.name(), testElement.getReferenced())) {
|
||||||
if (StringUtils.equals(testElement.getType(), ElementConstants.HTTP_SAMPLER)) {
|
if (StringUtils.equals(testElement.getType(), ElementConstants.HTTP_SAMPLER)) {
|
||||||
MsHTTPSamplerProxy http = (MsHTTPSamplerProxy) testElement;
|
MsHTTPSamplerProxy http = (MsHTTPSamplerProxy) testElement;
|
||||||
|
@ -105,7 +115,7 @@ public class ApiScenarioEnvService {
|
||||||
if (!StringUtils.equalsIgnoreCase(http.getReferenced(), ElementConstants.STEP_CREATED)
|
if (!StringUtils.equalsIgnoreCase(http.getReferenced(), ElementConstants.STEP_CREATED)
|
||||||
|| (http.getIsRefEnvironment() != null && http.getIsRefEnvironment())) {
|
|| (http.getIsRefEnvironment() != null && http.getIsRefEnvironment())) {
|
||||||
env.getProjectIds().add(http.getProjectId());
|
env.getProjectIds().add(http.getProjectId());
|
||||||
env.setFullUrl(false);
|
hasFullUrlList.add(false);
|
||||||
}
|
}
|
||||||
} else if (StringUtils.equals(testElement.getType(), ElementConstants.JDBC_SAMPLER)
|
} else if (StringUtils.equals(testElement.getType(), ElementConstants.JDBC_SAMPLER)
|
||||||
|| StringUtils.equals(testElement.getType(), ElementConstants.TCP_SAMPLER)) {
|
|| StringUtils.equals(testElement.getType(), ElementConstants.TCP_SAMPLER)) {
|
||||||
|
@ -114,18 +124,18 @@ public class ApiScenarioEnvService {
|
||||||
ApiTestCase testCase = apiTestCaseMapper.selectByPrimaryKey(testElement.getId());
|
ApiTestCase testCase = apiTestCaseMapper.selectByPrimaryKey(testElement.getId());
|
||||||
if (testCase != null) {
|
if (testCase != null) {
|
||||||
env.getProjectIds().add(testCase.getProjectId());
|
env.getProjectIds().add(testCase.getProjectId());
|
||||||
env.setFullUrl(false);
|
hasFullUrlList.add(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ApiDefinition apiDefinition = apiDefinitionService.get(testElement.getId());
|
ApiDefinition apiDefinition = apiDefinitionService.get(testElement.getId());
|
||||||
if (apiDefinition != null) {
|
if (apiDefinition != null) {
|
||||||
env.getProjectIds().add(apiDefinition.getProjectId());
|
env.getProjectIds().add(apiDefinition.getProjectId());
|
||||||
env.setFullUrl(false);
|
hasFullUrlList.add(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
env.getProjectIds().add(testElement.getProjectId());
|
env.getProjectIds().add(testElement.getProjectId());
|
||||||
env.setFullUrl(false);
|
hasFullUrlList.add(false);
|
||||||
}
|
}
|
||||||
} else if (StringUtils.equals(testElement.getType(), ElementConstants.SCENARIO) && StringUtils.isEmpty(testElement.getProjectId())) {
|
} else if (StringUtils.equals(testElement.getType(), ElementConstants.SCENARIO) && StringUtils.isEmpty(testElement.getProjectId())) {
|
||||||
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(testElement.getId());
|
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(testElement.getId());
|
||||||
|
@ -141,18 +151,14 @@ public class ApiScenarioEnvService {
|
||||||
if (StringUtils.equals(testElement.getType(), ElementConstants.HTTP_SAMPLER)) {
|
if (StringUtils.equals(testElement.getType(), ElementConstants.HTTP_SAMPLER)) {
|
||||||
// 校验是否是全路径
|
// 校验是否是全路径
|
||||||
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) testElement;
|
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) testElement;
|
||||||
if (httpSamplerProxy.isCustomizeReq()) {
|
checkCustomEnv(env, httpSamplerProxy.isCustomizeReq(), httpSamplerProxy.getProjectId(), httpSamplerProxy.getIsRefEnvironment(), httpSamplerProxy.getReferenced(), hasFullUrlList);
|
||||||
env.getProjectIds().add(httpSamplerProxy.getProjectId());
|
|
||||||
env.setFullUrl(httpSamplerProxy.getIsRefEnvironment() == null ? true : !httpSamplerProxy.getIsRefEnvironment());
|
|
||||||
} else if (!StringUtils.equalsIgnoreCase(httpSamplerProxy.getReferenced(), ElementConstants.STEP_CREATED) || (httpSamplerProxy.getIsRefEnvironment() != null && httpSamplerProxy.getIsRefEnvironment())) {
|
|
||||||
env.getProjectIds().add(httpSamplerProxy.getProjectId());
|
|
||||||
env.setFullUrl(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (StringUtils.equals(testElement.getType(), ElementConstants.JDBC_SAMPLER)
|
} else if (StringUtils.equals(testElement.getType(), ElementConstants.TCP_SAMPLER)) {
|
||||||
|| StringUtils.equals(testElement.getType(), ElementConstants.TCP_SAMPLER)) {
|
MsTCPSampler tcpSampler = (MsTCPSampler) testElement;
|
||||||
env.getProjectIds().add(testElement.getProjectId());
|
checkCustomEnv(env, tcpSampler.isCustomizeReq(), tcpSampler.getProjectId(), tcpSampler.getIsRefEnvironment(), tcpSampler.getReferenced(), hasFullUrlList);
|
||||||
env.setFullUrl(false);
|
} else if (StringUtils.equals(testElement.getType(), ElementConstants.JDBC_SAMPLER)) {
|
||||||
|
MsJDBCSampler jdbcSampler = (MsJDBCSampler) testElement;
|
||||||
|
checkCustomEnv(env, jdbcSampler.isCustomizeReq(), jdbcSampler.getProjectId(), jdbcSampler.getIsRefEnvironment(), jdbcSampler.getReferenced(), hasFullUrlList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.equals(testElement.getType(), ElementConstants.SCENARIO)
|
if (StringUtils.equals(testElement.getType(), ElementConstants.SCENARIO)
|
||||||
|
@ -161,6 +167,17 @@ public class ApiScenarioEnvService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkCustomEnv(ScenarioEnv env, boolean customizeReq, String projectId, Boolean isRefEnvironment, String referenced, List<Boolean> hasFullUrlList) {
|
||||||
|
if (customizeReq) {
|
||||||
|
env.getProjectIds().add(projectId);
|
||||||
|
hasFullUrlList.add(isRefEnvironment == null ? true : !isRefEnvironment);
|
||||||
|
} else if (!StringUtils.equalsIgnoreCase(referenced, ElementConstants.STEP_CREATED)
|
||||||
|
|| (isRefEnvironment != null && isRefEnvironment)) {
|
||||||
|
env.getProjectIds().add(projectId);
|
||||||
|
hasFullUrlList.add(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置场景的运行环境 环境组/环境JSON
|
* 设置场景的运行环境 环境组/环境JSON
|
||||||
*
|
*
|
||||||
|
|
|
@ -166,7 +166,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
||||||
transactionResult.getResponseResult().setConsole(console);
|
transactionResult.getResponseResult().setConsole(console);
|
||||||
//对响应内容进行进一步解析和处理。
|
//对响应内容进行进一步解析和处理。
|
||||||
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(transactionResult);
|
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(transactionResult);
|
||||||
if (StringUtils.equals(dto.getRunMode(), ApiRunMode.DEFINITION.name())) {
|
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
|
||||||
apiDefinitionEnvService.setEnvAndPoolName(transactionResult, expandDTO);
|
apiDefinitionEnvService.setEnvAndPoolName(transactionResult, expandDTO);
|
||||||
}
|
}
|
||||||
dto.setContent("result_" + JSON.toJSONString(expandDTO));
|
dto.setContent("result_" + JSON.toJSONString(expandDTO));
|
||||||
|
@ -176,7 +176,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
||||||
requestResult.getResponseResult().setConsole(console);
|
requestResult.getResponseResult().setConsole(console);
|
||||||
//对响应内容进行进一步解析和处理。
|
//对响应内容进行进一步解析和处理。
|
||||||
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(requestResult);
|
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(requestResult);
|
||||||
if (StringUtils.equals(dto.getRunMode(), ApiRunMode.DEFINITION.name())) {
|
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
|
||||||
apiDefinitionEnvService.setEnvAndPoolName(requestResult, expandDTO);
|
apiDefinitionEnvService.setEnvAndPoolName(requestResult, expandDTO);
|
||||||
}
|
}
|
||||||
dto.setContent("result_" + JSON.toJSONString(expandDTO));
|
dto.setContent("result_" + JSON.toJSONString(expandDTO));
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class MsKafkaListener {
|
||||||
LoggerUtil.info("接收到执行结果:", record.key());
|
LoggerUtil.info("接收到执行结果:", record.key());
|
||||||
if (ObjectUtils.isNotEmpty(record.value()) && WebSocketUtil.has(record.key().toString())) {
|
if (ObjectUtils.isNotEmpty(record.value()) && WebSocketUtil.has(record.key().toString())) {
|
||||||
MsgDTO dto = JSONUtil.parseObject(record.value(), MsgDTO.class);
|
MsgDTO dto = JSONUtil.parseObject(record.value(), MsgDTO.class);
|
||||||
if (StringUtils.equals(ApiRunMode.DEFINITION.name(), dto.getRunMode()) && dto.getContent().startsWith("result_")) {
|
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name()) && dto.getContent().startsWith("result_")) {
|
||||||
ApiDefinitionEnvService apiDefinitionEnvService = CommonBeanFactory.getBean(ApiDefinitionEnvService.class);
|
ApiDefinitionEnvService apiDefinitionEnvService = CommonBeanFactory.getBean(ApiDefinitionEnvService.class);
|
||||||
apiDefinitionEnvService.setEnvAndPoolName(dto);
|
apiDefinitionEnvService.setEnvAndPoolName(dto);
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,7 @@
|
||||||
</include>
|
</include>
|
||||||
</if>
|
</if>
|
||||||
<if test="${condition}.exec_result != null">
|
<if test="${condition}.exec_result != null">
|
||||||
and (t1.status
|
and (t3.status
|
||||||
<choose>
|
<choose>
|
||||||
<when test='${condition}.exec_result.operator == "in"'>
|
<when test='${condition}.exec_result.operator == "in"'>
|
||||||
in
|
in
|
||||||
|
@ -238,7 +238,7 @@
|
||||||
#{v}
|
#{v}
|
||||||
</foreach>
|
</foreach>
|
||||||
<if test="${condition}.exec_result.value.contains('') or ${condition}.exec_result.value.contains('PENDING')">
|
<if test="${condition}.exec_result.value.contains('') or ${condition}.exec_result.value.contains('PENDING')">
|
||||||
or t1.status is null or t1.status = ''
|
or t3.status is null or t3.status = ''
|
||||||
</if>
|
</if>
|
||||||
<if test="${condition}.exec_result != null">
|
<if test="${condition}.exec_result != null">
|
||||||
)
|
)
|
||||||
|
@ -250,10 +250,10 @@
|
||||||
#{v}
|
#{v}
|
||||||
</foreach>
|
</foreach>
|
||||||
<if test="${condition}.exec_result != null and (${condition}.exec_result.value.contains('') or ${condition}.exec_result.value.contains('PENDING'))">
|
<if test="${condition}.exec_result != null and (${condition}.exec_result.value.contains('') or ${condition}.exec_result.value.contains('PENDING'))">
|
||||||
and t1.status is not null and t1.status != ''
|
and t3.status is not null and t3.status != ''
|
||||||
</if>
|
</if>
|
||||||
<if test="${condition}.exec_result != null and !${condition}.exec_result.value.contains('PENDING')">
|
<if test="${condition}.exec_result != null and !${condition}.exec_result.value.contains('PENDING')">
|
||||||
or t1.status is null or t1.status = ''
|
or t3.status is null or t3.status = ''
|
||||||
</if>
|
</if>
|
||||||
<if test="${condition}.exec_result != null">
|
<if test="${condition}.exec_result != null">
|
||||||
)
|
)
|
||||||
|
@ -406,7 +406,7 @@
|
||||||
a.path,
|
a.path,
|
||||||
a.protocol,
|
a.protocol,
|
||||||
t1.tags,
|
t1.tags,
|
||||||
t1.status AS execResult,
|
t3.status AS execResult,
|
||||||
t1.last_result_id AS lastResultId,
|
t1.last_result_id AS lastResultId,
|
||||||
project.NAME AS project_name,
|
project.NAME AS project_name,
|
||||||
t1.delete_time,
|
t1.delete_time,
|
||||||
|
|
|
@ -253,6 +253,7 @@ public class TestResultService {
|
||||||
ApiTestCaseWithBLOBs apiTestCase = new ApiTestCaseWithBLOBs();
|
ApiTestCaseWithBLOBs apiTestCase = new ApiTestCaseWithBLOBs();
|
||||||
apiTestCase.setLastResultId(dto.getReportId());
|
apiTestCase.setLastResultId(dto.getReportId());
|
||||||
apiTestCase.setId(dto.getTestId());
|
apiTestCase.setId(dto.getTestId());
|
||||||
|
apiTestCase.setStatus(record.getStatus());
|
||||||
apiTestCaseService.updateByPrimaryKeySelective(apiTestCase);
|
apiTestCaseService.updateByPrimaryKeySelective(apiTestCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,10 +372,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_getCurrentUserId() {
|
_getCurrentUserId() {
|
||||||
const {id, userGroups} = getCurrentUser();
|
const { id, userGroups } = getCurrentUser();
|
||||||
if (userGroups) {
|
if (userGroups) {
|
||||||
// 是否是当前项目下的成员
|
// 是否是当前项目下的成员
|
||||||
let index = userGroups.findIndex(ug => ug.sourceId === getCurrentProjectID());
|
let index = userGroups.findIndex((ug) => ug.sourceId === getCurrentProjectID());
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -786,6 +786,7 @@ export default {
|
||||||
let automationData = this.$router.resolve({
|
let automationData = this.$router.resolve({
|
||||||
name: 'ApiAutomationWithQuery',
|
name: 'ApiAutomationWithQuery',
|
||||||
params: {
|
params: {
|
||||||
|
versionId: 'default',
|
||||||
redirectID: getUUID(),
|
redirectID: getUUID(),
|
||||||
dataType: 'scenario',
|
dataType: 'scenario',
|
||||||
dataSelectRange: 'edit:' + resource.id,
|
dataSelectRange: 'edit:' + resource.id,
|
||||||
|
|
|
@ -72,6 +72,18 @@
|
||||||
<el-input v-model="request.port" size="small" />
|
<el-input v-model="request.port" size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
|
<el-form-item>
|
||||||
|
<el-checkbox
|
||||||
|
v-if="isCustomizeReq"
|
||||||
|
class="is-ref-environment"
|
||||||
|
v-model="request.isRefEnvironment"
|
||||||
|
@change="setDomain"
|
||||||
|
:disabled="request.disabled">
|
||||||
|
{{ $t('api_test.request.refer_to_environment') }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -355,6 +355,7 @@ export default {
|
||||||
let automationData = this.$router.resolve({
|
let automationData = this.$router.resolve({
|
||||||
name: 'ApiAutomationWithQuery',
|
name: 'ApiAutomationWithQuery',
|
||||||
params: {
|
params: {
|
||||||
|
versionId: 'default',
|
||||||
redirectID: getUUID(),
|
redirectID: getUUID(),
|
||||||
dataType: 'scenario',
|
dataType: 'scenario',
|
||||||
dataSelectRange: 'edit:' + resource.id,
|
dataSelectRange: 'edit:' + resource.id,
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
v-model="controller.countController.interval"
|
v-model="controller.countController.interval"
|
||||||
:disabled="controller.disabled"
|
:disabled="controller.disabled"
|
||||||
:placeholder="$t('commons.millisecond')"
|
:placeholder="$t('commons.millisecond')"
|
||||||
:max="1000 * 10000000"
|
:max="1000 * 1000000"
|
||||||
:min="0"
|
:min="0"
|
||||||
:step="1000"
|
:step="1000"
|
||||||
size="small" />
|
size="small" />
|
||||||
|
@ -129,7 +129,7 @@
|
||||||
:disabled="controller.disabled"
|
:disabled="controller.disabled"
|
||||||
size="small"
|
size="small"
|
||||||
:placeholder="$t('commons.millisecond')"
|
:placeholder="$t('commons.millisecond')"
|
||||||
:max="1000 * 10000000"
|
:max="1000 * 1000000"
|
||||||
:min="0"
|
:min="0"
|
||||||
:step="1000" />
|
:step="1000" />
|
||||||
<span class="ms-span ms-radio">ms</span>
|
<span class="ms-span ms-radio">ms</span>
|
||||||
|
@ -165,12 +165,11 @@
|
||||||
:disabled="controller.disabled"
|
:disabled="controller.disabled"
|
||||||
size="small"
|
size="small"
|
||||||
:placeholder="$t('commons.millisecond')"
|
:placeholder="$t('commons.millisecond')"
|
||||||
:max="1000 * 10000000"
|
:max="1000 * 1000000"
|
||||||
:min="3000"
|
:min="3000"
|
||||||
:step="1000" />
|
:step="1000" />
|
||||||
<span class="ms-span ms-radio">ms</span>
|
<span class="ms-span ms-radio">ms</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-slot:debugStepCode>
|
<template v-slot:debugStepCode>
|
||||||
<span v-if="node.data.testing" class="ms-test-running">
|
<span v-if="node.data.testing" class="ms-test-running">
|
||||||
<i class="el-icon-loading" style="font-size: 16px" />
|
<i class="el-icon-loading" style="font-size: 16px" />
|
||||||
|
|
|
@ -162,6 +162,7 @@ export default {
|
||||||
let automationData = this.$router.resolve({
|
let automationData = this.$router.resolve({
|
||||||
name: 'ApiAutomationWithQuery',
|
name: 'ApiAutomationWithQuery',
|
||||||
params: {
|
params: {
|
||||||
|
versionId: 'default',
|
||||||
redirectID: getUUID(),
|
redirectID: getUUID(),
|
||||||
dataType: 'scenario',
|
dataType: 'scenario',
|
||||||
dataSelectRange: 'edit:' + response.data.id,
|
dataSelectRange: 'edit:' + response.data.id,
|
||||||
|
|
|
@ -73,6 +73,7 @@ export default {
|
||||||
home = this.$router.resolve({
|
home = this.$router.resolve({
|
||||||
name: 'ApiDefinitionWithQuery',
|
name: 'ApiDefinitionWithQuery',
|
||||||
params: {
|
params: {
|
||||||
|
versionId: 'default',
|
||||||
redirectID: uuid,
|
redirectID: uuid,
|
||||||
dataType: dataType,
|
dataType: dataType,
|
||||||
dataSelectRange: selectRange,
|
dataSelectRange: selectRange,
|
||||||
|
@ -84,6 +85,7 @@ export default {
|
||||||
home = this.$router.resolve({
|
home = this.$router.resolve({
|
||||||
name: 'ApiAutomationWithQuery',
|
name: 'ApiAutomationWithQuery',
|
||||||
params: {
|
params: {
|
||||||
|
versionId: 'default',
|
||||||
redirectID: uuid,
|
redirectID: uuid,
|
||||||
dataType: dataType,
|
dataType: dataType,
|
||||||
dataSelectRange: selectRange,
|
dataSelectRange: selectRange,
|
||||||
|
|
|
@ -246,6 +246,7 @@ export default {
|
||||||
let automationData = this.$router.resolve({
|
let automationData = this.$router.resolve({
|
||||||
name: 'ApiAutomationWithQuery',
|
name: 'ApiAutomationWithQuery',
|
||||||
params: {
|
params: {
|
||||||
|
versionId: 'default',
|
||||||
redirectID: getUUID(),
|
redirectID: getUUID(),
|
||||||
dataType: 'scenario',
|
dataType: 'scenario',
|
||||||
dataSelectRange: 'edit:' + resource.id,
|
dataSelectRange: 'edit:' + resource.id,
|
||||||
|
|
|
@ -179,7 +179,11 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
isSqlType() {
|
isSqlType() {
|
||||||
return (
|
return (
|
||||||
this.currentProtocol === 'SQL' && this.response.responseResult.responseCode === '200' && this.mode === 'table'
|
this.currentProtocol === 'SQL'
|
||||||
|
&& this.response
|
||||||
|
&& this.response.responseResult
|
||||||
|
&& this.response.responseResult.responseCode === '200'
|
||||||
|
&& this.mode === 'table'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
responseResult() {
|
responseResult() {
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
:style="isFixed ? 'opacity:100%; position: relative;z-index: 666;': 'opacity: 95%;position: fixed'"
|
:style="isFixed ? 'opacity:100%; position: relative;z-index: 666;': 'opacity: 95%;position: fixed'"
|
||||||
@mouseenter.native="collapseOpen"
|
@mouseenter.native="collapseOpen"
|
||||||
@mouseleave.native="collapseClose">
|
@mouseleave.native="collapseClose">
|
||||||
<ms-aside-header :sideTheme="sideTheme" :isCollapse="isCollapse"/>
|
<ms-aside-header :sideTheme="sideTheme" :isCollapse="isCollapse" :title="sysTitle"/>
|
||||||
<ms-aside-menus :sideTheme="sideTheme" :color="color" :isCollapse="isCollapse"/>
|
<ms-aside-menus :sideTheme="sideTheme" :color="color" :isCollapse="isCollapse"/>
|
||||||
<div class="ms-header-fixed" v-show="!isCollapse">
|
<div class="ms-header-fixed" v-show="!isCollapse">
|
||||||
<svg-icon iconClass="pushpin" class-name="ms-menu-pin" v-if="isFixed" @click.native="fixedChange(false)"/>
|
<svg-icon iconClass="pushpin" class-name="ms-menu-pin" v-if="isFixed" @click.native="fixedChange(false)"/>
|
||||||
|
@ -72,6 +72,7 @@ export default {
|
||||||
headerHeight: "0px",
|
headerHeight: "0px",
|
||||||
isFixed: false,
|
isFixed: false,
|
||||||
sideTheme: "",
|
sideTheme: "",
|
||||||
|
sysTitle: undefined
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -127,6 +128,11 @@ export default {
|
||||||
if (response.data && response.data[7] && response.data[7].paramValue) {
|
if (response.data && response.data[7] && response.data[7].paramValue) {
|
||||||
this.sideTheme = response.data[7].paramValue;
|
this.sideTheme = response.data[7].paramValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.data && response.data[6] && response.data[6].paramValue) {
|
||||||
|
this.sysTitle = response.data[6].paramValue;
|
||||||
|
}
|
||||||
|
|
||||||
let title = response.data[4].paramValue;
|
let title = response.data[4].paramValue;
|
||||||
if (title) {
|
if (title) {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
|
|
|
@ -178,6 +178,9 @@ export default {
|
||||||
if (title) {
|
if (title) {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}
|
}
|
||||||
|
if (response.data[0].paramValue) {
|
||||||
|
this.shortcutIcon();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -196,6 +199,7 @@ export default {
|
||||||
this.rules = this.getDefaultRules();
|
this.rules = this.getDefaultRules();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
document.addEventListener("keydown", this.watchEnter);
|
document.addEventListener("keydown", this.watchEnter);
|
||||||
|
@ -296,6 +300,13 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
shortcutIcon() {
|
||||||
|
let link = document.querySelector("link[rel*='icon']") || document.createElement('link');
|
||||||
|
link.type = 'image/x-icon';
|
||||||
|
link.rel = 'shortcut icon';
|
||||||
|
link.href = '/display/file/logo';
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(link);
|
||||||
|
},
|
||||||
redirectAuth(authId) {
|
redirectAuth(authId) {
|
||||||
if (authId === 'LDAP' || authId === 'LOCAL') {
|
if (authId === 'LDAP' || authId === 'LOCAL') {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -25,16 +25,15 @@ export default {
|
||||||
menuKey: 0,
|
menuKey: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
title() {
|
|
||||||
return localStorage.getItem("sysTitle") || "MeterSphere";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
sideTheme: String,
|
sideTheme: String,
|
||||||
isCollapse: {
|
isCollapse: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "MeterSphere"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<ms-table-column
|
<ms-table-column
|
||||||
prop="tags"
|
prop="tags"
|
||||||
|
sortable
|
||||||
:field="field"
|
:field="field"
|
||||||
:fields-width="fieldsWidth"
|
:fields-width="fieldsWidth"
|
||||||
sortable
|
:show-overflow-tooltip="false"
|
||||||
:label="$t('api_test.automation.tag')"
|
:label="$t('api_test.automation.tag')"
|
||||||
min-width="200px">
|
min-width="200px">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-tag v-for="(name, index) in scope.row.tags" :key="index" type="success" effect="plain"
|
<span v-if="scope.row.tags && scope.row.tags.length === 1">
|
||||||
:content="name" style="margin-left: 0px; margin-right: 2px"/>
|
<ms-tag
|
||||||
<span/>
|
v-for="(name, index) in scope.row.tags"
|
||||||
|
:key="index"
|
||||||
|
type="success"
|
||||||
|
effect="plain"
|
||||||
|
:content="name"
|
||||||
|
style="margin-left: 0; margin-right: 2px"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<el-tooltip class="item" effect="dark" placement="top" :enterable="false" v-else>
|
||||||
|
<div v-html="scope.row.tags ? scope.row.tags.join(','): ''" slot="content"></div>
|
||||||
|
<div class="oneLine">
|
||||||
|
<ms-tag
|
||||||
|
v-for="(name, index) in scope.row.tags"
|
||||||
|
:key="index"
|
||||||
|
type="success"
|
||||||
|
effect="plain"
|
||||||
|
:content="name"
|
||||||
|
style="margin-left: 0; margin-right: 2px"
|
||||||
|
/>
|
||||||
|
<span/>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</ms-table-column>
|
</ms-table-column>
|
||||||
</template>
|
</template>
|
||||||
|
@ -28,5 +50,9 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.oneLine {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -554,8 +554,8 @@ const message = {
|
||||||
title: '显示设置',
|
title: '显示设置',
|
||||||
logo: '系统 LOGO',
|
logo: '系统 LOGO',
|
||||||
loginLogo: '登录页左上角 LOGO',
|
loginLogo: '登录页左上角 LOGO',
|
||||||
loginImage: '登陆页面右侧图片',
|
loginImage: '登录页面右侧图片',
|
||||||
loginTitle: '登陆页面提示信息',
|
loginTitle: '登录页面提示信息',
|
||||||
pageTitle: '页面 Title',
|
pageTitle: '页面 Title',
|
||||||
sysTitle: '系统名称',
|
sysTitle: '系统名称',
|
||||||
theme_style: '菜单风格设置',
|
theme_style: '菜单风格设置',
|
||||||
|
|
|
@ -553,8 +553,8 @@ const message = {
|
||||||
title: '顯示設置',
|
title: '顯示設置',
|
||||||
logo: '系統 LOGO',
|
logo: '系統 LOGO',
|
||||||
loginLogo: '登錄頁左上角 LOGO',
|
loginLogo: '登錄頁左上角 LOGO',
|
||||||
loginImage: '登陸頁面右側圖片',
|
loginImage: '登錄頁面右側圖片',
|
||||||
loginTitle: '登陸頁面提示信息',
|
loginTitle: '登錄頁面提示信息',
|
||||||
pageTitle: '頁面 Title',
|
pageTitle: '頁面 Title',
|
||||||
sysTitle: '系統名稱',
|
sysTitle: '系統名稱',
|
||||||
theme_style: '菜單風格設置',
|
theme_style: '菜單風格設置',
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<update id="batchUpdateByResourceIds">
|
<update id="batchUpdateByResourceIds">
|
||||||
update ${tableName}
|
update ${tableName}
|
||||||
<include refid="updateValueColumn"/>
|
<include refid="updateValueColumn"/>
|
||||||
where resource_id in
|
where field_id = #{record.fieldId} and resource_id in
|
||||||
<foreach collection="resourceIds" item="resourceId" separator="," open="(" close=")">
|
<foreach collection="resourceIds" item="resourceId" separator="," open="(" close=")">
|
||||||
#{resourceId}
|
#{resourceId}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
|
|
@ -155,6 +155,8 @@ public interface ExtTestCaseMapper {
|
||||||
|
|
||||||
List<TestCase> getMaintainerMap(@Param("request") QueryTestCaseRequest request);
|
List<TestCase> getMaintainerMap(@Param("request") QueryTestCaseRequest request);
|
||||||
|
|
||||||
|
List<TestCase> getMaintainerMapForPlanRepeat(@Param("request") QueryTestCaseRequest request);
|
||||||
|
|
||||||
List<TestCaseDTO> getForNodeEdit(@Param("ids") List<String> ids);
|
List<TestCaseDTO> getForNodeEdit(@Param("ids") List<String> ids);
|
||||||
|
|
||||||
List<CustomFieldResourceCompatibleDTO> getForCompatibleCustomField(String projectId, int offset, int pageSize);
|
List<CustomFieldResourceCompatibleDTO> getForCompatibleCustomField(String projectId, int offset, int pageSize);
|
||||||
|
|
|
@ -1216,6 +1216,14 @@
|
||||||
and T2.case_id is null
|
and T2.case_id is null
|
||||||
order by test_case.`order` desc, test_case.sort desc
|
order by test_case.`order` desc, test_case.sort desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getMaintainerMapForPlanRepeat" resultType="io.metersphere.base.domain.TestCase">
|
||||||
|
select test_case.id as id, test_case.maintainer as maintainer
|
||||||
|
from test_case as test_case
|
||||||
|
<include refid="notInQueryWhereCondition"/>
|
||||||
|
order by test_case.`order` desc, test_case.sort desc
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="getForNodeEdit" resultType="io.metersphere.dto.TestCaseDTO">
|
<select id="getForNodeEdit" resultType="io.metersphere.dto.TestCaseDTO">
|
||||||
select test_case.id, test_case.node_id, test_case.node_path
|
select test_case.id, test_case.node_id, test_case.node_path
|
||||||
from test_case where node_id in
|
from test_case where node_id in
|
||||||
|
|
|
@ -48,6 +48,8 @@ public class IssueExcelData implements Serializable {
|
||||||
@ExcelIgnore
|
@ExcelIgnore
|
||||||
private Boolean addFlag;
|
private Boolean addFlag;
|
||||||
@ExcelIgnore
|
@ExcelIgnore
|
||||||
|
private Boolean updateFlag = true;
|
||||||
|
@ExcelIgnore
|
||||||
private String title;
|
private String title;
|
||||||
@ExcelIgnore
|
@ExcelIgnore
|
||||||
private String description;
|
private String description;
|
||||||
|
|
|
@ -121,6 +121,12 @@ public class IssueExcelListener extends AnalysisEventListener<Map<Integer, Strin
|
||||||
issueExcelData.setId(issues.getId());
|
issueExcelData.setId(issues.getId());
|
||||||
issueExcelData.setAddFlag(Boolean.FALSE);
|
issueExcelData.setAddFlag(Boolean.FALSE);
|
||||||
updateList.add(issueExcelData);
|
updateList.add(issueExcelData);
|
||||||
|
} else {
|
||||||
|
// 不覆盖模式
|
||||||
|
issueExcelData.setId(issues.getId());
|
||||||
|
issueExcelData.setAddFlag(Boolean.FALSE);
|
||||||
|
issueExcelData.setUpdateFlag(Boolean.FALSE);
|
||||||
|
updateList.add(issueExcelData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +154,7 @@ public class IssueExcelListener extends AnalysisEventListener<Map<Integer, Strin
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(updateList)) {
|
if (CollectionUtils.isNotEmpty(updateList)) {
|
||||||
List<IssuesUpdateRequest> issues = updateList.stream().map(this::convertToIssue).collect(Collectors.toList());
|
List<IssuesUpdateRequest> issues = updateList.stream().filter(IssueExcelData::getUpdateFlag).map(this::convertToIssue).collect(Collectors.toList());
|
||||||
issuesService.updateImportData(issues);
|
issuesService.updateImportData(issues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,7 @@ public class TestPlanMessageService {
|
||||||
result.put("apiCaseUnExecuteCount", v);
|
result.put("apiCaseUnExecuteCount", v);
|
||||||
break;
|
break;
|
||||||
case "errorreportresult":
|
case "errorreportresult":
|
||||||
|
case "fakeerror":
|
||||||
result.put("apiCaseErrorReportCount", v);
|
result.put("apiCaseErrorReportCount", v);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -318,12 +319,14 @@ public class TestPlanMessageService {
|
||||||
result.put("apiScenarioSuccessCount", v);
|
result.put("apiScenarioSuccessCount", v);
|
||||||
break;
|
break;
|
||||||
case "fail":
|
case "fail":
|
||||||
|
case "error":
|
||||||
result.put("apiScenarioFailedCount", v);
|
result.put("apiScenarioFailedCount", v);
|
||||||
break;
|
break;
|
||||||
case "unexecute":
|
case "unexecute":
|
||||||
result.put("apiScenarioUnExecuteCount", v);
|
result.put("apiScenarioUnExecuteCount", v);
|
||||||
break;
|
break;
|
||||||
case "errorreportresult":
|
case "errorreportresult":
|
||||||
|
case "fakeerror":
|
||||||
result.put("apiScenarioErrorReportCount", v);
|
result.put("apiScenarioErrorReportCount", v);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -53,6 +53,7 @@ import io.metersphere.service.ApiPoolDebugService;
|
||||||
import io.metersphere.xpack.track.dto.IssuesDao;
|
import io.metersphere.xpack.track.dto.IssuesDao;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
import org.apache.ibatis.session.ExecutorType;
|
||||||
|
@ -548,10 +549,14 @@ public class TestPlanService {
|
||||||
public void testPlanRelevance(PlanCaseRelevanceRequest request) {
|
public void testPlanRelevance(PlanCaseRelevanceRequest request) {
|
||||||
LinkedHashMap<String, String> userMap;
|
LinkedHashMap<String, String> userMap;
|
||||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
|
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
|
||||||
|
|
||||||
boolean isSelectAll = request.getRequest() != null && request.getRequest().isSelectAll();
|
boolean isSelectAll = request.getRequest() != null && request.getRequest().isSelectAll();
|
||||||
if (isSelectAll) {
|
if (isSelectAll) {
|
||||||
List<TestCase> maintainerMap = extTestCaseMapper.getMaintainerMap(request.getRequest());
|
List<TestCase> maintainerMap;
|
||||||
|
if (BooleanUtils.isTrue(testPlan.getRepeatCase())) {
|
||||||
|
maintainerMap = extTestCaseMapper.getMaintainerMapForPlanRepeat(request.getRequest());
|
||||||
|
} else {
|
||||||
|
maintainerMap = extTestCaseMapper.getMaintainerMap(request.getRequest());
|
||||||
|
}
|
||||||
userMap = maintainerMap.stream()
|
userMap = maintainerMap.stream()
|
||||||
.collect(LinkedHashMap::new, (m, v) -> m.put(v.getId(), v.getMaintainer()), LinkedHashMap::putAll);
|
.collect(LinkedHashMap::new, (m, v) -> m.put(v.getId(), v.getMaintainer()), LinkedHashMap::putAll);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -384,11 +384,15 @@ public class TestCaseService {
|
||||||
checkTestCustomNum(testCase);
|
checkTestCustomNum(testCase);
|
||||||
testCase.setUpdateTime(System.currentTimeMillis());
|
testCase.setUpdateTime(System.currentTimeMillis());
|
||||||
|
|
||||||
// 同步缺陷与需求的关联关系
|
try {
|
||||||
updateThirdPartyIssuesLink(testCase);
|
// 同步缺陷与需求的关联关系
|
||||||
|
updateThirdPartyIssuesLink(testCase);
|
||||||
|
|
||||||
// 同步用例与需求的关联关系
|
// 同步用例与需求的关联关系
|
||||||
addDemandHyperLink(testCase, "edit");
|
addDemandHyperLink(testCase, "edit");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(testCase.getDemandId())) {
|
if (StringUtils.isEmpty(testCase.getDemandId())) {
|
||||||
testCase.setDemandId(StringUtils.EMPTY);
|
testCase.setDemandId(StringUtils.EMPTY);
|
||||||
|
@ -425,6 +429,9 @@ public class TestCaseService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Project project = baseProjectService.getProjectById(testCase.getProjectId());
|
Project project = baseProjectService.getProjectById(testCase.getProjectId());
|
||||||
|
if (!StringUtils.equals(project.getPlatform(), IssuesManagePlatform.AzureDevops.name())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
IssuesRequest issuesRequest = new IssuesRequest();
|
IssuesRequest issuesRequest = new IssuesRequest();
|
||||||
if (!issuesService.isThirdPartTemplate(project)) {
|
if (!issuesService.isThirdPartTemplate(project)) {
|
||||||
issuesRequest.setDefaultCustomFields(issuesService.getDefaultCustomFields(testCase.getProjectId()));
|
issuesRequest.setDefaultCustomFields(issuesService.getDefaultCustomFields(testCase.getProjectId()));
|
||||||
|
@ -446,6 +453,7 @@ public class TestCaseService {
|
||||||
if (StringUtils.isBlank(testCase.getVersionId())) {
|
if (StringUtils.isBlank(testCase.getVersionId())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
testCase.setLatest(false);
|
||||||
TestCaseExample example = new TestCaseExample();
|
TestCaseExample example = new TestCaseExample();
|
||||||
example.createCriteria().andIdEqualTo(testCase.getId())
|
example.createCriteria().andIdEqualTo(testCase.getId())
|
||||||
.andVersionIdEqualTo(testCase.getVersionId());
|
.andVersionIdEqualTo(testCase.getVersionId());
|
||||||
|
|
|
@ -111,7 +111,6 @@ public class TestReviewTestCaseService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int deleteTestCase(DeleteRelevanceRequest request) {
|
public int deleteTestCase(DeleteRelevanceRequest request) {
|
||||||
checkReviewer(request.getReviewId());
|
|
||||||
return testCaseReviewTestCaseMapper.deleteByPrimaryKey(request.getId());
|
return testCaseReviewTestCaseMapper.deleteByPrimaryKey(request.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,21 +129,7 @@ public class TestReviewTestCaseService {
|
||||||
return testCaseReviewTestCaseMapper.updateByExampleSelective(record, example);
|
return testCaseReviewTestCaseMapper.updateByExampleSelective(record, example);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkReviewer(String reviewId) {
|
|
||||||
List<String> userIds = testCaseReviewService.getTestCaseReviewerIds(reviewId);
|
|
||||||
String currentId = SessionUtils.getUser().getId();
|
|
||||||
TestCaseReview caseReview = testCaseReviewMapper.selectByPrimaryKey(reviewId);
|
|
||||||
String creator = StringUtils.EMPTY;
|
|
||||||
if (caseReview != null) {
|
|
||||||
creator = caseReview.getCreator();
|
|
||||||
}
|
|
||||||
if (!userIds.contains(currentId) && !StringUtils.equals(creator, currentId)) {
|
|
||||||
MSException.throwException("没有权限,不能解除用例关联!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteTestCaseBatch(TestReviewCaseBatchRequest request) {
|
public void deleteTestCaseBatch(TestReviewCaseBatchRequest request) {
|
||||||
checkReviewer(request.getReviewId());
|
|
||||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||||
(query) -> extTestReviewCaseMapper.selectIds((QueryCaseReviewRequest) query));
|
(query) -> extTestReviewCaseMapper.selectIds((QueryCaseReviewRequest) query));
|
||||||
|
|
||||||
|
|
|
@ -593,7 +593,9 @@ export default {
|
||||||
// 这里先打开报告,建立 websock
|
// 这里先打开报告,建立 websock
|
||||||
// 否则可能执行完了才建立 websock,拿不到结果
|
// 否则可能执行完了才建立 websock,拿不到结果
|
||||||
this.$refs.apiCaseResult.open(reportId);
|
this.$refs.apiCaseResult.open(reportId);
|
||||||
run(row.id, reportId);
|
setTimeout(() => {
|
||||||
|
run(row.id, reportId);
|
||||||
|
}, 3000);
|
||||||
},
|
},
|
||||||
handleTestEnd(reportId) {
|
handleTestEnd(reportId) {
|
||||||
if (this.runningReport.has(reportId)) {
|
if (this.runningReport.has(reportId)) {
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
:modal-append-to-body="false"
|
:modal-append-to-body="false"
|
||||||
size="100%"
|
size="100%"
|
||||||
ref="drawer"
|
ref="drawer"
|
||||||
v-loading="loading">
|
v-loading="loading"
|
||||||
|
>
|
||||||
<template>
|
<template>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="17">
|
<el-col :span="17">
|
||||||
|
@ -16,11 +16,13 @@
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<el-header>
|
<el-header>
|
||||||
<el-row type="flex" class="head-bar">
|
<el-row type="flex" class="head-bar">
|
||||||
|
|
||||||
<el-col :span="4">
|
<el-col :span="4">
|
||||||
<el-button plain size="mini"
|
<el-button
|
||||||
icon="el-icon-back"
|
plain
|
||||||
@click="cancel">{{ $t('test_track.return') }}
|
size="mini"
|
||||||
|
icon="el-icon-back"
|
||||||
|
@click="cancel"
|
||||||
|
>{{ $t("test_track.return") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
@ -35,9 +37,9 @@
|
||||||
:pre-page-data="prePageData"
|
:pre-page-data="prePageData"
|
||||||
@pre="handlePre"
|
@pre="handlePre"
|
||||||
@next="handleNext"
|
@next="handleNext"
|
||||||
:list="testCases"/>
|
:list="testCases"
|
||||||
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row class="head-bar">
|
<el-row class="head-bar">
|
||||||
|
@ -47,82 +49,144 @@
|
||||||
class="test-case-name"
|
class="test-case-name"
|
||||||
type="text"
|
type="text"
|
||||||
:disabled="!hasProjectPermission"
|
:disabled="!hasProjectPermission"
|
||||||
@click="openTestTestCase(testCase)">
|
@click="openTestTestCase(testCase)"
|
||||||
<span
|
>
|
||||||
class="title-link"
|
<span
|
||||||
:title="testCase.name"
|
class="title-link"
|
||||||
:style="{'max-width': titleWith + 'px'}">
|
:title="testCase.name"
|
||||||
{{ testCase.customNum }}-{{ testCase.name }}
|
:style="{ 'max-width': titleWith + 'px' }"
|
||||||
</span>
|
>
|
||||||
|
{{ testCase.customNum }}-{{ testCase.name }}
|
||||||
|
</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-divider>
|
</el-divider>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-header>
|
</el-header>
|
||||||
<div class="case_container">
|
<div class="case_container">
|
||||||
|
|
||||||
<el-form :model="testCase">
|
<el-form :model="testCase">
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item :label="$t('test_track.case.module')" prop="nodePath"
|
<el-form-item
|
||||||
:label-width="formLabelWidth">
|
:label="$t('test_track.case.module')"
|
||||||
|
prop="nodePath"
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
{{ testCase.nodePath }}
|
{{ testCase.nodePath }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item :label="$t('test_track.plan.plan_project')" prop="projectName"
|
<el-form-item
|
||||||
:label-width="formLabelWidth">
|
:label="$t('test_track.plan.plan_project')"
|
||||||
|
prop="projectName"
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
{{ testCase.projectName }}
|
{{ testCase.projectName }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<el-form-item :label="$t('test_track.plan.load_case.execution_status')"
|
<el-form-item
|
||||||
:label-width="formLabelWidth">
|
:label="
|
||||||
<status-table-item :value="originalStatus"/>
|
$t('test_track.plan.load_case.execution_status')
|
||||||
|
"
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
|
<status-table-item :value="originalStatus" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-form ref="customFieldForm"
|
<el-form
|
||||||
v-if="isCustomFiledActive"
|
ref="customFieldForm"
|
||||||
class="case-form">
|
v-if="isCustomFiledActive"
|
||||||
|
class="case-form"
|
||||||
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="7" v-for="(item, index) in testCaseTemplate.customFields" :key="index">
|
<el-col
|
||||||
<el-form-item :label-width="formLabelWidth"
|
:span="7"
|
||||||
:label="item.system ? $t(systemNameMap[item.name]) : item.name"
|
v-for="(item, index) in testCaseTemplate.customFields"
|
||||||
:prop="item.name">
|
:key="index"
|
||||||
<custom-filed-component :disabled="true" :data="item" :form="{}" prop="defaultValue"/>
|
>
|
||||||
|
<el-form-item
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
:label="
|
||||||
|
item.system
|
||||||
|
? $t(systemNameMap[item.name])
|
||||||
|
: item.name
|
||||||
|
"
|
||||||
|
:prop="item.name"
|
||||||
|
>
|
||||||
|
<custom-filed-component
|
||||||
|
:disabled="true"
|
||||||
|
:data="item"
|
||||||
|
:form="{}"
|
||||||
|
prop="defaultValue"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<form-rich-text-item :label-width="formLabelWidth" :disabled="true"
|
<form-rich-text-item
|
||||||
:title="$t('test_track.case.prerequisite')" :data="testCase"
|
:label-width="formLabelWidth"
|
||||||
prop="prerequisite"/>
|
:disabled="true"
|
||||||
<step-change-item :disable="true" :label-width="formLabelWidth" :form="testCase"/>
|
:title="$t('test_track.case.prerequisite')"
|
||||||
<test-plan-case-step-results-item :label-width="formLabelWidth" :is-read-only="isReadOnly"
|
:data="testCase"
|
||||||
v-if="testCase.stepModel === 'STEP'" :test-case="testCase"/>
|
prop="prerequisite"
|
||||||
<form-rich-text-item :label-width="formLabelWidth" v-if="testCase.stepModel === 'TEXT'"
|
/>
|
||||||
:disabled="true" :title="$t('test_track.case.step_desc')" :data="testCase"
|
<step-change-item
|
||||||
prop="stepDescription"/>
|
:disable="true"
|
||||||
<form-rich-text-item :label-width="formLabelWidth" v-if="testCase.stepModel === 'TEXT'"
|
:label-width="formLabelWidth"
|
||||||
:disabled="true" :title="$t('test_track.case.expected_results')"
|
:form="testCase"
|
||||||
:data="testCase" prop="expectedResult"/>
|
/>
|
||||||
<form-rich-text-item :label-width="formLabelWidth" v-if="testCase.stepModel === 'TEXT'"
|
<test-plan-case-step-results-item
|
||||||
:title="$t('test_track.plan_view.actual_result')"
|
:label-width="formLabelWidth"
|
||||||
:data="testCase" prop="actualResult"/>
|
:is-read-only="isReadOnly"
|
||||||
|
v-if="testCase.stepModel === 'STEP'"
|
||||||
|
:test-case="testCase"
|
||||||
|
/>
|
||||||
|
<form-rich-text-item
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
v-if="testCase.stepModel === 'TEXT'"
|
||||||
|
:disabled="true"
|
||||||
|
:title="$t('test_track.case.step_desc')"
|
||||||
|
:data="testCase"
|
||||||
|
prop="stepDescription"
|
||||||
|
/>
|
||||||
|
<form-rich-text-item
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
v-if="testCase.stepModel === 'TEXT'"
|
||||||
|
:disabled="true"
|
||||||
|
:title="$t('test_track.case.expected_results')"
|
||||||
|
:data="testCase"
|
||||||
|
prop="expectedResult"
|
||||||
|
/>
|
||||||
|
<form-rich-text-item
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
v-if="testCase.stepModel === 'TEXT'"
|
||||||
|
:title="$t('test_track.plan_view.actual_result')"
|
||||||
|
:data="testCase"
|
||||||
|
prop="actualResult"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
<el-form-item :label="$t('test_track.case.other_info')" :label-width="formLabelWidth">
|
:label="$t('test_track.case.other_info')"
|
||||||
<test-case-edit-other-info :plan-id="testCase.planId" v-if="otherInfoActive" @openTest="openTest"
|
:label-width="formLabelWidth"
|
||||||
:is-test-plan-edit="true"
|
>
|
||||||
@syncRelationGraphOpen="syncRelationGraphOpen"
|
<test-case-edit-other-info
|
||||||
:read-only="true" :is-test-plan="true" :project-id="testCase.projectId"
|
:plan-id="testCase.planId"
|
||||||
:form="testCase" :case-id="testCase.caseId" ref="otherInfo"/>
|
v-if="otherInfoActive"
|
||||||
|
@openTest="openTest"
|
||||||
|
:is-test-plan-edit="true"
|
||||||
|
@syncRelationGraphOpen="syncRelationGraphOpen"
|
||||||
|
:read-only="true"
|
||||||
|
:is-test-plan="true"
|
||||||
|
:project-id="testCase.projectId"
|
||||||
|
:form="testCase"
|
||||||
|
:case-id="testCase.caseId"
|
||||||
|
ref="otherInfo"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
@ -135,11 +199,13 @@
|
||||||
:test-case="testCase"
|
:test-case="testCase"
|
||||||
:is-read-only="isReadOnly"
|
:is-read-only="isReadOnly"
|
||||||
:origin-status="originalStatus"
|
:origin-status="originalStatus"
|
||||||
@saveCase="saveCase"/>
|
@saveCase="saveCase"
|
||||||
|
/>
|
||||||
<review-comment
|
<review-comment
|
||||||
default-type="PLAN"
|
default-type="PLAN"
|
||||||
:case-id="testCase.caseId"
|
:case-id="testCase.caseId"
|
||||||
ref="comment"/>
|
ref="comment"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
@ -148,30 +214,40 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TestPlanTestCaseStatusButton from '../../../common/TestPlanTestCaseStatusButton';
|
import TestPlanTestCaseStatusButton from "../../../common/TestPlanTestCaseStatusButton";
|
||||||
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||||
import {getUUID, listenGoBack, removeGoBackListener} from "metersphere-frontend/src/utils"
|
import {
|
||||||
import {hasPermission} from "metersphere-frontend/src/utils/permission";
|
getUUID,
|
||||||
|
listenGoBack,
|
||||||
|
removeGoBackListener,
|
||||||
|
} from "metersphere-frontend/src/utils";
|
||||||
|
import { hasPermission } from "metersphere-frontend/src/utils/permission";
|
||||||
import TestCaseAttachment from "@/business/case/components/TestCaseAttachment";
|
import TestCaseAttachment from "@/business/case/components/TestCaseAttachment";
|
||||||
import CaseComment from "@/business/case/components/CaseComment";
|
import CaseComment from "@/business/case/components/CaseComment";
|
||||||
import MsPreviousNextButton from "metersphere-frontend/src/components/MsPreviousNextButton";
|
import MsPreviousNextButton from "metersphere-frontend/src/components/MsPreviousNextButton";
|
||||||
import ReviewComment from "@/business/review/commom/ReviewComment";
|
import ReviewComment from "@/business/review/commom/ReviewComment";
|
||||||
import {buildTestCaseOldFields, parseCustomField} from "metersphere-frontend/src/utils/custom_field";
|
import {
|
||||||
|
buildTestCaseOldFields,
|
||||||
|
parseCustomField,
|
||||||
|
} from "metersphere-frontend/src/utils/custom_field";
|
||||||
import FormRichTextItem from "metersphere-frontend/src/components/FormRichTextItem";
|
import FormRichTextItem from "metersphere-frontend/src/components/FormRichTextItem";
|
||||||
import MsFormDivider from "metersphere-frontend/src/components/MsFormDivider";
|
import MsFormDivider from "metersphere-frontend/src/components/MsFormDivider";
|
||||||
import TestCaseEditOtherInfo from "@/business/case/components/TestCaseEditOtherInfo";
|
import TestCaseEditOtherInfo from "@/business/case/components/TestCaseEditOtherInfo";
|
||||||
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
||||||
import {SYSTEM_FIELD_NAME_MAP} from "metersphere-frontend/src/utils/table-constants";
|
import { SYSTEM_FIELD_NAME_MAP } from "metersphere-frontend/src/utils/table-constants";
|
||||||
import IssueDescriptionTableItem from "@/business/issue/IssueDescriptionTableItem";
|
import IssueDescriptionTableItem from "@/business/issue/IssueDescriptionTableItem";
|
||||||
import StepChangeItem from "@/business/case/components/StepChangeItem";
|
import StepChangeItem from "@/business/case/components/StepChangeItem";
|
||||||
import TestCaseStepItem from "@/business/case/components/TestCaseStepItem";
|
import TestCaseStepItem from "@/business/case/components/TestCaseStepItem";
|
||||||
import TestPlanCaseStepResultsItem from "@/business/plan/view/comonents/functional/TestPlanCaseStepResultsItem";
|
import TestPlanCaseStepResultsItem from "@/business/plan/view/comonents/functional/TestPlanCaseStepResultsItem";
|
||||||
import TestPlanFunctionalExecute from "@/business/plan/view/comonents/functional/TestPlanFunctionalExecute";
|
import TestPlanFunctionalExecute from "@/business/plan/view/comonents/functional/TestPlanFunctionalExecute";
|
||||||
import StatusTableItem from "@/business/common/tableItems/planview/StatusTableItem";
|
import StatusTableItem from "@/business/common/tableItems/planview/StatusTableItem";
|
||||||
import {testPlanTestCaseEdit, testPlanTestCaseGet} from "@/api/remote/plan/test-plan-test-case";
|
import {
|
||||||
import {testPlanEditStatus} from "@/api/remote/plan/test-plan";
|
testPlanTestCaseEdit,
|
||||||
import {getTestTemplate} from "@/api/custom-field-template";
|
testPlanTestCaseGet,
|
||||||
import {checkProjectPermission} from "@/api/testCase";
|
} from "@/api/remote/plan/test-plan-test-case";
|
||||||
|
import { testPlanEditStatus } from "@/api/remote/plan/test-plan";
|
||||||
|
import { getTestTemplate } from "@/api/custom-field-template";
|
||||||
|
import { checkProjectPermission } from "@/api/testCase";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "FunctionalTestCaseEdit",
|
name: "FunctionalTestCaseEdit",
|
||||||
|
@ -190,7 +266,7 @@ export default {
|
||||||
MsPreviousNextButton,
|
MsPreviousNextButton,
|
||||||
CaseComment,
|
CaseComment,
|
||||||
TestPlanTestCaseStatusButton,
|
TestPlanTestCaseStatusButton,
|
||||||
TestCaseAttachment
|
TestCaseAttachment,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -201,34 +277,34 @@ export default {
|
||||||
index: 0,
|
index: 0,
|
||||||
editor: ClassicEditor,
|
editor: ClassicEditor,
|
||||||
test: {},
|
test: {},
|
||||||
activeTab: 'detail',
|
activeTab: "detail",
|
||||||
users: [],
|
users: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
comments: [],
|
comments: [],
|
||||||
testCaseTemplate: {},
|
testCaseTemplate: {},
|
||||||
formLabelWidth: '100px',
|
formLabelWidth: "100px",
|
||||||
isCustomFiledActive: false,
|
isCustomFiledActive: false,
|
||||||
otherInfoActive: true,
|
otherInfoActive: true,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
testCases: [],
|
testCases: [],
|
||||||
originalStatus: '',
|
originalStatus: "",
|
||||||
titleWith: 0
|
titleWith: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
total: {
|
total: {
|
||||||
type: Number
|
type: Number,
|
||||||
},
|
},
|
||||||
searchParam: {
|
searchParam: {
|
||||||
type: Object
|
type: Object,
|
||||||
},
|
},
|
||||||
pageNum: Number,
|
pageNum: Number,
|
||||||
pageSize: {
|
pageSize: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1,
|
||||||
},
|
},
|
||||||
nextPageData: Object,
|
nextPageData: Object,
|
||||||
prePageData: Object
|
prePageData: Object,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
systemNameMap() {
|
systemNameMap() {
|
||||||
|
@ -243,18 +319,18 @@ export default {
|
||||||
removeGoBackListener(this.handleClose);
|
removeGoBackListener(this.handleClose);
|
||||||
this.showDialog = false;
|
this.showDialog = false;
|
||||||
this.searchParam.status = null;
|
this.searchParam.status = null;
|
||||||
this.$emit('update:search-param', this.searchParam);
|
this.$emit("update:search-param", this.searchParam);
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
this.handleClose();
|
this.handleClose();
|
||||||
this.$emit('refreshTable');
|
this.$emit("refreshTable");
|
||||||
},
|
},
|
||||||
getOption(param) {
|
getOption(param) {
|
||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
let url = '/test/case/edit/testPlan';
|
let url = "/test/case/edit/testPlan";
|
||||||
|
|
||||||
if (this.$refs.otherInfo && this.$refs.otherInfo.uploadList) {
|
if (this.$refs.otherInfo && this.$refs.otherInfo.uploadList) {
|
||||||
this.$refs.otherInfo.uploadList.forEach(f => {
|
this.$refs.otherInfo.uploadList.forEach((f) => {
|
||||||
formData.append("file", f);
|
formData.append("file", f);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -271,17 +347,20 @@ export default {
|
||||||
return key === "file" ? undefined : value;
|
return key === "file" ? undefined : value;
|
||||||
});
|
});
|
||||||
|
|
||||||
formData.append('request', new Blob([requestJson], {
|
formData.append(
|
||||||
type: "application/json "
|
"request",
|
||||||
}));
|
new Blob([requestJson], {
|
||||||
|
type: "application/json ",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
url: url,
|
url: url,
|
||||||
data: formData,
|
data: formData,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': undefined
|
"Content-Type": undefined,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
saveCase() {
|
saveCase() {
|
||||||
|
@ -302,12 +381,18 @@ export default {
|
||||||
result.actualResult = this.testCase.steptResults[i].actualResult;
|
result.actualResult = this.testCase.steptResults[i].actualResult;
|
||||||
result.executeResult = this.testCase.steptResults[i].executeResult;
|
result.executeResult = this.testCase.steptResults[i].executeResult;
|
||||||
if (result.actualResult && result.actualResult.length > 500) {
|
if (result.actualResult && result.actualResult.length > 500) {
|
||||||
this.$warning(this.$t('test_track.plan_view.actual_result')
|
this.$warning(
|
||||||
+ this.$t('test_track.length_less_than') + '500');
|
this.$t("test_track.plan_view.actual_result") +
|
||||||
|
this.$t("test_track.length_less_than") +
|
||||||
|
"500"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result.executeResult === 'Failure' && this.testCase.status === 'Pass') {
|
if (
|
||||||
this.$warning(this.$t('test_track.plan_view.execute_tip'));
|
result.executeResult === "Failure" &&
|
||||||
|
this.testCase.status === "Pass"
|
||||||
|
) {
|
||||||
|
this.$warning(this.$t("test_track.plan_view.execute_tip"));
|
||||||
this.testCase.status = this.originalStatus;
|
this.testCase.status = this.originalStatus;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -315,20 +400,19 @@ export default {
|
||||||
}
|
}
|
||||||
param.results = JSON.stringify(param.results);
|
param.results = JSON.stringify(param.results);
|
||||||
param.actualResult = this.testCase.actualResult;
|
param.actualResult = this.testCase.actualResult;
|
||||||
testPlanTestCaseEdit(param)
|
testPlanTestCaseEdit(param).then(() => {
|
||||||
.then(() => {
|
this.$request(option);
|
||||||
this.$request(option);
|
|
||||||
|
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t("commons.save_success"));
|
||||||
this.updateTestCases(param);
|
this.updateTestCases(param);
|
||||||
this.setPlanStatus(this.testCase.planId);
|
this.setPlanStatus(this.testCase.planId);
|
||||||
|
|
||||||
if (this.testCase.comment) {
|
if (this.testCase.comment) {
|
||||||
this.$refs.comment.getComments();
|
this.$refs.comment.getComments();
|
||||||
this.testCase.comment = '';
|
this.testCase.comment = "";
|
||||||
}
|
}
|
||||||
this.originalStatus = this.testCase.status;
|
this.originalStatus = this.testCase.status;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
updateTestCases(param) {
|
updateTestCases(param) {
|
||||||
for (let i = 0; i < this.testCases.length; i++) {
|
for (let i = 0; i < this.testCases.length; i++) {
|
||||||
|
@ -345,7 +429,7 @@ export default {
|
||||||
if (this.isLastData()) {
|
if (this.isLastData()) {
|
||||||
return;
|
return;
|
||||||
} else if (this.index === this.testCases.length - 1) {
|
} else if (this.index === this.testCases.length - 1) {
|
||||||
this.$emit('nextPage');
|
this.$emit("nextPage");
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -354,20 +438,23 @@ export default {
|
||||||
this.reloadOtherInfo();
|
this.reloadOtherInfo();
|
||||||
},
|
},
|
||||||
isLastData() {
|
isLastData() {
|
||||||
return this.index === this.testCases.length - 1 && this.pageNum === this.pageTotal;
|
return (
|
||||||
|
this.index === this.testCases.length - 1 &&
|
||||||
|
this.pageNum === this.pageTotal
|
||||||
|
);
|
||||||
},
|
},
|
||||||
reloadOtherInfo() {
|
reloadOtherInfo() {
|
||||||
this.otherInfoActive = false;
|
this.otherInfoActive = false;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.otherInfoActive = true;
|
this.otherInfoActive = true;
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
handlePre() {
|
handlePre() {
|
||||||
if (this.index === 0 && this.pageNum === 1) {
|
if (this.index === 0 && this.pageNum === 1) {
|
||||||
this.$warning('已经是第一页');
|
this.$warning("已经是第一页");
|
||||||
return;
|
return;
|
||||||
} else if (this.index === 0) {
|
} else if (this.index === 0) {
|
||||||
this.$emit('prePage');
|
this.$emit("prePage");
|
||||||
this.index = this.pageSize - 1;
|
this.index = this.pageSize - 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -378,66 +465,69 @@ export default {
|
||||||
getTestCase(id) {
|
getTestCase(id) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
// id 为 TestPlanTestCase 的 id
|
// id 为 TestPlanTestCase 的 id
|
||||||
testPlanTestCaseGet(id)
|
testPlanTestCaseGet(id).then((response) => {
|
||||||
.then(response => {
|
this.loading = false;
|
||||||
this.loading = false;
|
let item = {};
|
||||||
let item = {};
|
Object.assign(item, response.data);
|
||||||
Object.assign(item, response.data);
|
if (item.results) {
|
||||||
if (item.results) {
|
item.results = JSON.parse(item.results);
|
||||||
item.results = JSON.parse(item.results);
|
} else if (item.steps) {
|
||||||
} else if (item.steps) {
|
item.results = [item.steps.length];
|
||||||
item.results = [item.steps.length];
|
}
|
||||||
}
|
if (item.issues) {
|
||||||
if (item.issues) {
|
item.issues = JSON.parse(item.issues);
|
||||||
item.issues = JSON.parse(item.issues);
|
} else {
|
||||||
} else {
|
item.issues = {};
|
||||||
item.issues = {};
|
}
|
||||||
}
|
item.steps = JSON.parse(item.steps);
|
||||||
item.steps = JSON.parse(item.steps);
|
if (!item.stepModel) {
|
||||||
if (!item.stepModel) {
|
item.stepModel = "STEP";
|
||||||
item.stepModel = 'STEP';
|
}
|
||||||
}
|
item.steptResults = [];
|
||||||
item.steptResults = [];
|
if (item.steps) {
|
||||||
if (item.steps) {
|
for (let i = 0; i < item.steps.length; i++) {
|
||||||
for (let i = 0; i < item.steps.length; i++) {
|
if (item.results) {
|
||||||
if (item.results) {
|
if (item.results[i]) {
|
||||||
if (item.results[i]) {
|
item.steps[i].actualResult = item.results[i].actualResult;
|
||||||
item.steps[i].actualResult = item.results[i].actualResult;
|
item.steps[i].executeResult = item.results[i].executeResult;
|
||||||
item.steps[i].executeResult = item.results[i].executeResult;
|
|
||||||
}
|
|
||||||
item.steptResults.push(item.steps[i]);
|
|
||||||
} else {
|
|
||||||
item.steptResults.push({
|
|
||||||
actualResult: '',
|
|
||||||
executeResult: ''
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
item.steptResults.push(item.steps[i]);
|
||||||
|
} else {
|
||||||
|
item.steptResults.push({
|
||||||
|
actualResult: "",
|
||||||
|
executeResult: "",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.testCase = item;
|
}
|
||||||
this.originalStatus = this.testCase.status;
|
this.testCase = item;
|
||||||
parseCustomField(this.testCase, this.testCaseTemplate, null, buildTestCaseOldFields(this.testCase));
|
this.originalStatus = this.testCase.status;
|
||||||
this.testCaseTemplate.customFields.forEach(item => {
|
parseCustomField(
|
||||||
try {
|
this.testCase,
|
||||||
item.defaultValue = JSON.parse(item.defaultValue);
|
this.testCaseTemplate,
|
||||||
} catch (e) {
|
null,
|
||||||
// nothing
|
buildTestCaseOldFields(this.testCase)
|
||||||
}
|
);
|
||||||
});
|
this.testCaseTemplate.customFields.forEach((item) => {
|
||||||
this.isCustomFiledActive = true;
|
try {
|
||||||
if (!this.testCase.actualResult) {
|
item.defaultValue = JSON.parse(item.defaultValue);
|
||||||
// 如果没值,使用模板的默认值
|
} catch (e) {
|
||||||
this.testCase.actualResult = this.testCaseTemplate.actualResult;
|
// nothing
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.isCustomFiledActive = true;
|
||||||
|
if (!this.testCase.actualResult) {
|
||||||
|
// 如果没值,使用模板的默认值
|
||||||
|
this.testCase.actualResult = this.testCaseTemplate.actualResult;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
openTestCaseEdit(testCase, tableData) {
|
openTestCaseEdit(testCase, tableData) {
|
||||||
checkProjectPermission(testCase.projectId)
|
checkProjectPermission(testCase.projectId).then((r) => {
|
||||||
.then(r => {
|
this.hasProjectPermission = r.data;
|
||||||
this.hasProjectPermission = r.data;
|
});
|
||||||
});
|
|
||||||
this.showDialog = true;
|
this.showDialog = true;
|
||||||
this.activeTab = 'detail';
|
this.activeTab = "detail";
|
||||||
this.originalStatus = testCase.status;
|
this.originalStatus = testCase.status;
|
||||||
this.setTitleWith();
|
this.setTitleWith();
|
||||||
|
|
||||||
|
@ -454,11 +544,10 @@ export default {
|
||||||
|
|
||||||
listenGoBack(this.handleClose);
|
listenGoBack(this.handleClose);
|
||||||
let initFuc = this.getTestCase;
|
let initFuc = this.getTestCase;
|
||||||
getTestTemplate(testCase.projectId)
|
getTestTemplate(testCase.projectId).then((template) => {
|
||||||
.then((template) => {
|
this.testCaseTemplate = template;
|
||||||
this.testCaseTemplate = template;
|
initFuc(testCase.id);
|
||||||
initFuc(testCase.id);
|
});
|
||||||
});
|
|
||||||
if (this.$refs.otherInfo) {
|
if (this.$refs.otherInfo) {
|
||||||
this.$refs.otherInfo.reset();
|
this.$refs.otherInfo.reset();
|
||||||
}
|
}
|
||||||
|
@ -466,16 +555,16 @@ export default {
|
||||||
testRun(reportId) {
|
testRun(reportId) {
|
||||||
this.testCase.reportId = reportId;
|
this.testCase.reportId = reportId;
|
||||||
this.saveReport(reportId);
|
this.saveReport(reportId);
|
||||||
this.activeTab = 'result';
|
this.activeTab = "result";
|
||||||
},
|
},
|
||||||
testTabChange(data) {
|
testTabChange(data) {
|
||||||
if (this.testCase.type === 'performance' && data.paneName === 'result') {
|
if (this.testCase.type === "performance" && data.paneName === "result") {
|
||||||
this.$refs.performanceTestResult.checkReportStatus();
|
this.$refs.performanceTestResult.checkReportStatus();
|
||||||
this.$refs.performanceTestResult.init();
|
this.$refs.performanceTestResult.init();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
saveReport(reportId) {
|
saveReport(reportId) {
|
||||||
testPlanTestCaseEdit({id: this.testCase.id, reportId: reportId});
|
testPlanTestCaseEdit({ id: this.testCase.id, reportId: reportId });
|
||||||
},
|
},
|
||||||
openTest(item) {
|
openTest(item) {
|
||||||
const type = item.testType;
|
const type = item.testType;
|
||||||
|
@ -483,25 +572,34 @@ export default {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performance": {
|
case "performance": {
|
||||||
let performanceData = this.$router.resolve({
|
let performanceData = this.$router.resolve({
|
||||||
path: '/performance/test/edit/' + id,
|
path: "/performance/test/edit/" + id,
|
||||||
})
|
});
|
||||||
window.open(performanceData.href, '_blank');
|
window.open(performanceData.href, "_blank");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "testcase": {
|
case "testcase": {
|
||||||
let caseData = this.$router.resolve({
|
let caseData = this.$router.resolve({
|
||||||
name: 'ApiDefinition',
|
name: "ApiDefinition",
|
||||||
params: {redirectID: getUUID(), dataType: "apiTestCase", dataSelectRange: 'single:' + id}
|
params: {
|
||||||
|
versionId: "default",
|
||||||
|
redirectID: getUUID(),
|
||||||
|
dataType: "apiTestCase",
|
||||||
|
dataSelectRange: "single:" + id,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
window.open(caseData.href, '_blank');
|
window.open(caseData.href, "_blank");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "automation": {
|
case "automation": {
|
||||||
let automationData = this.$router.resolve({
|
let automationData = this.$router.resolve({
|
||||||
name: 'ApiAutomation',
|
name: "ApiAutomation",
|
||||||
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + id}
|
params: {
|
||||||
|
redirectID: getUUID(),
|
||||||
|
dataType: "scenario",
|
||||||
|
dataSelectRange: "edit:" + id,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
window.open(automationData.href, '_blank');
|
window.open(automationData.href, "_blank");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,26 +617,28 @@ export default {
|
||||||
this.relationGraphOpen = val;
|
this.relationGraphOpen = val;
|
||||||
},
|
},
|
||||||
openTestTestCase(item) {
|
openTestTestCase(item) {
|
||||||
let TestCaseData = this.$router.resolve(
|
let TestCaseData = this.$router.resolve({
|
||||||
{
|
path: "/track/case/all",
|
||||||
path: '/track/case/all',
|
query: {
|
||||||
query: {redirectID: getUUID(), dataType: "testCase", dataSelectRange: item.caseId, projectId: item.projectId}
|
redirectID: getUUID(),
|
||||||
}
|
dataType: "testCase",
|
||||||
);
|
dataSelectRange: item.caseId,
|
||||||
window.open(TestCaseData.href, '_blank');
|
projectId: item.projectId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
window.open(TestCaseData.href, "_blank");
|
||||||
},
|
},
|
||||||
addPLabel(str) {
|
addPLabel(str) {
|
||||||
return "<p>" + str + "</p>";
|
return "<p>" + str + "</p>";
|
||||||
},
|
},
|
||||||
setPlanStatus(planId) {
|
setPlanStatus(planId) {
|
||||||
testPlanEditStatus(planId);
|
testPlanEditStatus(planId);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.cast_label {
|
.cast_label {
|
||||||
color: dimgray;
|
color: dimgray;
|
||||||
}
|
}
|
||||||
|
@ -587,7 +687,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-switch :deep(.el-switch__label.is-active) {
|
.el-switch :deep(.el-switch__label.is-active) {
|
||||||
color: #409EFF;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<ms-container>
|
<ms-container>
|
||||||
<ms-main-container class="report-content">
|
<ms-main-container class="report-content" :class="isShare || isTemplate? 'full-screen-container' : 'with-header-container'" id = "planReportContainer">
|
||||||
<el-card v-loading="loading">
|
<el-card v-loading="loading">
|
||||||
<test-plan-report-buttons :is-db="isDb" :plan-id="planId" :is-share="isShare" :report="report"
|
<test-plan-report-buttons :is-db="isDb" :plan-id="planId" :is-share="isShare" :report="report"
|
||||||
v-if="!isTemplate && !isShare"/>
|
v-if="!isTemplate && !isShare"/>
|
||||||
|
@ -190,13 +190,17 @@ export default {
|
||||||
if (!this.isTemplate) {
|
if (!this.isTemplate) {
|
||||||
if (this.isShare) {
|
if (this.isShare) {
|
||||||
getShareTestPlanExtReport(this.shareId, this.planId, this.reportId).then((response) => {
|
getShareTestPlanExtReport(this.shareId, this.planId, this.reportId).then((response) => {
|
||||||
this.runMode = response.data.runMode;
|
if (response.data) {
|
||||||
this.resourcePool = response.data.resourcePool;
|
this.runMode = response.data.runMode;
|
||||||
|
this.resourcePool = response.data.resourcePool;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
getTestPlanExtReport(this.planId, this.reportId).then((response) => {
|
getTestPlanExtReport(this.planId, this.reportId).then((response) => {
|
||||||
this.runMode = response.data.runMode;
|
if (response.data) {
|
||||||
this.resourcePool = response.data.resourcePool;
|
this.runMode = response.data.runMode;
|
||||||
|
this.resourcePool = response.data.resourcePool;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,8 +340,15 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
|
.with-header-container {
|
||||||
|
height: calc(100vh - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-screen-container {
|
||||||
|
height: calc(100vh - 10px);
|
||||||
|
}
|
||||||
|
|
||||||
.el-card {
|
.el-card {
|
||||||
/*width: 95% !important;*/
|
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
activeName() {
|
activeName() {
|
||||||
let target = document.getElementById(this.activeName);
|
let target = document.getElementById(this.activeName);
|
||||||
target.parentNode.parentNode.parentNode.scrollTop = target.offsetTop - 100;
|
document.getElementById('planReportContainer').scrollTop = target.offsetTop - 100;
|
||||||
},
|
},
|
||||||
overviewEnable() {
|
overviewEnable() {
|
||||||
this.setData();
|
this.setData();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<el-drawer
|
<el-drawer
|
||||||
:before-close="handleClose"
|
:before-close="handleClose"
|
||||||
:visible.sync="showDialog"
|
:visible.sync="showDialog"
|
||||||
|
@ -7,28 +6,27 @@
|
||||||
:modal-append-to-body="false"
|
:modal-append-to-body="false"
|
||||||
size="100%"
|
size="100%"
|
||||||
ref="drawer"
|
ref="drawer"
|
||||||
v-loading="loading">
|
v-loading="loading"
|
||||||
|
>
|
||||||
<template>
|
<template>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="17">
|
<el-col :span="17">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<el-card>
|
<el-card>
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
|
<el-header style="height: 100%">
|
||||||
<el-header style="height: 100%;">
|
|
||||||
|
|
||||||
<el-row type="flex" class="head-bar">
|
<el-row type="flex" class="head-bar">
|
||||||
|
|
||||||
<el-col :span="2">
|
<el-col :span="2">
|
||||||
<el-button plain size="mini"
|
<el-button
|
||||||
icon="el-icon-back"
|
plain
|
||||||
@click="cancel">{{ $t('test_track.return') }}
|
size="mini"
|
||||||
|
icon="el-icon-back"
|
||||||
|
@click="cancel"
|
||||||
|
>{{ $t("test_track.return") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="22" class="head-right">
|
<el-col :span="22" class="head-right">
|
||||||
|
|
||||||
<ms-previous-next-button
|
<ms-previous-next-button
|
||||||
:index="index"
|
:index="index"
|
||||||
:page-num="pageNum"
|
:page-num="pageNum"
|
||||||
|
@ -39,90 +37,146 @@
|
||||||
:pre-page-data="prePageData"
|
:pre-page-data="prePageData"
|
||||||
:list="testCases"
|
:list="testCases"
|
||||||
@pre="handlePre"
|
@pre="handlePre"
|
||||||
@next="handleNext"/>
|
@next="handleNext"
|
||||||
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row style="margin-top: 0;">
|
<el-row style="margin-top: 0">
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-divider content-position="left" class="title-divider">
|
<el-divider content-position="left" class="title-divider">
|
||||||
<el-button class="test-case-name" type="text" @click="openTestTestCase(testCase)">
|
<el-button
|
||||||
<span
|
class="test-case-name"
|
||||||
class="title-link"
|
type="text"
|
||||||
:title="testCase.name"
|
@click="openTestTestCase(testCase)"
|
||||||
:style="{'max-width': titleWith + 'px'}">
|
>
|
||||||
{{ testCase.num }}-{{ testCase.name }}
|
<span
|
||||||
</span>
|
class="title-link"
|
||||||
|
:title="testCase.name"
|
||||||
|
:style="{ 'max-width': titleWith + 'px' }"
|
||||||
|
>
|
||||||
|
{{ testCase.num }}-{{ testCase.name }}
|
||||||
|
</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-divider>
|
</el-divider>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</el-header>
|
</el-header>
|
||||||
|
|
||||||
<div class="case_container">
|
<div class="case_container">
|
||||||
<el-form>
|
<el-form>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item :label="$t('test_track.case.module')" prop="nodePath"
|
<el-form-item
|
||||||
:label-width="formLabelWidth">
|
:label="$t('test_track.case.module')"
|
||||||
|
prop="nodePath"
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
{{ testCase.nodePath }}
|
{{ testCase.nodePath }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item :label="$t('test_track.plan.plan_project')" prop="projectName"
|
<el-form-item
|
||||||
:label-width="formLabelWidth">
|
:label="$t('test_track.plan.plan_project')"
|
||||||
|
prop="projectName"
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
{{ testCase.projectName }}
|
{{ testCase.projectName }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<el-form-item :label="$t('评审状态')" :label-width="formLabelWidth">
|
<el-form-item
|
||||||
<status-table-item :value="oldReviewStatus"/>
|
:label="$t('评审状态')"
|
||||||
</el-form-item >
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
|
<status-table-item :value="oldReviewStatus" />
|
||||||
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-form ref="customFieldForm"
|
<el-form
|
||||||
v-if="isCustomFiledActive"
|
ref="customFieldForm"
|
||||||
class="case-form">
|
v-if="isCustomFiledActive"
|
||||||
|
class="case-form"
|
||||||
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="7" v-for="(item, index) in testCaseTemplate.customFields" :key="index">
|
<el-col
|
||||||
<el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name"
|
:span="7"
|
||||||
:prop="item.name"
|
v-for="(item, index) in testCaseTemplate.customFields"
|
||||||
:label-width="formLabelWidth">
|
:key="index"
|
||||||
<custom-filed-component :disabled="true" :data="item" :form="{}" prop="defaultValue"/>
|
>
|
||||||
|
<el-form-item
|
||||||
|
:label="
|
||||||
|
item.system
|
||||||
|
? $t(systemNameMap[item.name])
|
||||||
|
: item.name
|
||||||
|
"
|
||||||
|
:prop="item.name"
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
>
|
||||||
|
<custom-filed-component
|
||||||
|
:disabled="true"
|
||||||
|
:data="item"
|
||||||
|
:form="{}"
|
||||||
|
prop="defaultValue"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<form-rich-text-item :label-width="formLabelWidth" :disabled="true"
|
<form-rich-text-item
|
||||||
:title="$t('test_track.case.prerequisite')"
|
:label-width="formLabelWidth"
|
||||||
:data="testCase" prop="prerequisite"/>
|
:disabled="true"
|
||||||
<step-change-item :disable="true" :label-width="formLabelWidth" :form="testCase"/>
|
:title="$t('test_track.case.prerequisite')"
|
||||||
<form-rich-text-item :label-width="formLabelWidth" :disabled="true"
|
:data="testCase"
|
||||||
v-if="testCase.stepModel === 'TEXT'" :title="$t('test_track.case.step_desc')"
|
prop="prerequisite"
|
||||||
:data="testCase" prop="stepDescription"/>
|
/>
|
||||||
<form-rich-text-item :label-width="formLabelWidth" :disabled="true"
|
<step-change-item
|
||||||
v-if="testCase.stepModel === 'TEXT'"
|
:disable="true"
|
||||||
:title="$t('test_track.case.expected_results')" :data="testCase"
|
:label-width="formLabelWidth"
|
||||||
prop="expectedResult"/>
|
:form="testCase"
|
||||||
|
/>
|
||||||
|
<form-rich-text-item
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
:disabled="true"
|
||||||
|
v-if="testCase.stepModel === 'TEXT'"
|
||||||
|
:title="$t('test_track.case.step_desc')"
|
||||||
|
:data="testCase"
|
||||||
|
prop="stepDescription"
|
||||||
|
/>
|
||||||
|
<form-rich-text-item
|
||||||
|
:label-width="formLabelWidth"
|
||||||
|
:disabled="true"
|
||||||
|
v-if="testCase.stepModel === 'TEXT'"
|
||||||
|
:title="$t('test_track.case.expected_results')"
|
||||||
|
:data="testCase"
|
||||||
|
prop="expectedResult"
|
||||||
|
/>
|
||||||
|
|
||||||
<test-case-step-item :label-width="formLabelWidth" :read-only="true"
|
<test-case-step-item
|
||||||
v-if="testCase.stepModel === 'STEP'" :form="testCase"/>
|
:label-width="formLabelWidth"
|
||||||
|
:read-only="true"
|
||||||
|
v-if="testCase.stepModel === 'STEP'"
|
||||||
|
:form="testCase"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-form-item :label="$t('test_track.case.other_info')" :label-width="formLabelWidth">
|
<el-form-item
|
||||||
<test-case-edit-other-info @openTest="openTest" :read-only="true"
|
:label="$t('test_track.case.other_info')"
|
||||||
@syncRelationGraphOpen="syncRelationGraphOpen"
|
:label-width="formLabelWidth"
|
||||||
:project-id="projectId" :form="testCase" :case-id="testCase.caseId"
|
>
|
||||||
ref="otherInfo"/>
|
<test-case-edit-other-info
|
||||||
|
@openTest="openTest"
|
||||||
|
:read-only="true"
|
||||||
|
@syncRelationGraphOpen="syncRelationGraphOpen"
|
||||||
|
:project-id="projectId"
|
||||||
|
:form="testCase"
|
||||||
|
:case-id="testCase.caseId"
|
||||||
|
ref="otherInfo"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -133,30 +187,38 @@
|
||||||
:test-case="testCase"
|
:test-case="testCase"
|
||||||
:is-read-only="isReadOnly"
|
:is-read-only="isReadOnly"
|
||||||
:origin-status="oldReviewStatus"
|
:origin-status="oldReviewStatus"
|
||||||
@saveCase="saveCase()"/>
|
@saveCase="saveCase()"
|
||||||
|
/>
|
||||||
|
|
||||||
<review-comment
|
<review-comment
|
||||||
default-type="REVIEW"
|
default-type="REVIEW"
|
||||||
:case-id="testCase.caseId"
|
:case-id="testCase.caseId"
|
||||||
@saveCaseReview="saveCaseReview"
|
@saveCaseReview="saveCaseReview"
|
||||||
ref="comment"/>
|
ref="comment"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
import { getCurrentProjectID } from "metersphere-frontend/src/utils/token";
|
||||||
import {getUUID, listenGoBack, removeGoBackListener} from "metersphere-frontend/src/utils"
|
import {
|
||||||
|
getUUID,
|
||||||
|
listenGoBack,
|
||||||
|
removeGoBackListener,
|
||||||
|
} from "metersphere-frontend/src/utils";
|
||||||
import ReviewComment from "@/business/review/commom/ReviewComment";
|
import ReviewComment from "@/business/review/commom/ReviewComment";
|
||||||
import TestCaseAttachment from "@/business/case/components/TestCaseAttachment";
|
import TestCaseAttachment from "@/business/case/components/TestCaseAttachment";
|
||||||
import {buildTestCaseOldFields, getTemplate, parseCustomField} from "metersphere-frontend/src/utils/custom_field";
|
import {
|
||||||
|
buildTestCaseOldFields,
|
||||||
|
getTemplate,
|
||||||
|
parseCustomField,
|
||||||
|
} from "metersphere-frontend/src/utils/custom_field";
|
||||||
import TestCaseEditOtherInfo from "@/business/case/components/TestCaseEditOtherInfo";
|
import TestCaseEditOtherInfo from "@/business/case/components/TestCaseEditOtherInfo";
|
||||||
import {SYSTEM_FIELD_NAME_MAP} from "metersphere-frontend/src/utils/table-constants";
|
import { SYSTEM_FIELD_NAME_MAP } from "metersphere-frontend/src/utils/table-constants";
|
||||||
import FormRichTextItem from "metersphere-frontend/src/components/FormRichTextItem";
|
import FormRichTextItem from "metersphere-frontend/src/components/FormRichTextItem";
|
||||||
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
||||||
import StepChangeItem from "@/business/case/components/StepChangeItem";
|
import StepChangeItem from "@/business/case/components/StepChangeItem";
|
||||||
|
@ -164,12 +226,12 @@ import TestCaseStepItem from "@/business/case/components/TestCaseStepItem";
|
||||||
import MsPreviousNextButton from "metersphere-frontend/src/components/MsPreviousNextButton";
|
import MsPreviousNextButton from "metersphere-frontend/src/components/MsPreviousNextButton";
|
||||||
import TestReviewTestCaseExecute from "./TestReviewTestCaseExecute";
|
import TestReviewTestCaseExecute from "./TestReviewTestCaseExecute";
|
||||||
import StatusTableItem from "@/business/common/tableItems/planview/StatusTableItem";
|
import StatusTableItem from "@/business/common/tableItems/planview/StatusTableItem";
|
||||||
import {getTestTemplate} from "@/api/custom-field-template";
|
import { getTestTemplate } from "@/api/custom-field-template";
|
||||||
import {
|
import {
|
||||||
editTestCaseReviewStatus,
|
editTestCaseReviewStatus,
|
||||||
editTestReviewTestCase,
|
editTestReviewTestCase,
|
||||||
getRelateTest,
|
getRelateTest,
|
||||||
getTestReviewTestCase
|
getTestReviewTestCase,
|
||||||
} from "@/api/test-review";
|
} from "@/api/test-review";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -184,7 +246,7 @@ export default {
|
||||||
FormRichTextItem,
|
FormRichTextItem,
|
||||||
TestCaseEditOtherInfo,
|
TestCaseEditOtherInfo,
|
||||||
ReviewComment,
|
ReviewComment,
|
||||||
TestCaseAttachment
|
TestCaseAttachment,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -193,44 +255,44 @@ export default {
|
||||||
testCase: {},
|
testCase: {},
|
||||||
index: 0,
|
index: 0,
|
||||||
testCases: [],
|
testCases: [],
|
||||||
readConfig: {toolbar: []},
|
readConfig: { toolbar: [] },
|
||||||
test: {},
|
test: {},
|
||||||
activeTab: 'detail',
|
activeTab: "detail",
|
||||||
isFailure: true,
|
isFailure: true,
|
||||||
users: [],
|
users: [],
|
||||||
activeName: 'comment',
|
activeName: "comment",
|
||||||
comments: [],
|
comments: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
currentScenario: {},
|
currentScenario: {},
|
||||||
mark: 'detail',
|
mark: "detail",
|
||||||
api: {},
|
api: {},
|
||||||
apiCase: {},
|
apiCase: {},
|
||||||
testCaseTemplate: {},
|
testCaseTemplate: {},
|
||||||
formLabelWidth: '100px',
|
formLabelWidth: "100px",
|
||||||
isCustomFiledActive: false,
|
isCustomFiledActive: false,
|
||||||
oldReviewStatus: '',
|
oldReviewStatus: "",
|
||||||
titleWith: 0,
|
titleWith: 0,
|
||||||
relationGraphOpen: false,
|
relationGraphOpen: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
total: {
|
total: {
|
||||||
type: Number
|
type: Number,
|
||||||
},
|
},
|
||||||
searchParam: {
|
searchParam: {
|
||||||
type: Object
|
type: Object,
|
||||||
},
|
},
|
||||||
isReadOnly: {
|
isReadOnly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
pageNum: Number,
|
pageNum: Number,
|
||||||
pageSize: {
|
pageSize: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1,
|
||||||
},
|
},
|
||||||
nextPageData: Object,
|
nextPageData: Object,
|
||||||
prePageData: Object
|
prePageData: Object,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
projectId() {
|
projectId() {
|
||||||
|
@ -241,7 +303,7 @@ export default {
|
||||||
},
|
},
|
||||||
pageTotal() {
|
pageTotal() {
|
||||||
return Math.ceil(this.total / this.pageSize);
|
return Math.ceil(this.total / this.pageSize);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openTest(item) {
|
openTest(item) {
|
||||||
|
@ -250,25 +312,35 @@ export default {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performance": {
|
case "performance": {
|
||||||
let performanceData = this.$router.resolve({
|
let performanceData = this.$router.resolve({
|
||||||
path: '/performance/test/edit/' + id,
|
path: "/performance/test/edit/" + id,
|
||||||
});
|
});
|
||||||
window.open(performanceData.href, '_blank');
|
window.open(performanceData.href, "_blank");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "testcase": {
|
case "testcase": {
|
||||||
let caseData = this.$router.resolve({
|
let caseData = this.$router.resolve({
|
||||||
name: 'ApiDefinition',
|
name: "ApiDefinition",
|
||||||
params: {redirectID: getUUID(), dataType: "apiTestCase", dataSelectRange: 'single:' + id}
|
params: {
|
||||||
|
versionId: "default",
|
||||||
|
redirectID: getUUID(),
|
||||||
|
dataType: "apiTestCase",
|
||||||
|
dataSelectRange: "single:" + id,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
window.open(caseData.href, '_blank');
|
window.open(caseData.href, "_blank");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "automation": {
|
case "automation": {
|
||||||
let automationData = this.$router.resolve({
|
let automationData = this.$router.resolve({
|
||||||
name: 'ApiAutomation',
|
name: "ApiAutomation",
|
||||||
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + id}
|
params: {
|
||||||
|
versionId: "default",
|
||||||
|
redirectID: getUUID(),
|
||||||
|
dataType: "scenario",
|
||||||
|
dataSelectRange: "edit:" + id,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
window.open(automationData.href, '_blank');
|
window.open(automationData.href, "_blank");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +354,7 @@ export default {
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
this.handleClose();
|
this.handleClose();
|
||||||
this.$emit('refreshTable');
|
this.$emit("refreshTable");
|
||||||
},
|
},
|
||||||
saveCase() {
|
saveCase() {
|
||||||
let param = {};
|
let param = {};
|
||||||
|
@ -291,22 +363,21 @@ export default {
|
||||||
param.reviewId = this.testCase.reviewId;
|
param.reviewId = this.testCase.reviewId;
|
||||||
param.comment = this.testCase.comment;
|
param.comment = this.testCase.comment;
|
||||||
param.status = this.testCase.reviewStatus;
|
param.status = this.testCase.reviewStatus;
|
||||||
editTestReviewTestCase(param)
|
editTestReviewTestCase(param).then(() => {
|
||||||
.then(() => {
|
this.$success(this.$t("commons.save_success"));
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.updateTestCases(param);
|
||||||
this.updateTestCases(param);
|
this.setReviewStatus(this.testCase.reviewId);
|
||||||
this.setReviewStatus(this.testCase.reviewId);
|
|
||||||
|
|
||||||
// 修改当前用例在整个用例列表的状态
|
// 修改当前用例在整个用例列表的状态
|
||||||
this.testCases[this.index].status = this.testCase.status;
|
this.testCases[this.index].status = this.testCase.status;
|
||||||
// 切换状态后需要修改旧的状态
|
// 切换状态后需要修改旧的状态
|
||||||
this.oldReviewStatus = this.testCase.reviewStatus;
|
this.oldReviewStatus = this.testCase.reviewStatus;
|
||||||
|
|
||||||
if (this.testCase.comment) {
|
if (this.testCase.comment) {
|
||||||
this.$refs.comment.getComments();
|
this.$refs.comment.getComments();
|
||||||
this.testCase.comment = '';
|
this.testCase.comment = "";
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
saveCaseReview() {
|
saveCaseReview() {
|
||||||
let param = {};
|
let param = {};
|
||||||
|
@ -315,18 +386,17 @@ export default {
|
||||||
param.caseId = this.testCase.caseId;
|
param.caseId = this.testCase.caseId;
|
||||||
param.reviewId = this.testCase.reviewId;
|
param.reviewId = this.testCase.reviewId;
|
||||||
param.status = status;
|
param.status = status;
|
||||||
editTestReviewTestCase(param)
|
editTestReviewTestCase(param).then(() => {
|
||||||
.then(() => {
|
this.updateTestCases(param);
|
||||||
this.updateTestCases(param);
|
this.setReviewStatus(this.testCase.reviewId);
|
||||||
this.setReviewStatus(this.testCase.reviewId);
|
this.oldReviewStatus = status;
|
||||||
this.oldReviewStatus = status;
|
// 修改当前用例在整个用例列表的状态
|
||||||
// 修改当前用例在整个用例列表的状态
|
this.testCases[this.index].status = status;
|
||||||
this.testCases[this.index].status = status;
|
if (this.index < this.testCases.length - 1) {
|
||||||
if (this.index < this.testCases.length - 1) {
|
this.handleNext();
|
||||||
this.handleNext();
|
}
|
||||||
}
|
this.$success(this.$t("commons.save_success"));
|
||||||
this.$success(this.$t('commons.save_success'));
|
});
|
||||||
});
|
|
||||||
},
|
},
|
||||||
updateTestCases(param) {
|
updateTestCases(param) {
|
||||||
for (let i = 0; i < this.testCases.length; i++) {
|
for (let i = 0; i < this.testCases.length; i++) {
|
||||||
|
@ -338,12 +408,15 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleNext() {
|
handleNext() {
|
||||||
if (this.index === this.testCases.length - 1 && this.pageNum === this.pageTotal) {
|
if (
|
||||||
|
this.index === this.testCases.length - 1 &&
|
||||||
|
this.pageNum === this.pageTotal
|
||||||
|
) {
|
||||||
// 最后一条不处理
|
// 最后一条不处理
|
||||||
return;
|
return;
|
||||||
} else if (this.index === this.testCases.length - 1) {
|
} else if (this.index === this.testCases.length - 1) {
|
||||||
// 到本页最后一条数据,则翻页
|
// 到本页最后一条数据,则翻页
|
||||||
this.$emit('nextPage');
|
this.$emit("nextPage");
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -351,13 +424,16 @@ export default {
|
||||||
this.getTestCase(this.testCases[this.index].id);
|
this.getTestCase(this.testCases[this.index].id);
|
||||||
},
|
},
|
||||||
isLastData() {
|
isLastData() {
|
||||||
return this.index === this.testCases.length - 1 && this.pageNum === this.pageTotal;
|
return (
|
||||||
|
this.index === this.testCases.length - 1 &&
|
||||||
|
this.pageNum === this.pageTotal
|
||||||
|
);
|
||||||
},
|
},
|
||||||
handlePre() {
|
handlePre() {
|
||||||
if (this.index === 0 && this.pageNum === 1) {
|
if (this.index === 0 && this.pageNum === 1) {
|
||||||
return;
|
return;
|
||||||
} else if (this.index === 0) {
|
} else if (this.index === 0) {
|
||||||
this.$emit('prePage');
|
this.$emit("prePage");
|
||||||
this.index = this.pageSize - 1;
|
this.index = this.pageSize - 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -366,31 +442,35 @@ export default {
|
||||||
},
|
},
|
||||||
getTestCase(id) {
|
getTestCase(id) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
getTestReviewTestCase(id)
|
getTestReviewTestCase(id).then((response) => {
|
||||||
.then((response) => {
|
this.loading = false;
|
||||||
this.loading = false;
|
let item = {};
|
||||||
let item = {};
|
let data = response.data;
|
||||||
let data = response.data;
|
Object.assign(item, data);
|
||||||
Object.assign(item, data);
|
item.results = JSON.parse(item.results);
|
||||||
item.results = JSON.parse(item.results);
|
if (item.issues) {
|
||||||
if (item.issues) {
|
item.issues = JSON.parse(item.issues);
|
||||||
item.issues = JSON.parse(item.issues);
|
} else {
|
||||||
} else {
|
item.issues = {};
|
||||||
item.issues = {};
|
}
|
||||||
}
|
item.steps = JSON.parse(item.steps);
|
||||||
item.steps = JSON.parse(item.steps);
|
if (!item.stepModel) {
|
||||||
if (!item.stepModel) {
|
item.stepModel = "STEP";
|
||||||
item.stepModel = 'STEP';
|
}
|
||||||
}
|
parseCustomField(
|
||||||
parseCustomField(item, this.testCaseTemplate, null, buildTestCaseOldFields(item));
|
item,
|
||||||
this.isCustomFiledActive = true;
|
this.testCaseTemplate,
|
||||||
this.testCase = item;
|
null,
|
||||||
this.oldReviewStatus = this.testCase.reviewStatus;
|
buildTestCaseOldFields(item)
|
||||||
if (!this.testCase.actualResult) {
|
);
|
||||||
// 如果没值,使用模板的默认值
|
this.isCustomFiledActive = true;
|
||||||
this.testCase.actualResult = this.testCaseTemplate.actualResult;
|
this.testCase = item;
|
||||||
}
|
this.oldReviewStatus = this.testCase.reviewStatus;
|
||||||
});
|
if (!this.testCase.actualResult) {
|
||||||
|
// 如果没值,使用模板的默认值
|
||||||
|
this.testCase.actualResult = this.testCaseTemplate.actualResult;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
setTitleWith() {
|
setTitleWith() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
@ -405,7 +485,7 @@ export default {
|
||||||
this.showDialog = true;
|
this.showDialog = true;
|
||||||
// 一开始加载时候需要保存用例评审旧的状态
|
// 一开始加载时候需要保存用例评审旧的状态
|
||||||
this.oldReviewStatus = testCase.reviewStatus;
|
this.oldReviewStatus = testCase.reviewStatus;
|
||||||
this.activeTab = 'detail';
|
this.activeTab = "detail";
|
||||||
listenGoBack(this.handleClose);
|
listenGoBack(this.handleClose);
|
||||||
let initFuc = this.getTestCase;
|
let initFuc = this.getTestCase;
|
||||||
this.setTitleWith();
|
this.setTitleWith();
|
||||||
|
@ -421,26 +501,34 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTestTemplate(testCase.projectId)
|
getTestTemplate(testCase.projectId).then((response) => {
|
||||||
.then((response) => {
|
this.testCaseTemplate = response;
|
||||||
this.testCaseTemplate = response;
|
initFuc(testCase.id);
|
||||||
initFuc(testCase.id);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if (this.$refs.otherInfo) {
|
if (this.$refs.otherInfo) {
|
||||||
this.$refs.otherInfo.reset();
|
this.$refs.otherInfo.reset();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openTestTestCase(item) {
|
openTestTestCase(item) {
|
||||||
let testCaseData = this.$router.resolve(
|
let testCaseData = this.$router.resolve({
|
||||||
{path: '/track/case/all', query: {redirectID: getUUID(), dataType: "testCase", dataSelectRange: item.caseId}}
|
path: "/track/case/all",
|
||||||
);
|
query: {
|
||||||
window.open(testCaseData.href, '_blank');
|
redirectID: getUUID(),
|
||||||
|
dataType: "testCase",
|
||||||
|
dataSelectRange: item.caseId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
window.open(testCaseData.href, "_blank");
|
||||||
},
|
},
|
||||||
getRelatedTest() {
|
getRelatedTest() {
|
||||||
if (this.testCase.method === 'auto' && this.testCase.testId && this.testCase.testId !== 'other') {
|
if (
|
||||||
getRelateTest(this.testCase.type, this.testCase.testId)
|
this.testCase.method === "auto" &&
|
||||||
.then((response) => {
|
this.testCase.testId &&
|
||||||
|
this.testCase.testId !== "other"
|
||||||
|
) {
|
||||||
|
getRelateTest(this.testCase.type, this.testCase.testId).then(
|
||||||
|
(response) => {
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
if (data) {
|
if (data) {
|
||||||
this.test = data;
|
this.test = data;
|
||||||
|
@ -448,8 +536,9 @@ export default {
|
||||||
this.test = {};
|
this.test = {};
|
||||||
this.$warning(this.$t("test_track.case.relate_test_not_find"));
|
this.$warning(this.$t("test_track.case.relate_test_not_find"));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
} else if (this.testCase.testId === 'other') {
|
);
|
||||||
|
} else if (this.testCase.testId === "other") {
|
||||||
this.$warning(this.$t("test_track.case.other_relate_test_not_find"));
|
this.$warning(this.$t("test_track.case.other_relate_test_not_find"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -457,18 +546,20 @@ export default {
|
||||||
editTestCaseReviewStatus(reviewId);
|
editTestCaseReviewStatus(reviewId);
|
||||||
},
|
},
|
||||||
stepResultChange() {
|
stepResultChange() {
|
||||||
if (this.testCase.method === 'manual') {
|
if (this.testCase.method === "manual") {
|
||||||
this.isFailure = this.testCase.steptResults.filter(s => {
|
this.isFailure =
|
||||||
return s.executeResult === 'Failure' || s.executeResult === 'Blocking';
|
this.testCase.steptResults.filter((s) => {
|
||||||
}).length > 0;
|
return (
|
||||||
|
s.executeResult === "Failure" || s.executeResult === "Blocking"
|
||||||
|
);
|
||||||
|
}).length > 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.border-hidden :deep(.el-textarea__inner) {
|
.border-hidden :deep(.el-textarea__inner) {
|
||||||
border-style: hidden;
|
border-style: hidden;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
@ -509,7 +600,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-switch :deep(.el-switch__label.is-active) {
|
.el-switch :deep(.el-switch__label.is-active) {
|
||||||
color: #409EFF;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container :deep(.el-card__body) {
|
.container :deep(.el-card__body) {
|
||||||
|
|
|
@ -1120,7 +1120,7 @@ export default {
|
||||||
resource.protocol = 'DUBBO'
|
resource.protocol = 'DUBBO'
|
||||||
}
|
}
|
||||||
let definitionData = this.$router.resolve({
|
let definitionData = this.$router.resolve({
|
||||||
path: '/api/definition/'+getUUID()+'/api/edit:'+resource.id+'/'+resource.projectId+'/'+resource.protocol+'/'+workspaceId,
|
path: '/api/definition/default/' + getUUID() + '/api/edit:' + resource.id + '/' + resource.projectId + '/' + resource.protocol + '/' + workspaceId,
|
||||||
});
|
});
|
||||||
if (isTurnSpace) {
|
if (isTurnSpace) {
|
||||||
window.open(definitionData.href, '_blank');
|
window.open(definitionData.href, '_blank');
|
||||||
|
|
|
@ -607,7 +607,7 @@ export default {
|
||||||
edit(row) {
|
edit(row) {
|
||||||
let uuid = getUUID();
|
let uuid = getUUID();
|
||||||
let apiResolve = this.$router.resolve({
|
let apiResolve = this.$router.resolve({
|
||||||
path: '/api/automation/'+uuid+'/scenario/edit:'+row.id+'/'+row.projectId+'/'+getCurrentWorkspaceId(),
|
path: '/api/automation/default/' + uuid + '/scenario/edit:' + row.id + '/' + row.projectId + '/' + getCurrentWorkspaceId(),
|
||||||
});
|
});
|
||||||
window.open(apiResolve.href, '_blank');
|
window.open(apiResolve.href, '_blank');
|
||||||
},
|
},
|
||||||
|
|
|
@ -654,12 +654,13 @@ export default {
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
},
|
},
|
||||||
handleEdit(testCase, column) {
|
handleEdit(testCase, column) {
|
||||||
this.$router.push({
|
let caseResolve = this.$router.resolve({
|
||||||
path: '/track/case/edit',
|
path: '/track/case/edit',
|
||||||
query:{
|
query: {
|
||||||
caseId:testCase.id,
|
caseId: testCase.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
window.open(caseResolve.href, '_blank');
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.$refs.table.clear();
|
this.$refs.table.clear();
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card">
|
<el-card class="table-card">
|
||||||
<ms-table
|
<ms-table
|
||||||
:table-is-loading="page.result.loading"
|
v-loading="loading"
|
||||||
|
row-key="id"
|
||||||
:data="page.data"
|
:data="page.data"
|
||||||
:enableSelection="false"
|
:enableSelection="false"
|
||||||
:condition="page.condition"
|
:condition="page.condition"
|
||||||
|
@ -10,13 +11,16 @@
|
||||||
:show-select-all="false"
|
:show-select-all="false"
|
||||||
:screen-height="screenHeight"
|
:screen-height="screenHeight"
|
||||||
:remember-order="true"
|
:remember-order="true"
|
||||||
@handlePageChange="getIssues"
|
|
||||||
@handleRowClick="handleEdit"
|
|
||||||
:fields.sync="fields"
|
:fields.sync="fields"
|
||||||
:field-key="tableHeaderKey"
|
:field-key="tableHeaderKey"
|
||||||
@refresh="getIssues"
|
:custom-fields="issueTemplate.customFields"
|
||||||
ref="table"
|
@headChange="handleHeadChange"
|
||||||
>
|
@handleRowClick="handleEdit"
|
||||||
|
@filter="search"
|
||||||
|
@order="getIssues"
|
||||||
|
@handlePageChange="getIssues"
|
||||||
|
ref="table">
|
||||||
|
|
||||||
<ms-table-column
|
<ms-table-column
|
||||||
v-for="(item) in fields" :key="item.key"
|
v-for="(item) in fields" :key="item.key"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
|
@ -88,6 +92,7 @@
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</ms-table-column>
|
</ms-table-column>
|
||||||
|
|
||||||
</ms-table>
|
</ms-table>
|
||||||
|
|
||||||
<ms-table-pagination :change="getIssues" :current-page.sync="page.currentPage" :page-size.sync="page.pageSize"
|
<ms-table-pagination :change="getIssues" :current-page.sync="page.currentPage" :page-size.sync="page.pageSize"
|
||||||
|
@ -104,46 +109,94 @@ import MsTablePagination from "metersphere-frontend/src/components/pagination/Ta
|
||||||
import {
|
import {
|
||||||
ISSUE_PLATFORM_OPTION,
|
ISSUE_PLATFORM_OPTION,
|
||||||
ISSUE_STATUS_MAP,
|
ISSUE_STATUS_MAP,
|
||||||
SYSTEM_FIELD_NAME_MAP,
|
|
||||||
TAPD_ISSUE_STATUS_MAP
|
TAPD_ISSUE_STATUS_MAP
|
||||||
} from "metersphere-frontend/src/utils/table-constants";
|
} from "metersphere-frontend/src/utils/table-constants";
|
||||||
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
||||||
import {getDashboardIssues, getIssuePartTemplateWithProject, getIssues, getPlatformOption} from "@/api/issue";
|
|
||||||
|
import {
|
||||||
|
getDashboardIssues,
|
||||||
|
getIssuePartTemplateWithProject,
|
||||||
|
getIssues,
|
||||||
|
getPlatformOption,
|
||||||
|
} from "@/api/issue";
|
||||||
import {
|
import {
|
||||||
getCustomFieldValue,
|
getCustomFieldValue,
|
||||||
getCustomTableWidth,
|
getCustomTableWidth,
|
||||||
getLastTableSortField,
|
getPageInfo, getTableHeaderWithCustomFields, getLastTableSortField, getCustomFieldFilter, parseCustomFilesForList
|
||||||
getPageDate,
|
|
||||||
getPageInfo, parseCustomFilesForList
|
|
||||||
} from "metersphere-frontend/src/utils/tableUtils";
|
} from "metersphere-frontend/src/utils/tableUtils";
|
||||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||||
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
||||||
import {getProjectMember} from "@/api/user";
|
import {getProjectMember, getProjectMemberUserFilter} from "@/api/user";
|
||||||
import {getTableHeaderWithCustomFieldsByXpack} from "@/business/component/js/table-head-util";
|
|
||||||
import {LOCAL} from "metersphere-frontend/src/utils/constants";
|
import {LOCAL} from "metersphere-frontend/src/utils/constants";
|
||||||
|
import {TEST_TRACK_ISSUE_LIST} from "metersphere-frontend/src/components/search/search-components";
|
||||||
|
import {
|
||||||
|
getAdvSearchCustomField
|
||||||
|
} from "metersphere-frontend/src/components/search/custom-component";
|
||||||
|
import MsMarkDownText from "metersphere-frontend/src/components/MsMarkDownText";
|
||||||
import MsReviewTableItem from "@/business/component/MsReviewTableItem";
|
import MsReviewTableItem from "@/business/component/MsReviewTableItem";
|
||||||
import {getUUID} from "metersphere-frontend/src/utils";
|
import IssueDescriptionTableItem from "@/business/component/IssueDescriptionTableItem";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "IssueTableList",
|
name: "IssueList",
|
||||||
components: {
|
components: {
|
||||||
MsMainContainer,
|
|
||||||
MsReviewTableItem,
|
MsReviewTableItem,
|
||||||
|
MsMarkDownText,
|
||||||
|
MsMainContainer,
|
||||||
MsContainer,
|
MsContainer,
|
||||||
|
IssueDescriptionTableItem,
|
||||||
MsTableHeader,
|
MsTableHeader,
|
||||||
MsTablePagination, MsTableButton, MsTableOperators, MsTableColumn, MsTable
|
MsTablePagination, MsTableButton, MsTableOperators, MsTableColumn, MsTable
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
page: getPageInfo(),
|
page: getPageInfo({
|
||||||
|
components: TEST_TRACK_ISSUE_LIST,
|
||||||
|
custom: false,
|
||||||
|
}),
|
||||||
fields: [],
|
fields: [],
|
||||||
|
customFields: [], // 通过表头过滤后的自定义字段列表
|
||||||
tableHeaderKey: "ISSUE_LIST",
|
tableHeaderKey: "ISSUE_LIST",
|
||||||
fieldsWidth: getCustomTableWidth('ISSUE_LIST'),
|
fieldsWidth: getCustomTableWidth('ISSUE_LIST'),
|
||||||
issueTemplate: {},
|
issueTemplate: {},
|
||||||
members: [],
|
members: [],
|
||||||
|
userFilter: [],
|
||||||
isThirdPart: false,
|
isThirdPart: false,
|
||||||
|
creatorFilters: [],
|
||||||
|
loading: false,
|
||||||
|
dataSelectRange: "",
|
||||||
platformOptions: [],
|
platformOptions: [],
|
||||||
|
platformStatus: [],
|
||||||
|
platformStatusMap: new Map(),
|
||||||
|
hasLicense: false,
|
||||||
|
columns: {
|
||||||
|
num: {
|
||||||
|
sortable: true,
|
||||||
|
minWidth: 100
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
sortable: true,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
platform: {
|
||||||
|
minWidth: 80,
|
||||||
|
filters: this.platformFilters
|
||||||
|
},
|
||||||
|
platformStatus: {
|
||||||
|
minWidth: 110,
|
||||||
|
},
|
||||||
|
creatorName: {
|
||||||
|
columnKey: 'creator',
|
||||||
|
minWidth: 100,
|
||||||
|
filters: this.creatorFilters
|
||||||
|
},
|
||||||
|
resourceName: {},
|
||||||
|
createTime: {
|
||||||
|
sortable: true,
|
||||||
|
minWidth: 180
|
||||||
|
},
|
||||||
|
caseCount: {}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
activated() {
|
activated() {
|
||||||
|
@ -192,48 +245,87 @@ export default {
|
||||||
tapdIssueStatusMap() {
|
tapdIssueStatusMap() {
|
||||||
return TAPD_ISSUE_STATUS_MAP;
|
return TAPD_ISSUE_STATUS_MAP;
|
||||||
},
|
},
|
||||||
systemNameMap() {
|
|
||||||
return SYSTEM_FIELD_NAME_MAP;
|
|
||||||
},
|
|
||||||
projectId() {
|
projectId() {
|
||||||
return getCurrentProjectID();
|
return getCurrentProjectID();
|
||||||
},
|
},
|
||||||
|
workspaceId() {
|
||||||
|
return getCurrentWorkspaceId();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getMaintainerOptions();
|
||||||
|
this.page.result.loading = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
getProjectMember((data) => {
|
||||||
|
this.members = data;
|
||||||
|
});
|
||||||
|
getIssuePartTemplateWithProject((template) => {
|
||||||
|
this.initFields(template);
|
||||||
|
this.page.result.loading = false;
|
||||||
|
});
|
||||||
|
this.getIssues();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getCustomFieldValue(row, field) {
|
getCustomFieldValue(row, field, defaultVal) {
|
||||||
let value = getCustomFieldValue(row, field, this.members);
|
let value = getCustomFieldValue(row, field, this.members);
|
||||||
if (!value) {
|
return value ? value : defaultVal;
|
||||||
if (field.name === '处理人') {
|
},
|
||||||
return row.maintainerName;
|
getCustomFieldFilter(field) {
|
||||||
}
|
return getCustomFieldFilter(field, this.userFilter);
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
},
|
||||||
initFields(template) {
|
initFields(template) {
|
||||||
this.issueTemplate = template;
|
if (template.platform === LOCAL) {
|
||||||
if (this.issueTemplate.platform === LOCAL) {
|
|
||||||
this.isThirdPart = false;
|
this.isThirdPart = false;
|
||||||
} else {
|
} else {
|
||||||
this.isThirdPart = true;
|
this.isThirdPart = true;
|
||||||
}
|
}
|
||||||
this.fields = getTableHeaderWithCustomFieldsByXpack('ISSUE_LIST_HEAD', this.issueTemplate.customFields);
|
let fields = getTableHeaderWithCustomFields('ISSUE_LIST', template.customFields, this.members);
|
||||||
if (!this.isThirdPart) {
|
if (!this.isThirdPart) {
|
||||||
for (let i = 0; i < this.fields.length; i++) {
|
for (let i = 0; i < fields.length; i++) {
|
||||||
if (this.fields[i].id === 'platformStatus') {
|
if (fields[i].id === 'platformStatus') {
|
||||||
this.fields.splice(i, 1);
|
fields.splice(i, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果不是三方平台则移除备选字段中的平台状态
|
// 如果不是三方平台则移除备选字段中的平台状态
|
||||||
let removeField = {id: 'platformStatus', name: 'platformStatus', remove: true};
|
let removeField = {id: 'platformStatus', name: 'platformStatus', remove: true};
|
||||||
this.issueTemplate.customFields.push(removeField);
|
template.customFields.push(removeField);
|
||||||
}
|
}
|
||||||
this.$nextTick(() => {
|
this.issueTemplate = template;
|
||||||
if (this.$refs.table) {
|
fields.forEach(item => {
|
||||||
this.$refs.table.reloadTable();
|
if (this.columns[item.id]) {
|
||||||
|
Object.assign(item, this.columns[item.id]);
|
||||||
|
if (this.columns[item.id].filters) {
|
||||||
|
item.filters = this.columns[item.id].filters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.fields = fields;
|
||||||
|
|
||||||
|
// 过滤自定义字段
|
||||||
|
this.page.condition.components = this.page.condition.components.filter(item => item.custom !== true);
|
||||||
|
let comp = getAdvSearchCustomField(this.page.condition, template.customFields);
|
||||||
|
this.page.condition.components.push(...comp);
|
||||||
|
|
||||||
|
this.initCustomFieldValue();
|
||||||
|
|
||||||
|
if (this.$refs.table) {
|
||||||
|
this.$refs.table.reloadTable();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search() {
|
||||||
|
// 添加搜索条件时,当前页设置成第一页
|
||||||
|
this.page.currentPage = 1;
|
||||||
|
this.getIssues();
|
||||||
|
},
|
||||||
|
handleHeadChange() {
|
||||||
|
this.initFields(this.issueTemplate);
|
||||||
|
},
|
||||||
|
handleEdit(resource) {
|
||||||
|
let issueData = this.$router.resolve({path: '/track/issue', query: {id: resource.id}});
|
||||||
|
window.open(issueData.href, '_blank');
|
||||||
},
|
},
|
||||||
getIssues() {
|
getIssues() {
|
||||||
if (this.isSelectAll === false) {
|
if (this.isSelectAll === false) {
|
||||||
|
@ -313,24 +405,11 @@ export default {
|
||||||
});
|
});
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
|
getMaintainerOptions() {
|
||||||
handleEdit(resource) {
|
getProjectMemberUserFilter((data) => {
|
||||||
let issueData = this.$router.resolve({path: '/track/issue', query: {id: resource.id}});
|
this.creatorFilters = data;
|
||||||
window.open(issueData.href, '_blank');
|
});
|
||||||
},
|
},
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.page.result.loading = true;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
getProjectMember((data) => {
|
|
||||||
this.members = data;
|
|
||||||
});
|
|
||||||
getIssuePartTemplateWithProject((template) => {
|
|
||||||
this.initFields(template);
|
|
||||||
this.page.result.loading = false;
|
|
||||||
});
|
|
||||||
this.getIssues();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
width="80"
|
width="80"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span @click="link(scope.row)" style="cursor: pointer;">{{ scope.row.name }}</span>
|
<span @click="link(scope.row)" style="cursor: pointer;">{{ scope.row.num }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.case_ref')" :visible.sync="visible"
|
<el-dialog
|
||||||
:modal="false" width="45%" :destroy-on-close="true">
|
:close-on-click-modal="false"
|
||||||
<span>{{ $t('api_test.automation.scenario_ref') }}:</span>
|
:title="$t('api_test.automation.case_ref')"
|
||||||
|
:visible.sync="visible"
|
||||||
|
:modal="false"
|
||||||
|
width="45%"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
>
|
||||||
|
<span>{{ $t("api_test.automation.scenario_ref") }}:</span>
|
||||||
<div class="refs" v-loading="scenarioLoading">
|
<div class="refs" v-loading="scenarioLoading">
|
||||||
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">
|
<div
|
||||||
|
v-for="(item, index) in scenarioRefs"
|
||||||
|
:key="index"
|
||||||
|
class="el-button--text"
|
||||||
|
>
|
||||||
<el-link @click="openScenario(item)">
|
<el-link @click="openScenario(item)">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span>{{ $t('api_test.automation.plan_ref') }}:</span>
|
<span>{{ $t("api_test.automation.plan_ref") }}:</span>
|
||||||
<div class="refs">
|
<div class="refs">
|
||||||
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">
|
<div
|
||||||
|
v-for="(item, index) in planRefs"
|
||||||
|
:key="index"
|
||||||
|
class="el-button--text"
|
||||||
|
>
|
||||||
<el-link @click="openTestPlan(item)">
|
<el-link @click="openTestPlan(item)">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</el-link>
|
</el-link>
|
||||||
|
@ -21,8 +35,12 @@
|
||||||
|
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" @click="visible = false" @keydown.enter.native.prevent>
|
<el-button
|
||||||
{{ $t('commons.confirm') }}
|
type="primary"
|
||||||
|
@click="visible = false"
|
||||||
|
@keydown.enter.native.prevent
|
||||||
|
>
|
||||||
|
{{ $t("commons.confirm") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -30,93 +48,105 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {
|
||||||
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
getCurrentProjectID,
|
||||||
import {getUUID} from "metersphere-frontend/src/utils";
|
getCurrentWorkspaceId,
|
||||||
import {getOwnerProjectIds, getProject} from "@/api/project";
|
} from "metersphere-frontend/src/utils/token";
|
||||||
import {getScenarioReference} from "@/api/scenario";
|
import { getUUID } from "metersphere-frontend/src/utils";
|
||||||
|
import { getOwnerProjectIds, getProject } from "@/api/project";
|
||||||
|
import { getScenarioReference } from "@/api/scenario";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsReferenceView",
|
name: "MsReferenceView",
|
||||||
components: {},
|
components: {},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
scenarioLoading: false,
|
scenarioLoading: false,
|
||||||
scenarioRefs: [],
|
scenarioRefs: [],
|
||||||
planRefs: []
|
planRefs: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getReferenceData(row) {
|
||||||
|
if (row.id === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.scenarioLoading = true;
|
||||||
|
this.scenarioRefs = [];
|
||||||
|
getScenarioReference(row).then((response) => {
|
||||||
|
this.scenarioRefs = response.data.scenarioList;
|
||||||
|
this.planRefs = response.data.testPlanList;
|
||||||
|
this.scenarioLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
open(row) {
|
||||||
|
this.getReferenceData(row);
|
||||||
|
this.visible = true;
|
||||||
|
},
|
||||||
|
openScenario(resource) {
|
||||||
|
let workspaceId = getCurrentWorkspaceId();
|
||||||
|
let isTurnSpace = true;
|
||||||
|
if (resource.projectId !== getCurrentProjectID()) {
|
||||||
|
isTurnSpace = false;
|
||||||
|
getProject(resource.projectId).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
workspaceId = response.data.workspaceId;
|
||||||
|
isTurnSpace = true;
|
||||||
|
this.checkPermission(resource, workspaceId, isTurnSpace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.checkPermission(resource, workspaceId, isTurnSpace);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
gotoTurn(resource, workspaceId, isTurnSpace) {
|
||||||
getReferenceData(row) {
|
let automationData = this.$router.resolve({
|
||||||
if (row.id === undefined) {
|
name: "ApiAutomation",
|
||||||
return;
|
params: {
|
||||||
}
|
versionId: "default",
|
||||||
this.scenarioLoading = true;
|
redirectID: getUUID(),
|
||||||
this.scenarioRefs = [];
|
dataType: "scenario",
|
||||||
getScenarioReference(row).then(response => {
|
dataSelectRange: "edit:" + resource.id,
|
||||||
this.scenarioRefs = response.data.scenarioList;
|
projectId: resource.projectId,
|
||||||
this.planRefs = response.data.testPlanList;
|
workspaceId: workspaceId,
|
||||||
this.scenarioLoading = false;
|
},
|
||||||
})
|
});
|
||||||
},
|
if (isTurnSpace) {
|
||||||
open(row) {
|
window.open(automationData.href, "_blank");
|
||||||
this.getReferenceData(row);
|
|
||||||
this.visible = true
|
|
||||||
},
|
|
||||||
openScenario(resource) {
|
|
||||||
let workspaceId = getCurrentWorkspaceId();
|
|
||||||
let isTurnSpace = true
|
|
||||||
if (resource.projectId !== getCurrentProjectID()) {
|
|
||||||
isTurnSpace = false;
|
|
||||||
getProject(resource.projectId).then(response => {
|
|
||||||
if (response.data) {
|
|
||||||
workspaceId = response.data.workspaceId;
|
|
||||||
isTurnSpace = true;
|
|
||||||
this.checkPermission(resource, workspaceId, isTurnSpace);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.checkPermission(resource, workspaceId, isTurnSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
gotoTurn(resource, workspaceId, isTurnSpace) {
|
|
||||||
let automationData = this.$router.resolve({
|
|
||||||
name: 'ApiAutomation',
|
|
||||||
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + resource.id, projectId: resource.projectId, workspaceId: workspaceId}
|
|
||||||
});
|
|
||||||
if (isTurnSpace) {
|
|
||||||
window.open(automationData.href, '_blank');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
checkPermission(resource, workspaceId, isTurnSpace) {
|
|
||||||
getOwnerProjectIds().then(res => {
|
|
||||||
const project = res.data.find(p => p === resource.projectId);
|
|
||||||
if (!project) {
|
|
||||||
this.$warning(this.$t('commons.no_permission'));
|
|
||||||
} else {
|
|
||||||
this.gotoTurn(resource, workspaceId, isTurnSpace)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
openTestPlan(item){
|
|
||||||
let automationData = this.$router.resolve({
|
|
||||||
path: '/track/plan/view/' + item.id,
|
|
||||||
query: { workspaceId: item.workspaceId, projectId: item.projectId, charType: 'api'}
|
|
||||||
});
|
|
||||||
window.open(automationData.href, '_blank');
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
checkPermission(resource, workspaceId, isTurnSpace) {
|
||||||
|
getOwnerProjectIds().then((res) => {
|
||||||
|
const project = res.data.find((p) => p === resource.projectId);
|
||||||
|
if (!project) {
|
||||||
|
this.$warning(this.$t("commons.no_permission"));
|
||||||
|
} else {
|
||||||
|
this.gotoTurn(resource, workspaceId, isTurnSpace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openTestPlan(item) {
|
||||||
|
let automationData = this.$router.resolve({
|
||||||
|
path: "/track/plan/view/" + item.id,
|
||||||
|
query: {
|
||||||
|
workspaceId: item.workspaceId,
|
||||||
|
projectId: item.projectId,
|
||||||
|
charType: "api",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
window.open(automationData.href, "_blank");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.refs {
|
.refs {
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue