Add subtasks to the PR
Change-Id: I386be06949a54dee518e9b6a23344d76099b88ba
diff --git a/server/subtasks/service_test.go b/server/subtasks/service_test.go
index 158bcdc..0a8e473 100644
--- a/server/subtasks/service_test.go
+++ b/server/subtasks/service_test.go
@@ -2,6 +2,7 @@
import (
"context"
+ "os"
"strings"
"testing"
"time"
@@ -482,6 +483,160 @@
}
}
+func TestGenerateSubtaskFile(t *testing.T) {
+ mockProvider := NewMockLLMProvider([]string{})
+ service := NewSubtaskService(mockProvider, nil, []string{"backend"}, nil, "example", "repo", nil)
+
+ subtask := tm.SubtaskProposal{
+ Title: "Implement API endpoints",
+ Description: "Create REST API endpoints for user management",
+ Priority: tm.PriorityHigh,
+ AssignedTo: "backend",
+ EstimatedHours: 12,
+ Dependencies: []string{"0"},
+ RequiredSkills: []string{"go", "rest_api"},
+ }
+
+ taskID := "parent-task-subtask-1"
+ parentTaskID := "parent-task"
+
+ content := service.generateSubtaskFile(subtask, taskID, parentTaskID)
+
+ // Verify YAML frontmatter
+ if !strings.Contains(content, "id: parent-task-subtask-1") {
+ t.Error("Generated file should contain task ID in frontmatter")
+ }
+ if !strings.Contains(content, "title: Implement API endpoints") {
+ t.Error("Generated file should contain task title in frontmatter")
+ }
+ if !strings.Contains(content, "assignee: backend") {
+ t.Error("Generated file should contain assignee in frontmatter")
+ }
+ if !strings.Contains(content, "status: todo") {
+ t.Error("Generated file should have 'todo' status")
+ }
+ if !strings.Contains(content, "priority: high") {
+ t.Error("Generated file should contain priority in frontmatter")
+ }
+ if !strings.Contains(content, "parent_task_id: parent-task") {
+ t.Error("Generated file should contain parent task ID")
+ }
+ if !strings.Contains(content, "estimated_hours: 12") {
+ t.Error("Generated file should contain estimated hours")
+ }
+
+ // Verify dependencies are converted properly
+ if !strings.Contains(content, "dependencies:") {
+ t.Error("Generated file should contain dependencies section")
+ }
+ if !strings.Contains(content, "- parent-task-subtask-1") {
+ t.Error("Dependencies should be converted to subtask IDs")
+ }
+
+ // Verify required skills
+ if !strings.Contains(content, "required_skills:") {
+ t.Error("Generated file should contain required skills section")
+ }
+ if !strings.Contains(content, "- go") {
+ t.Error("Generated file should contain required skills")
+ }
+
+ // Verify markdown content
+ if !strings.Contains(content, "# Task Description") {
+ t.Error("Generated file should contain markdown task description")
+ }
+ if !strings.Contains(content, "Create REST API endpoints for user management") {
+ t.Error("Generated file should contain task description in body")
+ }
+}
+
+func TestUpdateParentTaskAsCompleted(t *testing.T) {
+ mockProvider := NewMockLLMProvider([]string{})
+ service := NewSubtaskService(mockProvider, nil, []string{"backend"}, nil, "example", "repo", nil)
+
+ // Create a temporary task file for testing
+ taskContent := `---
+id: test-task-123
+title: Test Task
+description: A test task for validation
+assignee: backend
+status: todo
+priority: high
+created_at: 2024-01-01T10:00:00Z
+updated_at: 2024-01-01T10:00:00Z
+completed_at: null
+---
+
+# Task Description
+
+A test task for validation
+`
+
+ // Create temporary file
+ tmpFile, err := os.CreateTemp("", "test-task-*.md")
+ if err != nil {
+ t.Fatalf("Failed to create temp file: %v", err)
+ }
+ defer os.Remove(tmpFile.Name())
+
+ if err := os.WriteFile(tmpFile.Name(), []byte(taskContent), 0644); err != nil {
+ t.Fatalf("Failed to write temp file: %v", err)
+ }
+
+ // Create analysis with subtasks
+ analysis := &tm.SubtaskAnalysis{
+ ParentTaskID: "test-task-123",
+ EstimatedTotalHours: 20,
+ Subtasks: []tm.SubtaskProposal{
+ {
+ Title: "Subtask 1",
+ AssignedTo: "backend",
+ },
+ {
+ Title: "Subtask 2",
+ AssignedTo: "frontend",
+ },
+ },
+ }
+
+ // Update the parent task
+ err = service.updateParentTaskAsCompleted(tmpFile.Name(), analysis)
+ if err != nil {
+ t.Fatalf("updateParentTaskAsCompleted failed: %v", err)
+ }
+
+ // Read the updated file
+ updatedContent, err := os.ReadFile(tmpFile.Name())
+ if err != nil {
+ t.Fatalf("Failed to read updated file: %v", err)
+ }
+
+ updatedString := string(updatedContent)
+
+ // Verify the status was changed to completed
+ if !strings.Contains(updatedString, "status: completed") {
+ t.Error("Updated file should contain 'status: completed'")
+ }
+
+ // Verify completed_at was set (should not be null)
+ if strings.Contains(updatedString, "completed_at: null") {
+ t.Error("Updated file should have completed_at timestamp, not null")
+ }
+
+ // Verify subtask information was added
+ if !strings.Contains(updatedString, "## Subtasks Created") {
+ t.Error("Updated file should contain subtasks information")
+ }
+
+ if !strings.Contains(updatedString, "test-task-123-subtask-1") {
+ t.Error("Updated file should reference created subtask IDs")
+ }
+
+ if !strings.Contains(updatedString, "**Total Estimated Hours:** 20") {
+ t.Error("Updated file should contain total estimated hours")
+ }
+}
+
func TestClose(t *testing.T) {
mockProvider := NewMockLLMProvider([]string{})
service := NewSubtaskService(mockProvider, nil, []string{"backend"}, nil, "example", "repo", nil)