fix(项目设置): 保存模板解析默认值报错

This commit is contained in:
AgAngle 2023-10-24 13:37:58 +08:00 committed by Craftsman
parent dc017c84c4
commit 7454357e58
26 changed files with 589 additions and 27 deletions

View File

@ -56,12 +56,7 @@ public enum CustomFieldType {
/** /**
* 多值输入框标签输入框 * 多值输入框标签输入框
*/ */
MULTIPLE_INPUT(false), MULTIPLE_INPUT(false);
/**
* 级联下拉框
* 第三方平台可能会使用
*/
CASCADING_SELECT(false);
private final Boolean hasOption; private final Boolean hasOption;

View File

@ -19,6 +19,6 @@ public class TemplateCustomFieldDTO {
private String apiFieldId; private String apiFieldId;
@Schema(title = "默认值") @Schema(title = "默认值")
private String defaultValue; private Object defaultValue;
} }

View File

@ -22,5 +22,5 @@ public class TemplateCustomFieldRequest {
private String apiFieldId; private String apiFieldId;
@Schema(title = "默认值") @Schema(title = "默认值")
private String defaultValue; private Object defaultValue;
} }

View File

@ -406,6 +406,7 @@ user_role_relation_remove_admin_user_permission_error=无法将 admin 用户将
internal_custom_field_permission_error=系统字段或模板无法删除! internal_custom_field_permission_error=系统字段或模板无法删除!
internal_template_permission_error=系统模板无法删除! internal_template_permission_error=系统模板无法删除!
default_template_permission_error=默认模板无法删除! default_template_permission_error=默认模板无法删除!
field_validate_error={0}字段参数值不合法
#result message #result message
http_result_success=操作成功 http_result_success=操作成功
@ -444,7 +445,7 @@ plugin_permission_error=没有该插件的访问权限
template_scene_illegal_error=使用场景不合法 template_scene_illegal_error=使用场景不合法
# 内置的模板或字段 # 内置的模板或字段
custom_field.functional_priority=优先 custom_field.functional_priority=用例等
template.default=默认模板 template.default=默认模板
parent.node.not_blank=父节点不能为空 parent.node.not_blank=父节点不能为空

View File

@ -409,6 +409,7 @@ user_role_relation_remove_admin_user_permission_error=Unable to delete the admin
internal_custom_field_permission_error=System fields cannot be deleted internal_custom_field_permission_error=System fields cannot be deleted
internal_template_permission_error=System template cannot be deleted internal_template_permission_error=System template cannot be deleted
default_template_permission_error=Default templates cannot be deleted default_template_permission_error=Default templates cannot be deleted
field_validate_error=The field {0} value is invalid
#result message #result message
http_result_success=operate success http_result_success=operate success
@ -447,7 +448,7 @@ plugin_permission_error=No access to this plugin
scheduled_tasks=Scheduled Tasks scheduled_tasks=Scheduled Tasks
template_scene_illegal_error=Scene is illegal template_scene_illegal_error=Scene is illegal
# 内置的模板或字段 # 内置的模板或字段
custom_field.functional_priority=Priority custom_field.functional_priority=Case Priority
template.default=Default template.default=Default
set_default_template=Set the default template set_default_template=Set the default template

View File

@ -406,6 +406,7 @@ user_role_relation_remove_admin_user_permission_error=无法将 admin 用户将
internal_custom_field_permission_error=系统字段或模板无法删除! internal_custom_field_permission_error=系统字段或模板无法删除!
internal_template_permission_error=系统模板无法删除! internal_template_permission_error=系统模板无法删除!
default_template_permission_error=默认模板无法删除! default_template_permission_error=默认模板无法删除!
field_validate_error={0}字段参数值不合法
#result message #result message
http_result_success=操作成功 http_result_success=操作成功
@ -445,7 +446,7 @@ plugin_permission_error=没有该插件的访问权限
scheduled_tasks=定时任务 scheduled_tasks=定时任务
template_scene_illegal_error=使用场景不合法 template_scene_illegal_error=使用场景不合法
# 内置的模板或字段 # 内置的模板或字段
custom_field.functional_priority=优先 custom_field.functional_priority=用例等
template.default=默认模板 template.default=默认模板
set_default_template=设置默认模板 set_default_template=设置默认模板

