添加新需求

This commit is contained in:
super
2026-07-16 13:12:46 +08:00
parent 8543dad514
commit 69784b8d32
20 changed files with 1116 additions and 12 deletions

View File

@@ -1,7 +1,11 @@
package com.nanri.aiimage.modules.appearancepatent.service;
import com.nanri.aiimage.modules.appearancepatent.model.dto.AppearancePatentResultRowDto;
import com.nanri.aiimage.modules.appearancepatent.model.vo.AppearancePatentParsedRowVo;
import org.junit.jupiter.api.Test;
import java.util.LinkedHashMap;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AppearancePatentTaskServiceTest {
@@ -13,4 +17,21 @@ class AppearancePatentTaskServiceTest {
assertEquals("\u6210\u529f", AppearancePatentTaskService.resolveResultStatus("\u4fb5\u6743"));
assertEquals("\u6210\u529f", AppearancePatentTaskService.resolveResultStatus("\u65e0\u4fb5\u6743"));
}
@Test
void resultBrandPrefersPythonThenFallsBackToSourceFile() {
AppearancePatentParsedRowVo parsedRow = new AppearancePatentParsedRowVo();
parsedRow.setValues(new LinkedHashMap<>());
parsedRow.getValues().put("品牌", "Source Brand");
AppearancePatentResultRowDto resultRow = new AppearancePatentResultRowDto();
resultRow.setBrand("Python Brand");
assertEquals("Python Brand", AppearancePatentTaskService.resolveBrand(resultRow, parsedRow));
resultRow.setBrand(" ");
assertEquals("Source Brand", AppearancePatentTaskService.resolveBrand(resultRow, parsedRow));
parsedRow.getValues().clear();
assertEquals("", AppearancePatentTaskService.resolveBrand(resultRow, parsedRow));
}
}

View File

@@ -0,0 +1,83 @@
package com.nanri.aiimage.modules.imagevideo.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nanri.aiimage.config.ImageVideoProperties;
import com.nanri.aiimage.modules.file.service.oss.OssStorageService;
import com.nanri.aiimage.modules.imagevideo.mapper.ImageVideoAsyncTaskMapper;
import com.nanri.aiimage.modules.imagevideo.model.entity.ImageVideoAsyncTaskEntity;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
class ImageVideoArchiveServiceTest {
@Test
void extractsNestedAndMultipleVideoUrlsWithoutDuplicates() {
Map<String, Object> result = Map.of(
"output", "{\"data\":{\"video_url\":\"https://cdn.example/a.mp4\"}}",
"items", List.of(
Map.of("outputVideoUrl", "https://cdn.example/b.mp4"),
Map.of("video_url", "https://cdn.example/a.mp4")));
List<String> urls = ImageVideoArchiveService.findUrls(
result, Set.of("videourl", "video", "outputvideourl", "resultvideourl"));
assertThat(urls).containsExactlyInAnyOrder(
"https://cdn.example/a.mp4", "https://cdn.example/b.mp4");
}
@Test
void preservesSubmitResponseAndPrefersItsDebugUrl() {
ObjectMapper objectMapper = new ObjectMapper();
ImageVideoArchiveService service = new ImageVideoArchiveService(
mock(ImageVideoAsyncTaskMapper.class),
mock(OssStorageService.class),
new ImageVideoProperties(),
objectMapper);
ImageVideoAsyncTaskEntity task = new ImageVideoAsyncTaskEntity();
task.setTaskType(ImageVideoArchiveService.TASK_TYPE);
service.captureSubmitResponse(task, Map.of(
"execute_id", "exec-1",
"debug_url", "https://coze.example/debug/exec-1"));
service.enrichCompletedTask(task, Map.of(
"debug_url", "https://coze.example/debug/final",
"video_url", "https://cdn.example/final.mp4"));
assertEquals("https://coze.example/debug/exec-1", task.getDebugUrl());
assertEquals("PENDING", task.getArchiveStatus());
assertEquals("[\"https://cdn.example/final.mp4\"]", task.getVideoUrlsJson());
assertEquals("exec-1", objectMapper.convertValue(
readJson(objectMapper, task.getSubmitResponseJson()), Map.class).get("execute_id"));
}
@Test
void capturesDebugUrlFromPollResponseWhenSubmitResponseDidNotContainIt() {
ImageVideoArchiveService service = new ImageVideoArchiveService(
mock(ImageVideoAsyncTaskMapper.class),
mock(OssStorageService.class),
new ImageVideoProperties(),
new ObjectMapper());
ImageVideoAsyncTaskEntity task = new ImageVideoAsyncTaskEntity();
task.setTaskType(ImageVideoArchiveService.TASK_TYPE);
service.capturePollResponse(task, Map.of("data", List.of(Map.of(
"debug_url", "https://coze.example/debug/from-poll"))));
assertEquals("https://coze.example/debug/from-poll", task.getDebugUrl());
}
private Object readJson(ObjectMapper objectMapper, String json) {
try {
return objectMapper.readValue(json, Object.class);
} catch (Exception ex) {
throw new AssertionError(ex);
}
}
}

