From c16df086168d83ec1fdcca7749ee7cc93ea68623 Mon Sep 17 00:00:00 2001 From: song-tianyang Date: Tue, 13 Jul 2021 17:50:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96,=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=89=8D=E5=90=8E=E7=BD=AESQL=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --story=1001742 --user=宋天阳 增加前后置SQL请求步骤 https://www.tapd.cn/55049933/s/1025292 --- .../dto/definition/request/MsTestElement.java | 6 +- .../processors/post/MsJDBCPostProcessor.java | 283 ++++++++++++++++++ .../processors/pre/MsJDBCPreProcessor.java | 283 ++++++++++++++++++ .../api/automation/scenario/Setting.js | 24 +- .../scenario/common/JDBCProcessorContent.vue | 272 +++++++++++++++++ .../scenario/component/ComponentConfig.vue | 19 +- .../scenario/component/JDBCProcessor.vue | 90 ++++++ .../api/automation/scenario/menu/Menu.js | 30 +- .../jdbc-post-processor/index.js | 38 +++ .../jdbc-pre-processor/index.js | 38 +++ .../components/ApiDefinitionStepButton.vue | 32 +- .../request/database/BasisParameters.vue | 12 + .../definition/components/step/JmxStep.vue | 10 + .../api/definition/model/ApiTestModel.js | 15 + frontend/src/i18n/en-US.js | 2 + frontend/src/i18n/zh-CN.js | 2 + frontend/src/i18n/zh-TW.js | 2 + 17 files changed, 1143 insertions(+), 15 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJDBCPostProcessor.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJDBCPreProcessor.java create mode 100644 frontend/src/business/components/api/automation/scenario/common/JDBCProcessorContent.vue create mode 100644 frontend/src/business/components/api/automation/scenario/component/JDBCProcessor.vue create mode 100644 frontend/src/business/components/api/definition/components/jmeter/components/post-processors/jdbc-post-processor/index.js create mode 100644 frontend/src/business/components/api/definition/components/jmeter/components/pre-processors/jdbc-pre-processor/index.js diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java index 9d5078f9d7..a9d9765027 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java @@ -13,7 +13,9 @@ import io.metersphere.api.dto.definition.request.controller.MsLoopController; import io.metersphere.api.dto.definition.request.controller.MsTransactionController; import io.metersphere.api.dto.definition.request.extract.MsExtract; import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor; +import io.metersphere.api.dto.definition.request.processors.post.MsJDBCPostProcessor; import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor; +import io.metersphere.api.dto.definition.request.processors.pre.MsJDBCPreProcessor; import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; import io.metersphere.api.dto.definition.request.sampler.MsDubboSampler; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; @@ -59,6 +61,8 @@ import java.util.stream.Collectors; @JsonSubTypes.Type(value = MsJSR223Processor.class, name = "JSR223Processor"), @JsonSubTypes.Type(value = MsJSR223PostProcessor.class, name = "JSR223PostProcessor"), @JsonSubTypes.Type(value = MsJSR223PreProcessor.class, name = "JSR223PreProcessor"), + @JsonSubTypes.Type(value = MsJDBCPreProcessor.class, name = "JDBCPreProcessor"), + @JsonSubTypes.Type(value = MsJDBCPostProcessor.class, name = "JDBCPostProcessor"), @JsonSubTypes.Type(value = MsTestPlan.class, name = "TestPlan"), @JsonSubTypes.Type(value = MsThreadGroup.class, name = "ThreadGroup"), @JsonSubTypes.Type(value = MsAuthManager.class, name = "AuthManager"), @@ -75,7 +79,7 @@ import java.util.stream.Collectors; @JsonSubTypes.Type(value = MsJmeterElement.class, name = "JmeterElement"), }) -@JSONType(seeAlso = {MsHTTPSamplerProxy.class, MsHeaderManager.class, MsJSR223Processor.class, MsJSR223PostProcessor.class, +@JSONType(seeAlso = {MsHTTPSamplerProxy.class, MsHeaderManager.class, MsJSR223Processor.class, MsJSR223PostProcessor.class, MsJDBCPreProcessor.class, MsJDBCPostProcessor.class, MsJSR223PreProcessor.class, MsTestPlan.class, MsThreadGroup.class, MsAuthManager.class, MsAssertions.class, MsExtract.class, MsTCPSampler.class, MsDubboSampler.class, MsJDBCSampler.class, MsConstantTimer.class, MsIfController.class, MsTransactionController.class, MsScenario.class, MsLoopController.class, MsJmeterElement.class}, typeKey = "type") @Data diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJDBCPostProcessor.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJDBCPostProcessor.java new file mode 100644 index 0000000000..20b707d325 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJDBCPostProcessor.java @@ -0,0 +1,283 @@ +package io.metersphere.api.dto.definition.request.processors.post; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson.annotation.JSONType; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; +import io.metersphere.api.dto.scenario.DatabaseConfig; +import io.metersphere.api.dto.scenario.KeyValue; +import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.service.ApiDefinitionService; +import io.metersphere.api.service.ApiTestCaseService; +import io.metersphere.api.service.ApiTestEnvironmentService; +import io.metersphere.base.domain.ApiDefinitionWithBLOBs; +import io.metersphere.base.domain.ApiTestCaseWithBLOBs; +import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; +import io.metersphere.commons.constants.DelimiterConstants; +import io.metersphere.commons.constants.MsTestElementConstants; +import io.metersphere.commons.constants.RunModeConstants; +import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.CommonBeanFactory; +import io.metersphere.commons.utils.LogUtil; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.jmeter.config.Arguments; +import org.apache.jmeter.protocol.jdbc.config.DataSourceElement; +import org.apache.jmeter.protocol.jdbc.processor.JDBCPostProcessor; +import org.apache.jmeter.save.SaveService; +import org.apache.jmeter.testelement.TestElement; +import org.apache.jorphan.collections.HashTree; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author song.tianyang + * @Date 2021/7/13 11:08 上午 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@JSONType(typeName = "JDBCPostProcessor") +public class MsJDBCPostProcessor extends MsTestElement { + // type 必须放最前面,以便能够转换正确的类 + private String type = "JDBCPostProcessor"; + @JSONField(ordinal = 20) + private DatabaseConfig dataSource; + @JSONField(ordinal = 21) + private String query; + @JSONField(ordinal = 22) + private long queryTimeout; + @JSONField(ordinal = 23) + private String resultVariable; + @JSONField(ordinal = 24) + private String variableNames; + @JSONField(ordinal = 25) + private List variables; + @JSONField(ordinal = 26) + private String environmentId; + @JSONField(ordinal = 28) + private String dataSourceId; + @JSONField(ordinal = 29) + private String protocol = "SQL"; + + @JSONField(ordinal = 30) + private String useEnvironment; + + @Override + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { + // 非导出操作,且不是启用状态则跳过执行 + if (!config.isOperating() && !this.isEnable()) { + return; + } + if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { + this.setRefElement(); + } + if (config.getConfig() == null) { + // 单独接口执行 + this.setProjectId(config.getProjectId()); + config.setConfig(getEnvironmentConfig(StringUtils.isNotEmpty(useEnvironment) ? useEnvironment : environmentId)); + } + + // 数据兼容处理 + if (config.getConfig() != null && StringUtils.isNotEmpty(this.getProjectId()) && config.getConfig().containsKey(this.getProjectId())) { + // 1.8 之后 当前正常数据 + } else if (config.getConfig() != null && config.getConfig().containsKey(getParentProjectId())) { + // 1.8 前后 混合数据 + this.setProjectId(getParentProjectId()); + } else { + // 1.8 之前 数据 + if (config.getConfig() != null) { + if (config.getConfig().containsKey(RunModeConstants.HIS_PRO_ID.toString())) { + this.setProjectId(RunModeConstants.HIS_PRO_ID.toString()); + } else { + // 测试计划执行 + Iterator it = config.getConfig().keySet().iterator(); + if (it.hasNext()) { + this.setProjectId(it.next()); + } + } + } + } + //如果当前数据源为null,则获取已选环境的数据源 + if(this.dataSource == null){ + // 自选了数据源 + if (config.isEffective(this.getProjectId()) && CollectionUtils.isNotEmpty(config.getConfig().get(this.getProjectId()).getDatabaseConfigs()) + && isDataSource(config.getConfig().get(this.getProjectId()).getDatabaseConfigs())) { + this.initDataSource(); + } else { + // 取当前环境下默认的一个数据源 + if (config.isEffective(this.getProjectId()) && CollectionUtils.isNotEmpty(config.getConfig().get(this.getProjectId()).getDatabaseConfigs())) { + this.dataSource = config.getConfig().get(this.getProjectId()).getDatabaseConfigs().get(0); + } + } + } + if (this.dataSource == null) { + // 用自身的数据 + if (StringUtils.isNotEmpty(dataSourceId)) { + this.dataSource = null; + this.initDataSource(); + } + if (this.dataSource == null) { + MSException.throwException("数据源为空无法执行"); + } + } + final HashTree samplerHashTree = tree.add(jdbcPostProcessor(config)); + tree.add(jdbcDataSource()); + Arguments arguments = arguments(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "Arguments", this.getVariables()); + if (arguments != null) { + tree.add(arguments); + } + if (CollectionUtils.isNotEmpty(hashTree)) { + hashTree.forEach(el -> { + el.toHashTree(samplerHashTree, el.getHashTree(), config); + }); + } + } + + private boolean isDataSource(List databaseConfigs) { + List ids = databaseConfigs.stream().map(DatabaseConfig::getId).collect(Collectors.toList()); + if (StringUtils.isNotEmpty(this.dataSourceId) && ids.contains(this.dataSourceId)) { + return true; + } + return false; + } + + private String getParentProjectId() { + MsTestElement parent = this.getParent(); + while (parent != null) { + if (StringUtils.isNotBlank(parent.getProjectId())) { + return parent.getProjectId(); + } + parent = parent.getParent(); + } + return ""; + } + + private void setRefElement() { + try { + ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + MsJDBCPostProcessor proxy = null; + if (StringUtils.equals(this.getRefType(), "CASE")) { + ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class); + ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId()); + if (bloBs != null) { + this.setName(bloBs.getName()); + this.setProjectId(bloBs.getProjectId()); + proxy = mapper.readValue(bloBs.getRequest(), new TypeReference() { + }); + } + } else { + ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId()); + if (apiDefinition != null) { + this.setProjectId(apiDefinition.getProjectId()); + proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference() { + }); + this.setName(apiDefinition.getName()); + } + } + if (proxy != null) { + this.setHashTree(proxy.getHashTree()); + this.setDataSource(proxy.getDataSource()); + this.setDataSourceId(proxy.getDataSourceId()); + this.setQuery(proxy.getQuery()); + this.setVariables(proxy.getVariables()); + this.setVariableNames(proxy.getVariableNames()); + this.setResultVariable(proxy.getResultVariable()); + this.setQueryTimeout(proxy.getQueryTimeout()); + } + } catch (Exception ex) { + ex.printStackTrace(); + LogUtil.error(ex.getMessage()); + } + } + + private void initDataSource() { + ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); + ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId); + if (environment != null && environment.getConfig() != null) { + EnvironmentConfig envConfig = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + if (CollectionUtils.isNotEmpty(envConfig.getDatabaseConfigs())) { + envConfig.getDatabaseConfigs().forEach(item -> { + if (item.getId().equals(this.dataSourceId)) { + this.dataSource = item; + return; + } + }); + } + } + } + + private Arguments arguments(String name, List variables) { + if (CollectionUtils.isNotEmpty(variables)) { + Arguments arguments = new Arguments(); + arguments.setEnabled(true); + arguments.setName(name + "JDBC_Argument"); + arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); + arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); + variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> + arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") + ); + return arguments; + } + return null; + } + + private JDBCPostProcessor jdbcPostProcessor(ParameterConfig config) { + JDBCPostProcessor jdbcPostProcessor = new JDBCPostProcessor(); + jdbcPostProcessor.setEnabled(this.isEnable()); + jdbcPostProcessor.setName(this.getName()); + String name = this.getParentName(this.getParent()); + if (StringUtils.isNotEmpty(name) && !config.isOperating()) { + jdbcPostProcessor.setName(this.getName() + DelimiterConstants.SEPARATOR.toString() + name); + } + jdbcPostProcessor.setProperty(TestElement.TEST_CLASS, JDBCPostProcessor.class.getName()); + jdbcPostProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); + jdbcPostProcessor.setProperty("MS-ID", this.getId()); + List id_names = new LinkedList<>(); + this.getScenarioSet(this, id_names); + jdbcPostProcessor.setProperty("MS-SCENARIO", JSON.toJSONString(id_names)); + + // request.getDataSource() 是ID,需要转换为Name + jdbcPostProcessor.setProperty("dataSource", this.dataSource.getName()); + jdbcPostProcessor.setProperty("query", this.getQuery()); + jdbcPostProcessor.setProperty("queryTimeout", String.valueOf(this.getQueryTimeout())); + jdbcPostProcessor.setProperty("resultVariable", this.getResultVariable()); + jdbcPostProcessor.setProperty("variableNames", this.getVariableNames()); + jdbcPostProcessor.setProperty("resultSetHandler", "Store as String"); + jdbcPostProcessor.setProperty("queryType", "Callable Statement"); + return jdbcPostProcessor; + } + + private DataSourceElement jdbcDataSource() { + DataSourceElement dataSourceElement = new DataSourceElement(); + dataSourceElement.setEnabled(true); + dataSourceElement.setName(this.getName() + " JDBCDataSource"); + dataSourceElement.setProperty(TestElement.TEST_CLASS, DataSourceElement.class.getName()); + dataSourceElement.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); + dataSourceElement.setProperty("autocommit", true); + dataSourceElement.setProperty("keepAlive", true); + dataSourceElement.setProperty("preinit", false); + dataSourceElement.setProperty("dataSource", dataSource.getName()); + dataSourceElement.setProperty("dbUrl", dataSource.getDbUrl()); + dataSourceElement.setProperty("driver", dataSource.getDriver()); + dataSourceElement.setProperty("username", dataSource.getUsername()); + dataSourceElement.setProperty("password", dataSource.getPassword()); + dataSourceElement.setProperty("poolMax", dataSource.getPoolMax()); + dataSourceElement.setProperty("timeout", String.valueOf(dataSource.getTimeout())); + dataSourceElement.setProperty("connectionAge", 5000); + dataSourceElement.setProperty("trimInterval", 6000); + dataSourceElement.setProperty("transactionIsolation", "DEFAULT"); + return dataSourceElement; + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJDBCPreProcessor.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJDBCPreProcessor.java new file mode 100644 index 0000000000..127c458bfc --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJDBCPreProcessor.java @@ -0,0 +1,283 @@ +package io.metersphere.api.dto.definition.request.processors.pre; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson.annotation.JSONType; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; +import io.metersphere.api.dto.scenario.DatabaseConfig; +import io.metersphere.api.dto.scenario.KeyValue; +import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.service.ApiDefinitionService; +import io.metersphere.api.service.ApiTestCaseService; +import io.metersphere.api.service.ApiTestEnvironmentService; +import io.metersphere.base.domain.ApiDefinitionWithBLOBs; +import io.metersphere.base.domain.ApiTestCaseWithBLOBs; +import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; +import io.metersphere.commons.constants.DelimiterConstants; +import io.metersphere.commons.constants.MsTestElementConstants; +import io.metersphere.commons.constants.RunModeConstants; +import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.CommonBeanFactory; +import io.metersphere.commons.utils.LogUtil; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.jmeter.config.Arguments; +import org.apache.jmeter.protocol.jdbc.config.DataSourceElement; +import org.apache.jmeter.protocol.jdbc.processor.JDBCPreProcessor; +import org.apache.jmeter.save.SaveService; +import org.apache.jmeter.testelement.TestElement; +import org.apache.jorphan.collections.HashTree; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author song.tianyang + * @Date 2021/7/13 11:08 上午 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@JSONType(typeName = "JDBCPreProcessor") +public class MsJDBCPreProcessor extends MsTestElement { + // type 必须放最前面,以便能够转换正确的类 + private String type = "JDBCPreProcessor"; + @JSONField(ordinal = 20) + private DatabaseConfig dataSource; + @JSONField(ordinal = 21) + private String query; + @JSONField(ordinal = 22) + private long queryTimeout; + @JSONField(ordinal = 23) + private String resultVariable; + @JSONField(ordinal = 24) + private String variableNames; + @JSONField(ordinal = 25) + private List variables; + @JSONField(ordinal = 26) + private String environmentId; + @JSONField(ordinal = 28) + private String dataSourceId; + @JSONField(ordinal = 29) + private String protocol = "SQL"; + + @JSONField(ordinal = 30) + private String useEnvironment; + + @Override + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { + // 非导出操作,且不是启用状态则跳过执行 + if (!config.isOperating() && !this.isEnable()) { + return; + } + if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { + this.setRefElement(); + } + if (config.getConfig() == null) { + // 单独接口执行 + this.setProjectId(config.getProjectId()); + config.setConfig(getEnvironmentConfig(StringUtils.isNotEmpty(useEnvironment) ? useEnvironment : environmentId)); + } + + // 数据兼容处理 + if (config.getConfig() != null && StringUtils.isNotEmpty(this.getProjectId()) && config.getConfig().containsKey(this.getProjectId())) { + // 1.8 之后 当前正常数据 + } else if (config.getConfig() != null && config.getConfig().containsKey(getParentProjectId())) { + // 1.8 前后 混合数据 + this.setProjectId(getParentProjectId()); + } else { + // 1.8 之前 数据 + if (config.getConfig() != null) { + if (config.getConfig().containsKey(RunModeConstants.HIS_PRO_ID.toString())) { + this.setProjectId(RunModeConstants.HIS_PRO_ID.toString()); + } else { + // 测试计划执行 + Iterator it = config.getConfig().keySet().iterator(); + if (it.hasNext()) { + this.setProjectId(it.next()); + } + } + } + } + //如果当前数据源为null,则获取已选环境的数据源 + if(this.dataSource == null){ + // 自选了数据源 + if (config.isEffective(this.getProjectId()) && CollectionUtils.isNotEmpty(config.getConfig().get(this.getProjectId()).getDatabaseConfigs()) + && isDataSource(config.getConfig().get(this.getProjectId()).getDatabaseConfigs())) { + this.initDataSource(); + } else { + // 取当前环境下默认的一个数据源 + if (config.isEffective(this.getProjectId()) && CollectionUtils.isNotEmpty(config.getConfig().get(this.getProjectId()).getDatabaseConfigs())) { + this.dataSource = config.getConfig().get(this.getProjectId()).getDatabaseConfigs().get(0); + } + } + } + if (this.dataSource == null) { + // 用自身的数据 + if (StringUtils.isNotEmpty(dataSourceId)) { + this.dataSource = null; + this.initDataSource(); + } + if (this.dataSource == null) { + MSException.throwException("数据源为空无法执行"); + } + } + final HashTree samplerHashTree = tree.add(jdbcPreProcessor(config)); + tree.add(jdbcDataSource()); + Arguments arguments = arguments(StringUtils.isNotEmpty(this.getName()) ? this.getName() : "Arguments", this.getVariables()); + if (arguments != null) { + tree.add(arguments); + } + if (CollectionUtils.isNotEmpty(hashTree)) { + hashTree.forEach(el -> { + el.toHashTree(samplerHashTree, el.getHashTree(), config); + }); + } + } + + private boolean isDataSource(List databaseConfigs) { + List ids = databaseConfigs.stream().map(DatabaseConfig::getId).collect(Collectors.toList()); + if (StringUtils.isNotEmpty(this.dataSourceId) && ids.contains(this.dataSourceId)) { + return true; + } + return false; + } + + private String getParentProjectId() { + MsTestElement parent = this.getParent(); + while (parent != null) { + if (StringUtils.isNotBlank(parent.getProjectId())) { + return parent.getProjectId(); + } + parent = parent.getParent(); + } + return ""; + } + + private void setRefElement() { + try { + ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + MsJDBCPreProcessor proxy = null; + if (StringUtils.equals(this.getRefType(), "CASE")) { + ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class); + ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId()); + if (bloBs != null) { + this.setName(bloBs.getName()); + this.setProjectId(bloBs.getProjectId()); + proxy = mapper.readValue(bloBs.getRequest(), new TypeReference() { + }); + } + } else { + ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId()); + if (apiDefinition != null) { + this.setProjectId(apiDefinition.getProjectId()); + proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference() { + }); + this.setName(apiDefinition.getName()); + } + } + if (proxy != null) { + this.setHashTree(proxy.getHashTree()); + this.setDataSource(proxy.getDataSource()); + this.setDataSourceId(proxy.getDataSourceId()); + this.setQuery(proxy.getQuery()); + this.setVariables(proxy.getVariables()); + this.setVariableNames(proxy.getVariableNames()); + this.setResultVariable(proxy.getResultVariable()); + this.setQueryTimeout(proxy.getQueryTimeout()); + } + } catch (Exception ex) { + ex.printStackTrace(); + LogUtil.error(ex.getMessage()); + } + } + + private void initDataSource() { + ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); + ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId); + if (environment != null && environment.getConfig() != null) { + EnvironmentConfig envConfig = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + if (CollectionUtils.isNotEmpty(envConfig.getDatabaseConfigs())) { + envConfig.getDatabaseConfigs().forEach(item -> { + if (item.getId().equals(this.dataSourceId)) { + this.dataSource = item; + return; + } + }); + } + } + } + + private Arguments arguments(String name, List variables) { + if (CollectionUtils.isNotEmpty(variables)) { + Arguments arguments = new Arguments(); + arguments.setEnabled(true); + arguments.setName(name + "JDBC_Argument"); + arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); + arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); + variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> + arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") + ); + return arguments; + } + return null; + } + + private JDBCPreProcessor jdbcPreProcessor(ParameterConfig config) { + JDBCPreProcessor jdbcPreProcessor = new JDBCPreProcessor(); + jdbcPreProcessor.setEnabled(this.isEnable()); + jdbcPreProcessor.setName(this.getName()); + String name = this.getParentName(this.getParent()); + if (StringUtils.isNotEmpty(name) && !config.isOperating()) { + jdbcPreProcessor.setName(this.getName() + DelimiterConstants.SEPARATOR.toString() + name); + } + jdbcPreProcessor.setProperty(TestElement.TEST_CLASS, JDBCPreProcessor.class.getName()); + jdbcPreProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); + jdbcPreProcessor.setProperty("MS-ID", this.getId()); + List id_names = new LinkedList<>(); + this.getScenarioSet(this, id_names); + jdbcPreProcessor.setProperty("MS-SCENARIO", JSON.toJSONString(id_names)); + + // request.getDataSource() 是ID,需要转换为Name + jdbcPreProcessor.setProperty("dataSource", this.dataSource.getName()); + jdbcPreProcessor.setProperty("query", this.getQuery()); + jdbcPreProcessor.setProperty("queryTimeout", String.valueOf(this.getQueryTimeout())); + jdbcPreProcessor.setProperty("resultVariable", this.getResultVariable()); + jdbcPreProcessor.setProperty("variableNames", this.getVariableNames()); + jdbcPreProcessor.setProperty("resultSetHandler", "Store as String"); + jdbcPreProcessor.setProperty("queryType", "Callable Statement"); + return jdbcPreProcessor; + } + + private DataSourceElement jdbcDataSource() { + DataSourceElement dataSourceElement = new DataSourceElement(); + dataSourceElement.setEnabled(true); + dataSourceElement.setName(this.getName() + " JDBCDataSource"); + dataSourceElement.setProperty(TestElement.TEST_CLASS, DataSourceElement.class.getName()); + dataSourceElement.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); + dataSourceElement.setProperty("autocommit", true); + dataSourceElement.setProperty("keepAlive", true); + dataSourceElement.setProperty("preinit", false); + dataSourceElement.setProperty("dataSource", dataSource.getName()); + dataSourceElement.setProperty("dbUrl", dataSource.getDbUrl()); + dataSourceElement.setProperty("driver", dataSource.getDriver()); + dataSourceElement.setProperty("username", dataSource.getUsername()); + dataSourceElement.setProperty("password", dataSource.getPassword()); + dataSourceElement.setProperty("poolMax", dataSource.getPoolMax()); + dataSourceElement.setProperty("timeout", String.valueOf(dataSource.getTimeout())); + dataSourceElement.setProperty("connectionAge", 5000); + dataSourceElement.setProperty("trimInterval", 6000); + dataSourceElement.setProperty("transactionIsolation", "DEFAULT"); + return dataSourceElement; + } +} diff --git a/frontend/src/business/components/api/automation/scenario/Setting.js b/frontend/src/business/components/api/automation/scenario/Setting.js index 62b6d0de54..66d10a187f 100644 --- a/frontend/src/business/components/api/automation/scenario/Setting.js +++ b/frontend/src/business/components/api/automation/scenario/Setting.js @@ -1,23 +1,25 @@ export const ELEMENTS = new Map([ ['ALL', ["scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "IfController","TransactionController", "LoopController", "ConstantTimer", "JSR223Processor", "CustomizeReq"]], ['scenario', ["HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "CASE", "OT_IMPORT", "IfController", "ConstantTimer", "JSR223Processor", "CustomizeReq"]], - ['HTTPSamplerProxy', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], - ['DubboSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], - ['JDBCSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], - ['TCPSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], - ['OT_IMPORT', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], - ['IfController', ["IfController", "TransactionController","scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]], - ['TransactionController', ["TransactionController", "scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]], - ['LoopController', ["IfController", "TransactionController","scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]], + ['HTTPSamplerProxy', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor',"Assertions", "Extract"]], + ['DubboSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor',"Assertions", "Extract"]], + ['JDBCSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor', "Assertions", "Extract"]], + ['TCPSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor', "Assertions", "Extract"]], + ['OT_IMPORT', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor', "Assertions", "Extract"]], + ['IfController', ["IfController", "TransactionController","scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor',"Assertions", "Extract", "CustomizeReq"]], + ['TransactionController', ["TransactionController", "scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor', "Assertions", "Extract", "CustomizeReq"]], + ['LoopController', ["IfController", "TransactionController","scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", 'JDBCPreProcessor','JDBCPostProcessor', "Assertions", "Extract", "CustomizeReq"]], ['ConstantTimer', []], ['JSR223Processor', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], ['JSR223PreProcessor', []], ['JSR223PostProcessor', []], + ['JDBCPreProcessor', []], + ['JDBCPostProcessor', []], ['Assertions', []], ['Extract', []], ['JmeterElement', []], - ['CustomizeReq', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], - ['MaxSamplerProxy', ["JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]], + ['CustomizeReq', ["ConstantTimer", "JSR223PreProcessor","JSR223PostProcessor", "JDBCPostProcessor", "JDBCPreProcessor", "Assertions", "Extract"]], + ['MaxSamplerProxy', ["JSR223PreProcessor", "JSR223PostProcessor", "JDBCPreProcessor","JDBCPostProcessor","Assertions", "Extract"]], ['AllSamplerProxy', ["HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler"]], ['AllCanExecType', ["HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "JSR223Processor"]] ]) @@ -32,6 +34,8 @@ export const ELEMENT_TYPE = { JSR223Processor: "JSR223Processor", JSR223PreProcessor: "JSR223PreProcessor", JSR223PostProcessor: "JSR223PostProcessor", + JDBCPostProcessor : "JDBCPostProcessor", + JDBCPreProcessor : "JDBCPreProcessor", Assertions: "Assertions", Extract: "Extract", CustomizeReq: "CustomizeReq", diff --git a/frontend/src/business/components/api/automation/scenario/common/JDBCProcessorContent.vue b/frontend/src/business/components/api/automation/scenario/common/JDBCProcessorContent.vue new file mode 100644 index 0000000000..1104f32026 --- /dev/null +++ b/frontend/src/business/components/api/automation/scenario/common/JDBCProcessorContent.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue b/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue index efca9a9076..eaa4dd073f 100644 --- a/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue +++ b/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue @@ -21,10 +21,11 @@ import MsLoopController from "./LoopController"; import MsApiScenarioComponent from "./ApiScenarioComponent"; import JmeterElementComponent from "./JmeterElementComponent"; + import MsJdbcProcessor from "@/business/components/api/automation/scenario/component/JDBCProcessor"; export default { name: "ComponentConfig", - components: {MsConstantTimer, MsIfController, MsTransactionController, MsJsr233Processor, MsApiAssertions, MsApiExtract, MsApiComponent, MsLoopController, MsApiScenarioComponent, JmeterElementComponent}, + components: {MsConstantTimer, MsIfController, MsTransactionController, MsJsr233Processor, MsApiAssertions, MsApiExtract, MsApiComponent, MsLoopController, MsApiScenarioComponent, MsJdbcProcessor,JmeterElementComponent}, props: { type: String, scenario: {}, @@ -77,6 +78,12 @@ case ELEMENT_TYPE.JSR223PostProcessor: name = this.getComponent(ELEMENT_TYPE.JSR223PostProcessor); break; + case ELEMENT_TYPE.JDBCPostProcessor: + name = this.getComponent(ELEMENT_TYPE.JDBCPostProcessor); + break; + case ELEMENT_TYPE.JDBCPreProcessor: + name = this.getComponent(ELEMENT_TYPE.JDBCPreProcessor); + break; case ELEMENT_TYPE.Assertions: name = "MsApiAssertions"; break; @@ -116,6 +123,16 @@ this.titleColor = "#783887"; this.backgroundColor = "#F2ECF3"; return "MsJsr233Processor"; + }if (type === ELEMENT_TYPE.JDBCPreProcessor) { + this.title = this.$t('api_test.definition.request.pre_sql'); + this.titleColor = "#FE6F71"; + this.backgroundColor = "#F2ECF3"; + return "MsJdbcProcessor"; + } else if (type === ELEMENT_TYPE.JDBCPostProcessor) { + this.title = this.$t('api_test.definition.request.post_sql'); + this.titleColor = "#1483F6"; + this.backgroundColor = "#F2ECF3"; + return "MsJdbcProcessor"; } else { this.title = this.$t('api_test.automation.customize_script'); this.titleColor = "#7B4D12"; diff --git a/frontend/src/business/components/api/automation/scenario/component/JDBCProcessor.vue b/frontend/src/business/components/api/automation/scenario/component/JDBCProcessor.vue new file mode 100644 index 0000000000..3585e67fd9 --- /dev/null +++ b/frontend/src/business/components/api/automation/scenario/component/JDBCProcessor.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/frontend/src/business/components/api/automation/scenario/menu/Menu.js b/frontend/src/business/components/api/automation/scenario/menu/Menu.js index 0537eb126b..d393a76f44 100644 --- a/frontend/src/business/components/api/automation/scenario/menu/Menu.js +++ b/frontend/src/business/components/api/automation/scenario/menu/Menu.js @@ -1,5 +1,5 @@ import {ELEMENT_TYPE} from "@/business/components/api/automation/scenario/Setting"; -import {Assertions, ConstantTimer, Extract, IfController, JSR223Processor, LoopController, TransactionController} from "@/business/components/api/definition/model/ApiTestModel"; +import {Assertions, ConstantTimer, Extract, IfController, JSR223Processor, JDBCProcessor,LoopController, TransactionController} from "@/business/components/api/definition/model/ApiTestModel"; export function buttons() { let buttons = [ @@ -33,6 +33,26 @@ export function buttons() { this.addComponent('JSR223PreProcessor') } }, + { + title: this.$t('api_test.definition.request.post_sql'), + show: this.showButton("JDBCPostProcessor"), + titleColor: "#1483F6", + titleBgColor: "#F2ECF3", + icon: "skip_next", + click: () => { + this.addComponent('JDBCPostProcessor') + } + }, + { + title: this.$t('api_test.definition.request.pre_sql'), + show: this.showButton("JDBCPreProcessor"), + titleColor: "#FE6F71", + titleBgColor: "#F9F1EA", + icon: "skip_previous", + click: () => { + this.addComponent('JDBCPreProcessor') + } + }, { title: this.$t('api_test.automation.customize_script'), show: this.showButton("JSR223Processor"), @@ -147,6 +167,14 @@ export function setComponent(type, _this) { _this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new JSR223Processor({type: "JSR223PostProcessor"})) : _this.scenarioDefinition.push(new JSR223Processor({type: "JSR223PostProcessor"})); break; + case ELEMENT_TYPE.JDBCPreProcessor: + _this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new JDBCProcessor({type: "JDBCPreProcessor"})) : + _this.scenarioDefinition.push(new JDBCProcessor({type: "JDBCPreProcessor"})); + break; + case ELEMENT_TYPE.JDBCPostProcessor: + _this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new JDBCProcessor({type: "JDBCPostProcessor"})) : + _this.scenarioDefinition.push(new JDBCProcessor({type: "JDBCPostProcessor"})); + break; case ELEMENT_TYPE.Assertions: _this.selectedTreeNode !== undefined ? _this.selectedTreeNode.hashTree.push(new Assertions()) : _this.scenarioDefinition.push(new Assertions()); diff --git a/frontend/src/business/components/api/definition/components/jmeter/components/post-processors/jdbc-post-processor/index.js b/frontend/src/business/components/api/definition/components/jmeter/components/post-processors/jdbc-post-processor/index.js new file mode 100644 index 0000000000..326ac96a99 --- /dev/null +++ b/frontend/src/business/components/api/definition/components/jmeter/components/post-processors/jdbc-post-processor/index.js @@ -0,0 +1,38 @@ +import PostProcessor from "../post-processor"; + +const DEFAULT_OPTIONS = { + options: { + attributes: { + guiclass: "TestBeanGUI", + testclass: "JDBCPostProcessor", + testname: "JDBC PostProcessor", + enabled: "true" + }, + } +}; + +export default class JDBCPostProcessor extends PostProcessor { + constructor(options = DEFAULT_OPTIONS) { + super(options); + this.type = "JDBCPostProcessor"; + this.hashTree = []; + this.variables = []; + this.environmentId = undefined; + this.dataSource = undefined; + this.dataSourceId = undefined; + this.query = undefined; + this.queryType = undefined; + this.queryArguments = undefined; + this.queryArgumentsTypes = undefined; + this.queryTimeout = undefined; + this.resultSetHandler = undefined; + this.resultSetMaxRows = undefined; + this.resultVariable = undefined; + this.variableNames = undefined; + this.enable = true; + } +} + +export const schema = { + JDBCPostProcessor: JDBCPostProcessor +} diff --git a/frontend/src/business/components/api/definition/components/jmeter/components/pre-processors/jdbc-pre-processor/index.js b/frontend/src/business/components/api/definition/components/jmeter/components/pre-processors/jdbc-pre-processor/index.js new file mode 100644 index 0000000000..eddbdb82fc --- /dev/null +++ b/frontend/src/business/components/api/definition/components/jmeter/components/pre-processors/jdbc-pre-processor/index.js @@ -0,0 +1,38 @@ +import PostProcessor from "../pre-processor"; + +const DEFAULT_OPTIONS = { + options: { + attributes: { + guiclass: "TestBeanGUI", + testclass: "JDBCPreProcessor", + testname: "JDBC PreProcessor", + enabled: "true" + }, + } +}; + +export default class JDBCPreProcessor extends PostProcessor { + constructor(options = DEFAULT_OPTIONS) { + super(options); + this.type = "JDBCPreProcessor"; + this.hashTree = []; + this.variables = []; + this.environmentId = undefined; + this.dataSource = undefined; + this.dataSourceId = undefined; + this.query = undefined; + this.queryType = undefined; + this.queryArguments = undefined; + this.queryArgumentsTypes = undefined; + this.queryTimeout = undefined; + this.resultSetHandler = undefined; + this.resultSetMaxRows = undefined; + this.resultVariable = undefined; + this.variableNames = undefined; + this.enable = true; + } +} + +export const schema = { + JDBCPreProcessor: JDBCPreProcessor +} diff --git a/frontend/src/business/components/api/definition/components/request/components/ApiDefinitionStepButton.vue b/frontend/src/business/components/api/definition/components/request/components/ApiDefinitionStepButton.vue index 3fa34a1452..6fedf00536 100644 --- a/frontend/src/business/components/api/definition/components/request/components/ApiDefinitionStepButton.vue +++ b/frontend/src/business/components/api/definition/components/request/components/ApiDefinitionStepButton.vue @@ -4,6 +4,10 @@
+{{$t('api_test.definition.request.post_script')}}
+ +{{$t('api_test.definition.request.pre_sql')}} +
+ +{{$t('api_test.definition.request.post_sql')}} +
+{{$t('api_test.definition.request.assertions_rule')}}
+{{$t('api_test.definition.request.extract_param')}} @@ -39,6 +43,20 @@ } this.request.hashTree.push(jsr223PostProcessor); }, + addPreSql() { + let jdbcPreProcessor = createComponent("JDBCPreProcessor"); + if (!this.request.hashTree) { + this.request.hashTree = []; + } + this.request.hashTree.push(jdbcPreProcessor); + }, + addPostSql() { + let jdbcPostProcessor = createComponent("JDBCPostProcessor"); + if (!this.request.hashTree) { + this.request.hashTree = []; + } + this.request.hashTree.push(jdbcPostProcessor); + }, addAssertions() { let assertions = new Assertions(); if (!this.request.hashTree) { @@ -71,14 +89,24 @@ background-color: #F2ECF3; border: #F2ECF3; } - .ms-left-cell .el-button:nth-of-type(3) { + color: #FE6F71; + background-color: #F9F1EA; + border: #EBF2F2; + } + + .ms-left-cell .el-button:nth-of-type(4) { + color: #1483F6; + background-color: #F2ECF3; + border: #F2ECF3; + } + .ms-left-cell .el-button:nth-of-type(5) { color: #A30014; background-color: #F7E6E9; border: #F7E6E9; } - .ms-left-cell .el-button:nth-of-type(4) { + .ms-left-cell .el-button:nth-of-type(6) { color: #015478; background-color: #E6EEF2; border: #E6EEF2; diff --git a/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue b/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue index 8aa44afd78..015aea22c5 100644 --- a/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue +++ b/frontend/src/business/components/api/definition/components/request/database/BasisParameters.vue @@ -70,6 +70,10 @@
+{{$t('api_test.definition.request.post_script')}}
+ +{{$t('api_test.definition.request.pre_sql')}} +
+ +{{$t('api_test.definition.request.post_sql')}} +
+{{$t('api_test.definition.request.assertions_rule')}}
+{{$t('api_test.definition.request.extract_param')}} @@ -151,6 +155,14 @@ this.request.hashTree.push(jsr223PostProcessor); this.reload(); }, + addPreSql() { + let jdbcPreProcessor = createComponent("JDBCPreProcessor"); + this.request.hashTree.push(jdbcPreProcessor); + }, + addPostSql() { + let jdbcPostProcessor = createComponent("JDBCPostProcessor"); + this.request.hashTree.push(jdbcPostProcessor); + }, addAssertions() { let assertions = new Assertions(); this.request.hashTree.push(assertions); diff --git a/frontend/src/business/components/api/definition/components/step/JmxStep.vue b/frontend/src/business/components/api/definition/components/step/JmxStep.vue index 4ddb14cff7..659887eaf6 100644 --- a/frontend/src/business/components/api/definition/components/step/JmxStep.vue +++ b/frontend/src/business/components/api/definition/components/step/JmxStep.vue @@ -13,6 +13,14 @@ + + + +
@@ -35,10 +43,12 @@ import {getUUID} from "@/common/js/utils"; import BatchAddParameter from "../basis/BatchAddParameter"; import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor"; + import MsJdbcProcessor from "@/business/components/api/automation/scenario/component/JDBCProcessor"; export default { name: "MsJmxStep", components: { + MsJdbcProcessor, MsJsr233Processor, BatchAddParameter, MsApiExtract, diff --git a/frontend/src/business/components/api/definition/model/ApiTestModel.js b/frontend/src/business/components/api/definition/model/ApiTestModel.js index 611df32709..3ffedfb2b0 100644 --- a/frontend/src/business/components/api/definition/model/ApiTestModel.js +++ b/frontend/src/business/components/api/definition/model/ApiTestModel.js @@ -854,6 +854,21 @@ export class JSR223Processor extends BaseConfig { } } +export class JDBCProcessor extends BaseConfig { + constructor(options) { + super(); + this.resourceId = uuid(); + this.active = false; + this.type = "JDBCProcessor"; + this.enable = true; + this.variables = []; + this.dataSourceId = ""; + this.hashTree = []; + this.set(options); + } +} + + export class Regex extends AssertionType { constructor(options) { super(ASSERTION_TYPE.REGEX); diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 1b1fb8615c..d12a416d0e 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -812,6 +812,8 @@ export default { auth_config_info: "Request requires permission verification", pre_script: "Prescript", post_script: "Postscript", + pre_sql: "JDBC Preprocessor", + post_sql: "JDBC Postprocessor", extract_param: "Extract parameters", add_module: "Add module", edit_api: "Edit Api", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index b098524898..0f23cac108 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -813,6 +813,8 @@ export default { auth_config_info: "请求需要进行权限校验", pre_script: "前置脚本", post_script: "后置脚本", + pre_sql: "前置SQL", + post_sql: "后置SQL", extract_param: "提取参数", add_module: "创建模块", edit_api: "编辑接口", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 7eb5e3f032..001e83d01c 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -813,6 +813,8 @@ export default { auth_config_info: "請求需要進行權限校驗", pre_script: "前置腳本", post_script: "後置腳本", + pre_sql: "前置SQL", + post_sql: "後置SQL", extract_param: "提取參數", add_module: "創建模塊", edit_api: "編輯接口",