From 7a453643ad382ba036e3ae49a061dc98b035e0e1 Mon Sep 17 00:00:00 2001 From: AgAngle <1323481023@qq.com> Date: Fri, 23 Feb 2024 14:44:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E5=A4=84=E7=90=86=E6=89=A7=E8=A1=8C=E6=97=B6=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/ApiScenarioParseParam.java | 42 ++++++ .../MsCommentScriptElementConverter.java | 4 + .../parser/jmeter/constants/JmeterAlias.java | 1 + .../ScenarioScriptProcessorConverter.java | 7 + .../ScriptPostProcessorConverter.java | 8 +- .../ScriptPreProcessorConverter.java | 10 +- .../processor/ScriptProcessorConverter.java | 57 ++++++++- .../assertion/ScriptAssertionConverter.java | 22 ++-- .../api/service/ApiCommonService.java | 120 ++++++++++++++++-- .../api/service/ApiExecuteService.java | 5 +- .../api/service/debug/ApiDebugService.java | 7 +- .../definition/ApiDefinitionService.java | 5 +- .../definition/ApiTestCaseService.java | 5 +- .../service/scenario/ApiScenarioService.java | 38 +++--- .../controller/ApiDebugControllerTests.java | 42 +++++- .../ApiDefinitionControllerTests.java | 4 +- .../ApiTestCaseControllerTests.java | 6 +- .../api/controller/MsHTTPElementTest.java | 4 +- .../api/assertion/MsScriptAssertion.java | 31 +++-- .../api/processor/ScriptProcessor.java | 28 ++-- .../project/dto/CommonScriptInfo.java | 40 ++++++ .../service/CustomFunctionService.java | 20 +++ .../CustomFunctionControllerTests.java | 17 ++- .../EnvironmentControllerTests.java | 6 +- 24 files changed, 445 insertions(+), 84 deletions(-) create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParseParam.java create mode 100644 backend/services/project-management/src/main/java/io/metersphere/project/dto/CommonScriptInfo.java diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParseParam.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParseParam.java new file mode 100644 index 0000000000..fa42af8cbd --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParseParam.java @@ -0,0 +1,42 @@ +package io.metersphere.api.dto; + +import io.metersphere.api.dto.request.MsCommonElement; +import io.metersphere.api.dto.request.http.MsHTTPElement; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 执行场景解析参数时的临时参数 + * + * @Author: jianxing + * @CreateTime: 2024-02-22 11:27 + */ +@Data +public class ApiScenarioParseParam { + /** + * 步骤详情 Map + * key 为步骤ID + * value 为步骤详情字符串 + */ + private Map stepDetailMap; + /** + * 资源的请求内容 Map + * key 为资源ID + * value 为请求详情字符串 + */ + private Map resourceDetailMap; + /** + * MsHTTPElement Map + * key 为 stepType + * value 为 MsHTTPElement + */ + private Map> stepTypeHttpElementMap = new HashMap<>(); + /** + * 场景中所有的 MsCommonElement 列表 + */ + private List commonElements = new ArrayList<>(); +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/MsCommentScriptElementConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/MsCommentScriptElementConverter.java index a5180d4079..0fac8b5b4f 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/MsCommentScriptElementConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/MsCommentScriptElementConverter.java @@ -16,6 +16,7 @@ import org.apache.jorphan.collections.HashTree; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static io.metersphere.api.parser.jmeter.constants.JmeterAlias.USER_PARAMETERS_GUI; @@ -53,6 +54,9 @@ public class MsCommentScriptElementConverter extends AbstractJmeterElementConver scriptElement = new BeanShellSampler(); } ScriptProcessorConverter.parse(scriptElement, scriptProcessor); + // 添加公共脚本的参数 + Optional.ofNullable(ScriptProcessorConverter.getScriptArguments(scriptProcessor)) + .ifPresent(hashTree::add); hashTree.add(scriptElement); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/constants/JmeterAlias.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/constants/JmeterAlias.java index feadc616ff..01b71479e8 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/constants/JmeterAlias.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/constants/JmeterAlias.java @@ -20,4 +20,5 @@ public class JmeterAlias { public static final String COOKIE_PANEL = "CookiePanel"; public static final String HEADER_PANEL = "HeaderPanel"; public static final String AUTH_PANEL = "AuthPanel"; + public static final String ARGUMENTS_PANEL = "ArgumentsPanel"; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScenarioScriptProcessorConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScenarioScriptProcessorConverter.java index 45e6c46710..c1340322d9 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScenarioScriptProcessorConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScenarioScriptProcessorConverter.java @@ -8,6 +8,8 @@ import org.apache.jmeter.protocol.java.sampler.JSR223Sampler; import org.apache.jmeter.testelement.TestElement; import org.apache.jorphan.collections.HashTree; +import java.util.Optional; + /** * 环境场景级前置处理器处理 * @@ -31,6 +33,11 @@ public class ScenarioScriptProcessorConverter extends ScriptProcessorConverter { } parse(processor, scriptProcessor); + + // 添加公共脚本的参数 + Optional.ofNullable(getScriptArguments(scriptProcessor)) + .ifPresent(hashTree::add); + // 标记当前处理器是否关联场景结果 processor.setName("ASSOCIATE_RESULT_PROCESSOR_" + associateScenarioResult); hashTree.add(processor); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPostProcessorConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPostProcessorConverter.java index 6c5ccdbb68..963ee1ed01 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPostProcessorConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPostProcessorConverter.java @@ -7,6 +7,8 @@ import org.apache.jmeter.extractor.JSR223PostProcessor; import org.apache.jmeter.testelement.TestElement; import org.apache.jorphan.collections.HashTree; +import java.util.Optional; + /** * @Author: jianxing * @CreateTime: 2023-12-26 14:49 @@ -17,7 +19,6 @@ public class ScriptPostProcessorConverter extends ScriptProcessorConverter { if (!needParse(scriptProcessor, config) || !scriptProcessor.isValid()) { return; } - // todo 处理公共脚本 TestElement processor; if (isJSR233(scriptProcessor)) { processor = new JSR223PostProcessor(); @@ -25,6 +26,11 @@ public class ScriptPostProcessorConverter extends ScriptProcessorConverter { processor = new BeanShellPostProcessor(); } parse(processor, scriptProcessor); + + // 添加公共脚本的参数 + Optional.ofNullable(getScriptArguments(scriptProcessor)) + .ifPresent(hashTree::add); + hashTree.add(processor); } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPreProcessorConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPreProcessorConverter.java index 83445f8db3..60b6425cb8 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPreProcessorConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptPreProcessorConverter.java @@ -1,12 +1,14 @@ package io.metersphere.api.parser.jmeter.processor; -import io.metersphere.project.api.processor.ScriptProcessor; import io.metersphere.plugin.api.dto.ParameterConfig; +import io.metersphere.project.api.processor.ScriptProcessor; import org.apache.jmeter.modifiers.BeanShellPreProcessor; import org.apache.jmeter.modifiers.JSR223PreProcessor; import org.apache.jmeter.testelement.TestElement; import org.apache.jorphan.collections.HashTree; +import java.util.Optional; + /** * @Author: jianxing * @CreateTime: 2023-12-26 14:49 @@ -17,7 +19,6 @@ public class ScriptPreProcessorConverter extends ScriptProcessorConverter { if (!needParse(scriptProcessor, config) || !scriptProcessor.isValid()) { return; } - // todo 处理公共脚本 TestElement processor; if (isJSR233(scriptProcessor)) { processor = new JSR223PreProcessor(); @@ -25,6 +26,11 @@ public class ScriptPreProcessorConverter extends ScriptProcessorConverter { processor = new BeanShellPreProcessor(); } parse(processor, scriptProcessor); + + // 添加公共脚本的参数 + Optional.ofNullable(getScriptArguments(scriptProcessor)) + .ifPresent(hashTree::add); + hashTree.add(processor); } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptProcessorConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptProcessorConverter.java index 7ea4ab5f98..304127aef4 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptProcessorConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/ScriptProcessorConverter.java @@ -1,14 +1,22 @@ package io.metersphere.api.parser.jmeter.processor; -import io.metersphere.plugin.api.constants.ElementProperty; -import io.metersphere.project.constants.ScriptLanguageType; -import io.metersphere.project.api.processor.ScriptProcessor; import io.metersphere.api.parser.jmeter.constants.JmeterAlias; import io.metersphere.api.parser.jmeter.constants.JmeterProperty; +import io.metersphere.plugin.api.constants.ElementProperty; +import io.metersphere.project.api.KeyValueParam; +import io.metersphere.project.api.processor.ScriptProcessor; +import io.metersphere.project.constants.ScriptLanguageType; +import io.metersphere.project.dto.CommonScriptInfo; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.jmeter.config.Arguments; import org.apache.jmeter.save.SaveService; import org.apache.jmeter.testelement.TestElement; +import java.util.List; + +import static io.metersphere.api.parser.jmeter.constants.JmeterAlias.ARGUMENTS_PANEL; + /** * @Author: jianxing @@ -38,9 +46,48 @@ public abstract class ScriptProcessorConverter extends MsProcessorConverter params = commonScriptInfo.getParams() + .stream() + .filter(KeyValueParam::isValid) + .toList(); + + if (CollectionUtils.isEmpty(commonScriptInfo.getParams())) { + return null; + } + + Arguments arguments = new Arguments(); + arguments.setEnabled(true); + arguments.setName(scriptProcessor.getName() + "_Arguments"); + arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); + arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(ARGUMENTS_PANEL)); + for (KeyValueParam param : params) { + arguments.addArgument(param.getKey(), param.getValue(), "="); + } + return arguments; } public static boolean isJSR233(ScriptProcessor scriptProcessor) { diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ScriptAssertionConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ScriptAssertionConverter.java index facc80ed30..dcc2a9f17c 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ScriptAssertionConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ScriptAssertionConverter.java @@ -1,14 +1,15 @@ package io.metersphere.api.parser.jmeter.processor.assertion; -import io.metersphere.project.api.assertion.MsScriptAssertion; -import io.metersphere.project.api.processor.ScriptProcessor; import io.metersphere.api.parser.jmeter.processor.ScriptProcessorConverter; import io.metersphere.plugin.api.dto.ParameterConfig; +import io.metersphere.project.api.assertion.MsScriptAssertion; +import io.metersphere.project.api.processor.ScriptProcessor; import io.metersphere.sdk.util.BeanUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.jmeter.assertions.JSR223Assertion; import org.apache.jorphan.collections.HashTree; +import java.util.Optional; + /** * @Author: jianxing * @CreateTime: 2023-12-27 21:01 @@ -16,17 +17,18 @@ import org.apache.jorphan.collections.HashTree; public class ScriptAssertionConverter extends AssertionConverter { @Override public void parse(HashTree hashTree, MsScriptAssertion msAssertion, ParameterConfig config, boolean isIgnoreStatus) { - if (!needParse(msAssertion, config) || !isValid(msAssertion)) { + if (!needParse(msAssertion, config) || !msAssertion.isValid()) { return; } JSR223Assertion jsr223Assertion = new JSR223Assertion(); - ScriptProcessorConverter.parse(jsr223Assertion, BeanUtils.copyBean(new ScriptProcessor(), msAssertion)); + ScriptProcessor scriptProcessor = BeanUtils.copyBean(new ScriptProcessor(), msAssertion); + ScriptProcessorConverter.parse(jsr223Assertion, scriptProcessor); + + // 添加公共脚本的参数 + Optional.ofNullable(ScriptProcessorConverter.getScriptArguments(scriptProcessor)) + .ifPresent(hashTree::add); + hashTree.add(jsr223Assertion); } - - public boolean isValid(MsScriptAssertion msAssertion) { - // todo 公共脚本库 - return StringUtils.isNotBlank(msAssertion.getScript()); - } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiCommonService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiCommonService.java index 4147785348..1e5af056b3 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiCommonService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiCommonService.java @@ -3,16 +3,25 @@ package io.metersphere.api.service; import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.definition.ResponseBinaryBody; import io.metersphere.api.dto.definition.ResponseBody; +import io.metersphere.api.dto.request.MsCommonElement; import io.metersphere.api.dto.request.http.MsHTTPElement; import io.metersphere.api.dto.request.http.body.BinaryBody; import io.metersphere.api.dto.request.http.body.Body; import io.metersphere.api.dto.request.http.body.FormDataBody; import io.metersphere.api.dto.request.http.body.FormDataKV; import io.metersphere.plugin.api.spi.AbstractMsTestElement; +import io.metersphere.project.api.KeyValueParam; +import io.metersphere.project.api.processor.MsProcessor; +import io.metersphere.project.api.processor.ScriptProcessor; +import io.metersphere.project.domain.CustomFunction; +import io.metersphere.project.domain.CustomFunctionBlob; import io.metersphere.project.domain.FileAssociation; import io.metersphere.project.domain.FileMetadata; +import io.metersphere.project.dto.CommonScriptInfo; +import io.metersphere.project.service.CustomFunctionService; import io.metersphere.project.service.FileAssociationService; import io.metersphere.project.service.FileMetadataService; +import io.metersphere.sdk.util.JSON; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -22,6 +31,8 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -35,8 +46,12 @@ public class ApiCommonService { private FileAssociationService fileAssociationService; @Resource private FileMetadataService fileMetadataService; + @Resource + private CustomFunctionService customFunctionService; + /** * 根据 fileId 查找 MsHTTPElement 中的 ApiFile + * * @param fileId * @param msTestElement * @return @@ -63,24 +78,26 @@ public class ApiCommonService { /** * 设置关联的文件的最新信息 * 包括文件别名和是否被删除 + * * @param resourceId * @param msTestElement */ - public void updateLinkFileInfo(String resourceId, AbstractMsTestElement msTestElement) { - updateLinkFileInfo(resourceId, getApiFiles(msTestElement)); + public void setLinkFileInfo(String resourceId, AbstractMsTestElement msTestElement) { + setLinkFileInfo(resourceId, getApiFiles(msTestElement)); } /** * 设置关联的文件的最新信息 * 包括文件别名和是否被删除 + * * @param resourceId * @param responseBody */ - public void updateLinkFileInfo(String resourceId, ResponseBody responseBody) { - updateLinkFileInfo(resourceId, getApiBodyFiles(responseBody)); + public void setLinkFileInfo(String resourceId, ResponseBody responseBody) { + setLinkFileInfo(resourceId, getApiBodyFiles(responseBody)); } - private void updateLinkFileInfo(String resourceId, List apiFiles) { + private void setLinkFileInfo(String resourceId, List apiFiles) { List linkFiles = apiFiles.stream() .filter(file -> !file.getLocal() && !file.getDelete()) .toList(); @@ -114,7 +131,6 @@ public class ApiCommonService { /** - * * @param body * @return */ @@ -155,8 +171,96 @@ public class ApiCommonService { public void replaceApiFileInfo(List updateFiles, FileMetadata newFileMetadata) { for (ApiFile updateFile : updateFiles) { updateFile.setFileId(newFileMetadata.getId()); - // todo 重新设置文件名 - // updateFile.setFileName(); + updateFile.setFileName(newFileMetadata.getOriginalName()); } } + + /** + * 设置使用脚本前后置的公共脚本信息 + * @param msTestElement + */ + public void setEnableCommonScriptProcessorInfo(AbstractMsTestElement msTestElement) { + MsCommonElement msCommonElement = getMsCommonElement(msTestElement); + Optional.ofNullable(msCommonElement).ifPresent(item -> setEnableCommonScriptProcessorInfo(List.of(item))); + } + + /** + * 设置使用脚本前后置的公共脚本信息 + * + * @param commonElements + */ + public void setEnableCommonScriptProcessorInfo(List commonElements) { + List scriptsProcessors = getEnableCommonScriptProcessors(commonElements); + + List commonScriptIds = scriptsProcessors.stream() + .map(processor -> processor.getCommonScriptInfo().getId()) + .toList(); + + Map customFunctionBlobMap = customFunctionService.getBlobByIds(commonScriptIds).stream() + .collect(Collectors.toMap(CustomFunctionBlob::getId, Function.identity())); + + Map customFunctionMap = customFunctionService.getByIds(commonScriptIds).stream() + .collect(Collectors.toMap(CustomFunction::getId, Function.identity())); + + for (ScriptProcessor processor : scriptsProcessors) { + CommonScriptInfo commonScriptInfo = processor.getCommonScriptInfo(); + CustomFunctionBlob customFunctionBlob = customFunctionBlobMap.get(commonScriptInfo.getId()); + CustomFunction customFunction = customFunctionMap.get(commonScriptInfo.getId()); + + // 设置公共脚本信息 + Optional.ofNullable(customFunctionBlob.getParams()).ifPresent(paramsBlob -> { + List commonParams = JSON.parseArray(new String(paramsBlob), KeyValueParam.class); + // 替换用户输入值 + commonParams.forEach(commonParam -> + Optional.ofNullable(commonScriptInfo.getParams()).ifPresent(params -> + params.stream() + .filter(param -> StringUtils.equals(commonParam.getKey(), param.getKey())) + .findFirst() + .ifPresent(param -> commonParam.setValue(param.getValue())) + ) + ); + commonScriptInfo.setParams(commonParams); + }); + Optional.ofNullable(customFunctionBlob.getScript()).ifPresent(script -> + commonScriptInfo.setScript(new String(script))); + commonScriptInfo.setScriptLanguage(customFunction.getType()); + commonScriptInfo.setName(customFunction.getName()); + } + } + + /** + * 获取使用公共脚本的前后置 + * + * @param commonElements + * @return + */ + private List getEnableCommonScriptProcessors(List commonElements) { + List processors = new ArrayList<>(); + + for (MsCommonElement commonElement : commonElements) { + processors.addAll(commonElement.getPreProcessorConfig().getProcessors()); + processors.addAll(commonElement.getPostProcessorConfig().getProcessors()); + } + + // 获取使用公共脚本的前后置 + List scriptsProcessors = processors.stream() + .filter(processor -> processor instanceof ScriptProcessor) + .map(processor -> (ScriptProcessor) processor) + .filter(ScriptProcessor::getEnable) + .filter(ScriptProcessor::isEnableCommonScript) + .filter(ScriptProcessor::isValid) + .collect(Collectors.toList()); + return scriptsProcessors; + } + + public MsCommonElement getMsCommonElement(AbstractMsTestElement msTestElement) { + if (CollectionUtils.isNotEmpty(msTestElement.getChildren())) { + for (AbstractMsTestElement child : msTestElement.getChildren()) { + if (child instanceof MsCommonElement msCommonElement) { + return msCommonElement; + } + } + } + return null; + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteService.java index 9057c5527d..bea3bd85f5 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteService.java @@ -132,9 +132,6 @@ public class ApiExecuteService { parameterConfig.setGlobalParams(getGlobalParam(request)); - // todo 获取接口插件和jar包 - // todo 处理公共脚本 - // todo 接口用例 method 获取定义中的数据库字段 String executeScript = parseExecuteScript(request.getTestElement(), parameterConfig); doDebug(reportId, testId, taskRequest, executeScript, request.getProjectId()); @@ -318,7 +315,7 @@ public class ApiExecuteService { List fileMetadataList = fileManagementService.findJarByProjectId(List.of(taskRequest.getProjectId())); taskRequest.setFuncJars(fileMetadataList.stream() .map(file -> { - String fileName = file.getName() + "." + file.getType(); + String fileName = file.getOriginalName(); ApiExecuteFileInfo tempFileInfo = getApiExecuteFileInfo(file.getId(), fileName, file.getProjectId(), file.getStorage()); if (StorageType.isGit(file.getStorage())) { // 设置Git信息 diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java index 9db5f2c288..2badb889bc 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java @@ -78,7 +78,8 @@ public class ApiDebugService { ApiDebugDTO apiDebugDTO = new ApiDebugDTO(); BeanUtils.copyBean(apiDebugDTO, apiDebug); AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiDebugBlob.getRequest()), AbstractMsTestElement.class); - apiCommonService.updateLinkFileInfo(id, msTestElement); + apiCommonService.setLinkFileInfo(id, msTestElement); + apiCommonService.setEnableCommonScriptProcessorInfo(msTestElement); apiDebugDTO.setRequest(msTestElement); apiDebugDTO.setResponse(apiDebugDTO.getResponse()); return apiDebugDTO; @@ -218,6 +219,10 @@ public class ApiDebugService { paramConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap()); paramConfig.setTestElementClassProtocalMap(apiPluginService.getTestElementProtocolMap()); paramConfig.setReportId(reportId); + + // 设置使用脚本前后置的公共脚本信息 + apiCommonService.setEnableCommonScriptProcessorInfo(runRequest.getTestElement()); + apiExecuteService.debug(runRequest, paramConfig); return runRequest.getReportId(); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java index 367599eed3..fc85f07fe2 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java @@ -872,13 +872,14 @@ public class ApiDefinitionService { Optional apiDefinitionBlobOptional = Optional.ofNullable(apiDefinitionBlobMapper.selectByPrimaryKey(id)); apiDefinitionBlobOptional.ifPresent(blob -> { AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(blob.getRequest()), AbstractMsTestElement.class); - apiCommonService.updateLinkFileInfo(id, msTestElement); + apiCommonService.setLinkFileInfo(id, msTestElement); + apiCommonService.setEnableCommonScriptProcessorInfo(msTestElement); apiDefinitionDTO.setRequest(msTestElement); // blob.getResponse() 为 null 时不进行转换 if (blob.getResponse() != null) { List httpResponses = ApiDataUtils.parseArray(new String(blob.getResponse()), HttpResponse.class); for (HttpResponse httpResponse : httpResponses) { - apiCommonService.updateLinkFileInfo(id, httpResponse.getBody()); + apiCommonService.setLinkFileInfo(id, httpResponse.getBody()); } apiDefinitionDTO.setResponse(httpResponses); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java index e9c01c4ac6..018b885773 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java @@ -210,7 +210,10 @@ public class ApiTestCaseService { example.createCriteria().andCaseIdEqualTo(id).andUserIdEqualTo(userId); List followers = apiTestCaseFollowerMapper.selectByExample(example); apiTestCaseDTO.setFollow(CollectionUtils.isNotEmpty(followers)); - apiTestCaseDTO.setRequest(ApiDataUtils.parseObject(new String(testCaseBlob.getRequest()), AbstractMsTestElement.class)); + AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(testCaseBlob.getRequest()), AbstractMsTestElement.class); + apiCommonService.setLinkFileInfo(id, msTestElement); + apiCommonService.setEnableCommonScriptProcessorInfo(msTestElement); + apiTestCaseDTO.setRequest(msTestElement); return apiTestCaseDTO; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java index 5dd7ef32f0..07f2956173 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java @@ -1054,11 +1054,11 @@ public class ApiScenarioService { Map> refResourceMap = new HashMap<>(); buildRefResourceIdMap(steps, refResourceMap); + ApiScenarioParseParam parseParam = new ApiScenarioParseParam(); // 查询引用的资源详情 - Map resourceBlobMap = getResourceBlobMap(refResourceMap); - + parseParam.setResourceDetailMap(getResourceDetailMap(refResourceMap)); // 查询复制的步骤详情 - Map detailMap = getStepDetailMap(steps, request.getStepDetails()); + parseParam.setStepDetailMap(getStepDetailMap(steps, request.getStepDetails())); // 解析生成待执行的场景树 MsScenario msScenario = new MsScenario(); @@ -1068,10 +1068,11 @@ public class ApiScenarioService { // 获取场景环境相关配置 ApiScenarioParseEnvInfo scenarioParseEnvInfo = getScenarioParseEnvInfo(refResourceMap, request.getEnvironmentId(), request.getGrouped()); - Map> stepTypeHttpElementMap = new HashMap<>(); - parseStep2MsElement(msScenario, steps, resourceBlobMap, detailMap, stepTypeHttpElementMap, scenarioParseEnvInfo); + parseStep2MsElement(msScenario, steps, parseParam, scenarioParseEnvInfo); // 设置 HttpElement 的模块信息 - setHttpElementModuleId(stepTypeHttpElementMap); + setHttpElementModuleId(parseParam.getStepTypeHttpElementMap()); + // 设置使用脚本前后置的公共脚本信息 + apiCommonService.setEnableCommonScriptProcessorInfo(parseParam.getCommonElements()); ApiResourceRunRequest runRequest = BeanUtils.copyBean(new ApiResourceRunRequest(), request); runRequest.setProjectId(request.getProjectId()); @@ -1230,13 +1231,15 @@ public class ApiScenarioService { */ private void parseStep2MsElement(AbstractMsTestElement parentElement, List steps, - Map resourceBlobMap, - Map stepDetailMap, - Map> stepTypeHttpElementMap, + ApiScenarioParseParam parseParam, ApiScenarioParseEnvInfo scenarioParseEnvInfo) { if (CollectionUtils.isNotEmpty(steps)) { parentElement.setChildren(new LinkedList<>()); } + + Map stepDetailMap = parseParam.getStepDetailMap(); + Map resourceDetailMap = parseParam.getResourceDetailMap(); + Map> stepTypeHttpElementMap = parseParam.getStepTypeHttpElementMap(); for (ApiScenarioStepCommonDTO step : steps) { StepParser stepParser = StepParserFactory.getStepParser(step.getStepType()); if (BooleanUtils.isFalse(step.getEnable())) { @@ -1245,7 +1248,7 @@ public class ApiScenarioService { setPartialRefStepEnable(step, stepDetailMap); // 将步骤详情解析生成对应的MsTestElement - AbstractMsTestElement msTestElement = stepParser.parseTestElement(step, resourceBlobMap.get(step.getResourceId()), stepDetailMap.get(step.getId())); + AbstractMsTestElement msTestElement = stepParser.parseTestElement(step, resourceDetailMap.get(step.getResourceId()), stepDetailMap.get(step.getId())); if (msTestElement != null) { if (msTestElement instanceof MsHTTPElement msHTTPElement) { // 暂存http类型的步骤 @@ -1255,11 +1258,13 @@ public class ApiScenarioService { msTestElement.setProjectId(step.getProjectId()); msTestElement.setResourceId(step.getResourceId()); setMsScenarioParam(scenarioParseEnvInfo, step, msTestElement); + // 记录 msCommonElement + Optional.ofNullable(apiCommonService.getMsCommonElement(msTestElement)) + .ifPresent(msCommonElement -> parseParam.getCommonElements().add(msCommonElement)); parentElement.getChildren().add(msTestElement); } if (CollectionUtils.isNotEmpty(step.getChildren())) { - parseStep2MsElement(msTestElement, step.getChildren(), resourceBlobMap, - stepDetailMap, stepTypeHttpElementMap, scenarioParseEnvInfo); + parseStep2MsElement(msTestElement, step.getChildren(), parseParam, scenarioParseEnvInfo); } } } @@ -1383,7 +1388,7 @@ public class ApiScenarioService { return stepDetails; } - private Map getResourceBlobMap(Map> refResourceMap) { + private Map getResourceDetailMap(Map> refResourceMap) { Map resourceBlobMap = new HashMap<>(); List apiIds = refResourceMap.get(ApiScenarioStepType.API.name()); List apiDefinitionBlobs = apiDefinitionService.getBlobByIds(apiIds); @@ -1645,13 +1650,14 @@ public class ApiScenarioService { } StepParser stepParser = StepParserFactory.getStepParser(step.getStepType()); Object stepDetail = stepParser.parseDetail(step); - if (stepDetail instanceof MsHTTPElement msHTTPElement) { + if (stepDetail instanceof AbstractMsTestElement msTestElement) { // 设置关联的文件的最新信息 if (isRef(step.getRefType())) { - apiCommonService.updateLinkFileInfo(step.getResourceId(), msHTTPElement); + apiCommonService.setLinkFileInfo(step.getResourceId(), msTestElement); } else { - apiCommonService.updateLinkFileInfo(step.getScenarioId(), msHTTPElement); + apiCommonService.setLinkFileInfo(step.getScenarioId(), msTestElement); } + apiCommonService.setEnableCommonScriptProcessorInfo(msTestElement); } return stepDetail; } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java index 4a8e69cc21..6cf8d67aaa 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java @@ -28,10 +28,18 @@ import io.metersphere.api.service.BaseFileManagementTestService; import io.metersphere.api.service.BaseResourcePoolTestService; import io.metersphere.api.utils.ApiDataUtils; import io.metersphere.plugin.api.spi.AbstractMsTestElement; +import io.metersphere.project.api.KeyValueEnableParam; +import io.metersphere.project.api.KeyValueParam; +import io.metersphere.project.api.processor.ScriptProcessor; +import io.metersphere.project.constants.ScriptLanguageType; +import io.metersphere.project.domain.CustomFunction; import io.metersphere.project.domain.ProjectTestResourcePool; import io.metersphere.project.domain.ProjectTestResourcePoolExample; +import io.metersphere.project.dto.CommonScriptInfo; +import io.metersphere.project.dto.customfunction.request.CustomFunctionRequest; import io.metersphere.project.dto.filemanagement.FileInfo; import io.metersphere.project.mapper.ProjectTestResourcePoolMapper; +import io.metersphere.project.service.CustomFunctionService; import io.metersphere.project.service.FileAssociationService; import io.metersphere.sdk.constants.DefaultRepositoryDir; import io.metersphere.sdk.constants.PermissionConstants; @@ -93,6 +101,8 @@ public class ApiDebugControllerTests extends BaseTest { private ProjectTestResourcePoolMapper projectTestResourcePoolMapper; @Resource private TestResourcePoolMapper testResourcePoolMapper; + @Resource + private CustomFunctionService customFunctionService; private static ApiDebug addApiDebug; private static ApiDebug anotherAddApiDebug; private static String fileMetadataId; @@ -363,7 +373,7 @@ public class ApiDebugControllerTests extends BaseTest { ApiDebugDTO copyApiDebugDTO = BeanUtils.copyBean(new ApiDebugDTO(), apiDebugMapper.selectByPrimaryKey(addApiDebug.getId())); ApiDebugBlob apiDebugBlob = apiDebugBlobMapper.selectByPrimaryKey(addApiDebug.getId()); AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiDebugBlob.getRequest()), AbstractMsTestElement.class); - apiCommonService.updateLinkFileInfo(addApiDebug.getId(), msTestElement); + apiCommonService.setLinkFileInfo(addApiDebug.getId(), msTestElement); copyApiDebugDTO.setRequest(msTestElement); Assertions.assertEquals(apiDebugDTO, copyApiDebugDTO); @@ -477,6 +487,22 @@ public class ApiDebugControllerTests extends BaseTest { msAssertionConfig.setAssertions(MsHTTPElementTest.getGeneralXmlAssertions()); msCommonElement = new MsCommonElement(); msCommonElement.setAssertionConfig(msAssertionConfig); + + // 测试公共脚本 + ScriptProcessor scriptProcessor = new ScriptProcessor(); + scriptProcessor.setEnable(true); + scriptProcessor.setName("test"); + scriptProcessor.setScriptLanguage(ScriptLanguageType.JAVASCRIPT.name()); + CustomFunction customFunction = addCustomFunction(); + scriptProcessor.setCommonScriptInfo(new CommonScriptInfo()); + scriptProcessor.getCommonScriptInfo().setId(customFunction.getId()); + scriptProcessor.setEnableCommonScript(true); + KeyValueParam keyValueParam = new KeyValueParam(); + keyValueParam.setKey("a"); + keyValueParam.setValue("bb"); + scriptProcessor.getCommonScriptInfo().setParams(List.of(keyValueParam)); + msCommonElement.getPostProcessorConfig().getProcessors().add(scriptProcessor); + linkedList = new LinkedList(); linkedList.add(msCommonElement); msHTTPElement = MsHTTPElementTest.getMsHttpElement(); @@ -485,7 +511,6 @@ public class ApiDebugControllerTests extends BaseTest { request.setRequest(getMsElementParam(msHTTPElement)); this.requestPostWithOk(DEBUG, request); - // 测试请求体 MockMultipartFile file = getMockMultipartFile(); String fileId = doUploadTempFile(file); @@ -513,6 +538,19 @@ public class ApiDebugControllerTests extends BaseTest { requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_EXECUTE, DEBUG, request); } + private CustomFunction addCustomFunction() { + CustomFunctionRequest request = new CustomFunctionRequest(); + request.setScript("aaa"); + KeyValueEnableParam keyValueEnableParam = new KeyValueEnableParam(); + keyValueEnableParam.setKey("a"); + keyValueEnableParam.setValue("b"); + request.setParams(JSON.toJSONString(keyValueEnableParam)); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setType(ScriptLanguageType.BEANSHELL.name()); + request.setName(IDGenerator.nextStr()); + return customFunctionService.add(request, "admin"); + } + /** * 测试关联的文件更新 * diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java index 1b69ea59f7..ee9f56a809 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java @@ -348,11 +348,11 @@ public class ApiDefinitionControllerTests extends BaseTest { } if (apiDefinitionBlob != null) { AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class); - apiCommonService.updateLinkFileInfo(apiDefinition.getId(), msTestElement); + apiCommonService.setLinkFileInfo(apiDefinition.getId(), msTestElement); copyApiDefinitionDTO.setRequest(msTestElement); List httpResponses = ApiDataUtils.parseArray(new String(apiDefinitionBlob.getResponse()), HttpResponse.class); for (HttpResponse httpResponse : httpResponses) { - apiCommonService.updateLinkFileInfo(apiDefinition.getId(), httpResponse.getBody()); + apiCommonService.setLinkFileInfo(apiDefinition.getId(), httpResponse.getBody()); } copyApiDefinitionDTO.setResponse(httpResponses); } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java index 180674fb50..d4de5557da 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java @@ -415,12 +415,14 @@ public class ApiTestCaseControllerTests extends BaseTest { ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiTestCase.getApiDefinitionId()); copyApiDebugDTO.setMethod(apiDefinition.getMethod()); copyApiDebugDTO.setPath(apiDefinition.getPath()); - ApiTestCaseBlob apiDebugBlob = apiTestCaseBlobMapper.selectByPrimaryKey(apiTestCase.getId()); + ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMapper.selectByPrimaryKey(apiTestCase.getId()); ApiTestCaseFollowerExample example = new ApiTestCaseFollowerExample(); example.createCriteria().andCaseIdEqualTo(apiTestCase.getId()).andUserIdEqualTo("admin"); List followers = apiTestCaseFollowerMapper.selectByExample(example); copyApiDebugDTO.setFollow(CollectionUtils.isNotEmpty(followers)); - copyApiDebugDTO.setRequest(ApiDataUtils.parseObject(new String(apiDebugBlob.getRequest()), AbstractMsTestElement.class)); + AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class); + apiCommonService.setLinkFileInfo(apiTestCase.getId(), msTestElement); + copyApiDebugDTO.setRequest(msTestElement); Assertions.assertEquals(apiDebugDTO, copyApiDebugDTO); this.requestGetWithOk(GET + anotherApiTestCase.getId()) .andReturn(); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/MsHTTPElementTest.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/MsHTTPElementTest.java index 7bd6b212a5..5abdd18106 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/MsHTTPElementTest.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/MsHTTPElementTest.java @@ -27,6 +27,7 @@ import io.metersphere.project.api.processor.extract.RegexExtract; import io.metersphere.project.api.processor.extract.ResultMatchingExtract; import io.metersphere.project.api.processor.extract.XPathExtract; import io.metersphere.project.constants.ScriptLanguageType; +import io.metersphere.project.dto.CommonScriptInfo; import io.metersphere.sdk.constants.MsAssertionCondition; import io.metersphere.sdk.util.BeanUtils; import org.junit.jupiter.api.Assertions; @@ -363,7 +364,8 @@ public class MsHTTPElementTest { assertions.add(responseTimeAssertion); MsScriptAssertion scriptAssertion = new MsScriptAssertion(); - scriptAssertion.setScriptId("1111"); + scriptAssertion.setCommonScriptInfo(new CommonScriptInfo()); + scriptAssertion.getCommonScriptInfo().setId("1111"); scriptAssertion.setScript("1111"); scriptAssertion.setName("1111"); assertions.add(scriptAssertion); diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/api/assertion/MsScriptAssertion.java b/backend/services/project-management/src/main/java/io/metersphere/project/api/assertion/MsScriptAssertion.java index 9d2d39fc03..c81baa647a 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/api/assertion/MsScriptAssertion.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/api/assertion/MsScriptAssertion.java @@ -1,11 +1,12 @@ package io.metersphere.project.api.assertion; import com.fasterxml.jackson.annotation.JsonTypeName; -import io.metersphere.project.api.KeyValueParam; import io.metersphere.project.constants.ScriptLanguageType; +import io.metersphere.project.dto.CommonScriptInfo; +import jakarta.validation.Valid; import lombok.Data; - -import java.util.List; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; /** * 变量断言 @@ -27,13 +28,23 @@ public class MsScriptAssertion extends MsAssertion { /** * 是否启用公共脚本 */ - private Boolean enableCommonScript; + private Boolean enableCommonScript = false; /** - * 脚本ID + * 公共脚本信息 + * {@link CommonScriptInfo} */ - private String scriptId; - /** - * 公共脚本入参 - */ - private List params; + @Valid + private CommonScriptInfo commonScriptInfo; + + public boolean isValid() { + if (isEnableCommonScript()) { + return commonScriptInfo != null && StringUtils.isNotBlank(commonScriptInfo.getId()); + } else { + return StringUtils.isNotBlank(script); + } + } + + public boolean isEnableCommonScript() { + return BooleanUtils.isTrue(enableCommonScript); + } } diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/api/processor/ScriptProcessor.java b/backend/services/project-management/src/main/java/io/metersphere/project/api/processor/ScriptProcessor.java index e4a94ecf09..b99feeaf74 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/api/processor/ScriptProcessor.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/api/processor/ScriptProcessor.java @@ -2,16 +2,15 @@ package io.metersphere.project.api.processor; import com.fasterxml.jackson.annotation.JsonTypeName; import io.metersphere.project.constants.ScriptLanguageType; -import io.metersphere.project.api.KeyValueParam; +import io.metersphere.project.dto.CommonScriptInfo; import io.metersphere.system.valid.EnumValue; import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import java.util.List; - /** * @Author: jianxing @@ -29,6 +28,7 @@ public class ScriptProcessor extends MsProcessor { * {@link ScriptLanguageType} */ @Size(max = 20) + @NotBlank @EnumValue(enumClass = ScriptLanguageType.class) private String scriptLanguage; /** @@ -38,20 +38,22 @@ public class ScriptProcessor extends MsProcessor { */ private Boolean enableCommonScript = false; /** - * 公共脚本ID - */ - @Size(max = 50) - private String scriptId; - /** - * 公共脚本入参 + * 公共脚本信息 + * {@link CommonScriptInfo} */ @Valid - private List params; + private CommonScriptInfo commonScriptInfo; + public boolean isValid() { - if (BooleanUtils.isTrue(enableCommonScript) && StringUtils.isBlank(scriptId)) { - return false; + if (isEnableCommonScript()) { + return commonScriptInfo != null && StringUtils.isNotBlank(commonScriptInfo.getId()); + } else { + return StringUtils.isNotBlank(script); } - return StringUtils.isNotBlank(script); + } + + public boolean isEnableCommonScript() { + return BooleanUtils.isTrue(enableCommonScript); } } diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/dto/CommonScriptInfo.java b/backend/services/project-management/src/main/java/io/metersphere/project/dto/CommonScriptInfo.java new file mode 100644 index 0000000000..68166e0ff1 --- /dev/null +++ b/backend/services/project-management/src/main/java/io/metersphere/project/dto/CommonScriptInfo.java @@ -0,0 +1,40 @@ +package io.metersphere.project.dto; + +import io.metersphere.project.api.KeyValueParam; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +/** + * @Author: jianxing + * @CreateTime: 2024-02-23 13:34 + */ +@Data +public class CommonScriptInfo { + /** + * 公共脚本ID + */ + @Size(min = 1, max = 50) + private String id; + /** + * 公共脚本的名字 + * 页面展示需要 + */ + private String name; + /** + * 公共脚本的内容 + * 执行时设置 + */ + private String script; + /** + * 脚本语言 + */ + private String scriptLanguage; + /** + * 公共脚本入参 + */ + @Valid + private List params; +} diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java index 3670c31d30..745d319276 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/CustomFunctionService.java @@ -2,6 +2,7 @@ package io.metersphere.project.service; import io.metersphere.project.domain.CustomFunction; import io.metersphere.project.domain.CustomFunctionBlob; +import io.metersphere.project.domain.CustomFunctionBlobExample; import io.metersphere.project.domain.CustomFunctionExample; import io.metersphere.project.dto.customfunction.CustomFunctionDTO; import io.metersphere.project.dto.customfunction.request.CustomFunctionPageRequest; @@ -162,4 +163,23 @@ public class CustomFunctionService { } } + public List getBlobByIds(List commonScriptIds) { + if (CollectionUtils.isEmpty(commonScriptIds)) { + return List.of(); + } + CustomFunctionBlobExample example = new CustomFunctionBlobExample(); + example.createCriteria() + .andIdIn(commonScriptIds); + return customFunctionBlobMapper.selectByExampleWithBLOBs(example); + } + + public List getByIds(List commonScriptIds) { + if (CollectionUtils.isEmpty(commonScriptIds)) { + return List.of(); + } + CustomFunctionExample example = new CustomFunctionExample(); + example.createCriteria() + .andIdIn(commonScriptIds); + return customFunctionMapper.selectByExample(example); + } } diff --git a/backend/services/project-management/src/test/java/io/metersphere/project/controller/CustomFunctionControllerTests.java b/backend/services/project-management/src/test/java/io/metersphere/project/controller/CustomFunctionControllerTests.java index 461535bfad..f684bab6f8 100644 --- a/backend/services/project-management/src/test/java/io/metersphere/project/controller/CustomFunctionControllerTests.java +++ b/backend/services/project-management/src/test/java/io/metersphere/project/controller/CustomFunctionControllerTests.java @@ -9,6 +9,7 @@ import io.metersphere.project.dto.customfunction.request.CustomFunctionUpdateReq import io.metersphere.project.enums.result.ProjectResultCode; import io.metersphere.project.mapper.CustomFunctionBlobMapper; import io.metersphere.project.mapper.CustomFunctionMapper; +import io.metersphere.project.service.CustomFunctionService; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.JSON; @@ -29,6 +30,8 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * @author: LAN @@ -54,7 +57,8 @@ public class CustomFunctionControllerTests extends BaseTest { @Resource private CustomFunctionBlobMapper customFunctionBlobMapper; - + @Resource + private CustomFunctionService customFunctionService; @Test @Order(1) @@ -328,6 +332,16 @@ public class CustomFunctionControllerTests extends BaseTest { request.setFilter(filters); } + @Test + @Order(11) + public void testUncoveredFunc() { + // 在项目管理模块没有调用,手动调用 + customFunctionService.getBlobByIds(List.of()); + customFunctionService.getByIds(List.of()); + Assertions.assertEquals(customFunctionService.getBlobByIds(List.of(customFunction.getId())).size(), 1); + Assertions.assertEquals(customFunctionService.getByIds(List.of(customFunction.getId())).size(), 1); + } + @Test @Order(12) public void testDel() throws Exception { @@ -348,5 +362,4 @@ public class CustomFunctionControllerTests extends BaseTest { requestGetPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_DELETE, DELETE + "222"); } - } diff --git a/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java b/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java index 5a9c41ffd7..8121f52c79 100644 --- a/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java +++ b/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java @@ -6,6 +6,7 @@ import io.metersphere.project.api.assertion.*; import io.metersphere.project.api.assertion.body.*; import io.metersphere.project.api.processor.SQLProcessor; import io.metersphere.project.api.processor.ScriptProcessor; +import io.metersphere.project.dto.CommonScriptInfo; import io.metersphere.project.dto.environment.*; import io.metersphere.project.dto.environment.auth.AuthConfig; import io.metersphere.project.dto.environment.common.CommonParams; @@ -409,7 +410,8 @@ public class EnvironmentControllerTests extends BaseTest { assertions.add(responseTimeAssertion); MsScriptAssertion scriptAssertion = new MsScriptAssertion(); - scriptAssertion.setScriptId("1111"); + scriptAssertion.setCommonScriptInfo(new CommonScriptInfo()); + scriptAssertion.getCommonScriptInfo().setId("1111"); scriptAssertion.setScript("1111"); scriptAssertion.setName("1111"); assertions.add(scriptAssertion); @@ -671,7 +673,7 @@ public class EnvironmentControllerTests extends BaseTest { //校验日志 checkLog(response.getId(), OperationLogType.ADD); - //后置脚本 todo + //后置脚本 envConfig.setPostProcessorConfig(createEnvironmentProcessorConfig()); request.setName("postScript"); request.setConfig(envConfig);