You've already forked FrameTour-BE
refactor(puzzle): 重构元素DTO及新增元素基类
- 将ElementCreateRequest和PuzzleElementDTO中的elementType从Integer改为String - 删除所有类型特定字段,新增config和configMap支持JSON配置 - 新增BaseElement抽象基类定义元素通用行为 - 添加ElementConfig接口和具体实现类ImageConfig、TextConfig - 创建ElementFactory工厂类和ElementRegistrar注册器 - 新增ElementType枚举和ElementValidationException异常类 - 实现ImageElement和TextElement具体元素类 - 添加Position位置信息封装类
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package com.ycwl.basic.puzzle.element;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.enums.ElementType;
|
||||
import com.ycwl.basic.puzzle.element.impl.ImageElement;
|
||||
import com.ycwl.basic.puzzle.element.impl.TextElement;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* ElementFactory 单元测试
|
||||
*
|
||||
* @author Claude
|
||||
* @since 2025-01-18
|
||||
*/
|
||||
@SpringBootTest
|
||||
class ElementFactoryTest {
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() {
|
||||
// 确保Element已注册(Spring会自动调用ElementRegistrar)
|
||||
ElementFactory.register(ElementType.TEXT, TextElement.class);
|
||||
ElementFactory.register(ElementType.IMAGE, ImageElement.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTextElement_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "userName", 100, 200, 300, 50, 10,
|
||||
"测试文字", 24, "#333333"
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
assertInstanceOf(TextElement.class, element);
|
||||
assertEquals(ElementType.TEXT, element.getElementType());
|
||||
assertEquals("userName", element.getElementKey());
|
||||
assertEquals(100, element.getPosition().getX());
|
||||
assertEquals(200, element.getPosition().getY());
|
||||
assertEquals(300, element.getPosition().getWidth());
|
||||
assertEquals(50, element.getPosition().getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateImageElement_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg"
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
assertInstanceOf(ImageElement.class, element);
|
||||
assertEquals(ElementType.IMAGE, element.getElementType());
|
||||
assertEquals("userAvatar", element.getElementKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateElement_InvalidType() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("INVALID_TYPE");
|
||||
entity.setElementKey("test");
|
||||
entity.setConfig("{}");
|
||||
|
||||
// When & Then
|
||||
assertThrows(IllegalArgumentException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateElement_NullConfig() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("TEXT");
|
||||
entity.setElementKey("test");
|
||||
entity.setConfig(null);
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(50);
|
||||
|
||||
// When & Then
|
||||
assertThrows(IllegalArgumentException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.ycwl.basic.puzzle.element;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.exception.ElementValidationException;
|
||||
import com.ycwl.basic.puzzle.element.renderer.RenderContext;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* ImageElement 单元测试
|
||||
*
|
||||
* @author Claude
|
||||
* @since 2025-01-18
|
||||
*/
|
||||
class ImageElementTest {
|
||||
|
||||
private Graphics2D graphics;
|
||||
private RenderContext context;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
BufferedImage canvas = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
|
||||
graphics = canvas.createGraphics();
|
||||
|
||||
Map<String, String> dynamicData = new HashMap<>();
|
||||
context = new RenderContext(graphics, dynamicData, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_Creation_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg"
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
assertEquals("userAvatar", element.getElementKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_RoundedImage_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createRoundedImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg", 50
|
||||
);
|
||||
|
||||
// When
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// Then
|
||||
assertNotNull(element);
|
||||
// 验证配置包含圆角信息
|
||||
String schema = element.getConfigSchema();
|
||||
assertTrue(schema.contains("borderRadius"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_InvalidConfig_MissingDefaultImageUrl() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("IMAGE");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"imageFitMode\":\"FILL\"}"); // 缺少 defaultImageUrl
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(100);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_InvalidConfig_InvalidBorderRadius() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("IMAGE");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"defaultImageUrl\":\"test.jpg\",\"borderRadius\":-1}"); // 非法圆角
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(100);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImageElement_GetConfigSchema() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createImageElement(
|
||||
1L, "userAvatar", 50, 100, 100, 100, 5,
|
||||
"https://example.com/avatar.jpg"
|
||||
);
|
||||
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// When
|
||||
String schema = element.getConfigSchema();
|
||||
|
||||
// Then
|
||||
assertNotNull(schema);
|
||||
assertTrue(schema.contains("defaultImageUrl"));
|
||||
assertTrue(schema.contains("imageFitMode"));
|
||||
assertTrue(schema.contains("borderRadius"));
|
||||
}
|
||||
}
|
||||
107
src/test/java/com/ycwl/basic/puzzle/element/TextElementTest.java
Normal file
107
src/test/java/com/ycwl/basic/puzzle/element/TextElementTest.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package com.ycwl.basic.puzzle.element;
|
||||
|
||||
import com.ycwl.basic.puzzle.element.base.BaseElement;
|
||||
import com.ycwl.basic.puzzle.element.base.ElementFactory;
|
||||
import com.ycwl.basic.puzzle.element.exception.ElementValidationException;
|
||||
import com.ycwl.basic.puzzle.element.renderer.RenderContext;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.test.PuzzleTestDataBuilder;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* TextElement 单元测试
|
||||
*
|
||||
* @author Claude
|
||||
* @since 2025-01-18
|
||||
*/
|
||||
class TextElementTest {
|
||||
|
||||
private Graphics2D graphics;
|
||||
private RenderContext context;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
BufferedImage canvas = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
|
||||
graphics = canvas.createGraphics();
|
||||
|
||||
Map<String, String> dynamicData = new HashMap<>();
|
||||
context = new RenderContext(graphics, dynamicData, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_Render_Success() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "userName", 100, 200, 300, 50, 10,
|
||||
"默认文字", 24, "#333333"
|
||||
);
|
||||
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// 添加动态数据
|
||||
context.getDynamicData().put("userName", "张三");
|
||||
|
||||
// When & Then (不抛出异常即为成功)
|
||||
assertDoesNotThrow(() -> element.render(context));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_InvalidConfig_MissingDefaultText() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("TEXT");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"fontSize\":14,\"fontColor\":\"#000000\"}"); // 缺少 defaultText
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(50);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_InvalidConfig_InvalidFontSize() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = new PuzzleElementEntity();
|
||||
entity.setElementType("TEXT");
|
||||
entity.setElementKey("testKey");
|
||||
entity.setConfig("{\"defaultText\":\"test\",\"fontSize\":0,\"fontColor\":\"#000000\"}"); // 非法字号
|
||||
entity.setXPosition(0);
|
||||
entity.setYPosition(0);
|
||||
entity.setWidth(100);
|
||||
entity.setHeight(50);
|
||||
|
||||
// When & Then
|
||||
assertThrows(ElementValidationException.class, () -> ElementFactory.create(entity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextElement_GetConfigSchema() {
|
||||
// Given
|
||||
PuzzleElementEntity entity = PuzzleTestDataBuilder.createTextElement(
|
||||
1L, "userName", 100, 200, 300, 50, 10,
|
||||
"测试文字", 24, "#333333"
|
||||
);
|
||||
|
||||
BaseElement element = ElementFactory.create(entity);
|
||||
|
||||
// When
|
||||
String schema = element.getConfigSchema();
|
||||
|
||||
// Then
|
||||
assertNotNull(schema);
|
||||
assertTrue(schema.contains("defaultText"));
|
||||
assertTrue(schema.contains("fontSize"));
|
||||
assertTrue(schema.contains("fontColor"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user