package application import ( "testing" "time" "img_infinite_canvas/internal/domain/design" ) func TestGeneratorTaskStatusWaitsForActiveCanvasWork(t *testing.T) { threadID := "thread-image" project := design.Project{ ID: "project-image", LastThreadID: threadID, Status: design.StatusExploring, UpdatedAt: time.Now(), Nodes: []design.Node{ { ID: "image-1", Type: design.NodeTypeImage, Title: "Done image", Content: "http://localhost:19000/canvas-assets/done.png", Status: "success", }, { ID: "image-2", Type: design.NodeTypeImage, Title: "Pending image", Content: "pending prompt", Status: "generating", }, }, Messages: []design.Message{ {ID: "user", Role: "user", Type: "user", Content: "make two images", ThreadID: threadID}, {ID: "planner", Role: "assistant", Type: "assistant", Status: "success", ThreadID: threadID, Name: "agent_planner"}, {ID: "tool", Role: "tool", Type: "tool", Title: "GPT Image 2", Status: "running", ThreadID: threadID}, { ID: "artifact-1", Role: "tool", Type: "tool_use", Title: "generate_media", Name: "generate_media", ToolHint: "generate_image_gpt_image_2", Status: "success", ThreadID: threadID, CreatedAt: time.Now(), Content: `[{"event_data":{"artifact":[{"artifact_id":"image-1","artifact_type":"image_info","format":"png","height":1024,"image_name":"Done image","image_url":"http://localhost:19000/canvas-assets/done.png","prompt_text":"make two images","width":1024}]}}]`, }, }, } task := generatorTaskFromProject(project, threadID) if task.Status != "submitted" { t.Fatalf("expected active canvas work to keep task submitted, got %s", task.Status) } if len(task.Artifacts) != 1 { t.Fatalf("expected partial artifact to remain visible, got %#v", task.Artifacts) } } func TestGeneratorTaskStatusDoesNotCompleteExploringPlannerOnlyThread(t *testing.T) { threadID := "thread-planning" project := design.Project{ ID: "project-planning", LastThreadID: threadID, Status: design.StatusExploring, Messages: []design.Message{ {ID: "user", Role: "user", Type: "user", Content: "make images", ThreadID: threadID}, {ID: "planner", Role: "assistant", Type: "assistant", Status: "success", ThreadID: threadID, Name: "agent_planner"}, }, } task := generatorTaskFromProject(project, threadID) if task.Status != "submitted" { t.Fatalf("expected exploring planner-only thread to stay submitted, got %s", task.Status) } } func TestGeneratorTaskStatusCompletesWhenCanvasSettles(t *testing.T) { threadID := "thread-image" project := design.Project{ ID: "project-image", LastThreadID: threadID, Status: design.StatusReady, UpdatedAt: time.Now(), Nodes: []design.Node{ { ID: "image-1", Type: design.NodeTypeImage, Title: "Done image", Content: "http://localhost:19000/canvas-assets/done.png", Status: "success", }, }, Messages: []design.Message{ {ID: "user", Role: "user", Type: "user", Content: "make one image", ThreadID: threadID}, {ID: "tool", Role: "tool", Type: "tool", Title: "GPT Image 2", Status: "success", ThreadID: threadID}, { ID: "artifact-1", Role: "tool", Type: "tool_use", Title: "generate_media", Name: "generate_media", Status: "success", ThreadID: threadID, Content: `[{"event_data":{"artifact":[{"artifact_id":"image-1","artifact_type":"image_info","format":"png","height":1024,"image_name":"Done image","image_url":"http://localhost:19000/canvas-assets/done.png","prompt_text":"make one image","width":1024}]}}]`, }, {ID: "assistant", Role: "assistant", Type: "assistant", Status: "success", ThreadID: threadID}, }, } task := generatorTaskFromProject(project, threadID) if task.Status != "completed" { t.Fatalf("expected settled canvas task to complete, got %s", task.Status) } }