View File

@ -405,6 +405,7 @@ user_role_relation_remove_admin_user_permission_error=無法將 admin 用戶將
internal_custom_field_permission_error=系統字段或模板無法刪除! internal_custom_field_permission_error=系統字段或模板無法刪除!
internal_template_permission_error=系統模板無法刪除! internal_template_permission_error=系統模板無法刪除!
default_template_permission_error=默认模板无法删除! default_template_permission_error=默认模板无法删除!
field_validate_error={0}字段參數值不合法
#result message #result message
http_result_success=操作成功 http_result_success=操作成功
@ -444,7 +445,7 @@ scheduled_tasks=定時任務
template_scene_illegal_error=使用場景不合法 template_scene_illegal_error=使用場景不合法
# 内置的模板或字段 # 内置的模板或字段
custom_field.functional_priority=優先 custom_field.functional_priority=用例等
template.default=默認模板 template.default=默認模板
set_default_template=設置默認模板 set_default_template=設置默認模板

View File

@ -350,7 +350,7 @@ public class ProjectTemplateControllerTests extends BaseTest {
Assertions.assertEquals(customFieldDTO.getApiFieldId(), templateCustomField.getApiFieldId()); Assertions.assertEquals(customFieldDTO.getApiFieldId(), templateCustomField.getApiFieldId());
Assertions.assertEquals(customFieldDTO.getRequired(), templateCustomField.getRequired()); Assertions.assertEquals(customFieldDTO.getRequired(), templateCustomField.getRequired());
Assertions.assertEquals(templateCustomField.getTemplateId(), template.getId()); Assertions.assertEquals(templateCustomField.getTemplateId(), template.getId());
Assertions.assertEquals(customFieldDTO.getFieldName(), "优先"); Assertions.assertEquals(customFieldDTO.getFieldName(), "用例等");
} }
// @@校验权限 // @@校验权限

View File

@ -26,7 +26,8 @@ public enum CommonResultCode implements IResultCode {
TEMPLATE_EXIST(100013, "template.exist"), TEMPLATE_EXIST(100013, "template.exist"),
DEFAULT_TEMPLATE_PERMISSION(100014, "default_template_permission_error"), DEFAULT_TEMPLATE_PERMISSION(100014, "default_template_permission_error"),
STATUS_ITEM_NOT_EXIST(100015, "status_item.not.exist"), STATUS_ITEM_NOT_EXIST(100015, "status_item.not.exist"),
STATUS_ITEM_EXIST(100016, "status_item.exist"); STATUS_ITEM_EXIST(100016, "status_item.exist"),
FIELD_VALIDATE_ERROR(100017, "field_validate_error");
private int code; private int code;

View File

@ -0,0 +1,18 @@
package io.metersphere.system.dto;
import io.metersphere.system.domain.CustomField;
import lombok.Data;
import java.io.Serializable;
@Data
public class CustomFieldDao extends CustomField implements Serializable {
private static final long serialVersionUID = 1L;
private Boolean required;
private String defaultValue;
private Object value;
}

View File

@ -0,0 +1,77 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.CustomFieldDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import static io.metersphere.system.controller.handler.result.CommonResultCode.FIELD_VALIDATE_ERROR;
public abstract class AbstractCustomFieldResolver {
/**
* 校验参数是否合法
*
* @param customField
* @param value
*/
abstract public void validate(CustomFieldDao customField, Object value);
protected void throwValidateException(String name) {
throw new MSException(FIELD_VALIDATE_ERROR, Translator.get(FIELD_VALIDATE_ERROR.getMessage(), name));
}
protected void validateRequired(CustomFieldDao customField, Object value) {
if (!customField.getRequired()) {
return;
}
if (value == null) {
throwValidateException(customField.getName());
} else if (value instanceof String && StringUtils.isBlank(value.toString())) {
throwValidateException(customField.getName());
}
}
protected void validateArrayRequired(CustomFieldDao customField, Object value) {
if (!customField.getRequired()) {
return;
}
if (value == null || (value instanceof List && CollectionUtils.isEmpty((List) value))) {
throwValidateException(customField.getName());
}
}
protected void validateArray(String name, Object value) {
if (value == null) {
return;
}
if (value instanceof List) {
((List) value).forEach(v -> validateString(name, v));
} else {
throwValidateException(name);
}
}
protected void validateString(String name, Object v) {
if (!(v instanceof String)) {
throwValidateException(name);
}
}
public Object parse2Value(String value) {
return value;
}
public String parse2String(Object value) {
return value == null ? null : value.toString();
}
protected Object parse2Array(String value) {
return value == null ? null : JSON.parseArray(value);
}
}

View File

@ -0,0 +1,22 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.util.DateUtils;
import io.metersphere.system.dto.CustomFieldDao;
import org.apache.commons.lang3.StringUtils;
public class CustomFieldDateResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
validateString(customField.getName(), value);
try {
if (value != null && StringUtils.isNotBlank(value.toString())) {
DateUtils.getDate(value.toString());
}
} catch (Exception e) {
throwValidateException(customField.getName());
}
}
}

