(t *testing.T)
| 144 | } |
| 145 | |
| 146 | func TestProjects_JSONOutput(t *testing.T) { |
| 147 | resetProjectsFlags() |
| 148 | projectsFormat = "json" |
| 149 | |
| 150 | projectDir := createProjectWithTasks(t, "tasks", map[string]string{ |
| 151 | "001.md": taskFile("001", "Task A", "pending"), |
| 152 | "002.md": taskFile("002", "Task B", "in-progress"), |
| 153 | "003.md": taskFile("003", "Task C", "completed"), |
| 154 | }) |
| 155 | |
| 156 | setupGlobalRegistry(t, "projects:\n"+ |
| 157 | " - id: proj1\n"+ |
| 158 | " name: \"My Project\"\n"+ |
| 159 | " path: "+projectDir+"\n") |
| 160 | |
| 161 | stdout, _, err := captureProjectsOutput(t) |
| 162 | if err != nil { |
| 163 | t.Fatalf("unexpected error: %v", err) |
| 164 | } |
| 165 | |
| 166 | var summaries []ProjectSummary |
| 167 | if err := json.Unmarshal([]byte(stdout), &summaries); err != nil { |
| 168 | t.Fatalf("failed to parse JSON: %v\noutput: %s", err, stdout) |
| 169 | } |
| 170 | |
| 171 | if len(summaries) != 1 { |
| 172 | t.Fatalf("expected 1 project, got %d", len(summaries)) |
| 173 | } |
| 174 | |
| 175 | s := summaries[0] |
| 176 | if s.ID != "proj1" { |
| 177 | t.Errorf("expected id 'proj1', got %q", s.ID) |
| 178 | } |
| 179 | if s.Name != "My Project" { |
| 180 | t.Errorf("expected name 'My Project', got %q", s.Name) |
| 181 | } |
| 182 | if s.Tasks != 3 { |
| 183 | t.Errorf("expected 3 tasks, got %d", s.Tasks) |
| 184 | } |
| 185 | if s.Pending != 1 { |
| 186 | t.Errorf("expected 1 pending, got %d", s.Pending) |
| 187 | } |
| 188 | if s.InProgress != 1 { |
| 189 | t.Errorf("expected 1 in-progress, got %d", s.InProgress) |
| 190 | } |
| 191 | if s.Completed != 1 { |
| 192 | t.Errorf("expected 1 completed, got %d", s.Completed) |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | func TestProjects_UnreachablePath(t *testing.T) { |
| 197 | resetProjectsFlags() |
nothing calls this directly
no test coverage detected