(t *testing.T)
| 182 | } |
| 183 | |
| 184 | func TestNext_BasicRanking(t *testing.T) { |
| 185 | tmpDir := createNextTestTaskFiles(t) |
| 186 | |
| 187 | resetNextFlags() |
| 188 | nextFormat = "json" |
| 189 | nextLimit = 10 |
| 190 | |
| 191 | output, err := captureNextOutput(t, []string{tmpDir}) |
| 192 | if err != nil { |
| 193 | t.Fatalf("runNext failed: %v", err) |
| 194 | } |
| 195 | |
| 196 | var recs []Recommendation |
| 197 | if err := json.Unmarshal([]byte(output), &recs); err != nil { |
| 198 | t.Fatalf("Failed to parse JSON: %v\nOutput: %s", err, output) |
| 199 | } |
| 200 | |
| 201 | // Actionable tasks: 003, 004, 005, 007, 008 |
| 202 | // Blocked: 006 (dep 007 pending), 009 (dep 006 pending), 010 (dep 003 pending) |
| 203 | // Completed: 001, 002 |
| 204 | if len(recs) != 5 { |
| 205 | t.Errorf("Expected 5 actionable tasks, got %d", len(recs)) |
| 206 | for _, r := range recs { |
| 207 | t.Logf(" %s: %s (score=%d)", r.ID, r.Title, r.Score) |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | // Verify sorted by score descending |
| 212 | for i := 1; i < len(recs); i++ { |
| 213 | if recs[i].Score > recs[i-1].Score { |
| 214 | t.Errorf("Recommendations not sorted by score: [%d]=%d > [%d]=%d", |
| 215 | i, recs[i].Score, i-1, recs[i-1].Score) |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | // Verify rank field |
| 220 | for i, rec := range recs { |
| 221 | if rec.Rank != i+1 { |
| 222 | t.Errorf("Expected rank %d, got %d for %s", i+1, rec.Rank, rec.ID) |
| 223 | } |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | func TestNext_BlockedTasksExcluded(t *testing.T) { |
| 228 | tmpDir := createNextTestTaskFiles(t) |
nothing calls this directly
no test coverage detected