View File

@ -0,0 +1,22 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.util.DateUtils;
import io.metersphere.system.dto.CustomFieldDao;
import org.apache.commons.lang3.StringUtils;
public class CustomFieldDateTimeResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
try {
if (value != null && StringUtils.isNotBlank(value.toString())) {
DateUtils.getTime(value.toString());
}
} catch (Exception e) {
throwValidateException(customField.getName());
}
}
}

View File

@ -0,0 +1,20 @@
package io.metersphere.system.resolver.field;
import io.metersphere.system.dto.CustomFieldDao;
public class CustomFieldFloatResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
if (value != null && !(value instanceof Number)) {
throwValidateException(customField.getName());
}
}
@Override
public Object parse2Value(String value) {
return value == null ? null : Float.parseFloat(value);
}
}

View File

@ -0,0 +1,18 @@
package io.metersphere.system.resolver.field;
import io.metersphere.system.dto.CustomFieldDao;
public class CustomFieldIntegerResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
if (value != null && !(value instanceof Integer)) {
throwValidateException(customField.getName());
}
}
@Override
public Object parse2Value(String value) {
return value == null ? null : Integer.parseInt(value);
}
}

View File

@ -0,0 +1,13 @@
package io.metersphere.system.resolver.field;
import io.metersphere.system.dto.CustomFieldDao;
public class CustomFieldMemberResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
validateString(customField.getName(), value);
}
}

View File

@ -0,0 +1,24 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.dto.CustomFieldDao;
public class CustomFieldMultipleMemberResolver extends CustomFieldMemberResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateArrayRequired(customField, value);
validateArray(customField.getName(), value);
}
@Override
public String parse2String(Object value) {
return JSON.toJSONString(value);
}
@Override
public Object parse2Value(String value) {
return parse2Array(value);
}
}

View File

@ -0,0 +1,36 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.CustomFieldOption;
import io.metersphere.system.dto.CustomFieldDao;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class CustomFieldMultipleSelectResolver extends CustomFieldSelectResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateArrayRequired(customField, value);
validateArray(customField.getName(), value);
List<CustomFieldOption> options = getOptions(customField.getId());
Set<String> values = options.stream().map(CustomFieldOption::getValue).collect(Collectors.toSet());
for (String item : (List<String>)value) {
if (!values.contains(item)) {
throwValidateException(customField.getName());
}
}
}
@Override
public String parse2String(Object value) {
return JSON.toJSONString(value);
}
@Override
public Object parse2Value(String value) {
return parse2Array(value);
}
}

View File

@ -0,0 +1,25 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.dto.CustomFieldDao;
public class CustomFieldMultipleTextResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateArrayRequired(customField, value);
validateArray(customField.getName(), value);
}
@Override
public String parse2String(Object value) {
return JSON.toJSONString(value);
}
@Override
public Object parse2Value(String value) {
return parse2Array(value);
}
}

View File

