fix(接口测试): 修复多版本情况下场景引用复制问题

--bug=1009777 --user=赵勇 【接口自动化】-场景A中引用v1版本的场景B,删除场景B后场景A仍成功执行引用的场景B https://www.tapd.cn/55049933/s/1094931
This commit is contained in:
fit2-zhao 2022-01-20 12:41:58 +08:00 committed by fit2-zhao
parent 3baef16d16
commit 4f6f06108f
16 changed files with 299 additions and 147 deletions

View File

@ -70,7 +70,7 @@ public class ApiAutomationController {
@PostMapping("/list/all") @PostMapping("/list/all")
@RequiresPermissions("PROJECT_API_SCENARIO:READ") @RequiresPermissions("PROJECT_API_SCENARIO:READ")
public List<ApiScenarioWithBLOBs> listAll(@RequestBody ApiScenarioBatchRequest request) { public List<ApiScenarioDTO> listAll(@RequestBody ApiScenarioBatchRequest request) {
return apiAutomationService.listAll(request); return apiAutomationService.listAll(request);
} }
@ -194,7 +194,7 @@ public class ApiAutomationController {
} }
@PostMapping("/getApiScenarios") @PostMapping("/getApiScenarios")
public List<ApiScenarioWithBLOBs> getApiScenarios(@RequestBody List<String> ids) { public List<ApiScenarioDTO> getApiScenarios(@RequestBody List<String> ids) {
return apiAutomationService.getApiScenarios(ids); return apiAutomationService.getApiScenarios(ids);
} }

View File