View File

@@ -33,6 +33,8 @@ class ImageVideoAsyncTaskServiceTest {
mock(OssStorageService.class),
new ObjectMapper());
Map<String, Object> cozeResult = Map.of("data", List.of(Map.of(
"execute_id", "7662765765078843411",
"debug_url", "https://www.coze.cn/work_flow?execute_id=7662765765078843411",
"execute_status", "Success",
"output", "{\"node_status\":\"{}\",\"Output\":\"{\\\"data\\\":{\\\"source\\\":\\\"这条裙裤绝了,遮肉显腿长,快拍!\\\",\\\"video_url\\\":\\\"https://example.com/video.mp4\\\"}}\"}"
)));
@@ -41,6 +43,8 @@ class ImageVideoAsyncTaskServiceTest {
assertEquals("这条裙裤绝了,遮肉显腿长,快拍!", result.getRecognizedContent());
assertEquals("这条裙裤绝了,遮肉显腿长,快拍!", result.getScriptDraft());
assertEquals("7662765765078843411", result.getExecuteId());
assertEquals("https://www.coze.cn/work_flow?execute_id=7662765765078843411", result.getDebugUrl());
}
@Test
@@ -51,7 +55,7 @@ class ImageVideoAsyncTaskServiceTest {
ObjectMapper objectMapper = new ObjectMapper();
TaskExecutor directExecutor = Runnable::run;
ImageVideoAsyncTaskService service = new ImageVideoAsyncTaskService(
taskMapper, cozeService, workflowConfigService, objectMapper, directExecutor);
taskMapper, cozeService, workflowConfigService, mock(ImageVideoArchiveService.class), objectMapper, directExecutor);
ImageVideoAsyncTaskEntity task = waitingDouyinTask();
Map<String, Object> cozeResult = Map.of("data", List.of(Map.of(
@@ -86,7 +90,7 @@ class ImageVideoAsyncTaskServiceTest {
ImageVideoCozeService cozeService = mock(ImageVideoCozeService.class);
ImageVideoWorkflowConfigService workflowConfigService = mock(ImageVideoWorkflowConfigService.class);
ImageVideoAsyncTaskService service = new ImageVideoAsyncTaskService(
taskMapper, cozeService, workflowConfigService, new ObjectMapper(), Runnable::run);
taskMapper, cozeService, workflowConfigService, mock(ImageVideoArchiveService.class), new ObjectMapper(), Runnable::run);
ImageVideoAsyncTaskEntity task = waitingDouyinTask();
Map<String, Object> cozeResult = Map.of("data", List.of(Map.of("execute_status", "Running")));
@@ -106,6 +110,35 @@ class ImageVideoAsyncTaskServiceTest {
verify(taskMapper).updateById(task);
}
@Test
void failedWorkflowPollPreservesRawResultAndDebugUrl() {
ImageVideoAsyncTaskMapper taskMapper = mock(ImageVideoAsyncTaskMapper.class);
ImageVideoCozeService cozeService = mock(ImageVideoCozeService.class);
ImageVideoWorkflowConfigService workflowConfigService = mock(ImageVideoWorkflowConfigService.class);
ImageVideoArchiveService archiveService = mock(ImageVideoArchiveService.class);
ImageVideoAsyncTaskService service = new ImageVideoAsyncTaskService(
taskMapper, cozeService, workflowConfigService, archiveService, new ObjectMapper(), Runnable::run);
ImageVideoAsyncTaskEntity task = waitingWorkflowTask();
Map<String, Object> cozeResult = Map.of("data", List.of(Map.of(
"execute_status", "Fail",
"debug_url", "https://www.coze.cn/work_flow?execute_id=exec-98",
"error_message", "model unavailable")));
when(taskMapper.selectList(any())).thenReturn(List.of(task));
when(taskMapper.claimWaiting(98L)).thenReturn(1);
when(taskMapper.selectById(98L)).thenReturn(task);
when(workflowConfigService.imageVideoWorkflowId()).thenReturn("workflow-1");
when(cozeService.getWorkflowResult(1L, "workflow-1", "exec-98")).thenReturn(cozeResult);
service.pollWaitingTasks();
assertEquals("FAILED", task.getStatus());
assertEquals("FAIL", task.getCozeStatus());
assertTrue(task.getResultJson().contains("model unavailable"));
verify(archiveService).capturePollResponse(task, cozeResult);
verify(taskMapper).updateById(task);
}
private ImageVideoAsyncTaskEntity waitingDouyinTask() {
ImageVideoAsyncTaskEntity task = new ImageVideoAsyncTaskEntity();
task.setId(79L);
@@ -118,4 +151,12 @@ class ImageVideoAsyncTaskServiceTest {
task.setUpdatedAt(LocalDateTime.now());
return task;
}
private ImageVideoAsyncTaskEntity waitingWorkflowTask() {
ImageVideoAsyncTaskEntity task = waitingDouyinTask();
task.setId(98L);
task.setTaskType("IMAGE_VIDEO_WORKFLOW");
task.setCozeExecuteId("exec-98");
return task;
}
}