@ -0,0 +1,36 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.constants.CustomFieldType;
import java.util.HashMap;
public class CustomFieldResolverFactory {
private static final HashMap<String, AbstractCustomFieldResolver> resolverMap = new HashMap<>();
static {
resolverMap.put(CustomFieldType.SELECT.name(), new CustomFieldSelectResolver());
resolverMap.put(CustomFieldType.RADIO.name(), new CustomFieldSelectResolver());
resolverMap.put(CustomFieldType.MULTIPLE_SELECT.name(), new CustomFieldMultipleSelectResolver());
resolverMap.put(CustomFieldType.CHECKBOX.name(), new CustomFieldMultipleSelectResolver());
resolverMap.put(CustomFieldType.INPUT.name(), new CustomFieldTextResolver());
resolverMap.put(CustomFieldType.TEXTAREA.name(), new CustomFieldTextResolver());
resolverMap.put(CustomFieldType.MULTIPLE_INPUT.name(), new CustomFieldMultipleTextResolver());
resolverMap.put(CustomFieldType.DATE.name(), new CustomFieldDateResolver());
resolverMap.put(CustomFieldType.DATETIME.name(), new CustomFieldDateTimeResolver());
resolverMap.put(CustomFieldType.MEMBER.name(), new CustomFieldMemberResolver());
resolverMap.put(CustomFieldType.MULTIPLE_MEMBER.name(), new CustomFieldMultipleMemberResolver());
resolverMap.put(CustomFieldType.INT.name(), new CustomFieldIntegerResolver());
resolverMap.put(CustomFieldType.FLOAT.name(), new CustomFieldFloatResolver());
}
public static AbstractCustomFieldResolver getResolver(String type) {
return resolverMap.get(type);
}
}

View File

@ -0,0 +1,33 @@
package io.metersphere.system.resolver.field;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.system.domain.CustomFieldOption;
import io.metersphere.system.dto.CustomFieldDao;
import io.metersphere.system.service.BaseCustomFieldOptionService;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class CustomFieldSelectResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
if (value == null) {
return;
}
validateString(customField.getName(), value);
List<CustomFieldOption> options = getOptions(customField.getId());
Set<String> values = options.stream().map(CustomFieldOption::getValue).collect(Collectors.toSet());
if (!values.contains(value)) {
throwValidateException(customField.getName());
}
}
protected List<CustomFieldOption> getOptions(String id) {
BaseCustomFieldOptionService customFieldOptionService = CommonBeanFactory.getBean(BaseCustomFieldOptionService.class);
return customFieldOptionService.getByFieldId(id);
}
}

View File

@ -0,0 +1,13 @@
package io.metersphere.system.resolver.field;
import io.metersphere.system.dto.CustomFieldDao;
public class CustomFieldTextResolver extends AbstractCustomFieldResolver {
@Override
public void validate(CustomFieldDao customField, Object value) {
validateRequired(customField, value);
validateString(customField.getName(), value);
}
}

View File