@ -495,6 +495,75 @@ public class ElementUtil {
} }
} }
public static void mergeHashTree(JSONObject element, JSONArray targetHashTree) {
try {
JSONArray sourceHashTree = element.getJSONArray("hashTree");
if (CollectionUtils.isNotEmpty(sourceHashTree) && CollectionUtils.isNotEmpty(targetHashTree) && sourceHashTree.size() < targetHashTree.size()) {
element.put("hashTree", targetHashTree);
return;
}
List<String> sourceIds = new ArrayList<>();
List<String> delIds = new ArrayList<>();
Map<String, JSONObject> updateMap = new HashMap<>();
if (CollectionUtils.isEmpty(sourceHashTree)) {
if (CollectionUtils.isNotEmpty(targetHashTree)) {
element.put("hashTree", targetHashTree);
}
return;
}
if (CollectionUtils.isNotEmpty(targetHashTree)) {
for (int i = 0; i < targetHashTree.size(); i++) {
JSONObject item = targetHashTree.getJSONObject(i);
if (StringUtils.isNotEmpty(item.getString("id"))) {
updateMap.put(item.getString("id"), item);
}
}
}
// 找出待更新内容和源已经被删除的内容
if (CollectionUtils.isNotEmpty(sourceHashTree)) {
for (int i = 0; i < sourceHashTree.size(); i++) {
JSONObject source = sourceHashTree.getJSONObject(i);
if (source != null) {
sourceIds.add(source.getString("id"));
if (!StringUtils.equals(source.getString("label"), "SCENARIO-REF-STEP") && StringUtils.isNotEmpty(source.getString("id"))) {
if (updateMap.containsKey(source.getString("id"))) {
sourceHashTree.set(i, updateMap.get(source.getString("id")));
} else {
delIds.add(source.getString("id"));
}
}
// 历史数据兼容
if (StringUtils.isEmpty(source.getString("id")) && !StringUtils.equals(source.getString("label"), "SCENARIO-REF-STEP") && i < targetHashTree.size()) {
sourceHashTree.set(i, targetHashTree.get(i));
}
}
}
}
// 删除多余的步骤
for (int i = 0; i < sourceHashTree.size(); i++) {
JSONObject source = sourceHashTree.getJSONObject(i);
if (delIds.contains(source.getString("id"))) {
sourceHashTree.remove(i);
}
}
// 补充新增的源引用步骤
if (CollectionUtils.isNotEmpty(targetHashTree)) {
for (int i = 0; i < targetHashTree.size(); i++) {
JSONObject item = sourceHashTree.getJSONObject(i);
if (!sourceIds.contains(item.getString("id"))) {
sourceHashTree.add(item);
}
}
}
if (CollectionUtils.isNotEmpty(sourceHashTree)) {
element.put("hashTree", sourceHashTree);
}
} catch (Exception e) {
element.put("hashTree", targetHashTree);
}
}
public static String hashTreeToString(HashTree hashTree) { public static String hashTreeToString(HashTree hashTree) {
try (ByteArrayOutputStream bas = new ByteArrayOutputStream()) { try (ByteArrayOutputStream bas = new ByteArrayOutputStream()) {
SaveService.saveTree(hashTree, bas); SaveService.saveTree(hashTree, bas);

View File

@ -123,6 +123,8 @@ public class MsScenario extends MsTestElement {
} }
this.setHashTree(sourceHashTree); this.setHashTree(sourceHashTree);
hashTree = sourceHashTree; hashTree = sourceHashTree;
} else {
return;
} }
} catch (Exception ex) { } catch (Exception ex) {

View File

@ -26,6 +26,7 @@ import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.plugin.core.MsParameter; import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.utils.LoggerUtil;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -88,7 +89,11 @@ public class MsDubboSampler extends MsTestElement {
return; return;
} }
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.setRefElement(); boolean ref = this.setRefElement();
if (!ref) {
LoggerUtil.debug("引用对象已经被删除:" + this.getId());
return;
}
hashTree = this.getHashTree(); hashTree = this.getHashTree();
} }
@ -100,7 +105,7 @@ public class MsDubboSampler extends MsTestElement {
} }
} }
private void setRefElement() { private boolean setRefElement() {
try { try {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@ -139,11 +144,12 @@ public class MsDubboSampler extends MsTestElement {
this.setConsumerAndService(proxy.getConsumerAndService()); this.setConsumerAndService(proxy.getConsumerAndService());
this.setRegistryCenter(proxy.getRegistryCenter()); this.setRegistryCenter(proxy.getRegistryCenter());
this.setConfigCenter(proxy.getConfigCenter()); this.setConfigCenter(proxy.getConfigCenter());
return true;
} }
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex); LogUtil.error(ex);
} }
return false;
} }
private DubboSample dubboSample(ParameterConfig config) { private DubboSample dubboSample(ParameterConfig config) {

View File

@ -45,6 +45,7 @@ import io.metersphere.jmeter.utils.ScriptEngineUtils;
import io.metersphere.plugin.core.MsParameter; import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.track.service.TestPlanApiCaseService; import io.metersphere.track.service.TestPlanApiCaseService;
import io.metersphere.utils.LoggerUtil;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -133,7 +134,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
@JSONField(ordinal = 39) @JSONField(ordinal = 39)
private boolean customizeReq; private boolean customizeReq;
private void setRefElement() { private boolean setRefElement() {
try { try {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@ -171,11 +172,12 @@ public class MsHTTPSamplerProxy extends MsTestElement {
this.setRest(proxy.getRest()); this.setRest(proxy.getRest());
this.setArguments(proxy.getArguments()); this.setArguments(proxy.getArguments());
this.setHeaders(proxy.getHeaders()); this.setHeaders(proxy.getHeaders());
return true;
} }
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex); LogUtil.error(ex);
} }
return false;
} }
@Override @Override
@ -189,7 +191,11 @@ public class MsHTTPSamplerProxy extends MsTestElement {
return; return;
} }
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.setRefElement(); boolean ref = this.setRefElement();
if (!ref) {
LoggerUtil.debug("引用对象已经被删除:" + this.getId());
return;
}
hashTree = this.getHashTree(); hashTree = this.getHashTree();
} }
HTTPSamplerProxy sampler = new HTTPSamplerProxy(); HTTPSamplerProxy sampler = new HTTPSamplerProxy();
@ -749,22 +755,22 @@ public class MsHTTPSamplerProxy extends MsTestElement {
list.stream(). list.stream().
filter(KeyValue::isValid). filter(KeyValue::isValid).
filter(KeyValue::isEnable).forEach(keyValue -> { filter(KeyValue::isEnable).forEach(keyValue -> {
try { try {
String value = StringUtils.isNotEmpty(keyValue.getValue()) && keyValue.getValue().startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(keyValue.getValue()) : keyValue.getValue(); String value = StringUtils.isNotEmpty(keyValue.getValue()) && keyValue.getValue().startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(keyValue.getValue()) : keyValue.getValue();
HTTPArgument httpArgument = new HTTPArgument(keyValue.getName(), value); HTTPArgument httpArgument = new HTTPArgument(keyValue.getName(), value);
if (keyValue.getValue() == null) { if (keyValue.getValue() == null) {
httpArgument.setValue(""); httpArgument.setValue("");
}
httpArgument.setAlwaysEncoded(keyValue.isUrlEncode());
if (StringUtils.isNotBlank(keyValue.getContentType())) {
httpArgument.setContentType(keyValue.getContentType());
}
arguments.addArgument(httpArgument);
} catch (Exception e) {
}
} }
); httpArgument.setAlwaysEncoded(keyValue.isUrlEncode());
if (StringUtils.isNotBlank(keyValue.getContentType())) {
httpArgument.setContentType(keyValue.getContentType());
}
arguments.addArgument(httpArgument);
} catch (Exception e) {
}
}
);
return arguments; return arguments;
} }

