feat(接口设置): 处理http环境配置解析
This commit is contained in:
parent
282f6493d9
commit
92cbcc1939
|
@ -3,6 +3,7 @@ package io.metersphere.api.dto;
|
|||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||
import io.metersphere.project.dto.environment.GlobalParams;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -18,10 +19,18 @@ public class ApiParamConfig extends ParameterConfig {
|
|||
* 报告ID
|
||||
*/
|
||||
private String reportId;
|
||||
/**
|
||||
* 使用全局cookie
|
||||
*/
|
||||
private Boolean enableGlobalCookie = true;
|
||||
/**
|
||||
* 环境配置信息
|
||||
*/
|
||||
private EnvironmentInfoDTO envConfig;
|
||||
/**
|
||||
* 全局参数
|
||||
*/
|
||||
private GlobalParams globalParams;
|
||||
/**
|
||||
* AbstractMsTestElement 实现类与插件 ID 的映射
|
||||
* key 为 AbstractMsTestElement 实现类对象
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: jianxing
|
||||
* @CreateTime: 2024-02-17 18:46
|
||||
*/
|
||||
@Data
|
||||
public class ApiResourceModuleInfo {
|
||||
/**
|
||||
* 模块Id
|
||||
*/
|
||||
private String moduleId;
|
||||
/**
|
||||
* 资源id,接口定义,接口用例等
|
||||
*/
|
||||
private String resourceId;
|
||||
}
|
|
@ -15,8 +15,6 @@ public class ApiDebugRunRequest {
|
|||
@Schema(description = "报告ID")
|
||||
@NotNull
|
||||
private String reportId;
|
||||
@Schema(description = "环境ID")
|
||||
private String environmentId;
|
||||
@Schema(description = "点击调试时尚未保存的文件ID列表")
|
||||
private List<String> tempFileIds;
|
||||
@NotNull
|
||||
|
|
|
@ -43,6 +43,7 @@ public class MsScenario extends AbstractMsTestElement {
|
|||
private Boolean grouped;
|
||||
/**
|
||||
* {@link io.metersphere.api.constants.ApiScenarioStepRefType}
|
||||
* DIRECT 表示当前根场景
|
||||
*/
|
||||
private String refType;
|
||||
}
|
||||
|
|
|
@ -72,4 +72,9 @@ public class MsHTTPElement extends AbstractMsTestElement {
|
|||
*/
|
||||
@Valid
|
||||
private HTTPAuth authConfig;
|
||||
/**
|
||||
* 模块ID
|
||||
* 运行时参数,接口无需设置
|
||||
*/
|
||||
private String moduleId;
|
||||
}
|
|
@ -15,7 +15,7 @@ public class ScenarioOtherConfig {
|
|||
/**
|
||||
* 是否共享cookie
|
||||
*/
|
||||
private Boolean enableCookieShare;
|
||||
private Boolean enableCookieShare = false;
|
||||
/**
|
||||
* 场景步骤等待时间
|
||||
* 每一个步骤执行后都会等待相应的时间
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.mapper;
|
|||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.domain.ApiDefinitionCustomField;
|
||||
import io.metersphere.api.dto.ApiResourceModuleInfo;
|
||||
import io.metersphere.api.dto.converter.ApiDefinitionImportDetail;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.scenario.ScenarioSystemRequest;
|
||||
|
@ -61,4 +62,6 @@ public interface ExtApiDefinitionMapper {
|
|||
Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos);
|
||||
|
||||
Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos);
|
||||
|
||||
List<ApiResourceModuleInfo> getModuleInfoByIds(@Param("ids") List<String> ids);
|
||||
}
|
||||
|
|
|
@ -541,4 +541,12 @@
|
|||
</if>
|
||||
order by `pos` desc limit 1;
|
||||
</select>
|
||||
<select id="getModuleInfoByIds" resultType="io.metersphere.api.dto.ApiResourceModuleInfo">
|
||||
select id as resource_id, module_id
|
||||
from api_definition
|
||||
where id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
@ -34,4 +34,6 @@ public interface ExtApiDefinitionModuleMapper {
|
|||
List<BaseTreeNode> selectNodeByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<BaseTreeNode> selectBaseByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<String> getModuleIdsByParentIds(@Param("parentIds") List<String> parentIds);
|
||||
}
|
||||
|
|
|
@ -115,6 +115,14 @@
|
|||
</foreach>
|
||||
ORDER BY pos
|
||||
</select>
|
||||
<select id="getModuleIdsByParentIds" resultType="java.lang.String">
|
||||
SELECT id
|
||||
FROM api_definition_module
|
||||
WHERE parent_id IN
|
||||
<foreach collection="parentIds" item="parentId" open="(" separator="," close=")">
|
||||
#{parentId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<sql id="api_request">
|
||||
<where>
|
||||
|
|
|
@ -10,10 +10,12 @@ import io.metersphere.request.AssociateOtherCaseRequest;
|
|||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||
import org.apache.ibatis.annotations.MapKey;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author jianxing
|
||||
|
@ -62,4 +64,6 @@ public interface ExtApiTestCaseMapper {
|
|||
List<OptionDTO> selectVersionOptionByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<String> getIdsByModules(@Param("request") ScenarioSystemRequest caseRequest);
|
||||
|
||||
List<ApiTestCase> getApiCaseDefinitionInfo(@Param("ids") List<String> ids);
|
||||
}
|
|
@ -274,6 +274,14 @@
|
|||
and api_test_case.version_id = #{request.versionId}
|
||||
</if>
|
||||
</select>
|
||||
<select id="getApiCaseDefinitionInfo" resultType="io.metersphere.api.domain.ApiTestCase">
|
||||
select api_definition_id, id
|
||||
from api_test_case
|
||||
where id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
<sql id="report_filters">
|
||||
<if test="${filter} != null and ${filter}.size() > 0">
|
||||
<foreach collection="${filter}.entrySet()" index="key" item="values">
|
||||
|
|
|
@ -1,24 +1,42 @@
|
|||
package io.metersphere.api.parser.jmeter;
|
||||
|
||||
|
||||
import io.metersphere.api.dto.ApiParamConfig;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.dto.request.http.QueryParam;
|
||||
import io.metersphere.api.dto.request.http.body.Body;
|
||||
import io.metersphere.api.parser.jmeter.body.MsBodyConverter;
|
||||
import io.metersphere.api.parser.jmeter.body.MsBodyConverterFactory;
|
||||
import io.metersphere.api.parser.jmeter.body.MsFormDataBodyConverter;
|
||||
import io.metersphere.api.parser.jmeter.body.MsWWWFormBodyConverter;
|
||||
import io.metersphere.jmeter.mock.Mock;
|
||||
import io.metersphere.plugin.api.constants.ElementProperty;
|
||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
||||
import io.metersphere.project.api.KeyValueEnableParam;
|
||||
import io.metersphere.project.api.KeyValueParam;
|
||||
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||
import io.metersphere.project.dto.environment.GlobalParams;
|
||||
import io.metersphere.project.dto.environment.http.HttpConfig;
|
||||
import io.metersphere.project.dto.environment.http.HttpConfigPathMatchRule;
|
||||
import io.metersphere.project.dto.environment.http.SelectModule;
|
||||
import io.metersphere.sdk.util.EnumValidator;
|
||||
import io.metersphere.sdk.util.LogUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.protocol.http.control.Header;
|
||||
import org.apache.jmeter.protocol.http.control.HeaderManager;
|
||||
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.metersphere.api.parser.jmeter.constants.JmeterAlias.HEADER_PANEL;
|
||||
import static io.metersphere.api.parser.jmeter.constants.JmeterAlias.HTTP_TEST_SAMPLE_GUI;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +47,8 @@ import static io.metersphere.api.parser.jmeter.constants.JmeterAlias.HTTP_TEST_S
|
|||
*/
|
||||
public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTTPElement> {
|
||||
|
||||
private ParameterConfig config;
|
||||
public static final String URL_ENCODE = "${__urlencode(%s)}";
|
||||
public static final String COOKIE = "Cookie";
|
||||
|
||||
@Override
|
||||
public void toHashTree(HashTree tree, MsHTTPElement msHTTPElement, ParameterConfig config) {
|
||||
|
@ -37,26 +56,161 @@ public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTT
|
|||
LogUtils.info("MsHTTPElement is disabled");
|
||||
return;
|
||||
}
|
||||
this.config = config;
|
||||
|
||||
ApiParamConfig apiParamConfig = (ApiParamConfig) config;
|
||||
HttpConfig httpConfig = getHttpConfig(msHTTPElement, apiParamConfig);
|
||||
|
||||
HTTPSamplerProxy sampler = new HTTPSamplerProxy();
|
||||
sampler.setName(msHTTPElement.getName());
|
||||
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(HTTP_TEST_SAMPLE_GUI));
|
||||
|
||||
// TODO: 当前步骤唯一标识,很重要,结果和步骤匹配的关键
|
||||
setStepIdentification(msHTTPElement, config, sampler);
|
||||
|
||||
sampler.setMethod(msHTTPElement.getMethod());
|
||||
// path 设置完整的url
|
||||
sampler.setPath(getPath(msHTTPElement, httpConfig));
|
||||
|
||||
// 处理请求体
|
||||
handleBody(sampler, msHTTPElement, config);
|
||||
|
||||
HashTree httpTree = tree.add(sampler);
|
||||
// 处理请求头
|
||||
HeaderManager httpHeader = getHttpHeader(msHTTPElement, apiParamConfig, httpConfig);
|
||||
if (httpHeader != null) {
|
||||
httpTree.add(httpHeader);
|
||||
}
|
||||
|
||||
parseChild(httpTree, msHTTPElement, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置步骤标识
|
||||
* 当前步骤唯一标识,结果和步骤匹配的关键
|
||||
* @param msHTTPElement
|
||||
* @param config
|
||||
* @param sampler
|
||||
*/
|
||||
private void setStepIdentification(MsHTTPElement msHTTPElement, ParameterConfig config, HTTPSamplerProxy sampler) {
|
||||
sampler.setProperty(ElementProperty.MS_RESOURCE_ID.name(), msHTTPElement.getResourceId());
|
||||
sampler.setProperty(ElementProperty.MS_STEP_ID.name(), msHTTPElement.getStepId());
|
||||
sampler.setProperty(ElementProperty.MS_REPORT_ID.name(), config.getReportId());
|
||||
sampler.setProperty(ElementProperty.PROJECT_ID.name(), msHTTPElement.getProjectId());
|
||||
}
|
||||
|
||||
sampler.setMethod(msHTTPElement.getMethod());
|
||||
// todo 根据环境设置
|
||||
sampler.setDomain(msHTTPElement.getUrl());
|
||||
sampler.setPath(msHTTPElement.getPath());
|
||||
private String getPath(MsHTTPElement msHTTPElement, HttpConfig httpConfig) {
|
||||
String url = msHTTPElement.getPath();
|
||||
if (httpConfig != null) {
|
||||
// 接口调试没有环境,不取环境的配置
|
||||
String protocol = httpConfig.getProtocol().toLowerCase();
|
||||
url = protocol + "://" + (httpConfig.getUrl() + "/" + url).replace("//", "/");
|
||||
}
|
||||
return getPathWithQuery(url, msHTTPElement.getQuery());
|
||||
}
|
||||
|
||||
handleBody(sampler, msHTTPElement);
|
||||
HashTree httpTree = tree.add(sampler);
|
||||
parseChild(httpTree, msHTTPElement, config);
|
||||
private HeaderManager getHttpHeader(MsHTTPElement msHTTPElement, ApiParamConfig apiParamConfig, HttpConfig httpConfig) {
|
||||
Map<String, String> headerMap = new HashMap<>();
|
||||
|
||||
// 获取全局参数中的请求头
|
||||
GlobalParams globalParams = apiParamConfig.getGlobalParams();
|
||||
if (globalParams != null) {
|
||||
setHeaderMap(headerMap, globalParams.getHeaders());
|
||||
}
|
||||
|
||||
// 获取环境中的请求头
|
||||
if (httpConfig != null && CollectionUtils.isNotEmpty(httpConfig.getHeaders())) {
|
||||
Boolean enableGlobalCookie = apiParamConfig.getEnableGlobalCookie();
|
||||
List<KeyValueEnableParam> envHeaders = httpConfig.getHeaders();
|
||||
if (BooleanUtils.isFalse(enableGlobalCookie)) {
|
||||
// 如果不启用全局 cookie,则过滤 cookie
|
||||
envHeaders = envHeaders.stream()
|
||||
.filter(header -> !StringUtils.equalsIgnoreCase(header.getKey(), COOKIE))
|
||||
.toList();
|
||||
}
|
||||
setHeaderMap(headerMap, envHeaders);
|
||||
}
|
||||
|
||||
// 获取请求中的请求头
|
||||
if (CollectionUtils.isNotEmpty(msHTTPElement.getHeaders())) {
|
||||
setHeaderMap(headerMap, msHTTPElement.getHeaders());
|
||||
}
|
||||
|
||||
if (headerMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HeaderManager headerManager = new HeaderManager();
|
||||
headerManager.setEnabled(true);
|
||||
headerManager.setName(StringUtils.isNotEmpty(msHTTPElement.getName()) ? msHTTPElement.getName() + "_HeaderManager" : "HeaderManager");
|
||||
headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName());
|
||||
headerManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(HEADER_PANEL));
|
||||
headerMap.forEach((k, v) -> headerManager.add(new Header(k, Mock.buildFunctionCallString(v))));
|
||||
return headerManager;
|
||||
}
|
||||
|
||||
private void setHeaderMap(Map<String, String> headerMap, List<? extends KeyValueEnableParam> headers) {
|
||||
if (CollectionUtils.isEmpty(headers)) {
|
||||
return;
|
||||
}
|
||||
headers.stream()
|
||||
.filter(KeyValueEnableParam::getEnable)
|
||||
.filter(KeyValueParam::isValid)
|
||||
.forEach(header -> {
|
||||
if (StringUtils.equalsIgnoreCase(header.getKey(), COOKIE)) {
|
||||
String cookieValue = header.getValue();
|
||||
if (headerMap.get(COOKIE) != null && header.getValue() != null) {
|
||||
// 合并 cookie
|
||||
cookieValue = headerMap.get(COOKIE) + ";" + header.getValue();
|
||||
}
|
||||
headerMap.put(COOKIE, cookieValue);
|
||||
} else {
|
||||
headerMap.put(header.getKey(), header.getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取环境 http 配置
|
||||
*
|
||||
* @param msHTTPElement
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
private HttpConfig getHttpConfig(MsHTTPElement msHTTPElement, ApiParamConfig config) {
|
||||
ApiParamConfig apiParamConfig = config;
|
||||
EnvironmentInfoDTO envConfig = apiParamConfig.getEnvConfig();
|
||||
if (envConfig == null) {
|
||||
return null;
|
||||
}
|
||||
// http配置按优先级排序
|
||||
List<HttpConfig> httpConfigs = envConfig.getConfig().getHttpConfig()
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(HttpConfig::getModuleMatchRuleOrder))
|
||||
.toList();
|
||||
for (HttpConfig httpConfig : httpConfigs) {
|
||||
boolean match;
|
||||
if (httpConfig.isPathMatchRule()) {
|
||||
// 匹配路径
|
||||
HttpConfigPathMatchRule pathMatchRule = httpConfig.getPathMatchRule();
|
||||
HttpConfigPathMatchRule.MatchRuleCondition matchRuleCondition =
|
||||
EnumValidator.validateEnum(HttpConfigPathMatchRule.MatchRuleCondition.class, pathMatchRule.getCondition());
|
||||
match = matchRuleCondition.match(pathMatchRule.getPath(), msHTTPElement.getPath());
|
||||
} else if (httpConfig.isModuleMatchRule()) {
|
||||
// 匹配模块
|
||||
Set<String> moduleIds = httpConfig.getModuleMatchRule().getModules()
|
||||
.stream()
|
||||
.map(SelectModule::getModuleId)
|
||||
.collect(Collectors.toSet());
|
||||
match = moduleIds.contains(msHTTPElement.getModuleId());
|
||||
} else {
|
||||
// 无条件匹配
|
||||
match = true;
|
||||
}
|
||||
if (match) {
|
||||
return httpConfig;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +219,7 @@ public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTT
|
|||
* @param sampler
|
||||
* @param msHTTPElement
|
||||
*/
|
||||
private void handleBody(HTTPSamplerProxy sampler, MsHTTPElement msHTTPElement) {
|
||||
private void handleBody(HTTPSamplerProxy sampler, MsHTTPElement msHTTPElement, ParameterConfig config) {
|
||||
Body body = msHTTPElement.getBody();
|
||||
// 请求体处理
|
||||
if (body != null) {
|
||||
|
@ -80,4 +234,44 @@ public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTT
|
|||
converter.parse(sampler, body.getBodyDataByType(), config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 query 参数添加到 url 上
|
||||
*
|
||||
* @param path
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
private String getPathWithQuery(String path, List<QueryParam> query) {
|
||||
if (CollectionUtils.isEmpty(query)) {
|
||||
return path;
|
||||
}
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
stringBuffer.append(path);
|
||||
if (path.contains("?")) {
|
||||
stringBuffer.append("&");
|
||||
} else {
|
||||
stringBuffer.append("?");
|
||||
}
|
||||
query.stream()
|
||||
.filter(KeyValueEnableParam::getEnable)
|
||||
.filter(KeyValueParam::isValid)
|
||||
.forEach(queryParam -> {
|
||||
stringBuffer.append(queryParam.getEncode() ? String.format(URL_ENCODE, queryParam.getKey()) : queryParam.getKey());
|
||||
if (queryParam.getValue() != null) {
|
||||
try {
|
||||
String value = queryParam.getValue().startsWith("@") ? Mock.buildFunctionCallString(queryParam.getValue()) : queryParam.getValue();
|
||||
value = queryParam.getEncode() ? String.format(URL_ENCODE, value.replace(",", "\\,")) : value;
|
||||
if (StringUtils.isNotEmpty(value) && value.contains(StringUtils.CR)) {
|
||||
value = value.replaceAll(StringUtils.CR, StringUtils.EMPTY);
|
||||
}
|
||||
stringBuffer.append("=").append(value);
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(e);
|
||||
}
|
||||
}
|
||||
stringBuffer.append("&");
|
||||
});
|
||||
return stringBuffer.substring(0, stringBuffer.length() - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,17 @@ import io.metersphere.sdk.util.BeanUtils;
|
|||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.protocol.http.control.CookieManager;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static io.metersphere.api.parser.jmeter.constants.JmeterAlias.COOKIE_PANEL;
|
||||
|
||||
/**
|
||||
* @Author: jianxing
|
||||
* @CreateTime: 2023-10-27 10:07
|
||||
|
@ -40,11 +45,17 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
|||
ApiScenarioParamConfig config = (ApiScenarioParamConfig) msParameter;
|
||||
EnvironmentInfoDTO envInfo = config.getEnvConfig(msScenario.getProjectId());
|
||||
|
||||
if (isRootScenario(msScenario.getRefType()) && msScenario.getScenarioConfig().getOtherConfig().getEnableGlobalCookie()) {
|
||||
// 根场景,设置共享cookie
|
||||
tree.add(getCookieManager());
|
||||
}
|
||||
|
||||
// 添加环境的前置
|
||||
addEnvScenarioProcessor(tree, msScenario, config, envInfo, true);
|
||||
// 添加场景前置
|
||||
addScenarioProcessor(tree, msScenario, config, true);
|
||||
|
||||
// 解析子步骤
|
||||
ApiScenarioParamConfig chileConfig = getChileConfig(msScenario, config);
|
||||
parseChild(tree, msScenario, chileConfig);
|
||||
|
||||
|
@ -165,6 +176,10 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
|||
return StringUtils.equalsAny(refType, ApiScenarioStepRefType.REF.name(), ApiScenarioStepRefType.PARTIAL_REF.name());
|
||||
}
|
||||
|
||||
private boolean isRootScenario(String refType) {
|
||||
return StringUtils.equals(refType, ApiScenarioStepRefType.DIRECT.name());
|
||||
}
|
||||
|
||||
private boolean isCopy(String refType) {
|
||||
return StringUtils.equals(refType, ApiScenarioStepRefType.COPY.name());
|
||||
}
|
||||
|
@ -178,29 +193,47 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
|||
* @return
|
||||
*/
|
||||
private ApiScenarioParamConfig getChileConfig(MsScenario msScenario, ApiScenarioParamConfig config) {
|
||||
ApiScenarioParamConfig childConfig = config;
|
||||
if (!isRef(msScenario.getRefType())) {
|
||||
// 非引用的场景,使用当前环境参数
|
||||
return config;
|
||||
return childConfig;
|
||||
}
|
||||
ScenarioStepConfig scenarioStepConfig = msScenario.getScenarioStepConfig();
|
||||
if (scenarioStepConfig != null && BooleanUtils.isTrue(scenarioStepConfig.getEnableScenarioEnv())) {
|
||||
// 使用源场景环境
|
||||
ApiScenarioParamConfig chileConfig = BeanUtils.copyBean(new ApiScenarioParamConfig(), config);
|
||||
chileConfig.setGrouped(msScenario.getGrouped());
|
||||
childConfig = BeanUtils.copyBean(new ApiScenarioParamConfig(), config);
|
||||
childConfig.setGrouped(msScenario.getGrouped());
|
||||
// 清空环境信息
|
||||
chileConfig.setEnvConfig(null);
|
||||
chileConfig.setProjectEnvMap(null);
|
||||
childConfig.setEnvConfig(null);
|
||||
childConfig.setProjectEnvMap(null);
|
||||
if (BooleanUtils.isTrue(msScenario.getGrouped())) {
|
||||
// 环境组设置环境Map
|
||||
Map<String, EnvironmentInfoDTO> projectEnvMap = msScenario.getProjectEnvMap();
|
||||
chileConfig.setProjectEnvMap(projectEnvMap);
|
||||
childConfig.setProjectEnvMap(projectEnvMap);
|
||||
} else {
|
||||
// 设置环境信息
|
||||
EnvironmentInfoDTO environmentInfo = msScenario.getEnvironmentInfo();
|
||||
chileConfig.setEnvConfig(environmentInfo);
|
||||
childConfig.setEnvConfig(environmentInfo);
|
||||
}
|
||||
return chileConfig;
|
||||
}
|
||||
return config;
|
||||
|
||||
ScenarioConfig scenarioConfig = msScenario.getScenarioConfig();
|
||||
if (scenarioConfig != null) {
|
||||
// 设置是否使用全局cookie
|
||||
childConfig.setEnableGlobalCookie(scenarioConfig.getOtherConfig().getEnableCookieShare());
|
||||
}
|
||||
|
||||
return childConfig;
|
||||
}
|
||||
|
||||
private CookieManager getCookieManager() {
|
||||
CookieManager cookieManager = new CookieManager();
|
||||
cookieManager.setProperty(TestElement.TEST_CLASS, CookieManager.class.getName());
|
||||
cookieManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(COOKIE_PANEL));
|
||||
cookieManager.setEnabled(true);
|
||||
cookieManager.setName("CookieManager");
|
||||
cookieManager.setClearEachIteration(false);
|
||||
cookieManager.setControlledByThread(false);
|
||||
return cookieManager;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,6 @@ public class JmeterAlias {
|
|||
public static final String XPATH_ASSERTION_GUI = "XPathAssertionGui";
|
||||
public static final String X_PATH_2_ASSERTION_GUI = "XPath2AssertionGui";
|
||||
public static final String USER_PARAMETERS_GUI = "UserParametersGui";
|
||||
public static final String COOKIE_PANEL = "CookiePanel";
|
||||
public static final String HEADER_PANEL = "HeaderPanel";
|
||||
}
|
||||
|
|
|
@ -13,10 +13,9 @@ import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
|||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.project.domain.ProjectApplication;
|
||||
import io.metersphere.project.dto.customfunction.request.CustomFunctionRunRequest;
|
||||
import io.metersphere.project.service.FileAssociationService;
|
||||
import io.metersphere.project.service.FileManagementService;
|
||||
import io.metersphere.project.service.FileMetadataService;
|
||||
import io.metersphere.project.service.ProjectApplicationService;
|
||||
import io.metersphere.project.dto.environment.GlobalParams;
|
||||
import io.metersphere.project.dto.environment.GlobalParamsDTO;
|
||||
import io.metersphere.project.service.*;
|
||||
import io.metersphere.sdk.constants.ApiExecuteResourceType;
|
||||
import io.metersphere.sdk.constants.ApiExecuteRunMode;
|
||||
import io.metersphere.sdk.constants.ProjectApplicationType;
|
||||
|
@ -82,6 +81,8 @@ public class ApiExecuteService {
|
|||
private FileManagementService fileManagementService;
|
||||
@Resource
|
||||
private ApiPluginService apiPluginService;
|
||||
@Resource
|
||||
private GlobalParamsService globalParamsService;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
|
@ -128,6 +129,8 @@ public class ApiExecuteService {
|
|||
taskRequest.setMsRegexList(projectApplicationService.get(Collections.singletonList(request.getProjectId())));
|
||||
}
|
||||
|
||||
parameterConfig.setGlobalParams(getGlobalParam(request));
|
||||
|
||||
// todo 获取接口插件和jar包
|
||||
// todo 处理公共脚本
|
||||
// todo 接口用例 method 获取定义中的数据库字段
|
||||
|
@ -136,6 +139,14 @@ public class ApiExecuteService {
|
|||
doDebug(reportId, testId, taskRequest, executeScript, request.getProjectId());
|
||||
}
|
||||
|
||||
private GlobalParams getGlobalParam(ApiResourceRunRequest request) {
|
||||
GlobalParamsDTO globalParamsDTO = globalParamsService.get(request.getProjectId());
|
||||
if (globalParamsDTO != null) {
|
||||
return globalParamsDTO.getGlobalParams();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送执行任务
|
||||
*
|
||||
|
|
|
@ -13,8 +13,6 @@ import io.metersphere.api.service.ApiExecuteService;
|
|||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||
import io.metersphere.project.service.EnvironmentService;
|
||||
import io.metersphere.project.service.ProjectService;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
|
@ -55,8 +53,6 @@ public class ApiDebugService {
|
|||
private ApiExecuteService apiExecuteService;
|
||||
@Resource
|
||||
private ApiPluginService apiPluginService;
|
||||
@Resource
|
||||
private EnvironmentService environmentService;
|
||||
|
||||
public static final Long ORDER_STEP = 5000L;
|
||||
|
||||
|
@ -203,19 +199,13 @@ public class ApiDebugService {
|
|||
runRequest.setTestId(id);
|
||||
runRequest.setReportId(reportId);
|
||||
runRequest.setResourceType(ApiResourceType.API_DEBUG.name());
|
||||
runRequest.setEnvironmentId(request.getEnvironmentId());
|
||||
runRequest.setTestElement(ApiDataUtils.parseObject(JSON.toJSONString(request.getRequest()), AbstractMsTestElement.class));
|
||||
|
||||
ApiParamConfig paramConfig = new ApiParamConfig();
|
||||
paramConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap());
|
||||
paramConfig.setTestElementClassProtocalMap(apiPluginService.getTestElementProtocolMap());
|
||||
paramConfig.setReportId(reportId);
|
||||
EnvironmentInfoDTO environmentInfoDTO = environmentService.get(request.getEnvironmentId());
|
||||
// 设置环境
|
||||
paramConfig.setEnvConfig(environmentInfoDTO);
|
||||
|
||||
apiExecuteService.debug(runRequest, paramConfig);
|
||||
|
||||
return runRequest.getReportId();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -346,5 +347,10 @@ public class ApiDefinitionModuleService extends ModuleTreeService {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
public List<String> getModuleIdsByParentIds(List<String> parentIds) {
|
||||
if (CollectionUtils.isEmpty(parentIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return extApiDefinitionModuleMapper.getModuleIdsByParentIds(parentIds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import io.metersphere.api.constants.ApiDefinitionDocType;
|
|||
import io.metersphere.api.constants.ApiResourceType;
|
||||
import io.metersphere.api.controller.result.ApiResultCode;
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.ApiResourceModuleInfo;
|
||||
import io.metersphere.api.dto.converter.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
|
@ -1024,4 +1025,8 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<ApiResourceModuleInfo> getModuleInfoByIds(List<String> apiIds) {
|
||||
return extApiDefinitionMapper.getModuleInfoByIds(apiIds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.service.definition;
|
|||
|
||||
import io.metersphere.api.constants.ApiResourceType;
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.ApiResourceModuleInfo;
|
||||
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
|
@ -81,6 +82,8 @@ public class ApiTestCaseService {
|
|||
private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
|
||||
@Resource
|
||||
private OperationHistoryService operationHistoryService;
|
||||
@Resource
|
||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||
private static final String CASE_TABLE = "api_test_case";
|
||||
|
||||
private void checkProjectExist(String projectId) {
|
||||
|
@ -581,4 +584,18 @@ public class ApiTestCaseService {
|
|||
update.setUpdateTime(System.currentTimeMillis());
|
||||
apiTestCaseMapper.updateByPrimaryKeySelective(update);
|
||||
}
|
||||
|
||||
public List<ApiResourceModuleInfo> getModuleInfoByIds(List<String> ids) {
|
||||
// 获取接口定义ID和用例ID的映射
|
||||
Map<String, String> apiCaseDefinitionMap = extApiTestCaseMapper.getApiCaseDefinitionInfo(ids)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ApiTestCase::getApiDefinitionId, ApiTestCase::getId));
|
||||
|
||||
List<String> definitionIds = apiCaseDefinitionMap.keySet().stream().collect(Collectors.toList());
|
||||
List<ApiResourceModuleInfo> moduleInfos = extApiDefinitionMapper.getModuleInfoByIds(definitionIds);
|
||||
// 将 resourceId 从定义ID替换成用例ID
|
||||
moduleInfos.forEach(moduleInfo ->
|
||||
moduleInfo.setResourceId(apiCaseDefinitionMap.get(moduleInfo.getResourceId())));
|
||||
return moduleInfos;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ import io.metersphere.api.constants.ApiResourceType;
|
|||
import io.metersphere.api.constants.ApiScenarioStepRefType;
|
||||
import io.metersphere.api.constants.ApiScenarioStepType;
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.ApiResourceModuleInfo;
|
||||
import io.metersphere.api.dto.ApiScenarioParamConfig;
|
||||
import io.metersphere.api.dto.ApiScenarioParseEnvInfo;
|
||||
import io.metersphere.api.dto.EnvironmentModeDTO;
|
||||
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
||||
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
|
||||
import io.metersphere.api.dto.request.MsScenario;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||
import io.metersphere.api.dto.scenario.*;
|
||||
import io.metersphere.api.job.ApiScenarioScheduleJob;
|
||||
|
@ -18,6 +20,7 @@ import io.metersphere.api.parser.step.StepParser;
|
|||
import io.metersphere.api.parser.step.StepParserFactory;
|
||||
import io.metersphere.api.service.ApiExecuteService;
|
||||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionModuleService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||
import io.metersphere.api.service.definition.ApiTestCaseService;
|
||||
import io.metersphere.api.utils.ApiScenarioBatchOperationUtils;
|
||||
|
@ -26,10 +29,16 @@ import io.metersphere.project.domain.FileMetadata;
|
|||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.domain.ProjectExample;
|
||||
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||
import io.metersphere.project.dto.environment.http.HttpConfig;
|
||||
import io.metersphere.project.dto.environment.http.HttpConfigModuleMatchRule;
|
||||
import io.metersphere.project.dto.environment.http.SelectModule;
|
||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.project.service.*;
|
||||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.constants.ScheduleResourceType;
|
||||
import io.metersphere.sdk.domain.Environment;
|
||||
import io.metersphere.sdk.domain.EnvironmentExample;
|
||||
import io.metersphere.sdk.domain.EnvironmentGroup;
|
||||
|
@ -157,6 +166,8 @@ public class ApiScenarioService {
|
|||
private ApiTestCaseMapper apiTestCaseMapper;
|
||||
@Resource
|
||||
private ExtApiTestCaseMapper extApiTestCaseMapper;
|
||||
@Resource
|
||||
private ApiDefinitionModuleService apiDefinitionModuleService;
|
||||
|
||||
public static final String PRIORITY = "Priority";
|
||||
public static final String STATUS = "Status";
|
||||
|
@ -1046,7 +1057,10 @@ public class ApiScenarioService {
|
|||
|
||||
// 获取场景环境相关配置
|
||||
ApiScenarioParseEnvInfo scenarioParseEnvInfo = getScenarioParseEnvInfo(refResourceMap, request.getEnvironmentId(), request.getGrouped());
|
||||
parseStep2MsElement(msScenario, steps, resourceBlobMap, detailMap, scenarioParseEnvInfo);
|
||||
Map<String, List<MsHTTPElement>> stepTypeHttpElementMap = new HashMap<>();
|
||||
parseStep2MsElement(msScenario, steps, resourceBlobMap, detailMap, stepTypeHttpElementMap, scenarioParseEnvInfo);
|
||||
// 设置 HttpElement 的模块信息
|
||||
setHttpElementModuleId(stepTypeHttpElementMap);
|
||||
|
||||
ApiResourceRunRequest runRequest = BeanUtils.copyBean(new ApiResourceRunRequest(), request);
|
||||
runRequest.setProjectId(request.getProjectId());
|
||||
|
@ -1063,7 +1077,6 @@ public class ApiScenarioService {
|
|||
parseConfig.setTestElementClassProtocalMap(apiPluginService.getTestElementProtocolMap());
|
||||
parseConfig.setGrouped(request.getGrouped());
|
||||
parseConfig.setReportId(request.getReportId());
|
||||
scenarioParseEnvInfo.getPluginClassEnvConfigMap();
|
||||
if (BooleanUtils.isTrue(request.getGrouped())) {
|
||||
// 设置环境组 map
|
||||
parseConfig.setProjectEnvMap(getProjectEnvMap(scenarioParseEnvInfo, request.getEnvironmentId()));
|
||||
|
@ -1073,10 +1086,33 @@ public class ApiScenarioService {
|
|||
}
|
||||
|
||||
apiExecuteService.debug(runRequest, parseConfig);
|
||||
|
||||
return request.getReportId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 HttpElement 的模块信息
|
||||
* 用户环境中的模块过滤
|
||||
* @param stepTypeHttpElementMap
|
||||
*/
|
||||
private void setHttpElementModuleId(Map<String, List<MsHTTPElement>> stepTypeHttpElementMap) {
|
||||
setHttpElementModuleId(stepTypeHttpElementMap.get(ApiScenarioStepType.API.name()), apiDefinitionService::getModuleInfoByIds);
|
||||
setHttpElementModuleId(stepTypeHttpElementMap.get(ApiScenarioStepType.API_CASE.name()), apiTestCaseService::getModuleInfoByIds);
|
||||
}
|
||||
|
||||
private void setHttpElementModuleId(List<MsHTTPElement> httpElements, Function<List<String>, List<ApiResourceModuleInfo>> getModuleInfoFunc) {
|
||||
if (CollectionUtils.isNotEmpty(httpElements)) {
|
||||
List<String> apiIds = httpElements.stream().map(MsHTTPElement::getResourceId).collect(Collectors.toList());
|
||||
// 获取接口模块信息
|
||||
Map<String, String> resourceModuleMap = getModuleInfoFunc.apply(apiIds)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ApiResourceModuleInfo::getResourceId, ApiResourceModuleInfo::getModuleId));
|
||||
httpElements.forEach(httpElement -> {
|
||||
// httpElement 设置模块信息
|
||||
httpElement.setModuleId(resourceModuleMap.get(httpElement.getResourceId()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置脚本解析-环境相关参数
|
||||
*/
|
||||
|
@ -1128,9 +1164,48 @@ public class ApiScenarioService {
|
|||
|
||||
envInfo.setEnvGroupMap(envGroupMap);
|
||||
envInfo.setEnvMap(envMap);
|
||||
|
||||
envMap.forEach((envId, envInfoDTO) -> handleHttpModuleMatchRule(envInfoDTO));
|
||||
|
||||
return envInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理环境的 HTTP 配置模块匹配规则
|
||||
* 查询新增子模块
|
||||
* @param envInfoDTO
|
||||
*/
|
||||
private void handleHttpModuleMatchRule(EnvironmentInfoDTO envInfoDTO) {
|
||||
List<HttpConfig> httpConfigs = envInfoDTO.getConfig().getHttpConfig();
|
||||
for (HttpConfig httpConfig : httpConfigs) {
|
||||
if (!httpConfig.isModuleMatchRule()) {
|
||||
continue;
|
||||
}
|
||||
// 获取勾选了包含子模块的模块ID
|
||||
HttpConfigModuleMatchRule moduleMatchRule = httpConfig.getModuleMatchRule();
|
||||
List<SelectModule> selectModules = moduleMatchRule.getModules();
|
||||
List<String> containChildModuleIds = selectModules.stream()
|
||||
.filter(SelectModule::getContainChildModule)
|
||||
.map(SelectModule::getModuleId)
|
||||
.toList();
|
||||
|
||||
// 查询子模块ID, 并去重
|
||||
Set<String> moduleIds = apiDefinitionModuleService.getModuleIdsByParentIds(containChildModuleIds)
|
||||
.stream()
|
||||
.collect(Collectors.toSet());
|
||||
selectModules.forEach(selectModule -> moduleIds.add(selectModule.getModuleId()));
|
||||
|
||||
// 重新设置选中的模块ID
|
||||
moduleMatchRule.setModules(null);
|
||||
List<SelectModule> allSelectModules = moduleIds.stream().map(moduleId -> {
|
||||
SelectModule module = new SelectModule();
|
||||
module.setModuleId(moduleId);
|
||||
return module;
|
||||
}).collect(Collectors.toList());
|
||||
moduleMatchRule.setModules(allSelectModules);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ApiScenario> getApiScenarioByIds(List<String> apiScenarioIds) {
|
||||
ApiScenarioExample example = new ApiScenarioExample();
|
||||
example.createCriteria().andIdIn(apiScenarioIds);
|
||||
|
@ -1144,6 +1219,7 @@ public class ApiScenarioService {
|
|||
List<? extends ApiScenarioStepCommonDTO> steps,
|
||||
Map<String, String> resourceBlobMap,
|
||||
Map<String, String> stepDetailMap,
|
||||
Map<String, List<MsHTTPElement>> stepTypeHttpElementMap,
|
||||
ApiScenarioParseEnvInfo scenarioParseEnvInfo) {
|
||||
if (CollectionUtils.isNotEmpty(steps)) {
|
||||
parentElement.setChildren(new LinkedList<>());
|
||||
|
@ -1158,12 +1234,19 @@ public class ApiScenarioService {
|
|||
// 将步骤详情解析生成对应的MsTestElement
|
||||
AbstractMsTestElement msTestElement = stepParser.parseTestElement(step, resourceBlobMap.get(step.getResourceId()), stepDetailMap.get(step.getId()));
|
||||
if (msTestElement != null) {
|
||||
if (msTestElement instanceof MsHTTPElement msHTTPElement) {
|
||||
// 暂存http类型的步骤
|
||||
stepTypeHttpElementMap.putIfAbsent(step.getStepType(), new LinkedList<>());
|
||||
stepTypeHttpElementMap.get(step.getStepType()).add(msHTTPElement);
|
||||
}
|
||||
msTestElement.setProjectId(step.getProjectId());
|
||||
msTestElement.setResourceId(step.getResourceId());
|
||||
setMsScenarioParam(scenarioParseEnvInfo, step, msTestElement);
|
||||
parentElement.getChildren().add(msTestElement);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(step.getChildren())) {
|
||||
parseStep2MsElement(msTestElement, step.getChildren(), resourceBlobMap, stepDetailMap, scenarioParseEnvInfo);
|
||||
parseStep2MsElement(msTestElement, step.getChildren(), resourceBlobMap,
|
||||
stepDetailMap, stepTypeHttpElementMap, scenarioParseEnvInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,12 @@ package io.metersphere.api.controller;
|
|||
import io.metersphere.api.constants.*;
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.assertion.MsAssertionConfig;
|
||||
import io.metersphere.api.dto.debug.ModuleCreateRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionAddRequest;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseAddRequest;
|
||||
import io.metersphere.api.dto.request.http.Header;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.dto.request.http.QueryParam;
|
||||
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||
import io.metersphere.api.dto.response.OperationDataInfo;
|
||||
import io.metersphere.api.dto.scenario.*;
|
||||
|
@ -13,10 +16,12 @@ import io.metersphere.api.job.ApiScenarioScheduleJob;
|
|||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.service.ApiScenarioBatchOperationTestService;
|
||||
import io.metersphere.api.service.BaseResourcePoolTestService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionModuleService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||
import io.metersphere.api.service.definition.ApiTestCaseService;
|
||||
import io.metersphere.api.service.scenario.ApiScenarioService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.project.api.KeyValueEnableParam;
|
||||
import io.metersphere.project.api.assertion.MsResponseCodeAssertion;
|
||||
import io.metersphere.project.api.assertion.MsScriptAssertion;
|
||||
import io.metersphere.project.api.processor.MsProcessor;
|
||||
|
@ -25,6 +30,9 @@ import io.metersphere.project.dto.environment.EnvironmentConfig;
|
|||
import io.metersphere.project.dto.environment.EnvironmentGroupProjectDTO;
|
||||
import io.metersphere.project.dto.environment.EnvironmentGroupRequest;
|
||||
import io.metersphere.project.dto.environment.EnvironmentRequest;
|
||||
import io.metersphere.project.dto.environment.http.HttpConfig;
|
||||
import io.metersphere.project.dto.environment.http.HttpConfigPathMatchRule;
|
||||
import io.metersphere.project.dto.environment.http.SelectModule;
|
||||
import io.metersphere.project.dto.environment.processors.EnvProcessorConfig;
|
||||
import io.metersphere.project.dto.environment.processors.EnvRequestScriptProcessor;
|
||||
import io.metersphere.project.dto.environment.processors.EnvScenarioScriptProcessor;
|
||||
|
@ -49,10 +57,10 @@ import io.metersphere.system.controller.handler.ResultHolder;
|
|||
import io.metersphere.system.domain.Plugin;
|
||||
import io.metersphere.system.domain.Schedule;
|
||||
import io.metersphere.system.dto.request.PluginUpdateRequest;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.mapper.ScheduleMapper;
|
||||
import io.metersphere.system.service.PluginLoadService;
|
||||
import io.metersphere.system.service.PluginService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.uid.NumGenerator;
|
||||
|
@ -144,11 +152,11 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
@Resource
|
||||
private PluginService pluginService;
|
||||
@Resource
|
||||
private PluginLoadService pluginLoadService;
|
||||
@Resource
|
||||
private ApiDefinitionMapper apiDefinitionMapper;
|
||||
@Resource
|
||||
private ApiTestCaseMapper apiTestCaseMapper;
|
||||
@Resource
|
||||
private ApiDefinitionModuleService apiDefinitionModuleService;
|
||||
private static String fileMetadataId;
|
||||
private static String localFileId;
|
||||
private static ApiScenario addApiScenario;
|
||||
|
@ -159,6 +167,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
private static ApiTestCase apiTestCase;
|
||||
private static String envId;
|
||||
private static String envGroupId;
|
||||
private static String moduleId;
|
||||
|
||||
private static final List<CheckLogModel> LOG_CHECK_LIST = new ArrayList<>();
|
||||
|
||||
|
@ -284,6 +293,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
@Test
|
||||
@Order(1)
|
||||
public void add() throws Exception {
|
||||
initModule();
|
||||
initEnv();
|
||||
initTestData();
|
||||
|
||||
|
@ -482,6 +492,18 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
private void initTestData() {
|
||||
Header header1 = new Header();
|
||||
header1.setKey("a");
|
||||
header1.setValue("aaa");
|
||||
|
||||
Header header2 = new Header();
|
||||
header2.setKey("c");
|
||||
header2.setValue("cc");
|
||||
|
||||
Header header3 = new Header();
|
||||
header3.setKey("Cookie");
|
||||
header3.setValue("b=c");
|
||||
|
||||
ApiDefinitionAddRequest apiDefinitionAddRequest = new ApiDefinitionAddRequest();
|
||||
apiDefinitionAddRequest.setName("test scenario");
|
||||
apiDefinitionAddRequest.setProtocol(ApiConstants.HTTP_PROTOCOL);
|
||||
|
@ -489,11 +511,22 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
apiDefinitionAddRequest.setMethod("POST");
|
||||
apiDefinitionAddRequest.setPath("/api/admin/posts");
|
||||
apiDefinitionAddRequest.setStatus(ApiDefinitionStatus.PREPARE.getValue());
|
||||
apiDefinitionAddRequest.setModuleId("default");
|
||||
apiDefinitionAddRequest.setModuleId(moduleId);
|
||||
apiDefinitionAddRequest.setVersionId(extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID));
|
||||
apiDefinitionAddRequest.setDescription("描述内容");
|
||||
apiDefinitionAddRequest.setName("test scenario");
|
||||
MsHTTPElement msHttpElement = MsHTTPElementTest.getAddProcessorHttpElement();
|
||||
msHttpElement.setHeaders(List.of(header1, header2, header3));
|
||||
msHttpElement.setPath(apiDefinitionAddRequest.getPath());
|
||||
QueryParam queryParam1 = new QueryParam();
|
||||
queryParam1.setEncode(true);
|
||||
queryParam1.setKey("aa");
|
||||
queryParam1.setValue("bbb");
|
||||
QueryParam queryParam2 = new QueryParam();
|
||||
queryParam2.setEncode(false);
|
||||
queryParam2.setKey("aa2");
|
||||
queryParam2.setValue("bbb2");
|
||||
msHttpElement.setQuery(List.of(queryParam1, queryParam2));
|
||||
apiDefinitionAddRequest.setRequest(getMsElementParam(msHttpElement));
|
||||
apiDefinitionAddRequest.setResponse("{}");
|
||||
apiDefinition = apiDefinitionService.create(apiDefinitionAddRequest, "admin");
|
||||
|
@ -654,6 +687,8 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
pluginStepDetail.put("port", "port");
|
||||
pluginStepDetail.put("projectId", DEFAULT_PROJECT_ID);
|
||||
request.getStepDetails().put(pluginStep.getId(), pluginStepDetail);
|
||||
request.getScenarioConfig().getOtherConfig().setEnableCookieShare(true);
|
||||
request.getScenarioConfig().getOtherConfig().setEnableGlobalCookie(false);
|
||||
|
||||
Plugin plugin = addEnvTestPlugin();
|
||||
this.requestPostWithOk(DEBUG, request);
|
||||
|
@ -678,6 +713,14 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
return pluginService.add(request, mockMultipartFile);
|
||||
}
|
||||
|
||||
private void initModule() {
|
||||
ModuleCreateRequest request = new ModuleCreateRequest();
|
||||
request.setName("test");
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setParentId(ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||
moduleId = apiDefinitionModuleService.add(request, "admin");
|
||||
}
|
||||
|
||||
private void initEnv() {
|
||||
EnvironmentRequest envRequest = new EnvironmentRequest();
|
||||
envRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
|
@ -730,6 +773,41 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
responseCodeAssertion.setName("test");
|
||||
environmentConfig.getAssertionConfig().getAssertions().add(responseCodeAssertion);
|
||||
|
||||
KeyValueEnableParam header1 = new KeyValueEnableParam();
|
||||
header1.setKey("a");
|
||||
header1.setValue("aa");
|
||||
|
||||
KeyValueEnableParam header2 = new KeyValueEnableParam();
|
||||
header2.setKey("b");
|
||||
header2.setValue("bb");
|
||||
|
||||
KeyValueEnableParam header3 = new KeyValueEnableParam();
|
||||
header3.setKey("Cookie");
|
||||
header3.setValue("a=b");
|
||||
|
||||
HttpConfig httpNoneConfig = new HttpConfig();
|
||||
httpNoneConfig.setUrl("localhost:8081");
|
||||
httpNoneConfig.setType(HttpConfig.HttpConfigMatchType.NONE.name());
|
||||
httpNoneConfig.setHeaders(List.of(header1, header2, header3));
|
||||
|
||||
HttpConfig httpModuleConfig = new HttpConfig();
|
||||
httpModuleConfig.setUrl("localhost:8081");
|
||||
httpModuleConfig.setType(HttpConfig.HttpConfigMatchType.MODULE.name());
|
||||
SelectModule selectModule = new SelectModule();
|
||||
selectModule.setModuleId(moduleId);
|
||||
selectModule.setContainChildModule(true);
|
||||
httpModuleConfig.getModuleMatchRule().setModules(List.of(selectModule));
|
||||
httpModuleConfig.setHeaders(List.of(header1, header2, header3));
|
||||
|
||||
HttpConfig httpPathConfig = new HttpConfig();
|
||||
httpPathConfig.setUrl("localhost:8081");
|
||||
httpPathConfig.setType(HttpConfig.HttpConfigMatchType.PATH.name());
|
||||
httpPathConfig.getPathMatchRule().setPath("/test");
|
||||
httpPathConfig.getPathMatchRule().setCondition(HttpConfigPathMatchRule.MatchRuleCondition.CONTAINS.name());
|
||||
httpPathConfig.setHeaders(List.of(header1, header2, header3));
|
||||
|
||||
environmentConfig.setHttpConfig(List.of(httpNoneConfig, httpModuleConfig, httpPathConfig));
|
||||
|
||||
environmentConfig.setPluginConfigMap(pluginConfigMap);
|
||||
envRequest.setConfig(environmentConfig);
|
||||
Environment environment = environmentService.add(envRequest, "admin", null);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package io.metersphere.project.dto.environment.http;
|
||||
|
||||
import io.metersphere.project.api.KeyValueEnableParam;
|
||||
import io.metersphere.sdk.constants.ValueEnum;
|
||||
import io.metersphere.system.valid.EnumValue;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
@ -15,7 +17,9 @@ import java.util.List;
|
|||
public class HttpConfig implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "http协议类型(http/https)")
|
||||
@EnumValue(enumClass = HttpProtocolType.class)
|
||||
private String protocol = HttpProtocolType.HTTP.name();
|
||||
@Schema(description = "环境域名")
|
||||
private String url;
|
||||
/**
|
||||
|
@ -34,6 +38,24 @@ public class HttpConfig implements Serializable {
|
|||
@Schema(description = "请求头")
|
||||
private List<@Valid KeyValueEnableParam> headers = new ArrayList<>(0);
|
||||
|
||||
|
||||
public boolean isModuleMatchRule() {
|
||||
return StringUtils.equals(HttpConfigMatchType.MODULE.name(), type);
|
||||
}
|
||||
|
||||
public boolean isPathMatchRule() {
|
||||
return StringUtils.equals(HttpConfigMatchType.PATH.name(), type);
|
||||
}
|
||||
|
||||
public int getModuleMatchRuleOrder() {
|
||||
if (isPathMatchRule()) {
|
||||
return 0;
|
||||
} else if (isModuleMatchRule()) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用条件匹配类型
|
||||
*/
|
||||
|
@ -51,4 +73,23 @@ public class HttpConfig implements Serializable {
|
|||
*/
|
||||
NONE
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用条件匹配类型
|
||||
*/
|
||||
public enum HttpProtocolType implements ValueEnum {
|
||||
HTTP("http"),
|
||||
HTTPS("https");
|
||||
|
||||
private String value;
|
||||
|
||||
HttpProtocolType(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package io.metersphere.project.dto.environment.http;
|
|||
import io.metersphere.system.valid.EnumValue;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* @Author: jianxing
|
||||
|
@ -30,10 +32,20 @@ public class HttpConfigPathMatchRule implements Serializable {
|
|||
/**
|
||||
* 包含
|
||||
*/
|
||||
CONTAINS,
|
||||
CONTAINS((envPath, path) -> StringUtils.contains(path, envPath)),
|
||||
/**
|
||||
* 等于
|
||||
*/
|
||||
EQUALS
|
||||
EQUALS((envPath, path) -> StringUtils.equals(path, envPath));
|
||||
|
||||
MatchRuleCondition(BiFunction<String, String, Boolean> matchFunc) {
|
||||
this.matchFunc = matchFunc;
|
||||
}
|
||||
|
||||
private BiFunction<String, String, Boolean> matchFunc;
|
||||
|
||||
public boolean match(String value, String expect) {
|
||||
return matchFunc.apply(value, expect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public class PluginLoadService {
|
|||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public String loadPlugin(String fileName) {
|
||||
public synchronized String loadPlugin(String fileName) {
|
||||
MsFileUtils.validateFileName(fileName);
|
||||
String filePath = LocalRepositoryDir.getPluginDir() + "/" + fileName;
|
||||
File file = new File(filePath);
|
||||
|
|
|
@ -56,7 +56,7 @@ public class BasePluginTestService {
|
|||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public Plugin addJiraPlugin() throws Exception {
|
||||
public synchronized Plugin addJiraPlugin() throws Exception {
|
||||
if (hasJiraPlugin()) {
|
||||
return jiraPlugin;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public class BasePluginTestService {
|
|||
return serviceIntegration;
|
||||
}
|
||||
|
||||
public Plugin getJiraPlugin() throws Exception {
|
||||
public synchronized Plugin getJiraPlugin() throws Exception {
|
||||
if (!hasJiraPlugin()) {
|
||||
return this.addJiraPlugin();
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class BasePluginTestService {
|
|||
return jiraPlugin != null;
|
||||
}
|
||||
|
||||
public void deleteJiraPlugin() {
|
||||
public synchronized void deleteJiraPlugin() {
|
||||
if (jiraPlugin != null) {
|
||||
pluginService.delete(jiraPlugin.getId());
|
||||
jiraPlugin = null;
|
||||
|
|
Loading…
Reference in New Issue