@ -5,7 +5,10 @@ import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.domain.CustomField; import io.metersphere.system.domain.CustomField;
import io.metersphere.system.domain.TemplateCustomField; import io.metersphere.system.domain.TemplateCustomField;
import io.metersphere.system.domain.TemplateCustomFieldExample; import io.metersphere.system.domain.TemplateCustomFieldExample;
import io.metersphere.system.dto.CustomFieldDao;
import io.metersphere.system.mapper.TemplateCustomFieldMapper; import io.metersphere.system.mapper.TemplateCustomFieldMapper;
import io.metersphere.system.resolver.field.AbstractCustomFieldResolver;
import io.metersphere.system.resolver.field.CustomFieldResolverFactory;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -49,6 +52,17 @@ public class BaseTemplateCustomFieldService {
if (CollectionUtils.isEmpty(customFieldRequests)) { if (CollectionUtils.isEmpty(customFieldRequests)) {
return; return;
} }
// 过滤下不存在的字段
List<String> ids = customFieldRequests.stream().map(TemplateCustomFieldRequest::getFieldId).toList();
Set<String> fieldIdSet = baseCustomFieldService.getByIds(ids)
.stream()
.map(CustomField::getId)
.collect(Collectors.toSet());
customFieldRequests = customFieldRequests.stream()
.filter(item -> fieldIdSet.contains(item.getFieldId()))
.toList();
AtomicReference<Integer> pos = new AtomicReference<>(0); AtomicReference<Integer> pos = new AtomicReference<>(0);
List<TemplateCustomField> templateCustomFields = customFieldRequests.stream().map(field -> { List<TemplateCustomField> templateCustomFields = customFieldRequests.stream().map(field -> {
TemplateCustomField templateCustomField = new TemplateCustomField(); TemplateCustomField templateCustomField = new TemplateCustomField();
@ -56,19 +70,24 @@ public class BaseTemplateCustomFieldService {
BeanUtils.copyBean(templateCustomField, field); BeanUtils.copyBean(templateCustomField, field);
templateCustomField.setTemplateId(id); templateCustomField.setTemplateId(id);
templateCustomField.setPos(pos.getAndSet(pos.get() + 1)); templateCustomField.setPos(pos.getAndSet(pos.get() + 1));
templateCustomField.setDefaultValue(parseDefaultValue(field));
return templateCustomField; return templateCustomField;
}).toList(); }).toList();
// 过滤下不存在的字段
List<String> ids = templateCustomFields.stream().map(TemplateCustomField::getFieldId).toList();
Set<String> fieldIdSet = baseCustomFieldService.getByIds(ids).stream().map(CustomField::getId).collect(Collectors.toSet());
templateCustomFields = templateCustomFields.stream().filter(item -> fieldIdSet.contains(item.getFieldId())).toList();
if (templateCustomFields.size() > 0) { if (templateCustomFields.size() > 0) {
templateCustomFieldMapper.batchInsert(templateCustomFields); templateCustomFieldMapper.batchInsert(templateCustomFields);
} }
} }
private String parseDefaultValue(TemplateCustomFieldRequest field) {
CustomField customField = baseCustomFieldService.getWithCheck(field.getFieldId());
AbstractCustomFieldResolver customFieldResolver = CustomFieldResolverFactory.getResolver(customField.getType());
CustomFieldDao customFieldDao = BeanUtils.copyBean(new CustomFieldDao(), customField);
customFieldDao.setRequired(false);
customFieldResolver.validate(customFieldDao, field.getDefaultValue());
return customFieldResolver.parse2String(field.getDefaultValue());
}
public List<TemplateCustomField> getByTemplateId(String id) { public List<TemplateCustomField> getByTemplateId(String id) {
TemplateCustomFieldExample example = new TemplateCustomFieldExample(); TemplateCustomFieldExample example = new TemplateCustomFieldExample();
example.createCriteria().andTemplateIdEqualTo(id); example.createCriteria().andTemplateIdEqualTo(id);

View File

@ -7,6 +7,9 @@ import io.metersphere.sdk.dto.TemplateDTO;
import io.metersphere.sdk.dto.request.TemplateCustomFieldRequest; import io.metersphere.sdk.dto.request.TemplateCustomFieldRequest;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.resolver.field.AbstractCustomFieldResolver;
import io.metersphere.system.resolver.field.CustomFieldResolverFactory;
import io.metersphere.system.utils.ServiceUtils; import io.metersphere.system.utils.ServiceUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomField; import io.metersphere.system.domain.CustomField;
@ -96,20 +99,30 @@ public class BaseTemplateService {
// 查找字段名称 // 查找字段名称
List<String> fieldIds = templateCustomFields.stream().map(TemplateCustomField::getFieldId).toList(); List<String> fieldIds = templateCustomFields.stream().map(TemplateCustomField::getFieldId).toList();
Map<String, String> fieldNameMap = baseCustomFieldService.getByIds(fieldIds) List<CustomField> customFields = baseCustomFieldService.getByIds(fieldIds);
Map<String, CustomField> fieldMap = customFields
.stream() .stream()
.collect(Collectors.toMap(CustomField::getId, i -> { .collect(Collectors.toMap(CustomField::getId, customField -> {
if (i.getInternal()) { if (customField.getInternal()) {
return baseCustomFieldService.translateInternalField(i.getName()); customField.setName(baseCustomFieldService.translateInternalField(customField.getName()));
} }
return i.getName(); return customField;
})); }));
// 封装字段信息 // 封装字段信息
List<TemplateCustomFieldDTO> fieldDTOS = templateCustomFields.stream().map(i -> { List<TemplateCustomFieldDTO> fieldDTOS = templateCustomFields.stream().map(i -> {
CustomField customField = fieldMap.get(i.getFieldId());
TemplateCustomFieldDTO templateCustomFieldDTO = new TemplateCustomFieldDTO(); TemplateCustomFieldDTO templateCustomFieldDTO = new TemplateCustomFieldDTO();
BeanUtils.copyBean(templateCustomFieldDTO, i); BeanUtils.copyBean(templateCustomFieldDTO, i);
templateCustomFieldDTO.setFieldName(fieldNameMap.get(i.getFieldId())); templateCustomFieldDTO.setFieldName(customField.getName());
AbstractCustomFieldResolver customFieldResolver = CustomFieldResolverFactory.getResolver(customField.getType());
Object defaultValue = null;
try {
defaultValue = customFieldResolver.parse2Value(i.getDefaultValue());
} catch (Exception e) {
LogUtils.error(e);
}
templateCustomFieldDTO.setDefaultValue(defaultValue);
return templateCustomFieldDTO; return templateCustomFieldDTO;
}).toList(); }).toList();

View File

@ -0,0 +1,158 @@
package io.metersphere.system.base;
import io.metersphere.sdk.constants.CustomFieldType;
import io.metersphere.sdk.constants.InternalUser;
import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.dto.request.CustomFieldOptionRequest;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.domain.CustomField;
import io.metersphere.system.dto.CustomFieldDao;
import io.metersphere.system.resolver.field.AbstractCustomFieldResolver;
import io.metersphere.system.resolver.field.CustomFieldResolverFactory;
import io.metersphere.system.service.OrganizationCustomFieldService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static io.metersphere.system.controller.handler.result.CommonResultCode.FIELD_VALIDATE_ERROR;
/**
* @Author: jianxing
* @CreateTime: 2023-10-20 11:32
*/
@Service
public class BaseCustomFieldTestService {
@Resource
private OrganizationCustomFieldService organizationCustomFieldService;
private static Map<CustomFieldType, CustomField> customFields;
public static final String OPTION_VALUE = "OPTION_VALUE";
public Map<CustomFieldType, CustomField> addOrgTestCustomFields() {
if (customFields != null) {
return customFields;
}
customFields = new HashMap<>();
for (CustomFieldType customFieldType : CustomFieldType.values()) {
CustomFieldOptionRequest customFieldOptionRequest = new CustomFieldOptionRequest();
customFieldOptionRequest.setValue(OPTION_VALUE);
customFieldOptionRequest.setText("test");
List<CustomFieldOptionRequest> optionRequests = Arrays.asList(customFieldOptionRequest);
CustomField customField = new CustomField();
customField.setType(customFieldType.name());
customField.setName(customFieldType.name());
customField.setCreateUser(InternalUser.ADMIN.getValue());
customField.setScene(TemplateScene.FUNCTIONAL.name());
customField.setScopeId(BaseTest.DEFAULT_ORGANIZATION_ID);
customField = organizationCustomFieldService.add(customField, optionRequests);
customFields.put(customFieldType, customField);
}
return customFields;
}
public Map<CustomFieldType, CustomField> getCustomFields() {
return customFields;
}
public void testResolverEmptyValidate() {
Map<CustomFieldType, Object> emptyValueMap = new HashMap<>();
Arrays.stream(CustomFieldType.values()).forEach(i -> emptyValueMap.put(i, StringUtils.EMPTY));
emptyValueMap.put(CustomFieldType.MULTIPLE_SELECT, List.of());
emptyValueMap.put(CustomFieldType.MULTIPLE_INPUT, List.of());
emptyValueMap.put(CustomFieldType.CHECKBOX, List.of());
emptyValueMap.put(CustomFieldType.MULTIPLE_MEMBER, List.of());
emptyValueMap.put(CustomFieldType.INT, null);
emptyValueMap.put(CustomFieldType.FLOAT, null);
assertValidateError(emptyValueMap);
}
public void testResolverErrorValidate() {
Map<CustomFieldType, Object> errorValueMap = new HashMap<>();
Arrays.stream(CustomFieldType.values()).forEach(i -> errorValueMap.put(i, 1));
errorValueMap.put(CustomFieldType.MULTIPLE_SELECT, StringUtils.EMPTY);
errorValueMap.put(CustomFieldType.MULTIPLE_INPUT, StringUtils.EMPTY);
errorValueMap.put(CustomFieldType.CHECKBOX, StringUtils.EMPTY);
errorValueMap.put(CustomFieldType.MULTIPLE_MEMBER, StringUtils.EMPTY);
errorValueMap.put(CustomFieldType.INT, StringUtils.EMPTY);
errorValueMap.put(CustomFieldType.FLOAT, StringUtils.EMPTY);
assertValidateError(errorValueMap);
errorValueMap.clear();
Arrays.stream(CustomFieldType.values()).forEach(i -> errorValueMap.put(i, 1));
errorValueMap.put(CustomFieldType.DATE, "eeee");
errorValueMap.put(CustomFieldType.DATETIME, "eeee");
errorValueMap.put(CustomFieldType.DATETIME, "eeee");
errorValueMap.put(CustomFieldType.MULTIPLE_SELECT, List.of(1));
errorValueMap.put(CustomFieldType.MULTIPLE_INPUT, List.of(1));
errorValueMap.put(CustomFieldType.CHECKBOX, List.of(1));
errorValueMap.put(CustomFieldType.MULTIPLE_MEMBER, List.of(1));
errorValueMap.put(CustomFieldType.INT, "dd");
errorValueMap.put(CustomFieldType.FLOAT, "dd");
assertValidateError(errorValueMap);
}
public void testResolverParse() {
Map<CustomFieldType, Object> objectValueMap = new HashMap<>();
Arrays.stream(CustomFieldType.values()).forEach(i -> objectValueMap.put(i, "1"));
objectValueMap.put(CustomFieldType.SELECT, OPTION_VALUE);
objectValueMap.put(CustomFieldType.RADIO, OPTION_VALUE);
objectValueMap.put(CustomFieldType.DATE, "2021-10-10");
objectValueMap.put(CustomFieldType.DATETIME, "2021-10-10 10:10:10");
objectValueMap.put(CustomFieldType.RADIO, OPTION_VALUE);
objectValueMap.put(CustomFieldType.MULTIPLE_SELECT, List.of(OPTION_VALUE));
objectValueMap.put(CustomFieldType.CHECKBOX, List.of(OPTION_VALUE));
objectValueMap.put(CustomFieldType.MULTIPLE_INPUT, List.of(OPTION_VALUE));
objectValueMap.put(CustomFieldType.MULTIPLE_MEMBER, List.of(OPTION_VALUE));
objectValueMap.put(CustomFieldType.INT, 1);
objectValueMap.put(CustomFieldType.FLOAT, 1.2f);
for (CustomFieldType customFieldType : CustomFieldType.values()) {
// 校验 validate 调用成功
invokeValidate(objectValueMap, customFieldType);
AbstractCustomFieldResolver customFieldResolver = CustomFieldResolverFactory.getResolver(customFieldType.name());
CustomField customField = getCustomFields().get(customFieldType);
CustomFieldDao customFieldDao = BeanUtils.copyBean(new CustomFieldDao(), customField);
customFieldDao.setRequired(true);
String valueStr = customFieldResolver.parse2String(objectValueMap.get(customFieldType));
Object objectValue = customFieldResolver.parse2Value(valueStr);
// 校验 parse2String parse2Value 是否正确
if (objectValue instanceof List) {
Assertions.assertEquals(objectValue.toString(), objectValueMap.get(customFieldType).toString());
} else {
Assertions.assertEquals(objectValue, objectValueMap.get(customFieldType));
}
}
}
private void assertValidateError(Map<CustomFieldType, Object> errorValueMap) {
for (CustomFieldType customFieldType : CustomFieldType.values()) {
try {
invokeValidate(errorValueMap, customFieldType);
} catch (MSException e) {
Assertions.assertEquals(e.getErrorCode(), FIELD_VALIDATE_ERROR);
continue;
}
throw new MSException("自定义字段校验失败");
}
}
private void invokeValidate(Map<CustomFieldType, Object> valueMap, CustomFieldType customFieldType) {
AbstractCustomFieldResolver customFieldResolver = CustomFieldResolverFactory.getResolver(customFieldType.name());
CustomField customField = getCustomFields().get(customFieldType);
CustomFieldDao customFieldDao = BeanUtils.copyBean(new CustomFieldDao(), customField);
customFieldDao.setRequired(true);
customFieldResolver.validate(customFieldDao, valueMap.get(customFieldType));
}
}

View File

@ -9,6 +9,7 @@ import io.metersphere.sdk.dto.TemplateDTO;
import io.metersphere.sdk.dto.request.TemplateCustomFieldRequest; import io.metersphere.sdk.dto.request.TemplateCustomFieldRequest;
import io.metersphere.sdk.dto.request.TemplateUpdateRequest; import io.metersphere.sdk.dto.request.TemplateUpdateRequest;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.base.BaseCustomFieldTestService;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.param.TemplateUpdateRequestDefinition; import io.metersphere.system.controller.param.TemplateUpdateRequestDefinition;
import io.metersphere.system.domain.*; import io.metersphere.system.domain.*;
@ -37,7 +38,7 @@ import static io.metersphere.system.controller.result.SystemResultCode.ORGANIZAT
* @author jianxing * @author jianxing
* @date : 2023-8-30 * @date : 2023-8-30
*/ */
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc @AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class OrganizationTemplateControllerTests extends BaseTest { public class OrganizationTemplateControllerTests extends BaseTest {
@ -62,6 +63,8 @@ public class OrganizationTemplateControllerTests extends BaseTest {
private BaseOrganizationParameterService organizationParameterService; private BaseOrganizationParameterService organizationParameterService;
@Resource @Resource
private OrganizationTemplateService organizationTemplateService; private OrganizationTemplateService organizationTemplateService;
@Resource
private BaseCustomFieldTestService baseCustomFieldTestService;
private static Template addTemplate; private static Template addTemplate;
private static Template anotherTemplateField; private static Template anotherTemplateField;
@ -320,7 +323,7 @@ public class OrganizationTemplateControllerTests extends BaseTest {
Assertions.assertEquals(customFieldDTO.getApiFieldId(), templateCustomField.getApiFieldId()); Assertions.assertEquals(customFieldDTO.getApiFieldId(), templateCustomField.getApiFieldId());
Assertions.assertEquals(customFieldDTO.getRequired(), templateCustomField.getRequired()); Assertions.assertEquals(customFieldDTO.getRequired(), templateCustomField.getRequired());
Assertions.assertEquals(templateCustomField.getTemplateId(), template.getId()); Assertions.assertEquals(templateCustomField.getTemplateId(), template.getId());
Assertions.assertEquals(customFieldDTO.getFieldName(), "优先"); Assertions.assertEquals(customFieldDTO.getFieldName(), "用例等");
} }
// @@校验权限 // @@校验权限
@ -395,4 +398,16 @@ public class OrganizationTemplateControllerTests extends BaseTest {
// @@校验权限 // @@校验权限
requestGetPermissionTest(PermissionConstants.ORGANIZATION_TEMPLATE_READ, IS_ORGANIZATION_TEMPLATE_ENABLE, DEFAULT_ORGANIZATION_ID, TemplateScene.FUNCTIONAL.name()); requestGetPermissionTest(PermissionConstants.ORGANIZATION_TEMPLATE_READ, IS_ORGANIZATION_TEMPLATE_ENABLE, DEFAULT_ORGANIZATION_ID, TemplateScene.FUNCTIONAL.name());
} }
/**
* 测试自定义字段解析器
*/
@Test
@Order(9)
public void testCustomFiledResolver() {
baseCustomFieldTestService.addOrgTestCustomFields();
baseCustomFieldTestService.testResolverEmptyValidate();
baseCustomFieldTestService.testResolverErrorValidate();
baseCustomFieldTestService.testResolverParse();
}
} }