View File

@ -29,6 +29,7 @@ import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants; import io.metersphere.constants.RunModeConstants;
import io.metersphere.plugin.core.MsParameter; import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.utils.LoggerUtil;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -86,7 +87,11 @@ public class MsJDBCSampler extends MsTestElement {
return; return;
} }
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.setRefElement(); boolean ref = this.setRefElement();
if (!ref) {
LoggerUtil.debug("引用对象已经被删除:" + this.getId());
return;
}
hashTree = this.getHashTree(); hashTree = this.getHashTree();
} }
if (config != null && config.getConfig() == null) { if (config != null && config.getConfig() == null) {
@ -172,12 +177,12 @@ public class MsJDBCSampler extends MsTestElement {
} }
//处理全局前后置脚本(步骤内) //处理全局前后置脚本(步骤内)
String enviromentId = this.getEnvironmentId(); String environmentId = this.getEnvironmentId();
if (enviromentId == null) { if (environmentId == null) {
enviromentId = this.useEnvironment; environmentId = this.useEnvironment;
} }
//根据配置将脚本放置在私有脚本之前 //根据配置将脚本放置在私有脚本之前
JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.JDBC.name(), enviromentId, config, false); JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.JDBC.name(), environmentId, config, false);
HashTreeUtil hashTreeUtil = new HashTreeUtil(); HashTreeUtil hashTreeUtil = new HashTreeUtil();
@ -192,7 +197,7 @@ public class MsJDBCSampler extends MsTestElement {
}); });
} }
//根据配置将脚本放置在私有脚本之后 //根据配置将脚本放置在私有脚本之后
JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.JDBC.name(), enviromentId, config, true); JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.JDBC.name(), environmentId, config, true);
} }
@ -239,7 +244,7 @@ public class MsJDBCSampler extends MsTestElement {
return ""; return "";
} }
private void setRefElement() { private boolean setRefElement() {
try { try {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@ -278,11 +283,12 @@ public class MsJDBCSampler extends MsTestElement {
this.setVariableNames(proxy.getVariableNames()); this.setVariableNames(proxy.getVariableNames());
this.setResultVariable(proxy.getResultVariable()); this.setResultVariable(proxy.getResultVariable());
this.setQueryTimeout(proxy.getQueryTimeout()); this.setQueryTimeout(proxy.getQueryTimeout());
return true;
} }
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex); LogUtil.error(ex);
} }
return false;
} }
private EnvironmentConfig initDataSource() { private EnvironmentConfig initDataSource() {

View File

@ -28,6 +28,7 @@ import io.metersphere.commons.utils.LogUtil;
import io.metersphere.jmeter.utils.ScriptEngineUtils; import io.metersphere.jmeter.utils.ScriptEngineUtils;
import io.metersphere.plugin.core.MsParameter; import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.utils.LoggerUtil;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -123,7 +124,11 @@ public class MsTCPSampler extends MsTestElement {
return; return;
} }
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.setRefElement(); boolean ref = this.setRefElement();
if (!ref) {
LoggerUtil.debug("引用对象已经被删除:" + this.getId());
return;
}
hashTree = this.getHashTree(); hashTree = this.getHashTree();
} }
if (config.getConfig() == null) { if (config.getConfig() == null) {
@ -154,7 +159,7 @@ public class MsTCPSampler extends MsTestElement {
//增加误报全局断言 //增加误报全局断言
if (envConfig != null) { if (envConfig != null) {
if (envConfig.isUseErrorCode()) { if (envConfig.isUseErrorCode()) {
List<MsAssertions> errorReportAssertion =HashTreeUtil.getErrorReportByProjectId(this.getProjectId()); List<MsAssertions> errorReportAssertion = HashTreeUtil.getErrorReportByProjectId(this.getProjectId());
for (MsAssertions assertion : errorReportAssertion) { for (MsAssertions assertion : errorReportAssertion) {
assertion.toHashTree(samplerHashTree, assertion.getHashTree(), config); assertion.toHashTree(samplerHashTree, assertion.getHashTree(), config);
} }
@ -167,12 +172,12 @@ public class MsTCPSampler extends MsTestElement {
} }
//处理全局前后置脚本(步骤内) //处理全局前后置脚本(步骤内)
String enviromentId = this.getEnvironmentId(); String environmentId = this.getEnvironmentId();
if (enviromentId == null) { if (environmentId == null) {
enviromentId = this.useEnvironment; environmentId = this.useEnvironment;
} }
//根据配置将脚本放置在私有脚本之前 //根据配置将脚本放置在私有脚本之前
JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), enviromentId, config, false); JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), environmentId, config, false);
HashTreeUtil hashTreeUtil = new HashTreeUtil(); HashTreeUtil hashTreeUtil = new HashTreeUtil();
@ -187,23 +192,10 @@ public class MsTCPSampler extends MsTestElement {
}); });
} }
//根据配置将脚本放置在私有脚本之后 //根据配置将脚本放置在私有脚本之后
JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), enviromentId, config, true); JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), environmentId, config, true);
} }
private void addItemHashTree(MsTestElement element, HashTree samplerHashTree, ParameterConfig config) { private boolean setRefElement() {
if (element != null) {
if (element.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
element.setEnvironmentId(useEnvironment);
} else {
element.setEnvironmentId(this.getEnvironmentId());
}
}
element.toHashTree(samplerHashTree, element.getHashTree(), config);
}
}
private void setRefElement() {
try { try {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@ -239,11 +231,12 @@ public class MsTCPSampler extends MsTestElement {
this.setServer(proxy.getServer()); this.setServer(proxy.getServer());
this.setPort(proxy.getPort()); this.setPort(proxy.getPort());
this.setRequest(proxy.getRequest()); this.setRequest(proxy.getRequest());
return true;
} }
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex); LogUtil.error(ex);
} }
return false;
} }
private void parseEnvironment(EnvironmentConfig config) { private void parseEnvironment(EnvironmentConfig config) {

View File

@ -9,6 +9,8 @@ import io.metersphere.api.dto.automation.parse.ScenarioImport;
import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory; import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory;
import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.datacount.ApiMethodUrlDTO; import io.metersphere.api.dto.datacount.ApiMethodUrlDTO;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.ApiTestCaseInfo;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*; import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
@ -39,7 +41,10 @@ import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails; import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.api.AutomationReference; import io.metersphere.log.vo.api.AutomationReference;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.*; import io.metersphere.service.EnvironmentGroupProjectService;
import io.metersphere.service.QuotaService;
import io.metersphere.service.RelationshipEdgeService;
import io.metersphere.service.ScheduleService;
import io.metersphere.track.dto.TestPlanDTO; import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest;
@ -166,10 +171,10 @@ public class ApiAutomationService {
return list; return list;
} }
public List<ApiScenarioWithBLOBs> listAll(ApiScenarioBatchRequest request) { public List<ApiScenarioDTO> listAll(ApiScenarioBatchRequest request) {
ServiceUtils.getSelectAllIds(request, request.getCondition(), ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiScenarioMapper.selectIdsByQuery(query)); (query) -> extApiScenarioMapper.selectIdsByQuery(query));
List<ApiScenarioWithBLOBs> list = extApiScenarioMapper.selectIds(request.getIds()); List<ApiScenarioDTO> list = extApiScenarioMapper.selectIds(request.getIds());
return list; return list;
} }
@ -675,25 +680,84 @@ public class ApiAutomationService {
return scenarioWithBLOBs; return scenarioWithBLOBs;
} }
private final static List<String> requests = new ArrayList<String>() {{
this.add("HTTPSamplerProxy");
this.add("DubboSampler");
this.add("JDBCSampler");
this.add("TCPSampler");
}};
private void setElement(JSONObject element, Integer num, boolean enable, String versionName, boolean versionEnable) {
element.put("num", num);
element.put("enable", enable);
element.put("versionName", versionName);
element.put("versionEnable", versionEnable);
}
private JSONObject setRequest(JSONObject element) {
boolean enable = element.getBoolean("enable");
boolean isExist = false;
if (StringUtils.equalsIgnoreCase(element.getString("refType"), "CASE")) {
ApiTestCaseInfo apiTestCase = apiTestCaseService.get(element.getString("id"));
if (apiTestCase != null) {
JSONObject refElement = JSON.parseObject(apiTestCase.getRequest());
ElementUtil.dataFormatting(refElement);
if (refElement.get("hashTree") != null && StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
ElementUtil.mergeHashTree(element, refElement.getJSONArray("hashTree"));
element.put("referenced", "REF");
element.put("name", apiTestCase.getName());
} else {
element = refElement;
}
isExist = true;
this.setElement(element, apiTestCase.getNum(), enable, apiTestCase.getVersionName(), apiTestCase.getVersionEnable());
}
} else {
ApiDefinitionResult definitionWithBLOBs = apiDefinitionService.getById(element.getString("id"));
if (definitionWithBLOBs != null) {
this.setElement(element, definitionWithBLOBs.getNum(), enable, definitionWithBLOBs.getVersionName(), definitionWithBLOBs.getVersionEnable());
isExist = true;
}
}
if (!isExist) {
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element.put("enable", false);
}
element.put("num", "");
}
return element;
}
private JSONObject setRefScenario(JSONObject element) {
boolean enable = element.getBoolean("enable");
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.getString("id"));
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) {
boolean environmentEnable = element.getBoolean("environmentEnable");
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
element.put("referenced", "REF");
element.put("name", scenarioWithBLOBs.getName());
}
element.put("environmentEnable", environmentEnable);
this.setElement(element, scenarioWithBLOBs.getNum(), enable, scenarioWithBLOBs.getVersionName(), scenarioWithBLOBs.getVersionEnable());
} else {
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element.put("enable", false);
}
element.put("num", "");
}
return element;
}
public void dataFormatting(JSONArray hashTree) { public void dataFormatting(JSONArray hashTree) {
for (int i = 0; i < hashTree.size(); i++) { for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i); JSONObject element = hashTree.getJSONObject(i);
if (element != null && StringUtils.equalsIgnoreCase(element.getString("type"), "scenario")) { if (element != null && StringUtils.equalsIgnoreCase(element.getString("type"), "scenario")) {
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.getString("id")); element = this.setRefScenario(element);
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) { hashTree.set(i, element);
boolean enable = element.getBoolean("enable"); } else if (element != null && requests.contains(element.getString("type"))) {
boolean environmentEnable = element.getBoolean("environmentEnable"); element = this.setRequest(element);
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) { hashTree.set(i, element);
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
element.put("referenced", "REF");
}
element.put("num", scenarioWithBLOBs.getNum());
element.put("enable", enable);
element.put("environmentEnable", environmentEnable);
element.put("versionName", scenarioWithBLOBs.getVersionName());
element.put("versionEnable", scenarioWithBLOBs.getVersionEnable());
hashTree.set(i, element);
}
} }
if (element.containsKey("hashTree")) { if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree"); JSONArray elementJSONArray = element.getJSONArray("hashTree");
@ -704,20 +768,9 @@ public class ApiAutomationService {
public void dataFormatting(JSONObject element) { public void dataFormatting(JSONObject element) {
if (element != null && StringUtils.equalsIgnoreCase(element.getString("type"), "scenario")) { if (element != null && StringUtils.equalsIgnoreCase(element.getString("type"), "scenario")) {
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.getString("id")); element = this.setRefScenario(element);
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) { } else if (element != null && requests.contains(element.getString("type"))) {
boolean enable = element.getBoolean("enable"); element = this.setRequest(element);
boolean environmentEnable = element.getBoolean("environmentEnable");
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
element.put("referenced", "REF");
}
element.put("enable", enable);
element.put("environmentEnable", environmentEnable);
element.put("num", scenarioWithBLOBs.getNum());
element.put("versionName", scenarioWithBLOBs.getVersionName());
element.put("versionEnable", scenarioWithBLOBs.getVersionEnable());
}
} }
if (element != null && element.containsKey("hashTree")) { if (element != null && element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree"); JSONArray elementJSONArray = element.getJSONArray("hashTree");
@ -761,7 +814,7 @@ public class ApiAutomationService {
} }
public List<ApiScenarioWithBLOBs> getApiScenarios(List<String> ids) { public List<ApiScenarioDTO> getApiScenarios(List<String> ids) {
if (CollectionUtils.isNotEmpty(ids)) { if (CollectionUtils.isNotEmpty(ids)) {
return extApiScenarioMapper.selectIds(ids); return extApiScenarioMapper.selectIds(ids);
} }
@ -1050,9 +1103,8 @@ public class ApiAutomationService {
} }
public JmxInfoDTO genPerformanceTestJmx(GenScenarioRequest request) { public JmxInfoDTO genPerformanceTestJmx(GenScenarioRequest request) {
List<ApiScenarioWithBLOBs> apiScenarios = null;
List<String> ids = request.getIds(); List<String> ids = request.getIds();
apiScenarios = extApiScenarioMapper.selectIds(ids); List<ApiScenarioDTO> apiScenarios = extApiScenarioMapper.selectIds(ids);
String testName = ""; String testName = "";
String id = ""; String id = "";
if (!apiScenarios.isEmpty()) { if (!apiScenarios.isEmpty()) {
@ -1821,7 +1873,7 @@ public class ApiAutomationService {
List<JmxInfoDTO> returnList = new ArrayList<>(); List<JmxInfoDTO> returnList = new ArrayList<>();
List<String> ids = request.getIds(); List<String> ids = request.getIds();
List<ApiScenarioWithBLOBs> apiScenarioList = extApiScenarioMapper.selectIds(ids); List<ApiScenarioDTO> apiScenarioList = extApiScenarioMapper.selectIds(ids);
if (CollectionUtils.isEmpty(apiScenarioList)) { if (CollectionUtils.isEmpty(apiScenarioList)) {
return returnList; return returnList;
} else { } else {
@ -1845,7 +1897,7 @@ public class ApiAutomationService {
(query) -> extApiScenarioMapper.selectIdsByQuery(query)); (query) -> extApiScenarioMapper.selectIdsByQuery(query));
List<String> ids = request.getIds(); List<String> ids = request.getIds();
if (CollectionUtils.isEmpty(ids)) return; if (CollectionUtils.isEmpty(ids)) return;
List<ApiScenarioWithBLOBs> apiScenarioList = extApiScenarioMapper.selectIds(ids); List<ApiScenarioDTO> apiScenarioList = extApiScenarioMapper.selectIds(ids);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class); ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class);
Long nextOrder = ServiceUtils.getNextOrder(request.getProjectId(), extApiScenarioMapper::getLastOrder); Long nextOrder = ServiceUtils.getNextOrder(request.getProjectId(), extApiScenarioMapper::getLastOrder);

View File

@ -89,12 +89,12 @@
<select id="selectByIds" resultType="io.metersphere.api.dto.definition.ApiComputeResult"> <select id="selectByIds" resultType="io.metersphere.api.dto.definition.ApiComputeResult">
SELECT t1.api_definition_id apiDefinitionId,count(t1.id) caseTotal, SELECT t1.api_definition_id apiDefinitionId,count(t1.id) caseTotal,
SUM(case when t2.status ='success' then 1 else 0 end) as success ,SUM(case when t2.status ='error' then 1 else 0 end) as error, SUM(case when t2.status ='success' then 1 else 0 end) as success ,SUM(case when t2.status ='error' then 1 else 0 end) as error,
CONCAT(FORMAT(SUM(IF (t2.`status`='success',1,0))/COUNT(t1.id)*100,2),'%') passRate CONCAT(FORMAT(SUM(IF (t2.`status`='success',1,0))/COUNT(t1.id)*100,2),'%') passRate
FROM api_test_case t1 FROM api_test_case t1
LEFT JOIN api_definition_exec_result t2 ON t1.last_result_id=t2.id LEFT JOIN api_definition_exec_result t2 ON t1.last_result_id=t2.id
WHERE t1.project_id = #{projectId} WHERE t1.project_id = #{projectId}
group by t1.api_definition_id having t1.api_definition_id in group by t1.api_definition_id having t1.api_definition_id in
<foreach collection="ids" item="v" separator="," open="(" close=")"> <foreach collection="ids" item="v" separator="," open="(" close=")">
#{v} #{v}
</foreach> </foreach>
@ -182,9 +182,9 @@
<if test='${condition}.tags != null and ${objectKey}.operator == "not like"'> <if test='${condition}.tags != null and ${objectKey}.operator == "not like"'>
and (api_definition.tags is null or api_definition.tags and (api_definition.tags is null or api_definition.tags
<include refid="condition"> <include refid="condition">
<property name="object" value="${condition}.tags"/> <property name="object" value="${condition}.tags"/>
</include> </include>
) )
</if> </if>
<if test='${condition}.tags != null and ${objectKey}.operator == "like"'> <if test='${condition}.tags != null and ${objectKey}.operator == "like"'>
@ -297,10 +297,13 @@
api_definition.description,api_definition.request,api_definition.response,api_definition.environment_id, api_definition.description,api_definition.request,api_definition.response,api_definition.environment_id,
api_definition.status, api_definition.user_id, api_definition.create_time, api_definition.update_time, api_definition.status, api_definition.user_id, api_definition.create_time, api_definition.update_time,
project.name as project.name as
project_name, user.name as user_name project_name, user.name as user_name,
api_definition.version_id versionId,
project_version.name versionName,project.version_enable
from api_definition from api_definition
left join project on api_definition.project_id = project.id left join project on api_definition.project_id = project.id
left join user on api_definition.user_id = user.id left join user on api_definition.user_id = user.id
left join project_version on api_definition.project_id = project_version.project_id and api_definition.version_id = project_version.id
WHERE api_definition.id IN WHERE api_definition.id IN
<foreach collection="ids" item="v" separator="," open="(" close=")"> <foreach collection="ids" item="v" separator="," open="(" close=")">
#{v} #{v}
@ -320,7 +323,7 @@
set original_state=status, set original_state=status,
status = 'Trash', delete_user_id = #{operator},delete_time = #{operationTime} status = 'Trash', delete_user_id = #{operator},delete_time = #{operationTime}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Example_Where_Clause" /> <include refid="Example_Where_Clause"/>
</if> </if>
</update> </update>
@ -409,7 +412,7 @@
<if test="request.name != null"> <if test="request.name != null">
and (api_definition.name like CONCAT('%', #{request.name},'%') and (api_definition.name like CONCAT('%', #{request.name},'%')
or api_definition.num like CONCAT('%', #{request.name},'%') or api_definition.num like CONCAT('%', #{request.name},'%')
) )
</if> </if>
<if test="request.protocol != null"> <if test="request.protocol != null">
@ -748,11 +751,11 @@
<if test="request.versionId == null and request.refId == null and request.id == null"> <if test="request.versionId == null and request.refId == null and request.id == null">
AND ( AND (
version_id = (SELECT project_version.id version_id = (SELECT project_version.id
FROM api_definition tmp FROM api_definition tmp
JOIN project_version JOIN project_version
ON tmp.project_id = project_version.project_id AND tmp.version_id = project_version.id AND latest = TRUE ON tmp.project_id = project_version.project_id AND tmp.version_id = project_version.id AND latest = TRUE
WHERE ref_id = api_definition.ref_id WHERE ref_id = api_definition.ref_id
LIMIT 1) LIMIT 1)
OR OR
version_id = (SELECT project_version.id version_id = (SELECT project_version.id
FROM api_definition tmp FROM api_definition tmp
@ -826,7 +829,7 @@
and t3.`status`!='Trash' and t3.`status`!='Trash'
</select> </select>
<select id="countByIds" resultType="java.lang.Integer"> <select id="countByIds" resultType="java.lang.Integer">
select count(id) from api_definition select count(id) from api_definition
where id in where id in
<foreach collection="ids" item="id" separator="," open="(" close=")"> <foreach collection="ids" item="id" separator="," open="(" close=")">
#{id} #{id}
@ -837,7 +840,7 @@
<select id="countByExample" parameterType="io.metersphere.base.domain.ApiDefinitionExample" resultType="java.lang.Long"> <select id="countByExample" parameterType="io.metersphere.base.domain.ApiDefinitionExample" resultType="java.lang.Long">
select count(DISTINCT ref_id) from api_definition select count(DISTINCT ref_id) from api_definition
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="io.metersphere.base.mapper.ApiDefinitionMapper.Example_Where_Clause" /> <include refid="io.metersphere.base.mapper.ApiDefinitionMapper.Example_Where_Clause"/>
</if> </if>
</select> </select>
</mapper> </mapper>

View File

@ -23,7 +23,7 @@ public interface ExtApiScenarioMapper {
List<ApiScenarioWithBLOBs> selectByTagId(@Param("id") String id); List<ApiScenarioWithBLOBs> selectByTagId(@Param("id") String id);
List<ApiScenarioWithBLOBs> selectIds(@Param("ids") List<String> ids); List<ApiScenarioDTO> selectIds(@Param("ids") List<String> ids);
int selectTrash(@Param("projectId") String projectId); int selectTrash(@Param("projectId") String projectId);

View File

@ -351,8 +351,12 @@
select * from api_scenario where tags like CONCAT('%', #{id},'%') select * from api_scenario where tags like CONCAT('%', #{id},'%')
</select> </select>
<select id="selectIds" resultType="io.metersphere.base.domain.ApiScenarioWithBLOBs"> <select id="selectIds" resultType="io.metersphere.api.dto.automation.ApiScenarioDTO">
select * from api_scenario where id in select api_scenario.*, project_version.name as version_name, project.version_enable
from api_scenario
LEFT JOIN project_version on project_version.project_id = api_scenario.project_id and project_version.id = version_id
LEFT JOIN project on api_scenario.project_id = project.id
WHERE api_scenario.id in
<foreach collection="ids" item="v" separator="," open="(" close=")"> <foreach collection="ids" item="v" separator="," open="(" close=")">
#{v} #{v}
</foreach> </foreach>

View File

@ -600,9 +600,11 @@
</if> </if>
</select> </select>
<select id="getCaseInfo" resultType="io.metersphere.api.dto.definition.ApiTestCaseInfo"> <select id="getCaseInfo" resultType="io.metersphere.api.dto.definition.ApiTestCaseInfo">
select t1.*,a.method AS apiMethod select t1.*,a.method AS apiMethod,project_version.name as version_name, project.version_enable
from api_test_case t1 from api_test_case t1
inner join api_definition a on t1.api_definition_id = a.id inner join api_definition a on t1.api_definition_id = a.id
LEFT JOIN project ON t1.project_id = project.id
LEFT JOIN project_version on a.project_id = project_version.project_id AND project_version.id = t1.version_id
where 1 where 1
<if test="request.id != null and request.id!=''"> <if test="request.id != null and request.id!=''">
and t1.id = #{request.id} and t1.id = #{request.id}

View File

@ -1132,6 +1132,10 @@ export default {
request.active = false; request.active = false;
request.resourceId = getUUID(); request.resourceId = getUUID();
request.projectId = item.projectId; request.projectId = item.projectId;
request.num = item.num;
request.versionEnable = item.versionEnable;
request.versionId = item.versionId;
request.versionName = item.versionName;
request.requestResult = []; request.requestResult = [];
if (!request.url) { if (!request.url) {
request.url = ""; request.url = "";

View File

@ -115,7 +115,10 @@ export default {
referenced: referenced, referenced: referenced,
resourceId: getUUID(), resourceId: getUUID(),
hashTree: scenarioDefinition.hashTree, hashTree: scenarioDefinition.hashTree,
projectId: item.projectId projectId: item.projectId,
num: item.num,
versionName: item.versionName,
versionEnable: item.versionEnable
}; };
scenarios.push(obj); scenarios.push(obj);
} }

View File

@ -22,7 +22,7 @@
<i class="el-icon-warning"/> <i class="el-icon-warning"/>
</el-tooltip> </el-tooltip>
</span> </span>
<span v-xpack v-if="request.versionEnable&&showVersion">{{$t('project.version.name')}}: {{ request.versionName }}</span> <span v-xpack v-if="request.versionEnable&&showVersion">{{ $t('project.version.name') }}: {{ request.versionName }}</span>
</template> </template>
<template v-slot:behindHeaderLeft> <template v-slot:behindHeaderLeft>
@ -57,39 +57,39 @@
<legend style="width: 100%"> <legend style="width: 100%">
<div v-if="!ifFromVariableAdvance"> <div v-if="!ifFromVariableAdvance">
<customize-req-info :is-customize-req="isCustomizeReq" :request="request" @setDomain="setDomain"/> <customize-req-info :is-customize-req="isCustomizeReq" :request="request" @setDomain="setDomain"/>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p> <p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form <ms-api-request-form
v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'" v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
:scenario-definition="scenarioDefinition" :scenario-definition="scenarioDefinition"
@editScenarioAdvance="editScenarioAdvance" @editScenarioAdvance="editScenarioAdvance"
:isShowEnable="true" :isShowEnable="true"
:referenced="true" :referenced="true"
:headers="request.headers " :headers="request.headers "
:is-read-only="isCompReadOnly" :is-read-only="isCompReadOnly"
:request="request"/> :request="request"/>
<esb-definition <esb-definition
v-if="showXpackCompnent&&request.esbDataStruct!=null" v-if="showXpackCompnent&&request.esbDataStruct!=null"
v-xpack v-xpack
:request="request" :request="request"
:showScript="false" :showScript="false"
:is-read-only="isCompReadOnly" ref="esbDefinition"/> :is-read-only="isCompReadOnly" ref="esbDefinition"/>
<ms-tcp-format-parameters <ms-tcp-format-parameters
v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null " v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "
:is-read-only="isCompReadOnly" :is-read-only="isCompReadOnly"
:show-script="false" :request="request"/> :show-script="false" :request="request"/>
<ms-sql-basis-parameters <ms-sql-basis-parameters
v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'" v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
:request="request" :request="request"
:is-read-only="isCompReadOnly" :is-read-only="isCompReadOnly"
:showScript="false"/> :showScript="false"/>
<ms-dubbo-basis-parameters <ms-dubbo-basis-parameters
v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'" v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
:request="request" :request="request"
:is-read-only="isCompReadOnly" :is-read-only="isCompReadOnly"
:showScript="false"/> :showScript="false"/>
</div> </div>
</legend> </legend>
@ -228,11 +228,13 @@ export default {
this.request.projectId = getCurrentProjectID(); this.request.projectId = getCurrentProjectID();
} }
this.request.customizeReq = this.isCustomizeReq; this.request.customizeReq = this.isCustomizeReq;
if (this.request.num) { if (this.request.num) {
this.isShowNum = true; this.isShowNum = true;
this.getWorkspaceId(this.request.projectId);
} else {
this.isShowNum = false;
} }
//
this.getApiInfo();
if (this.request.protocol === 'HTTP') { if (this.request.protocol === 'HTTP') {
this.setUrl(this.request.url); this.setUrl(this.request.url);
this.setUrl(this.request.path); this.setUrl(this.request.path);

View File

@ -121,7 +121,7 @@ export default {
this.isShowNum = true; this.isShowNum = true;
this.getWorkspaceId(this.scenario.projectId); this.getWorkspaceId(this.scenario.projectId);
} else { } else {
this.isSameSpace = false; this.isShowNum = false;
} }
if (!this.scenario.projectId) { if (!this.scenario.projectId) {
this.scenario.projectId = getCurrentProjectID(); this.scenario.projectId = getCurrentProjectID();