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.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.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import static org.junit.jupiter.api.Assertions.*; /** * ImageElement 单元测试 * * @author Claude * @since 2025-01-18 */ class ImageElementTest { private Graphics2D graphics; private RenderContext context; @BeforeAll static void initRegistry() { ElementFactory.clearRegistry(); ElementFactory.register(ElementType.TEXT, TextElement.class); ElementFactory.register(ElementType.IMAGE, ImageElement.class); } static class TestableImageElement extends ImageElement { boolean isSafe(String url) { return isSafeRemoteUrl(url); } BufferedImage load(String path) { return downloadImage(path); } } @BeforeEach void setUp() { BufferedImage canvas = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB); graphics = canvas.createGraphics(); Map 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")); } @Test void testImageElement_SafeRemoteUrlChecks() { TestableImageElement element = new TestableImageElement(); assertFalse(element.isSafe("http://127.0.0.1/admin.png")); assertFalse(element.isSafe("http://localhost/private.png")); assertFalse(element.isSafe("file:///etc/passwd")); assertTrue(element.isSafe("https://8.8.8.8/logo.png")); } @Test void testImageElement_LoadLocalImageSuccess() throws IOException { Path temp = Files.createTempFile("puzzle-image", ".png"); try { BufferedImage bufferedImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB); ImageIO.write(bufferedImage, "png", temp.toFile()); TestableImageElement element = new TestableImageElement(); BufferedImage loaded = element.load(temp.toString()); assertNotNull(loaded); assertEquals(10, loaded.getWidth()); assertEquals(10, loaded.getHeight()); } finally { Files.deleteIfExists(temp); } } }